Linking error at tessellation shaders in GLSL - c++

I'm testing the triangle tessellation from the link http://prideout.net/blog/?p=48#shaders. All the shader are compiled correctly, but when I try to link the program using the command:
glLinkProgram(programID);
I got the following error:
Tessellation control info
(0): error C6029: No input primitive type
----------------------------------------
Tessellation evaluation info
(0): error c7005: No tessellation primitive mode specified
-----------------------------------------------------------
Geometry info
(0): error C6022: No input primitive type
(0): error C6029: No ouput primitive type
----------------------------------------
Not valid
It's so strange I declare output for TC Shader using command:
layout(vertices = 3) out;
And input layout for TE shader using command:
layout(triangles, equal_spacing, cw) in;
Why I still got this error?
I hope to see you answer about it.
I put my shaders in below:
Vertex shader:
#version 410 core
in vec4 Position;
out vec3 vPosition;
void main()
{
vPosition = Position.xyz;
}
TC shader:
#version 410 core
layout(vertices = 3) out;
in vec3 vPosition[];
out vec3 tcPosition[];
#define ID gl_InvocationID
void main()
{
float TessLevelInner = 3;
float TessLevelOuter = 2;
tcPosition[ID] = vPosition[ID];
if (ID == 0) {
gl_TessLevelInner[0] = TessLevelInner;
gl_TessLevelOuter[0] = TessLevelOuter;
gl_TessLevelOuter[1] = TessLevelOuter;
gl_TessLevelOuter[2] = TessLevelOuter;
}
}
TE Shader:
#version 410 core
//TessEval
layout(triangles, equal_spacing, cw) in;
in vec3 tcPosition[];
out vec3 tePosition;
out vec3 tePatchDistance;
uniform mat4 Projection;
uniform mat4 Modelview;
void main()
{
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
tePatchDistance = gl_TessCoord;
tePosition = normalize(p0 + p1 + p2);
gl_Position = Projection * Modelview * vec4(tePosition, 1);
}
Geometry shader:
#version 410 core
//geometry shader
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec3 tePosition[3];
in vec3 tePatchDistance[3];
out vec3 gFacetNormal;
out vec3 gPatchDistance;
out vec3 gTriDistance;
uniform mat4 Modelview;
uniform mat3 NormalMatrix;
void main()
{
vec3 A = tePosition[2] - tePosition[0];
vec3 B = tePosition[1] - tePosition[0];
gFacetNormal = NormalMatrix * normalize(cross(A, B));
gPatchDistance = tePatchDistance[0];
gTriDistance = vec3(1, 0, 0);
gl_Position = gl_in[0].gl_Position; EmitVertex();
gPatchDistance = tePatchDistance[1];
gTriDistance = vec3(0, 1, 0);
gl_Position = gl_in[1].gl_Position; EmitVertex();
gPatchDistance = tePatchDistance[2];
gTriDistance = vec3(0, 0, 1);
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
Fragment Shader:
#version 410 core
//fragment shader
out vec4 FragColor;
in vec3 gFacetNormal;
in vec3 gTriDistance;
in vec3 gPatchDistance;
in float gPrimitive;
uniform vec3 LightPosition;
float amplify(float d, float scale, float offset)
{
d = scale * d + offset;
d = clamp(d, 0, 1);
d = 1 - exp2(-2*d*d);
return d;
}
void main()
{
vec3 AmbientMaterial = vec3(0.04f, 0.04f, 0.04f);
vec3 DiffuseMaterial = vec3(0, 0.75, 0.75);
vec3 LightPosition = vec3(0.25, 0.25, 1);
vec3 N = normalize(gFacetNormal);
vec3 L = LightPosition;
float df = abs(dot(N, L));
vec3 color = AmbientMaterial + df * DiffuseMaterial;
float d1 = min(min(gTriDistance.x, gTriDistance.y), gTriDistance.z);
float d2 = min(min(gPatchDistance.x, gPatchDistance.y), gPatchDistance.z);
color = amplify(d1, 40, -0.5) * amplify(d2, 60, -0.5) * color;
FragColor = vec4(color, 1.0);
}
FINALLY, this is the code I set up shader sources:
std::string filename = "shaders//terrain//terrain_TCShader.glsl"
FILE* fp = fopen(fileName.c_str(), "rt");
if (!fp)
return;
// Get all lines from a file
vector<string> sLines;
char sLine[255];
while (fgets(sLine, 255, fp))
sLines.push_back(sLine);
fclose(fp);
const char** sProgram = new const char*[sLines.size()];
for (int i = 0; i < sLines.size(); i++){
sProgram[i] = sLines[i].c_str();
}
//Also for GL_TESS_EVALUATION_SHADER, ..VERTEX, ...FRAGMENT
pShader[st] = glCreateShader(GL_TESS_CONTROL_SHADER);
glShaderSource(pShader[st], 1, (const GLchar**)sProgram, NULL);
glAttachShader(pProgram, pShader[st]);
glCompileShader(pShader[st]);
//==> I tried to check error here but it's ok, the compiler do not notify anything
After compile all the shader, I link the program
glLinkProgram(pProgram);
//And check error again:
glGetProgramiv(pProgram, GL_INFO_LOG_LENGTH,&infologLength);
if (infologLength > 0)
{
infoLog = (char *)malloc(infologLength);
glGetProgramInfoLog(pProgram, infologLength, &charsWritten, infoLog);
}
//I got the error here, as I described above.

I solved the problem. The error is in the code of loading shader.
glShaderSource(pShader[st], 1, (const GLchar**)sProgram, NULL);
I changed 1 to size of the char* array sProgram

Related

Problem with Shader "The shader uses varying --- but previous shader does not write to it"

Does anyone know why I keep getting the error that says:
The ♦ shader uses varying _I;DATA;g_mapCoord, but previous shader does not write to it.
The ♦ shader uses varying _I;DATA;worldPosition, but previous shader does not write to it.
Take a look at my shaders here.
Vertex
#version 430
layout (location = 0) in vec2 position0;
out DATA {
vec2 v_mapCoord;
vec3 worldPosition;
} Out;
uniform vec3 u_cameraPosition;
uniform mat4 u_localMatrix;
uniform mat4 u_worldMatrix;
uniform float u_scaleY;
uniform int u_lod;
uniform vec2 u_index;
uniform float u_gap;
uniform vec2 u_location;
uniform sampler2D s_heightmap;
uniform int u_lodMorphArea[8];
float morphLatitude(vec2 position)
{
//not important code
return 0;
}
float morphLongitude(vec2 position)
{
//not important code
return 0;
}
vec2 morph(vec2 localPosition, int morph_area){
//not important code
return vec2(0);
}
void main()
{
vec2 localPosition = (u_localMatrix * vec4(position0.x,0,position0.y,1)).xz;
if (u_lod > 0) {
localPosition += morph(localPosition, u_lodMorphArea[u_lod-1]); // Translate position by morphing vector
}
float height = texture(s_heightmap, localPosition).r;
Out.v_mapCoord = localPosition;
vec4 _worldPosition = u_worldMatrix * vec4(localPosition.x, height, localPosition.y,1);
Out.worldPosition = _worldPosition.xyz;
gl_Position = u_worldMatrix * vec4(localPosition.x, height, localPosition.y,1);
}
Fragment
#version 430
layout (location = 0) out vec4 outputColor;
in DATA {
vec2 g_mapCoord;
vec3 worldPosition;
} In;
const vec3 lightDirection = vec3(-0.2, -1.0, -0.2);
const float intensity = 1.2;
uniform sampler2D s_textureNormal;
uniform sampler2D s_textureWater;
uniform sampler2D s_textureLand;
float diffuse(vec3 direction, vec3 normal, float intensity)
{
return max(0.01, dot(normal, -direction) * intensity);
}
void main()
{
vec3 normal = texture(s_textureNormal, In.g_mapCoord).rgb;
float diff = diffuse(lightDirection, normal, intensity);
outputColor = vec4(1,0,0,1);
}
Geom
#version 430
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in vec2 te_mapCoord[];
out vec2 g_mapCoord;
uniform mat4 u_viewProjection;
void main() {
for (int i = 0; i < gl_in.length(); ++i)
{
vec4 position = gl_in[i].gl_Position;
gl_Position = u_viewProjection * position;
g_mapCoord = te_mapCoord[i];
EmitVertex();
}
EndPrimitive();
}
TCS
#version 430
layout(vertices = 16) out;
in DATA {
vec2 v_mapCoord;
vec3 worldPosition;
} In[];
out vec2 tc_mapCoord[];
const int AB = 2;
const int BC = 3;
const int CD = 0;
const int DA = 1;
uniform int u_tessellationFactor;
uniform float u_tessellationSlope;
uniform float u_tessellationShift;
uniform vec3 u_cameraPosition;
// Calculate tessellation levels
float lodFactor(float dist)
{
float tessellationLevel = max(0.0, u_tessellationFactor/pow(dist, u_tessellationSlope) + u_tessellationShift);
return tessellationLevel;
}
void main()
{
if (gl_InvocationID == 0){
// Calculate mid points of the edges of the quad
vec3 abMid = vec3(gl_in[0].gl_Position + gl_in[3].gl_Position)/2.0; //Bottom left, Bottom right
vec3 bcMid = vec3(gl_in[3].gl_Position + gl_in[15].gl_Position)/2.0; //Bottom right Top right
vec3 cdMid = vec3(gl_in[15].gl_Position + gl_in[12].gl_Position)/2.0; //Top right, Top left
vec3 daMid = vec3(gl_in[12].gl_Position + gl_in[0].gl_Position)/2.0; //Top left, Bottom left
// Calculate distance between camera and mid points of the edges of the quad
float distanceAB = distance(abMid, u_cameraPosition);
float distanceBC = distance(bcMid, u_cameraPosition);
float distanceCD = distance(cdMid, u_cameraPosition);
float distanceDA = distance(daMid, u_cameraPosition);
// Tesselation levels used by tessellation primitive generator (define how much tessellation to apply to the patch). Value between 1 and gl_MaxTessGenLevel, depending on lodFactor.
gl_TessLevelOuter[AB] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceAB));
gl_TessLevelOuter[BC] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceBC));
gl_TessLevelOuter[CD] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceCD));
gl_TessLevelOuter[DA] = mix(1, gl_MaxTessGenLevel, lodFactor(distanceDA));
gl_TessLevelInner[0] = (gl_TessLevelOuter[BC] + gl_TessLevelOuter[DA])/4;
gl_TessLevelInner[1] = (gl_TessLevelOuter[AB] + gl_TessLevelOuter[CD])/4;
}
tc_mapCoord[gl_InvocationID] = In[gl_InvocationID].v_mapCoord; // Just pass to the next stage
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
}
TES
#version 430
layout(quads, fractional_odd_spacing, cw) in;
in vec2 tc_mapCoord[];
out vec2 te_mapCoord;
uniform sampler2D s_heightmap;
uniform float u_scaleY;
void main(){
float u = gl_TessCoord.x;
float v = gl_TessCoord.y;
// Compute new position for each tessellated vertex within the patch. gl_in with index 12, 0, 3, 15 are corners of the patch.
vec4 position = ((1 - u) * (1 - v) * gl_in[12].gl_Position + u * (1 - v) * gl_in[0].gl_Position + u * v * gl_in[3].gl_Position +(1 - u) * v * gl_in[15].gl_Position);
vec2 mapCoord = ((1 - u) * (1 - v) * tc_mapCoord[12] + u * (1 - v) * tc_mapCoord[0] + u * v * tc_mapCoord[3] +(1 - u) * v * tc_mapCoord[15]);
float height = texture(s_heightmap, mapCoord).r;
height *= u_scaleY;
position.y = height;
te_mapCoord = mapCoord;
gl_Position = position;
}
Can anyone help me find the error here which is why I'm getting that error message?
When you introduce a geometry shader you need to pass the varyings for the fragment shader from the geometry shader, not the vertex shader.
You can see how your geometry shader doing this:
out vec2 g_mapCoord;
is incompatible with your fragment shader expecting this:
in DATA {
vec2 g_mapCoord;
vec3 worldPosition;
} In;
Related question and subsequent answers here.

