c++openglglsl

Assistance in Debug OpenGL glsl Shader or Code using it


I am working on adding a phong shader to my working program. After I implemented my new shaders, my code got a "Segmentation Fault: 11" during:

glDrawArrays(GL_TRIANGLES, 0, mCubes.getArrayNumberOfElements());

I know the number of elements is correct because it worked for my previous, simple shader.

Here is my Vertex Shader:

// vertex shader
attribute vec4 vPosition;
attribute vec3 vNormal;
varying vec4 color; //vertex shader
// light and material properties
uniform vec4 AmbientProduct, DiffuseProduct, SpecularProduct; 
uniform mat4 ModelView;
//uniform mat4 Projection;
uniform vec4 LightPosition;
uniform float Shininess;
vec3 L, H, N, pos, E;
vec4 diffuse, specular, ambient;
float Kd, Ks;

void main()
{
    // Transform vertex position into eye coordinates 
    pos = (ModelView * vPosition).xyz; 
    L = normalize( LightPosition.xyz - pos ); 
    E = normalize( -pos );
    H = normalize( L + E );
    // Transform vertex normal into eye coordinates
    N = normalize( ModelView*vec4(vNormal, 0.0) ).xyz;
    // Compute terms in the illumination equation 
    ambient = AmbientProduct;
    Kd = max( dot(L, N), 0.0 );
    diffuse = Kd*DiffuseProduct;
    Ks = pow( max(dot(N, H), 0.0), Shininess );
    specular = Ks * SpecularProduct;
    if( dot(L, N) < 0.0 ) 
    specular = vec4(0.0, 0.0, 0.0, 1.0); 
    
    gl_Position = ModelView * vPosition;
    color = ambient + diffuse + specular;
    color.a = 1.0; 
}

Here is my display function in which the code ends up getting the fault:

void display(void) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    vector<float> cell = mCubes.getCell();

    mat4 matrix = rot * scale(1.0/cell[0], 1.0/cell[1], 1.0/cell[2]) * translate(-cell[0]/2.0, -cell[1]/2.0, -cell[2]/2.0);
    glUniformMatrix4fv(vShaderModelView, 1, GL_TRUE, matrix);
    glDrawArrays(GL_TRIANGLES, 0, mCubes.getArrayNumberOfElements()); 
    glutSwapBuffers();
    glFlush();
}

And here is my init function that mostly sets up and interacts with the shaders:

void init() {
    // Create a vertex array object
    GLuint vao;
    #ifdef __APPLE__
    glGenVertexArraysAPPLE( 1, &vao );
    glBindVertexArrayAPPLE( vao );
    #else
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    #endif
    
    // Create and initialize a buffer object
    GLuint buffer;
   
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData( GL_ARRAY_BUFFER,
                 mCubes.getDisplayArraySize() + mCubes.getDisplayArraySize()*3,                NULL, GL_STATIC_DRAW );
    GLintptr offset = 0;
    glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getDisplayArraySize(), mCubes.getDisplayArray());
    offset+= mCubes.getDisplayArraySize();
    
    glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getDisplayArraySize(), mCubes.getNormalVector());

    // Load shaders and use the resulting shader program
    string evname = "PROTCAD3DIR";
    string path = PCGeneralIO::getEnvironmentVariable(evname);

    path += "/data/shaders/";
    #ifdef __APPLE__
    string vshadername = path + "kw_vshader1_mac.glsl";
    string fshadername = path + "kw_fshader1_mac.glsl";
    //#else
    //  string vshadername = path + "kw_vshader1.glsl";
    //  string fshadername = path + "kw_fshader1.glsl";
    #endif

    GLuint program = InitShader( vshadername.c_str(), fshadername.c_str() );

    glUseProgram(program);
    // Initialize the vertex position attribute from the vertex shader    
    GLuint vShaderPosition = glGetAttribLocation(program, "vPosition");
    glEnableVertexAttribArray(vShaderPosition);
    glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    
    GLuint vShaderNormal = glGetAttribLocation(program, "vNormal");
    glEnableVertexAttribArray(vShaderNormal);
    //glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset)); //this was the ORIGINAL PROBLEM, now commented out and below is solution
      glVertexAttribPointer(vShaderNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));
   
    
    vShaderModelView = glGetUniformLocation(program, "ModelView");
    vShaderLightPosition = glGetUniformLocation(program, "LightPosition");
    
    vShaderAmbientProduct = glGetUniformLocation(program, "AmbientProduct");
    vShaderDiffuseProduct = glGetUniformLocation(program, "DiffuseProduct");
    vShaderSpecularProduct = glGetUniformLocation(program, "SpecularProduct");
    vShaderShininess = glGetUniformLocation(program, "SpecularProduct");
    glEnable( GL_DEPTH_TEST );
    
    vec4 light = vec4(0.5,1.5,1.0,0.0);
    glUniform4fv(vShaderLightPosition, 1, light);
    vec4 amb = vec4(1.0f,0.0f,0.20f,1.0f);
    glUniform4fv(vShaderAmbientProduct, 1, amb);
    vec4 diff = vec4(0.5f,0.5f,0.5f,1.0f);
    glUniform4fv(vShaderDiffuseProduct, 1, diff);
    vec4 spec = vec4(0.80f,0.80f,0.80f,1.0f);
    glUniform4fv(vShaderSpecularProduct, 1, spec);
    float shin = 6.0f;
    glUniform1f(vShaderShininess,shin);
     
    glClearColor(.2, .2, .2, 1); /* Grey background */
}

