Unable to link compiled shaders (GLSL)
I have a small class that allows me to load shaders and use them in my program. I am able to compile the shaders, but when it's time to link them, they just don't want to. Using glGetProgramInfoLog I got the following error log. I don't understand why it tells me that there are no program defined since the compilation worked fine...
Vertex info
-----------
(0) : error C3001: no program defined
Fragment info
-------------
(0) : error C3001: no program defined
The code below does the GLSL linking:
program_ = glCreateProgramObjectARB();
if (vertex_) {
glAttachObjectARB(program_, vertex_);
}
if (fragment_) {
glAttachObjectARB(program_, fragment_);
}
glLinkProgramARB(program_);
vertex_ and fragment_ are the vertex and fragment shader, and program_ is the ProgramObjectARB.
I'd like to know what are the necessary modifications I need to do in order to make this run.
Vertex shader:
varying vec4 OCPosition; // surface positon in world's coordinates
varying vec4 ECposition; // surface position in eye coordinates
varying vec4 ECballCenter; // ball center in eye coordinates
uniform vec4 BallCenter; // ball center in modelling coordinates
void main()
{
OCPosition = gl_Vertex;
ECposition = gl_ModelViewMatrix * OCPosition;
ECballCenter = gl_ModelViewMatrix * BallCenter;
gl_Position = gl_ProjectionMatrix * ECposition;
}
Fragment shader:
varying vec4 OCPosition; // surface position in world coordinates
varying vec4 ECposition; // surface position in eye coordinates
varying vec4 ECballCenter; // ball center in eye coor开发者_JAVA百科dinates
uniform vec4 LightDir; // light direction, should be normalized
uniform vec4 HVector; // reflection vector for infinite light source
uniform vec4 SpecularColor;
uniform vec4 BaseColor, StripeColor;
uniform float StripeWidth; // = 0.3
uniform float FWidth; // = 0.005
void main()
{
vec3 normal; // Analytically computed normal
vec4 p; // Point in shader space
vec4 surfColor; // Computed color of the surface
float intensity; // Computed light intensity
vec4 distance; // Computed distance values
float inorout; // Counter for computing star pattern
p.xyz = normalize(OCPosition.xyz); // Calculate p
p.w = 1.0;
distance.y = StripeWidth - abs(p.z);
distance.xy = smoothstep(-FWidth, FWidth, distance.xy);
surfColor = mix(BaseColor, StripeColor, distance.y);
// normal = point on surface for sphere at (0,0,0)
normal = normalize(ECposition.xyz - ECballCenter.xyz);
// Per fragment diffuse lighting
intensity = 0.2; // ambient
intensity += 0.8 * clamp(dot(LightDir.xyz, normal), 0.0, 1.0);
surfColor *= intensity;
// Per fragment specular lighting
intensity = clamp(dot(HVector.xyz, normal), 0.0, 1.0);
intensity = pow(intensity, SpecularColor.a);
surfColor += SpecularColor * intensity;
gl_FragColor = surfColor;
}
EDIT - SOLUTION It seems the method I used to read the source file was incorrect. The shader would compile, but at linking, it was not working correctly. Now I use this method to read my file and the linking is correct:
char *textFileRead(char *fn) {
FILE *fp;
char *content = NULL;
int count=0;
if (fn != NULL) {
fp = fopen(fn,"rt");
if (fp != NULL) {
fseek(fp, 0, SEEK_END);
count = ftell(fp);
rewind(fp);
if (count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
}
}
return content;
}
That specific error code from the GLSL compiler in the Nvidia driver means that it couldn't find a function called 'main' in your shader (either vertex or fragment in this case)
The most common reason for this is that you're not actually getting the program in to the driver when you think you are -- either the string you are passing in has not been initialized, or you're passing in a length of 0, and you're not actually compiling anything.
Edit
My best guess is there's something subtly wrong with the glCreateShader or glSetShaderSource calls. Much of the time, errors only show up when you try to link the shaders (rather than compile), as that's the first time the driver knows it has complete shaders and not just partial, incomplete shaders that need another shader linked in to be complete.
Your shaders work fine for me, I made a small test program to compile them and got no problems:
GLuint program = glCreateProgramObjectARB();
assert(program);
GLuint vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
assert(vertex_shader);
glShaderSourceARB(vertex_shader, 1, /*your vertex shader*/, 0);
glCompileShaderARB(vertex_shader);
GLint compile_status;
glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
assert(1 == compile_status);
GLuint fragment_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
assert(fragment_shader);
glShaderSourceARB(fragment_shader, 1, /*your fragment shader*/, 0);
glCompileShaderARB(fragment_shader);
glGetObjectParameterivARB(vertex_shader, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
assert(1 == compile_status);
glAttachObjectARB(program, vertex_shader);
assert(GL_NO_ERROR == glGetError());
glAttachObjectARB(program, fragment_shader);
assert(GL_NO_ERROR == glGetError());
glLinkProgramARB(program);
assert(GL_NO_ERROR == glGetError());
GLint link_status;
glGetObjectParameterivARB(program, GL_OBJECT_LINK_STATUS_ARB, &link_status);
assert(1 == link_status);
Do you do the same thing?
Try using glGetError after your glAttachObjectARB calls to see if these are failing.
精彩评论