【问题标题】:Lighting is misbehaving in shader program着色器程序中的照明行为异常
【发布时间】:2024-01-06 18:15:01
【问题描述】:

这是我的着色器程序:

#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 左右,关键的变化是我最初有 normal = 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() );

【问题讨论】:

  • 你把东西混在一起了。您应该在顶点着色器上将顶点乘以模型视图矩阵,而不是在片段着色器上计算 lightinh。
  • 为什么要在着色器片段上点亮?这是必需的还是可以在顶点着色器上完成?我在较旧的 opengl 中看到的大多数示例确实将几乎所有内容都放在了顶点着色器上,所以我不确定这是如何导致问题的。

标签: c++ opengl glsl lighting normals


【解决方案1】:

问题最终证明是我教授提供的模型加载器的问题,不知何故与现代 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));

    }

做事

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"

    }

【讨论】:

    最近更新 更多