If you have any questions, feel free to ask and I will elaborate. I feel that either the vertex shader itself has a problem, or the way I interact with the shader is doing something wonky. Any help or suggestions are accepted!

EDIT::: (code edited to reflect solution) The problem was in the second:

glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));

which should have read:

glVertexAttribPointer(vShaderNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));

And was a stupid copy/paste mistake. However, the finished product still does not look correct:

At Rotation 0 it seems to be fully colored:

at Rotation 0 it seems to be fully colored

Rotation of a little bit reveals some odd behavior:

Rotation of a little bit reveals some odd behavior

Even more rotation leads you to pull your hair out:

Even more rotation leads you to pull your hair out

Then it whites out and you know I screwed up!!

Then it whites out and you know I screwed up!!

So, as you rotate the color gets screwed up and turns white, black, patterned and everything, but this is obviously incorrect.

Edit::: This is my attempt to "Correct" the issue of passing the wrong amount of values with vNormal:

void init() {
  // Create a vertex array object
  GLuint vao;
    #ifdef __APPLE__
    glGenVertexArraysAPPLE( 1, &vao );
    glBindVertexArrayAPPLE( vao );
    #else
    glGenVertexArrays( 1, &vao );
    glBindVertexArray( vao );
    #endif
  
    // Create and initialize a buffer object
    GLuint buffer;
    realVec *normArray = new realVec[mCubes.getNormalArraySize()];//vec4 array compared to vec3 array     
    normArray = mCubes.getNormalVector(); // new array of normals
    
    for(int i=0; i<mCubes.getArrayNumberOfElements();i++){
        printf("Normal at %d  is %f \n",i,normArray[i][0]); //to print normals
        printf("Normal at %d  is %f \n",i,normArray[i][1]); //to print normals
        printf("Normal at %d  is %f \n",i,normArray[i][2]); //to print normals
    }
   
  glGenBuffers(1, &buffer);
  glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData( GL_ARRAY_BUFFER,
                 mCubes.getDisplayArraySize() + mCubes.getNormalArraySize(),                NULL, GL_STATIC_DRAW ); //Changed size for vec3 array of normals
    GLintptr offset = 0;
  glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getDisplayArraySize(), mCubes.getDisplayArray());
    offset+= mCubes.getDisplayArraySize();
    
    glBufferSubData(GL_ARRAY_BUFFER, offset, mCubes.getNormalArraySize(), normArray);

    // Load shaders and use the resulting shader program
    string evname = "PROTCAD3DIR";
    string path = PCGeneralIO::getEnvironmentVariable(evname);

    path += "/data/shaders/";
    #ifdef __APPLE__
    string vshadername = path + "kw_vshader1_mac.glsl";
    string fshadername = path + "kw_fshader1_mac.glsl";
    //#else
    //  string vshadername = path + "kw_vshader1.glsl";
    //  string fshadername = path + "kw_fshader1.glsl";
    #endif

    GLuint program = InitShader( vshadername.c_str(), fshadername.c_str() );

  glUseProgram(program);
    //offset =0;
  // Initialize the vertex position attribute from the vertex shader    
  GLuint vShaderPosition = glGetAttribLocation(program, "vPosition");
  glEnableVertexAttribArray(vShaderPosition);
  glVertexAttribPointer(vShaderPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
    
    GLuint vShaderNormal = glGetAttribLocation(program, "vNormal");
  glEnableVertexAttribArray(vShaderNormal);
  glVertexAttribPointer(vShaderNormal, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));
    
   
  //vShaderMatrix = glGetUniformLocation(program, "vMatrix");
  //vShaderColor = glGetUniformLocation(program, "vColor")
    vShaderModelView = glGetUniformLocation(program, "ModelView");
    vShaderLightPosition = glGetUniformLocation(program, "LightPosition");
    //vShaderProjection = glGetUniformLocation(program, "Projection");
    
    vShaderAmbientProduct = glGetUniformLocation(program, "AmbientProduct");
    vShaderDiffuseProduct = glGetUniformLocation(program, "DiffuseProduct");
    vShaderSpecularProduct = glGetUniformLocation(program, "SpecularProduct");
    vShaderShininess = glGetUniformLocation(program, "SpecularProduct");
  glEnable( GL_DEPTH_TEST );
    
    vec4 light = vec4(0.5,1.5,1.0,0.0);
    glUniform4fv(vShaderLightPosition, 1, light);
    vec4 amb = vec4(1.0f,0.0f,0.20f,1.0f);
    glUniform4fv(vShaderAmbientProduct, 1, amb);
    vec4 diff = vec4(0.5f,0.5f,0.5f,1.0f);
    glUniform4fv(vShaderDiffuseProduct, 1, diff);
    vec4 spec = vec4(0.80f,0.80f,0.80f,1.0f);
    glUniform4fv(vShaderSpecularProduct, 1, spec);
    float shin = 6.0f;
    glUniform1f(vShaderShininess,shin);
    
    glClearColor(.2, .2, .2, 1); /* Grey background */
}

Should I maybe change the light, ambient, specular, and diffuse properties? I am not sure what the problem is.


Solution

  • You pass your vNormal attribute data using the following code

    glVertexAttribPointer(vShaderNormal, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(offset));
    

    This indicates that your normal have 4 components, whereas in your vertex shader you declare it as

    attribute vec3 vNormal;
    

    This mismatch may be related to your problem if the normals are misinterpreted.