Reputation: 1090
I am attempting to use four shaders: A vertex Shader (VS), a Tessellation Control Shader (TCS), a Tessellation Evaluation Shader (TES), and a Fragment Shader (FS).
However, when I attempt to load these shaders, I get:
This has been most baffling, and I have already spent a couple of hours trying to sort it out. However, I cannot see "gl_Vertex" anywhere in my code, so I am stuck really. I don't even know which shader is the problem.
Here is my current code for loading shaders (It looks like a lot, but it's really all just repeated code with slight changes):
public static int loadShaderPair(String vertexShaderLocation, String fragmentShaderLocation, String tesShaderLocation, String tesscontrolShaderLocation) {
int shaderProgram = glCreateProgram();
int vertexShader = glCreateShader(GL_VERTEX_SHADER);
int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
int tesscontrolShader = glCreateShader(GL40.GL_TESS_CONTROL_SHADER);
int tesShader = glCreateShader(GL40.GL_TESS_EVALUATION_SHADER);
StringBuilder vertexShaderSource = new StringBuilder();
StringBuilder fragmentShaderSource = new StringBuilder();
StringBuilder tesShaderSource = new StringBuilder();
StringBuilder tesscontrolShaderSource = new StringBuilder();
BufferedReader tesShaderFileReader = null;
try {
tesShaderFileReader = new BufferedReader(new FileReader(tesShaderLocation));
String line;
while ((line = tesShaderFileReader.readLine()) != null) {
tesShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (tesShaderFileReader != null) {
try {
tesShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader tesscontrolShaderFileReader = null;
try {
tesscontrolShaderFileReader = new BufferedReader(new FileReader(tesscontrolShaderLocation));
String line;
while ((line = tesscontrolShaderFileReader.readLine()) != null) {
tesscontrolShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (tesscontrolShaderFileReader != null) {
try {
tesscontrolShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader vertexShaderFileReader = null;
try {
vertexShaderFileReader = new BufferedReader(new FileReader(vertexShaderLocation));
String line;
while ((line = vertexShaderFileReader.readLine()) != null) {
vertexShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (vertexShaderFileReader != null) {
try {
vertexShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
BufferedReader fragmentShaderFileReader = null;
try {
fragmentShaderFileReader = new BufferedReader(new FileReader(fragmentShaderLocation));
String line;
while ((line = fragmentShaderFileReader.readLine()) != null) {
fragmentShaderSource.append(line).append('\n');
}
} catch (IOException e) {
e.printStackTrace();
return -1;
} finally {
if (fragmentShaderFileReader != null) {
try {
fragmentShaderFileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
glShaderSource(vertexShader, vertexShaderSource);
glCompileShader(vertexShader);
if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Vertex shader wasn't able to be compiled correctly. Error log:");
System.err.println(glGetShaderInfoLog(vertexShader, 1024));
return -1;
}
glShaderSource(tesscontrolShader, tesscontrolShaderSource);
glCompileShader(tesscontrolShader);
if (glGetShaderi(tesscontrolShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("tesscontrol shader wasn't able to be compiled correctly. Error log:");
System.err.println(GL11.glGetString(GL11.glGetError()));
System.err.println(glGetShaderInfoLog(tesscontrolShader, 1024));
}
glShaderSource(fragmentShader, fragmentShaderSource);
glCompileShader(fragmentShader);
if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Fragment shader wasn't able to be compiled correctly. Error log:");
System.err.println(GL11.glGetString(GL11.glGetError()));
System.err.println(glGetShaderInfoLog(fragmentShader, 1024));
}
glShaderSource(tesShader, tesShaderSource);
glCompileShader(tesShader);
if (glGetShaderi(vertexShader, GL_COMPILE_STATUS) == GL_FALSE) {
System.err.println("Tessellation shader wasn't able to be compiled correctly. Error log:");
System.err.println(glGetShaderInfoLog(tesShader, 1024));
return -1;
}
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, tesShader);
glAttachShader(shaderProgram, tesscontrolShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
if (glGetProgrami(shaderProgram, GL_LINK_STATUS) == GL_FALSE) {
System.err.println("Shader program wasn't linked correctly.");
System.err.println(GL11.glGetString(GL11.glGetError()));
System.err.println(glGetProgramInfoLog(shaderProgram, 1024));
System.exit(1);
return -1;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
glDeleteShader(tesShader);
glDeleteShader(tesscontrolShader);
return shaderProgram;
}
And here are my shaders: VS:
layout (location = 0) in vec3 Position_VS_in;
layout (location = 1) in vec2 TexCoord_VS_in;
layout (location = 2) in vec3 Normal_VS_in;
uniform mat4 gWorld;
out vec3 WorldPos_CS_in;
out vec2 TexCoord_CS_in;
out vec3 Normal_CS_in;
void main()
{
WorldPos_CS_in = (gWorld * vec4(Position_VS_in, 1.0)).xyz;
TexCoord_CS_in = TexCoord_VS_in;
Normal_CS_in = (gWorld * vec4(Normal_VS_in, 0.0)).xyz;
gl_Position = ftransform();
}
TCS:
// define the number of CPs in the output patch
layout (vertices = 3) out;
uniform vec3 gEyeWorldPos;
// attributes of the input CPs
in vec3 WorldPos_CS_in[];
in vec2 TexCoord_CS_in[];
in vec3 Normal_CS_in[];
// attributes of the output CPs
out vec3 WorldPos_ES_in[];
out vec2 TexCoord_ES_in[];
out vec3 Normal_ES_in[];
float GetTessLevel(float Distance0, float Distance1)
{
float AvgDistance = (Distance0 + Distance1) / 2.0;
if (AvgDistance <= 2.0) {
return 10.0;
}
else if (AvgDistance <= 5.0) {
return 7.0;
}
else {
return 3.0;
}
}
void main()
{
// Set the control points of the output patch
TexCoord_ES_in[gl_InvocationID] = TexCoord_CS_in[gl_InvocationID];
Normal_ES_in[gl_InvocationID] = Normal_CS_in[gl_InvocationID];
WorldPos_ES_in[gl_InvocationID] = WorldPos_CS_in[gl_InvocationID];
// Calculate the distance from the camera to the three control points
float EyeToVertexDistance0 = distance(gEyeWorldPos, WorldPos_ES_in[0]);
float EyeToVertexDistance1 = distance(gEyeWorldPos, WorldPos_ES_in[1]);
float EyeToVertexDistance2 = distance(gEyeWorldPos, WorldPos_ES_in[2]);
// Calculate the tessellation levels
gl_TessLevelOuter[0] = GetTessLevel(EyeToVertexDistance1, EyeToVertexDistance2);
gl_TessLevelOuter[1] = GetTessLevel(EyeToVertexDistance2, EyeToVertexDistance0);
gl_TessLevelOuter[2] = GetTessLevel(EyeToVertexDistance0, EyeToVertexDistance1);
gl_TessLevelInner[0] = gl_TessLevelOuter[2];
}
TES:
layout(triangles, equal_spacing, ccw) in;
uniform mat4 gVP;
uniform sampler2D gDisplacementMap;
uniform float gDispFactor;
in vec3 WorldPos_ES_in[];
in vec2 TexCoord_ES_in[];
in vec3 Normal_ES_in[];
out vec3 WorldPos_FS_in;
out vec2 TexCoord_FS_in;
out vec3 Normal_FS_in;
vec2 interpolate2D(vec2 v0, vec2 v1, vec2 v2)
{
return vec2(gl_TessCoord.x) * v0 + vec2(gl_TessCoord.y) * v1 + vec2(gl_TessCoord.z) * v2;
}
vec3 interpolate3D(vec3 v0, vec3 v1, vec3 v2)
{
return vec3(gl_TessCoord.x) * v0 + vec3(gl_TessCoord.y) * v1 + vec3(gl_TessCoord.z) * v2;
}
void main()
{
// Interpolate the attributes of the output vertex using the barycentric coordinates
TexCoord_FS_in = interpolate2D(TexCoord_ES_in[0], TexCoord_ES_in[1], TexCoord_ES_in[2]);
Normal_FS_in = interpolate3D(Normal_ES_in[0], Normal_ES_in[1], Normal_ES_in[2]);
Normal_FS_in = normalize(Normal_FS_in);
WorldPos_FS_in = interpolate3D(WorldPos_ES_in[0], WorldPos_ES_in[1], WorldPos_ES_in[2]);
// Displace the vertex along the normal
float Displacement = texture(gDisplacementMap, TexCoord_FS_in.xy).x;
WorldPos_FS_in += Normal_FS_in * Displacement * gDispFactor;
gl_Position = gVP * vec4(WorldPos_FS_in, 1.0);
}
FS:
varying vec4 position_in_view_space;
uniform sampler2D color_texture;
void main()
{
float dist = distance(position_in_view_space,
vec4(0.0, 0.0, 0.0, 1.0));
if (dist < 1000.0)
{
gl_FragColor = gl_Color;
// color near origin
}
else
{
gl_FragColor = gl_Color;
//kill;
//discard;
//gl_FragColor = vec4(0.3, 0.3, 0.3, 1.0);
// color far from origin
}
}
If for any reason it helps, my PC supports up to (and including) OpenGL 4.0.
Since I have been unable to work out how I am supposedly using a line of code I am not using, I am hoping one of you will be able to diagnose the issue.
Upvotes: 0
Views: 314
Reputation: 45322
Well, the error message is very clear, and the reason is this:
layout (location = 0) in vec3 Position_VS_in;
[...]
gl_Position = ftransform();
ftransform
is a legacy function which uses the legacy bultin vertex position attribute gl_Vertex
to transform a vertex according to the also legacy bultin matrix uniforms.
The GL spec also requires the generic vertex attribute 0 to alias the old builtin gl_Vertex
, so your attribute index 0 is blocked by this and you must not assign some other attribute to this.
Now it is totally unclear why you use ftransform
here. It seems like you don't want that at all. But I can't be sure about that. But it will definitively not work that way. You shouldn't use that deprecated stuff at all, in my opinion.
UPDATE 1
Note that ftransform
is in princicple equivalent to gl_ModelViewProjectionMatrix * gl_Vertex
, with gl_ModelViewProjectionMatrix
being a builtin uniform representing the product P * MV
of the matrices you set for GL_PROJECTION
and GL_MODELVIEW
using the also-deprecated GL matrix stack, and gl_Vertex
being the builtin vertex position attribute set with glVertex...
/glVertexPointer
/glVertexAttribPointer(0,...)
. Both can be replaced by user-defined attributes/uniforms.
The only twist with ftransform
is that it is also guaranteed to get the exact same result as rendering with the fixed function pipeline does, for the same inputs. That was useful for multi-pass algorithms where some passed needed to render with shaders, while others used the fixed function pipelinew. Such a function was needed because there might be slight numerical differences if the shader does not use the exact same formula as the GL implementation when rendering without shaders.
Upvotes: 2