Geometry shader odd issue

I want to use geometry shader to draw triangles of mesh, but encounter a really odd issue.
Result As follow: The wrong output.
The Right output.
The only diff between wrong and right in code, is when converting 3d position vector to 4d position vector. The right one did in vertex shader. The wrong one did in geometry shader.
Code as follow. Why this happend?
#version 330 core
layout (location = 0) in vec3 pos;
layout (location = 1) in vec3 normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 project;
out vec3 normal_;
out vec4 pos_;
out vec3 pos_bug_;
out mat4 mvp_;
void main()
{
mvp_ = project * view * model;
normal_ = normal;
pos_ = vec4(pos, 1.0);
pos_bug_ = pos;
}
#version 330 core
layout (triangles) in;
layout (line_strip, max_vertices = 12) out;
uniform float length = 0.4f;
out vec4 color;
in mat4 mvp_[];
in vec3 normal_[];
in vec4 pos_[];
in vec3 pos_bug_[];
void GenNormal(int index) {
color = vec4(1, 1, 0, 1);
gl_Position = mvp_[0] * pos_[index];
EmitVertex();
gl_Position = mvp_[0] * pos_[index] + vec4(normal_[index], 0.0) * length;
EmitVertex();
EndPrimitive();
}
void GenTriangle(int index0, int index1) {
color = vec4(1, 1, 1, 1);
gl_Position = mvp_[0] * pos_[index0]; // Right
// gl_Position = mvp_[0] * vec4(pos_bug_[index0], 1.0); // Wrong
EmitVertex();
gl_Position = mvp_[0] * pos_[index1]; // Right
// gl_Position = mvp_[0] * vec4(pos_bug_[index1], 1.0); // Wrong
EmitVertex();
EndPrimitive();
}
void main()
{
GenNormal(0);
GenNormal(1);
GenNormal(2);
GenTriangle(0, 1);
GenTriangle(1, 2);
GenTriangle(0, 2);
}

