4

I am learning tessellation now. Trying to pass the colour via tesselation shaders. Like I found here, the most consistent answer: Passing data through tessellation shaders to the fragment shader
So far consulting also these sources, but did not find the problem in my code yet:
https://www.khronos.org/opengl/wiki/Tessellation_Control_Shader
https://www.khronos.org/opengl/wiki/Tessellation_Evaluation_Shader
As failing to pass for complex shapes, I narrowed problem down to simple basic triangle. Here is the problem. Only the last, third color is taken from the triangle data passed to shaders, see the TessTriangleRainbow::points in the C++ code snippet for tessellated triangle. No matter that I do, the first ad second color is ignored:
enter image description here
Note, exactly the same code and data but not tessellated looks ok:
enter image description here
Vertex shader for tessellated triangle:

#version 430 core layout(location = 0) in vec3 pos; layout(location = 1) in vec3 color; out vec4 vs_color; void main() { gl_Position = vec4(pos, 1.f); vs_color = vec4(color, 1.f); } 

Tessellation control shader:

#version 430 core layout (vertices = 3) out; in vec4 vs_color []; patch out vec4 patch_color; void main() { gl_TessLevelOuter[0] = 10.0; gl_TessLevelOuter[1] = 10.0; gl_TessLevelOuter[2] = 10.0; gl_TessLevelInner[0] = 5.0; gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; patch_color = vs_color [gl_InvocationID]; } 

Tesselation evaluation shader:

#version 430 core layout (triangles, equal_spacing, cw) in; patch in vec4 patch_color; out vec4 tes_color; void main(void) { gl_Position= ( gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position ); tes_color = patch_color; } 

Fragment shader for tessellated triangle:

#version 430 core out vec4 color; in vec4 tes_color; void main() { color = tes_color; } 

Tessellated triangle source:

GLfloat TessTriangleRainbow::points[] = { //x y z r g b -0.5f, -0.5f, 0.0f, 0.0f, 0.f, 1.f, // first xyz vertex + rgb color 0.5f, -0.5f, 0.0f, 1.0f, 0.f, 0.f, // second xyz vertex + rgb color 0.0f, 0.5f, 0.0f, 0.0f, 1.f, 0.f // third xyz vertex + rgb color }; //The base class Tess is tesselation shader aware //It is responsible for compiling linking the shaders TessTriangleRainbow::TessTriangleRainbow() : Tess ("shaders/tesselation/triangleRainbow.tcs", "shaders/tesselation/triangleRainbow.tes", "shaders/tesselation/triangleRainbow.vs", "shaders/tesselation/triangleRainbow.fs") { build(); } void TessTriangleRainbow::build() { glGenVertexArrays(1, &vao); glBindVertexArray(vao); unsigned int vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(points), &points, GL_STATIC_DRAW); //get XYZ values into location 0 on vertex shader glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)0); glEnableVertexAttribArray(0); //RGBA to location 1 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(float), (void*)(3 * sizeof(float))); glEnableVertexAttribArray(1); glBindVertexArray(0); } void TessTriangleRainbow::draw() { glUseProgram(*this); //the inherited overloaded (int) operator returns the program id glPatchParameteri(GL_PATCH_VERTICES, 3); glBindVertexArray(vao); glDrawArrays(GL_PATCHES, 0, 3); } 

Vertex shader for non tessellated triangle:

#version 430 core layout(location = 0) in vec3 pos; layout(location = 1) in vec3 color; out vec4 vs_color; void main() { gl_Position = vec4(pos, 1.f); vs_color = vec4(color, 1.f); } 

Fragment shader for non tessellated triangle:

#version 430 core out vec4 color; in vec4 vs_color; void main() { color = vs_color; } 

Non tessellated triangle source, is almost identical to the tessellated one:

GLfloat TriangleRainbow::points[] = identically the same as tessellated ones //base Shape class builds the program from shaders TriangleRainbow::TriangleRainbow() : Shape ( "shaders/tesselation/triangleRainbow.1.vs", "shaders/tesselation/triangleRainbow.1.fs") { build(); } void TriangleRainbow::build() { ... it is identically the same as the tessellated one } void TriangleRainbow::draw() { glUseProgram(*this); //the inherited overloaded (int) operator returns the program id glBindVertexArray(vao); glDrawArrays(GL_TRIANGLES, 0, 3); } 

Piece of main function:

 TessTriangleRainbow tessTriRainbow; TriangleRainbow triRainbow; ... other shapes if (!tessTriRainbow.program.success) /*report tessellated triangle shader compile errors*/ ... if (!triRainbow.program.success) /*report triangle shader compile errors*/ ... ... glDisable(GL_CULL_FACE); //glEnable(GL_DEPTH_TEST); int currentShape = 0; while (!glfwWindowShouldClose(window)) { processInputs(window); if (keyPressed) { /* change here currentShape to draw*/ ... } glClearColor(0.f, 0.f, 1.f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); switch (currentShape) { case 0: triRainbow.draw(); break; case 1: tessTriRainbow.draw(); break; ... 

1 Answer 1

2

You are using Per-patch output. So all the color attributes in the primitive become the same (from the last vertex in the patch):

patch out vec4 patch_color; void main() { // [...] patch_color = vs_color [gl_InvocationID]; } 

If you want a color per vertex, you have to use Per-vertex outputs. The output variable has to be an array.

Tessellation control shader:

out vec4 vertex_color[]; void main { // [...] vertex_color[gl_InvocationID] = vs_color[gl_InvocationID]; } 

Tesselation evaluation shader:

#version 430 core layout (triangles, equal_spacing, cw) in; in vec4 vertex_color[]; out vec4 tes_color; void main(void) { gl_Position = gl_TessCoord.x * gl_in[0].gl_Position + gl_TessCoord.y * gl_in[1].gl_Position + gl_TessCoord.z * gl_in[2].gl_Position; tes_color = gl_TessCoord.x * vertex_color[0] + gl_TessCoord.y * vertex_color[1] + gl_TessCoord.z * vertex_color[2]; } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.