开发者

Why My Flatten Shader (from Lighthouse3d Tutorial) Is Not Working?

开发者 https://www.devze.com 2023-03-13 06:53 出处:网络
The tutorial has an example called the Flatten Shader, which displays the GLUT teapot as a flatten teapot. Here is the link to the Flatten Shader.

The tutorial has an example called the Flatten Shader, which displays the GLUT teapot as a flatten teapot. Here is the link to the Flatten Shader.

I have done everything exactly like the steps mentioned in the tutorial, but my teapot is not flat like how the teapot in the tutorial looks like. It just looks like a normal teapot.

Here is the code for the vertex shader:

  void main()
  {
     vec4 v = vec4(gl_Vertex);
     v.z = 0.0;
     gl_Position = gl_ModelViewProjectionMatrix * v;
  }

Here is my fragment shader:

 void main()
 {
    gl_FragColor = gl_Color;
 }

And here is how I draw the Teapot:

 void display ( void )
{   
    glClearDepth(1.0);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode( GL_MODELVIEW );

    glLoadIdentity();

    gluLookAt( 0.0, 0.0, 2.0,
           0.0, 0.0, 0.0,
           0.0, 1.0, 0.0
             );

    glMultMatrixd(trackball->getRotation());

    const GLfloat diffuseIntensity[] = { 0.8, 0.4, 0.4, 1.0 };
    const GLfloat specularIntensity[] = { 0.5, 0.5, 0.5, 1.0 };

    glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, diffuseIntensity);
    glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, specularIntensity);
    glMaterialf( GL_FRONT_AND_BACK, GL_SHININESS, 5.0 );

    glutSolidTeapot(1.0);

    glutSwapBuffers();
}

While it is supposed to be "Flat", the Teapot that gets displayed is like a normal teapot. If you think that I missed some initial configurations / setup st开发者_运维百科eps, then don't because I already did them:

GLuint createShader ( const GLchar* const source, GLenum type )
{
     GLuint shader = glCreateShader( type );
     glShaderSource( shader, 1, const_cast<const GLchar**>(&source), 0 );
     glCompileShader( shader );

     return shader;
}

and:

GLuint createProgram ( const GLuint shader )
{
     GLuint program = glCreateProgram();
     glAttachShader(program, shader);
     glLinkProgram(program);

     return program;
}

And here is where everything gets together:

    GLuint vertexShader = createShader(vertexShaderSource, GL_VERTEX_SHADER);
    GLuint fragmentShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER);

    GLuint vertexShaderProgram = createProgram(vertexShader);
    GLuint fragmentShaderProgram = createProgram(fragmentShader);

    glUseProgram(vertexShaderProgram);
    glUseProgram(fragmentShaderProgram);

Where am I going wrong?


A few things:

  1. You are not binding your shaders correctly. Your createProgram function needs to bind both the fragment shader and the vertex shader together. You should replace it with code that looks like this:

    GLuint createProgram ( const GLuint fshader, const GLuint vshader )
    {
         GLuint program = glCreateProgram();
         glAttachShader(program, fshader);
         glAttachShader(program, vshader);       
         glLinkProgram(program);
         return program;
    

    }

  2. And correspondingly, you should modify your last snippet to look like this:

    GLuint vertexShader = createShader(vertexShaderSource, GL_VERTEX_SHADER);
    GLuint fragmentShader = createShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
    GLuint shaderProgram = createProgram(fragmentShader, vertexShader);
    glUseProgram(shaderProgram);
    
  3. Also, there could be other issues. You should use glGet(Shader|Program)InfoLog to help debug your shaders, and also make calls to glGetError to help diagnose where your program failed.

  4. Finally, I can't vouch for the credibility of this stack exchange answer, but apparently on some older ATi implementations gl_Color is a vec3, not a vec4, and so you need to cast it before assigning. See the following discussion: GLSL fragment shader syntax error


As an addition to Mikola's answer, you don't need to check the info log every time; you can check if your shaders compiled correctly and if your program linked correctly and only call glGetShaderInfoLog and glGetProgramInfoLog if an error occurred.

Here's some code to do just that (in Python but translation to C++ is trivial):

# create your vertex shader, attach its source, etc.
glCompileShader(vertex_shader)
rc_compile = GLint()
glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, rc_compile)
if rc_compile.value == GL_FALSE: # shader compilation failed
  info = create_string_buffer(1024)
  glGetShaderInfoLog(vertex_shader, 1024, None, info)
  glDeleteShader(vertex_shader)
  raise Exception(info.value)

# do the same thing for a fragment shader and create a program to link the two
glAttachShader(program, vertex_shader)
glAttachShader(program, fragment_shader)
rc_link = GLint()
glGetProgramiv(program, GL_LINK_STATUS, rc_link)
if rc_link.value == GL_FALSE: # program link failed
  info = create_string_buffer(1024)
  glGetProgramInfoLog(program, 1024, None, info)
  glDeleteProgram(program)
  raise Exception(info.value)
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号