Commit 051c5bc9 authored by Bastian Krayer's avatar Bastian Krayer

added example for tessellation shader

parent 87783205
cmake_minimum_required(VERSION 2.8)
include(${CMAKE_MODULE_PATH}/DefaultExecutable.cmake)
\ No newline at end of file
#include <CVK_2/CVK_Framework.h>
#include <iostream>
const int WIDTH = 800;
const int HEIGHT = 800;
// To control tessellation in shader
glm::vec4 tessOuter = glm::vec4(8.0f);
glm::vec2 tessInner = glm::vec2(5.0f, 3.0f);
float maxTessLevel = 64.0f;
// Window
GLFWwindow* window = nullptr;
int initWindow() {
glfwInit();
CVK::useOpenGL33CoreProfile();
window = glfwCreateWindow(WIDTH, HEIGHT, "Example Tessellation", 0, 0);
glfwSetWindowPos(window, 100, 50);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize OpenGL context" << std::endl;
return -1;
}
return 0;
}
// Shaders
CVK::ShaderSet* shaderTessTri = nullptr;
CVK::ShaderSet* shaderTessQuad = nullptr;
void initOpenGL() {
// Shaders
auto sPath = CVK::State::getInstance()->getShaderPath();
shaderTessTri = new CVK::ShaderSet(
VERTEX_SHADER_BIT | FRAGMENT_SHADER_BIT | TESS_CONTROL_BIT |
TESS_EVAL_BIT,
{sPath + "/BasicTessellation/basicTessellation.vert",
sPath + "/BasicTessellation/basicTessellation.tcs",
sPath + "/BasicTessellation/basicTessellationTriangle.tes",
sPath + "/BasicTessellation/basicTessellation.frag"});
shaderTessQuad = new CVK::ShaderSet(
VERTEX_SHADER_BIT | FRAGMENT_SHADER_BIT | TESS_CONTROL_BIT |
TESS_EVAL_BIT,
{sPath + "/BasicTessellation/basicTessellation.vert",
sPath + "/BasicTessellation/basicTessellation.tcs",
sPath + "/BasicTessellation/basicTessellationQuad.tes",
sPath + "/BasicTessellation/basicTessellation.frag"});
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
// We want to draw a wireframe mesh
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
// we use 3 control points for our patches
glPatchParameteri(GL_PATCH_VERTICES, 3);
// query the maximum tessellation level
int maxLevel;
glGetIntegerv(GL_MAX_TESS_GEN_LEVEL, &maxLevel);
maxTessLevel = static_cast<float>(maxLevel);
std::cout << "Maximum tessellation level: " << maxLevel << std::endl;
}
void resizeCallback(GLFWwindow* window, int w, int h) {
glViewport(0, 0, w, h);
}
// Helper, so we have all buffers initialized
CVK::Geometry* triangle = nullptr;
void initGeometry() {
triangle = new CVK::Triangle(glm::vec3(0.0f, 0.0f, 0.0f),
glm::vec3(1.0f, 0.0f, 0.0f),
glm::vec3(1.0f, 1.0f, 1.0f));
}
void cleanup() {
delete triangle;
delete shaderTessTri;
delete shaderTessQuad;
}
void charCallback(GLFWwindow* window, unsigned int key) {
const float incr = 1.0f;
switch (key) {
case 'q':
tessInner.x += incr;
break;
case 'w':
tessInner.y += incr;
break;
case 'e':
tessOuter.x += incr;
break;
case 'r':
tessOuter.y += incr;
break;
case 't':
tessOuter.z += incr;
break;
case 'z':
tessOuter.w += incr;
break;
case 'a':
tessInner.x -= incr;
break;
case 's':
tessInner.y -= incr;
break;
case 'd':
tessOuter.x -= incr;
break;
case 'f':
tessOuter.y -= incr;
break;
case 'g':
tessOuter.z -= incr;
break;
case 'h':
tessOuter.w -= incr;
break;
default:
break;
}
tessInner = glm::clamp(tessInner, 1.0f, maxTessLevel);
tessOuter = glm::clamp(tessOuter, 1.0f, maxTessLevel);
}
int main(int argc, const char* argv[]) {
initWindow();
initOpenGL();
initGeometry();
glfwSetWindowSizeCallback(window, resizeCallback);
glfwSetCharCallback(window, charCallback);
while (!glfwWindowShouldClose(window)) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw triangle based tessellation
{
shaderTessTri->useProgram();
glm::mat4 M = glm::identity<glm::mat4>();
M = glm::translate(M, glm::vec3(-0.75f, -0.25f, 0.0f));
M = glm::scale(M, glm::vec3(0.5f));
glUniformMatrix4fv(
glGetUniformLocation(shaderTessTri->getProgramID(),
"modelMatrix"),
1, GL_FALSE, glm::value_ptr(M));
glUniform2fv(glGetUniformLocation(shaderTessTri->getProgramID(),
"tessInner"),
1, glm::value_ptr(tessInner));
glUniform4fv(glGetUniformLocation(shaderTessTri->getProgramID(),
"tessOuter"),
1, glm::value_ptr(tessOuter));
// Important!
// We have to use GL_PATCHES as topology mode to use the
// tessellation shader
glBindVertexArray(triangle->getVAO());
glDrawArrays(GL_PATCHES, 0, 3);
}
// Draw quad based tessellation
// Important!
// We can use the same number of patch vertices (3), as the tessellation
// is independant of the patch vertices. These are defined by us and can
// be used in the tessellation evaluation shader to produce the final
// positions and attributes
{
shaderTessQuad->useProgram();
glm::mat4 M = glm::identity<glm::mat4>();
M = glm::translate(M, glm::vec3(-0.15f, -0.25f, 0.0f));
M = glm::scale(M, glm::vec3(0.5f));
glUniformMatrix4fv(
glGetUniformLocation(shaderTessQuad->getProgramID(),
"modelMatrix"),
1, GL_FALSE, glm::value_ptr(M));
glUniform2fv(glGetUniformLocation(shaderTessQuad->getProgramID(),
"tessInner"),
1, glm::value_ptr(tessInner));
glUniform4fv(glGetUniformLocation(shaderTessQuad->getProgramID(),
"tessOuter"),
1, glm::value_ptr(tessOuter));
// Important!
// We have to use GL_PATCHES as topology mode to use the
// tessellation shader
glBindVertexArray(triangle->getVAO());
glDrawArrays(GL_PATCHES, 0, 3);
}
glfwSwapBuffers(window);
glfwPollEvents();
}
cleanup();
glfwDestroyWindow(window);
glfwTerminate();
}
\ No newline at end of file
#version 330
out vec4 fragColor;
void main()
{
fragColor = vec4(1.0);
}
\ No newline at end of file
#version 400 core
// The number of patch vertices
// These are completely independent of the tessellation geometry
layout (vertices = 3) out;
// To control tessellation from outside
uniform vec2 tessInner;
uniform vec4 tessOuter;
void main()
{
// Set the levels according to input
// These are defined per patch and not per vertex
gl_TessLevelInner[0] = tessInner[0];
gl_TessLevelInner[1] = tessInner[1];
gl_TessLevelOuter[0] = tessOuter[0];
gl_TessLevelOuter[1] = tessOuter[1];
gl_TessLevelOuter[2] = tessOuter[2];
gl_TessLevelOuter[3] = tessOuter[3];
// The control shader is invoced for all patch vertices
// gl_InvocationID tells us, which of the patch vertices that is
// so we can write its position (and possible attributes) to the correct position
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
\ No newline at end of file
#version 330
layout (location = 0) in vec4 Position;
uniform mat4 modelMatrix;
void main()
{
gl_Position = modelMatrix * Position;
}
\ No newline at end of file
#version 400 core
layout (quads) in;
void main()
{
// The tessellation is generated from a quad, but we only need
// 3 vertices to define a parallelogram, so these are our control points
// Read them in for easer reading
vec4 a = gl_in[0].gl_Position;
vec4 b = gl_in[1].gl_Position;
vec4 c = gl_in[2].gl_Position;
// Side vectors
vec4 ab = b - a;
vec4 ac = c - a;
// Compute the final position
// For quads primitives, gl_TessCoord contains uv coordinates in xy
gl_Position = a + ab * gl_TessCoord.x + ac * gl_TessCoord.y;
}
\ No newline at end of file
#version 400 core
layout (triangles) in;
void main()
{
// Compute the position
// For triangles primitives, gl_TessCoord contains the barycentric coordinates in xyz
gl_Position = gl_in[0].gl_Position * gl_TessCoord.x
+ gl_in[1].gl_Position * gl_TessCoord.y
+ gl_in[2].gl_Position * gl_TessCoord.z;
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment