Reputation: 3924
my tessellation shader generates a bezier curve for two vertices. the vertices consists of two coordinates x and y (vec2). now every vertex has a color. my question: how to interpolate the color per vertex on the generated curve? right now the fragment shader sets a default color value (red). but i want him to get the interpolated color.
for example:
vertex 1 [vec2(0.0, 0.0), vec4(1.0, 0.0, 0.0, 1.0)] // red
vertex 2 [vec2(1.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0)] // blue
so there should be a gradient from red to blue. how can i do this with the tessellation shader?
vertex shader:
#version 400
layout (location = 0 ) in vec2 in_position;
layout (location = 1 ) in vec4 in_color;
void main()
{
gl_Position = vec4(in_position, 0.0, 1.0);
}
tessellation control shader:
#version 400
layout( vertices = 2 ) out;
uniform int NumSegments;
uniform int NumStrips;
void main()
{
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
gl_TessLevelOuter[0] = float(NumSegments);
gl_TessLevelOuter[1] = float(NumStrips);
}
tessellation evaluation shader:
#version 400
layout( isolines ) in;
uniform mat4 Projection;
uniform mat4 Modelview;
void main()
{
float u = gl_TessCoord.x;
vec3 p0 = gl_in[0].gl_Position.xyz;
vec3 p1 = vec3(0.5, gl_in[0].gl_Position.y, 0.0);
vec3 p2 = vec3(0.5, gl_in[1].gl_Position.y, 0.0);
vec3 p3 = gl_in[1].gl_Position.xyz;
float u1 = (1.0 - u);
float u2 = u * u;
// Bernstein polynomials
float b3 = u2 * u;
float b2 = 3.0 * u2 * u1;
float b1 = 3.0 * u * u1 * u1;
float b0 = u1 * u1 * u1;
// Cubic Bezier interpolation
vec3 p = p0 * b0 + p1 * b1 + p2 * b2 + p3 * b3;
gl_Position = Projection * Modelview * vec4(p, 1.0);
}
fragment shader:
#version 400
layout ( location = 0 ) out vec4 FragColor;
void main()
{
FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
Upvotes: 0
Views: 2364
Reputation: 473946
This is all pretty straightforward. Just follow the pattern of your already existing inputs and outputs.
Your vertex shader outputs a gl_Position
value. Therefore, it should also output a color value:
layout (location = 0 ) in vec2 in_position;
layout (location = 1 ) in vec4 in_color;
out vec4 color;
void main()
{
gl_Position = vec4(in_position, 0.0, 1.0);
color = in_color;
}
Your tessellation control shader takes an array of gl_Position
s. So you take an array of colors. It also needs to write to an array of colors:
layout( vertices = 2 ) out;
uniform int NumSegments;
uniform int NumStrips;
in vec4 color[];
out Tess
{
vec4 color;
} Out[];
void main()
{
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
Out[gl_InvocationID].color = color[gl_InvocationID];
gl_TessLevelOuter[0] = float(NumSegments);
gl_TessLevelOuter[1] = float(NumStrips);
}
In your evaluation shader, you again need to take an array of input and output layout qualifiers. We used an output interface block called Tess
, so we need to match it with an input interface block of the same name:
layout( isolines ) in;
uniform mat4 Projection;
uniform mat4 Modelview;
in Tess
{
vec4 color;
} In[];
out vec4 color;
void main()
{
float u = gl_TessCoord.x;
/** Do whatever interpolation stuff you do **/
// Cubic Bezier interpolation
vec3 p = p0 * b0 + p1 * b1 + p2 * b2 + p3 * b3;
gl_Position = Projection * Modelview * vec4(p, 1.0);
color = Interpolate(In[0].color, In[1].color, ...); //More interpolation stuff.
}
And that's that. Your fragment shader takes as an input a vec4 color
.
Also, a small note: this is not a Bezier spline. Bezier splines require patches of 4 positions, not 2. The way you synthesized the other two values doesn't make them correct.
Upvotes: 1