照明程序中的照明行为不当

时间:2014-04-03 18:27:39

标签: c++ opengl glsl lighting normals

这是我的着色器程序:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec3 vertexNormal_modelspace;


// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform mat3 blNormalMatrix;
uniform vec3 lightPos;
out vec4 forFragColor;
const vec3 diffuseColor = vec3(0.55, 0.09, 0.09);

void main(){

    // Output position of the vertex, in clip space : MVP * position
  gl_Position =  MVP * vec4(vertexPosition_modelspace,1);
    vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * diffuseColor;
  // all following gemetric computations are performed in the
  // camera coordinate system (aka eye coordinates)
  vec3 vertexNormal_cameraspace = (V*M*vec4(vertexNormal_modelspace,0)).xyz;
  vec4 vertexPosition_cameraspace4 = V*M* vec4(vertexPosition_modelspace,1);
  vec3 vertexPosition_cameraspace = vec3(vertexPosition_cameraspace4).xyz;
  vec3 lightDir = normalize(lightPos - vertexPosition_cameraspace);

  float lambertian = clamp(dot(lightDir,vertexNormal_cameraspace), 0.0,1.0);
  forFragColor = vec4(lambertian*diffuseColor , 1.0);

}

我的问题是这个“工作”在旧的opengl配置文件中,甚至没有版本号,我认为它是在Opengl 2.1左右,关键的变化是我原来有正常= gl_normalMatrix * gl_normal和事情很有效。

然而,这是基于我的教授的代码,我已经更新到3.3+核心配置文件,在修改了已弃用的功能后,我现在还剩下这个:

https://drive.google.com/file/d/0B6oLZ_d7S-U7cVpkUXpVXzdaZEk/edit?usp=sharing是指向我的计划行为视频的链接。

光源应该是(0,0,3)左右的点光源,不应该移动;但是它没有遵循特别合乎逻辑的行为模式,我无法理解它。

我尝试传递模型矩阵的逆转置并将它们用作替换normalMatrix,但它破坏了我的法线。所以我不知道。

这是我的常规矩阵:

glm::mat3 MyNormalMatrix = glm::mat3(glm::transpose(glm::inverse(ModelMatrix)));

编辑:这是我的显示代码:

   glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   
   glEnable(GL_DEPTH_TEST);

      // Use our shader
   glUseProgram(programID);

   // Get our transformations iff we move the camera around.
   glm::mat4 MyModelMatrix = ModelMatrix * thisTran * ThisRot;

   MVP = ProjectionMatrix * ViewMatrix * MyModelMatrix;
   glm::mat4 ModelView = ViewMatrix * MyModelMatrix;
   glm::mat3 MyNormalMatrix = glm::mat3(glm::transpose(glm::inverse(ModelView)));
   glm::vec3 newLightPos = lightPos;
      // Send our transformation to the currently bound shader, 
      // in the "MVP" uniform
   glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &MVP[0][0]);
   glUniformMatrix4fv(ModelMatrixID, 1, GL_FALSE, &MyModelMatrix[0][0]);
   glUniformMatrix4fv(ViewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);
   glUniformMatrix4fv(BlNormalMatrix,1,GL_FALSE, &MyNormalMatrix[0][0]);
   glUniformMatrix4fv(BlRotations, 1, GL_FALSE, &ThisRot[0][0]);
   glUniform3f(BlCamera, cameraLoc.x, cameraLoc.y, cameraLoc.z);
   glUniform3f(lPosition, newLightPos.x,newLightPos.y,newLightPos.z);

   // VBO buffer: vertices
      // 1rst attribute buffer : vertices
   glEnableVertexAttribArray(0);
   glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
   glVertexAttribPointer(
      0,                  // attribute
      3,                  // size
      GL_FLOAT,           // type
      GL_FALSE,           // normalized?
      0,                  // stride
      (void*)0            // array buffer offset
   );

   // 2rd attribute buffer : normals
   glEnableVertexAttribArray(1);
   glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
   glVertexAttribPointer(
      1,                                // attribute
      3,                                // size
      GL_FLOAT,                         // type
      GL_FALSE,                         // normalized?
      0,                                // stride
      (void*)0                          // array buffer offset
   );

   // draw object using opengl 3.3 shit
   glDrawArrays(GL_TRIANGLES, 0, vertices.size() );