glsl fragment shader how to get non-interpolated data from each vertex

tl;dr:
What is the best method for accessing data from each individual vertex whilst in the fragment shader?
e.g.
The triangle in this fragment is made up from vertices v0,v1 and v2 and I want to give each vertex a specific integer which I can use to pick a texture and then fade between the 3 in the fragment shader; I don't want these ids to be interpolated and it is important that I can access each vertex's id.
Current Situation:
I am currently writing a shader for rendering terrain; I have a function in my fragment shader which will return the appropriate texture colour from uvs for a given ID (By means of a texture atlas). I can then fade between the 3 textures to give the give smoothly textured terrain
Current Code
Vertex Shader:
#version 330 core
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_uv_coords;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in float in_texture_id;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
out vec2 pass_uv_coords;
out vec3 pass_normal;
out vec3 texture_ratio;
out float pass_fake_brightness;
out float pass_id0;
out float pass_id1;
out float pass_id2;
void CalculateFakeLighting()
{
const vec3 light_direction = normalize(vec3(1,-1,1));
vec3 unit_normal = normalize(in_normal);
float normal_dot_light = dot(unit_normal, -light_direction);
pass_fake_brightness = max(0.2, normal_dot_light);
}
void main()
{
pass_uv_coords = in_uv_coords;
pass_normal = in_normal;
gl_Position = projection_matrix * view_matrix * vec4(in_position, 1.0);
int tile_track = int(mod(gl_VertexID, 3));
switch(tile_track)
{
case 0:
texture_ratio = vec3(1,0,0);
pass_id0 = in_texture_id;
break;
case 1:
texture_ratio = vec3(0,1,0);
pass_id1 = in_texture_id;
break;
case 2:
texture_ratio = vec3(0,0,1);
pass_id0 = in_texture_id;
break;
};
CalculateFakeLighting();
}
Fragment Shader:
#version 330 core
in vec2 pass_uv_coords;
in vec3 pass_normal;
in vec3 texture_ratio;
in float pass_fake_brightness;
in float pass_id0;
in float pass_id1;
in float pass_id2;
const int HORIZONTAL_IDS = 8;
const int VERTICAL_IDS = 8;
uniform sampler2D texture0_sampler;
out vec4 colour;
void UseFakeLighting()
{
colour *= pass_fake_brightness;
}
vec2 CorrectUVs(vec2 uvs)
{
vec2 corrected_uvs = uvs;
const float cushion = 0.001;
//Correct UV scale
while(corrected_uvs.x >= 1)
corrected_uvs.x--;
while(corrected_uvs.y >= 1)
corrected_uvs.y--;
if(corrected_uvs.x < cushion)
corrected_uvs.x = cushion;
if(corrected_uvs.x > 1 - cushion)
corrected_uvs.x = 1 - cushion;
if(corrected_uvs.y < cushion)
corrected_uvs.y = cushion;
if(corrected_uvs.y > 1 - cushion)
corrected_uvs.y = 1 - cushion;
return corrected_uvs;
}
vec4 GetTexture(float id, vec2 uv_coords)
{
vec2 step = vec2(
1.0/HORIZONTAL_IDS,
1.0/VERTICAL_IDS
);
uv_coords.x/=HORIZONTAL_IDS;
uv_coords.y/=VERTICAL_IDS;
uv_coords.x += step.x * mod(id, HORIZONTAL_IDS);
uv_coords.y += step.y * floor(id/VERTICAL_IDS);
//Texture is upsidedown
uv_coords.y = 1.0 - uv_coords.y;
return texture(texture0_sampler, uv_coords);
}
void main()
{
vec2 corrected_uvs = CorrectUVs(pass_uv_coords);
vec3 correct_ratio = normalize(texture_ratio);
colour = GetTexture(pass_id0, corrected_uvs) * correct_ratio.x +
GetTexture(pass_id1, corrected_uvs) * correct_ratio.y +
GetTexture(pass_id2, corrected_uvs) * correct_ratio.z;
if(colour.a == 0)
discard;
UseFakeLighting();
}
By default the output variables from the vertex shader to the fragment shader use perspective-correct interpolation. If you want no interpolation done then qualify your variables with flat:
flat out vec3 pass_id0;
For more info see GLSL Type Qualifiers. Also see this question “flat” qualifier in glsl?
As recommended by #aslg and #AndonM.Coleman, geometry is a good solution to this issue. A flat vec3 is passed out of the geometry stage, which stores the id of each vertex which is then accessible in the fragment shader.
The key lines are in the geometry shader; one part of the output is
flat vec3 texture_ids;
Which is then set as such:
vertex_out.texture_ids.x = vertex_in[0].texture_id;
vertex_out.texture_ids.y = vertex_in[1].texture_id;
vertex_out.texture_ids.z = vertex_in[2].texture_id;
Full Shader Sources:
Vertex
#version 330 core
layout(location = 0) in vec3 in_position;
layout(location = 1) in vec2 in_uv_coords;
layout(location = 2) in vec3 in_normal;
layout(location = 3) in float in_texture_id;
out VertexData
{
vec2 uv_coord;
vec3 normal;
uint texture_id;
} vertex_out;
void main()
{
vertex_out.uv_coord = in_uv_coords;
vertex_out.normal = in_normal;
vertex_out.texture_id = uint(round(in_texture_id));
gl_Position = vec4(in_position, 1.0);
}
Geometry
#version 330 core
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
uniform mat4 view_matrix;
uniform mat4 projection_matrix;
mat4 vp_matrix = projection_matrix * view_matrix;
in VertexData
{
vec2 uv_coord;
vec3 normal;
uint texture_id;
} vertex_in[];
out VertexDataPass
{
vec2 uv_coord;
vec3 normal;
vec3 texture_ratio;
float brightness;
flat vec3 texture_ids;
} vertex_out;
void CalculateFakeBrightness(int index)
{
const vec3 light_direction = normalize(vec3(1,-1,1));
vec3 unit_normal = normalize(vertex_in[index].normal);
float normal_dot_light = dot(unit_normal, -light_direction);
vertex_out.brightness = max(0.2, normal_dot_light);
}
void main()
{
for(int i = 0; i < gl_in.length(); i++)
{
gl_Position = vp_matrix * gl_in[i].gl_Position;
vertex_out.uv_coord = vertex_in[i].uv_coord;
vertex_out.normal = vertex_in[i].normal;
vertex_out.texture_ids.x = vertex_in[0].texture_id;
vertex_out.texture_ids.y = vertex_in[1].texture_id;
vertex_out.texture_ids.z = vertex_in[2].texture_id;
CalculateFakeBrightness(i);
switch(int(mod(i,3)))
{
case 0:
vertex_out.texture_ratio = vec3(1,0,0);
break;
case 1:
vertex_out.texture_ratio = vec3(0,1,0);
break;
case 2:
vertex_out.texture_ratio = vec3(0,0,1);
break;
};
EmitVertex();
}
EndPrimitive();
}
Fragment
#version 330 core
in VertexDataPass
{
vec2 uv_coord;
vec3 normal;
vec3 texture_ratio;
float brightness;
flat vec3 texture_ids;
} vertex_data;
const int HORIZONTAL_IDS = 8;
const int VERTICAL_IDS = 8;
uniform sampler2D texture0_sampler;
out vec4 colour;
vec2 CorrectUVs(vec2 uvs)
{
vec2 corrected_uvs = uvs;
const float cushion = 0.001;
//Correct UV scale
while(corrected_uvs.x >= 1)
corrected_uvs.x--;
while(corrected_uvs.y >= 1)
corrected_uvs.y--;
if(corrected_uvs.x < cushion)
corrected_uvs.x = cushion;
if(corrected_uvs.x > 1 - cushion)
corrected_uvs.x = 1 - cushion;
if(corrected_uvs.y < cushion)
corrected_uvs.y = cushion;
if(corrected_uvs.y > 1 - cushion)
corrected_uvs.y = 1 - cushion;
return corrected_uvs;
}
vec4 GetTexture(uint id, vec2 uv_coords)
{
vec2 step = vec2(
1.0/HORIZONTAL_IDS,
1.0/VERTICAL_IDS
);
uv_coords.x/=HORIZONTAL_IDS;
uv_coords.y/=VERTICAL_IDS;
uv_coords.x += step.x * mod(id, HORIZONTAL_IDS);
uv_coords.y += step.y * floor(float(id)/VERTICAL_IDS);
//Texture is upsidedown
uv_coords.y = 1.0 - uv_coords.y;
return texture(texture0_sampler, uv_coords);
}
void main()
{
vec2 uvs = CorrectUVs(vertex_data.uv_coord);
colour =
GetTexture(uint(vertex_data.texture_ids.x), uvs) * vertex_data.texture_ratio.x +
GetTexture(uint(vertex_data.texture_ids.y), uvs) * vertex_data.texture_ratio.y +
GetTexture(uint(vertex_data.texture_ids.z), uvs) * vertex_data.texture_ratio.z;
if(colour.a == 0)
discard;
colour.xyz *= vertex_data.brightness;
}

