tags:

views:

419

answers:

3

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 coordinates

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;
}
+2  A: 

Try using glGetError after your glAttachObjectARB calls to see if these are failing.

tkerwin
glGetError after both calls returns 0.
tomzx
You can also try:bool fragCompiled, vertCompiled;glGetShaderiv(fragment_, GL_COMPILE_STATUS, glGetShaderiv(vertex_, GL_COMPILE_STATUS,
tkerwin
I changed your bool to a GLint, and they both return 1, thus they are compiled.
tomzx
Seems like you might have stumbled into a driver bug.
tkerwin
+3  A: 

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.

Chris Dodd
Compilation looks fine, if I empty one of the files it doesn't work anymore, giving me another error about EOF. I believe the compiling is correct, but the linking cannot occur for some reason... I'm passing an initialized string, null terminated.
tomzx
+3  A: 

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?

Andreas Brinck
I tried your program, and yet it still fails at the linking, link_status == 0 and the assert fails.
tomzx
@tomzx Can you show how you call `glShaderSourceARB`? What kind of graphics card do you have and which driver?
Andreas Brinck
glShaderSourceARB(fragment_shader, 1, (const GLcharARB**)cstr is a pointer to a char dynamically allocated (char* cstr = new char[]).I have an nVidia GeForce 8800GT, drivers are the default one, version 191.07.
tomzx
@tomzx I'm guessing that there's something subtly wrong with the data in `cstr`. Possible things to check for: 1. Is it zero terminated? 2. Is there a newline at the end of the source (this shouldn't matter, but sometimes it does anyway ;)?
Andreas Brinck