1 个答案:

答案 0 :(得分:0)

这个问题最终成了我教授提供的模型装载机的一个问题,它与现代的opengl不相容,只会“大部分”工作,因为它显然缺少左/右法线或者它们具有无效值。解决了使用Assimp的实现。

与assimp链接的代码是这样的:

void blInitResWAssimp() {
    cout << "blInitResWAssimp" << endl;
    blCreateModelViewProjectionMatrix();

    //loads object
    bool res = loadAssImp("Resources/RCSS-subdiv.obj", indices, indexed_vertices, indexed_uvs, indexed_normals);
    //bool res = loadAssImp("Resources/cheb.obj", indices, indexed_vertices, indexed_uvs, indexed_normals);

    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // Load it into a VBO
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, indexed_vertices.size() * sizeof(glm::vec3), &indexed_vertices[0], GL_STATIC_DRAW);

    // Normal buffer
    glGenBuffers(1, &normalbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
    glBufferData(GL_ARRAY_BUFFER, indexed_normals.size() * sizeof(glm::vec3), &indexed_normals[0], GL_STATIC_DRAW);

    // Generate a buffer for the indices as well
    glGenBuffers(1, &elementbuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);

    //ModelMatrix = ModelMatrix * glm::translate(glm::mat4(1.0f), glm::vec3(-0.5, -0.5, 0));

    }

Assimp stuff

bool loadAssImp(
    const char * path,
    std::vector<unsigned short> & indices,
    std::vector<glm::vec3> & vertices,
    std::vector<glm::vec2> & uvs,
    std::vector<glm::vec3> & normals
    ){

    Assimp::Importer importer;

    const aiScene* scene = importer.ReadFile(path, 0/*aiProcess_JoinIdenticalVertices | aiProcess_SortByPType*/);
    if (!scene) {
        fprintf(stderr, importer.GetErrorString());
        getchar();
        return false;
    }
    const aiMesh* mesh = scene->mMeshes[0]; // In this simple example code we always use the 1rst mesh (in OBJ files there is often only one anyway)
    const aiMaterial* material = scene->mMaterials[0];

    // Fill vertices positions
    vertices.reserve(mesh->mNumVertices);
    for (unsigned int i = 0; i<mesh->mNumVertices; i++){
        aiVector3D pos = mesh->mVertices[i];
        vertices.push_back(glm::vec3(pos.x, pos.y, pos.z));
    }

    // Fill vertices texture coordinates
    /*
    uvs.reserve(mesh->mNumVertices);
    for (unsigned int i = 0; i<mesh->mNumVertices; i++){
        aiVector3D UVW = mesh->mTextureCoords[0][i]; // Assume only 1 set of UV coords; AssImp supports 8 UV sets.
        uvs.push_back(glm::vec2(UVW.x, UVW.y));
    }*/

    // Fill vertices normals
    normals.reserve(mesh->mNumVertices);
    for (unsigned int i = 0; i<mesh->mNumVertices; i++){
        aiVector3D n = mesh->mNormals[i];
        //aiVector3D n = mesh->mVertices[i];
        normals.push_back(glm::vec3(n.x, n.y, n.z));
    }


    // Fill face ind5ices
    indices.reserve(3 * mesh->mNumFaces);
    for (unsigned int i = 0; i<mesh->mNumFaces; i++){
        // Assume the model has only triangles.
        indices.push_back(mesh->mFaces[i].mIndices[0]);
        indices.push_back(mesh->mFaces[i].mIndices[1]);
        indices.push_back(mesh->mFaces[i].mIndices[2]);
    }

    // The "scene" pointer will be deleted automatically by "importer"

    }