Flicker artifacts in texture with tessellation

I encountered a problem when using tessellation.
Please refer to the link below
You may see some grey area after the rendering. If I rotate camera, they also changed (like a shinning effect.)
Could any one help me to figure out what is the reason? Thanks in advance.
Here is my code:
Vertex Shader:
in vec3 vertex_position;
in vec2 vertex_texcoord;
void main()
{
v_pos = vec3(vertex_position);
v_texcoord = vertex_texcoord;
}
TC shader:
layout(vertices = 3) out;
in vec3 v_pos[];
in vec2 v_texcoord[];
out vec3 tc_pos[];
out vec2 tc_texcoord[];
#define ID gl_InvocationID
#define TESS_LEVEL_INNER 3.0
#define TESS_LEVEL_OUTER 2.0
void main()
{
tc_pos[ID] = v_pos[ID];
tc_texcoord[ID] = v_texcoord[ID];
if (ID == 0)
{
gl_TessLevelInner[0] = TESS_LEVEL_INNER;
gl_TessLevelOuter[0] = TESS_LEVEL_OUTER;
gl_TessLevelOuter[1] = TESS_LEVEL_OUTER;
gl_TessLevelOuter[2] = TESS_LEVEL_OUTER;
}
}
Te shader:
layout(triangles, equal_spacing, cw) in;
in vec3 tc_pos[];
in vec2 tc_texcoord[];
out vec3 te_pos;
out vec2 te_texcoord;
void main()
{
vec3 p0 = gl_TessCoord.x * tc_pos[0];
vec3 p1 = gl_TessCoord.y * tc_pos[1];
vec3 p2 = gl_TessCoord.z * tc_pos[2];
vec2 t0 = gl_TessCoord.x * tc_texcoord[0];
vec2 t1 = gl_TessCoord.y * tc_texcoord[1];
vec2 t2 = gl_TessCoord.z * tc_texcoord[2];
te_pos = p0 + p1 + p2;
te_texcoord = t0 + t1 + t2;
vec4 p_t = vec4(te_pos-cam_pos.xyz,1.0) * cam_ori;
gl_Position = perspective_mat * p_t;
}
geometry shader:
layout (triangles) in;
layout (triangle_strip, max_vertices=3) out;
in vec3 te_pos[3];
in vec2 te_texcoord[3];
out vec2 g_texcoord;
void main()
{
gl_Position = gl_in[0].gl_Position;
g_texcoord = te_texcoord[0];
EmitVertex();
gl_Position = gl_in[1].gl_Position;
g_texcoord = te_texcoord[1];
EmitVertex();
gl_Position = gl_in[2].gl_Position;
g_texcoord = te_texcoord[2];
EmitVertex();
EndPrimitive();
}
Fragment:
in vec2 g_texcoord;
out vec4 frag_color;
void main()
{
frag_color = texture(tex_unit, g_texcoord);
}
Rendering Result

GLSL Tessellation Displacement Mapping

in my recent project I am working with hardware side tessellation. The pipeline I want to implement should take a low poly mesh, tessellate it and apply a displacement map.
The Tessellation works fine and just as I expected it to look like. However, when I apply the displacement map in the tessellation evaluation shader I get an output which is somewhat random.
This is the output without displacement (I used the heightmap as a texture to verify whether my texCoords are accurate)
This is what I get when I enable my displacement (using the same texture for both coloring and displacement):
The shader code is as follows:
//VERTEX SHADER
#version 430
layout(location = 0) in vec4 vertex;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec2 texCoord;
out vec3 vPosition;
out vec3 vNormal;
out vec2 vTexCoord;
void main() {
vPosition = vertex.xyz;
vNormal = normal.xyz;
vTexCoord = texCoord;
}
//TESS CONTROL
#version 430
layout(vertices = 3) out;
in vec3 vPosition[];
in vec3 vNormal[];
in vec2 vTexCoord[];
out vec3 tcPosition[];
out vec3 tcNormal[];
out vec2 tcTexCoord[];
uniform float innerTessLevel;
uniform float outerTessLevel;
void main(){
float inTess = innerTessLevel;
float outTess = outerTessLevel;
tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];
tcNormal[gl_InvocationID] = vNormal[gl_InvocationID];
tcTexCoord[gl_InvocationID] = vTexCoord[gl_InvocationID];
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = inTess;
gl_TessLevelInner[1] = inTess;
gl_TessLevelOuter[0] = outTess;
gl_TessLevelOuter[1] = outTess;
gl_TessLevelOuter[2] = outTess;
gl_TessLevelOuter[3] = outTess;
}
}
//TESS EVAL
#version 430
layout(triangles, equal_spacing, ccw) in;
in vec3 tcPosition[];
in vec3 tcNormal[];
in vec2 tcTexCoord[];
out vec3 tePosition;
out vec2 teTexCoord;
uniform mat4 ModelViewProjection;
uniform mat4 ModelView;
uniform sampler2D texHeight;
void main(){
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
vec3 pos = p0 + p1 + p2;
vec3 n0 = gl_TessCoord.x * tcNormal[0];
vec3 n1 = gl_TessCoord.y * tcNormal[1];
vec3 n2 = gl_TessCoord.z * tcNormal[2];
vec3 normal = normalize(n0 + n1 + n2);
vec2 tc0 = gl_TessCoord.x * tcTexCoord[0];
vec2 tc1 = gl_TessCoord.y * tcTexCoord[1];
vec2 tc2 = gl_TessCoord.z * tcTexCoord[2];
teTexCoord = tc0 + tc1 + tc2;
float height = texture(texHeight, teTexCoord).x;
pos += normal * (height * 0.2f);
gl_Position = ModelViewProjection * vec4(pos, 1);
tePosition = vec3(ModelView * vec4(pos,1.0)).xyz;
}
//GEOMETRY
#version 430
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
uniform mat4 ModelView;
in vec3 tePosition[3];
in vec3 tePatchDistance[3];
in vec2 teTexCoord[3];
out vec3 gFacetNormal;
out vec2 gTexCoord;
void main() {
vec3 A = tePosition[2] - tePosition[0];
vec3 B = tePosition[1] - tePosition[0];
vec4 N = vec4( normalize(cross(A, B)) , 0.0);
gFacetNormal = N.xyz;
gTexCoord = teTexCoord[0];
gl_Position = gl_in[0].gl_Position; EmitVertex();
gTexCoord = teTexCoord[1];
gl_Position = gl_in[1].gl_Position; EmitVertex();
gTexCoord = teTexCoord[2];
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
//FRAGMENT
#version 430
layout(location = 0) out vec4 fragColor;
in vec3 gFacetNormal;
in vec2 gTexCoord;
uniform float lit;
uniform vec3 light;
uniform sampler2D texHeight;
void main() {
#ifndef ORANGE_PURPLE
vec3 color = gl_FrontFacing ? vec3(1.0,0.0,0.0) : vec3(0.0,0.0,1.0);
#else
vec3 color = gl_FrontFacing ? vec3(1.0,0.6,0.0) : vec3(0.6,0.0,1.0);
#endif
if (lit > 0.5) {
color = texture(texHeight, gTexCoord).xyz;
vec3 N = normalize(gFacetNormal);
vec3 L = light;
float df = abs(dot(N,L));
color = df * color;
fragColor = vec4(color,1.0);
}
else {
fragColor = vec4(color,1.0);
}
}
It would be nice if someone could help me on that one.
Thanks to #AndonM.Coleman I solved the matter
In fact: the output gFacetNormal is only defined for your first vertex in the geometry shader. Outputs have to be set after every EmitVertex (...) as-per the GLSL specification, or they will be undefined. Many implementations re-use the last value set, but you cannot rely on that behavior if you want this to work portably. You need to set gFacetNormal once before every EmitVertex. void EmitVertex () - "Emits the current values of output variables to the current output primitive. On return from this call, the values of output variables are undefined."
Stupid of me not to notice that, but here is the working code:
//VERTEX
#version 430
layout(location = 0) in vec4 vertex;
layout(location = 1) in vec4 normal;
layout(location = 2) in vec2 texCoord;
out vec3 vPosition;
out vec3 vNormal;
out vec2 vTexCoord;
void main() {
vPosition = vertex.xyz;
vNormal = normal.xyz;
vTexCoord = texCoord;
}
//TESSELLATION CONTROL
#version 430
layout(vertices = 3) out;
in vec3 vPosition[];
in vec3 vNormal[];
in vec2 vTexCoord[];
out vec3 tcPosition[];
out vec3 tcNormal[];
out vec2 tcTexCoord[];
uniform float innerTessLevel;
uniform float outerTessLevel;
void main(){
float inTess = innerTessLevel;
float outTess = outerTessLevel;
tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];
tcNormal[gl_InvocationID] = vNormal[gl_InvocationID];
tcTexCoord[gl_InvocationID] = vTexCoord[gl_InvocationID];
if(gl_InvocationID == 0) {
gl_TessLevelInner[0] = inTess;
gl_TessLevelInner[1] = inTess;
gl_TessLevelOuter[0] = outTess;
gl_TessLevelOuter[1] = outTess;
gl_TessLevelOuter[2] = outTess;
gl_TessLevelOuter[3] = outTess;
}
}
//TESSELLATION EVALUATION
#version 430
layout(triangles, equal_spacing, ccw) in;
in vec3 tcPosition[];
in vec3 tcNormal[];
in vec2 tcTexCoord[];
out vec3 tePosition;
out vec2 teTexCoord;
out vec3 teNormal;
uniform mat4 ModelViewProjection;
uniform mat4 ModelView;
uniform sampler2D texHeight;
void main(){
vec3 p0 = gl_TessCoord.x * tcPosition[0];
vec3 p1 = gl_TessCoord.y * tcPosition[1];
vec3 p2 = gl_TessCoord.z * tcPosition[2];
vec3 pos = p0 + p1 + p2;
vec3 n0 = gl_TessCoord.x * tcNormal[0];
vec3 n1 = gl_TessCoord.y * tcNormal[1];
vec3 n2 = gl_TessCoord.z * tcNormal[2];
vec3 normal = normalize(n0 + n1 + n2);
vec2 tc0 = gl_TessCoord.x * tcTexCoord[0];
vec2 tc1 = gl_TessCoord.y * tcTexCoord[1];
vec2 tc2 = gl_TessCoord.z * tcTexCoord[2];
teTexCoord = tc0 + tc1 + tc2;
float height = texture(texHeight, teTexCoord).x;
pos += normal * (height * 0.5f);
gl_Position = ModelViewProjection * vec4(pos, 1);
teNormal = vec3(ModelView * vec4(normal,0.0)).xyz;
tePosition = vec3(ModelView * vec4(pos,1.0)).xyz;
}
//GEOMETRY
#version 430
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
uniform mat4 ModelView;
in vec3 tePosition[3];
in vec2 teTexCoord[3];
in vec3 teNormal[3];
out vec3 gFacetNormal;
out vec2 gTexCoord;
void main() {
gFacetNormal = teNormal[0];
gTexCoord = teTexCoord[0];
gl_Position = gl_in[0].gl_Position; EmitVertex();
gFacetNormal = teNormal[1];
gTexCoord = teTexCoord[1];
gl_Position = gl_in[1].gl_Position; EmitVertex();
gFacetNormal = teNormal[2];
gTexCoord = teTexCoord[2];
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}
//FRAGMENT
#version 430
layout(location = 0) out vec4 fragColor;
in vec3 gFacetNormal;
in vec2 gTexCoord;
uniform float lit;
uniform vec3 light;
uniform sampler2D texHeight;
void main() {
#ifndef ORANGE_PURPLE
vec3 color = gl_FrontFacing ? vec3(1.0,0.0,0.0) : vec3(0.0,0.0,1.0);
#else
vec3 color = gl_FrontFacing ? vec3(1.0,0.6,0.0) : vec3(0.6,0.0,1.0);
#endif
if (lit > 0.5) {
color = texture(texHeight, gTexCoord).xyz;
vec3 N = normalize(gFacetNormal);
vec3 L = light;
float df = abs(dot(N,L));
color = df * color;
fragColor = vec4(color,1.0);
}
else {
fragColor = vec4(color,1.0);
}
}