【问题标题】:OPENGL: drawing multiple point lightsOPENGL:绘制多个点光源
【发布时间】:2014-03-08 22:13:48
【问题描述】:

我在场景中绘制多个点光源时遇到问题。我正在 OpenGL 中开发一个简单的迷宫式游戏,其中迷宫是随机生成的。迷宫中的每个“房间”都由一个 Room 结构体表示,如下所示:

struct Room
{
    int x, z;
    bool already_visited, n, s, e, w;
    GLuint vertex_buffer, texture, uv_buffer, normal_buffer;
    std::vector<glm::vec3>vertices, normals;
    std::vector<glm::vec2>uvs;
    glm::vec3 light_pos; //Stores the position of a light in the room
};

每个房间里都有一盏灯,这盏灯的位置存储在light_pos中。该灯光用于简单的逐顶点着色器,如下所示:

layout(location = 0) in vec3 pos;
layout(location = 1) in vec2 uv_coords;
layout(location = 2) in vec3 normal;
uniform mat4 mvpMatrix;
uniform mat4 mvMatrix;
uniform vec3 lightpos;
out vec2 vs_uv;
out vec3 vs_normal;
out vec3 color;
void main()
{
    gl_Position = mvpMatrix * vec4(pos,1.0);
    vs_normal = normal;
    vs_uv = uv_coords;
    vec3 lightVector = normalize(lightpos - pos);
    float diffuse = clamp(dot(normal,lightVector),0.0,1.0);
    color = vec3(diffuse,diffuse,diffuse);
}

我的片段着色器看起来像这样(忽略“vs_normal”,暂时不用):

in vec2 vs_uv;
in vec3 vs_normal;
in vec3 color;
uniform sampler2D tex;
out vec4 frag_color;

void main()
{
    frag_color = vec4(color,1.0) * texture(tex,vs_uv).rgba;
}

我的绘图代码如下所示:

mat4 mvMatrix = view_matrix*model_matrix;
mat4 mvpMatrix = projection_matrix * mvMatrix;
glBindVertexArray(vertexBufferObjectID);
glUseProgram(shaderProgram);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
for (int x = 0; x < NUM_ROOMS_X; x++)
{
   for (int z = 0; z < NUM_ROOMS_Z; z++)
   {
      //int x = int(std::round(position.x / ROOM_SIZE_X_MAX));
      //int z = int(std::round(position.z / ROOM_SIZE_Z_MAX));
      Room rm = room_array[x][z];
      glBindBuffer(GL_ARRAY_BUFFER, rm.vertex_buffer);
      glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);

      glBindBuffer(GL_ARRAY_BUFFER, rm.uv_buffer);
      glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, (void*) 0);

      glBindBuffer(GL_ARRAY_BUFFER, rm.normal_buffer);
      glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0);

      glUniformMatrix4fv(mvpMatrixID, 1, GL_FALSE, &mvpMatrix[0][0]);
      glUniformMatrix4fv(mvMatrixID, 1, GL_FALSE, &mvMatrix[0][0]);
      glUniform3fv(light_ID, 3, &rm.light_pos[0]); //Here is where I'm setting the new light position. It looks like this is ignored

      glActiveTexture(GL_TEXTURE0);
      glBindTexture(GL_TEXTURE_2D, rm.texture);
      glUniform1i(texture_ID, 0);

      glDrawArrays(GL_QUADS, 0, rm.vertices.size());
   }
}
glUseProgram(0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glBindTexture(GL_TEXTURE_2D, 0);

但是,结果如下所示(我修改了我的绘图代码以在每个灯所在的位置绘制一个框,并在位置 (0,0) 处圈出房间):

http://imgur.com/w4uPMD6

如您所见,看起来只有位置 (0,0) 的灯光会影响地图上的任何房间,其他灯光会被忽略。我知道灯的位置正确,因为我用来显示位置的框是正确的。我想即使我设置了新的light_pos,由于某种原因它没有通过。有什么想法吗?

【问题讨论】:

    标签: c++ opengl lighting


    【解决方案1】:

    您正在做的一件不太常见的事情是将灯光位置作为顶点属性传递。最佳情况下,您应该将其作为统一变量传递给着色器,就像处理矩阵一样。但我怀疑这就是问题所在。

    我相信你的问题是你在不同的空间进行光计算。您绘制的曲面的顶点位于 object/model 空间中,而我猜,您的光位于 world 空间中定义的点。尝试将光照位置乘以应用于顶点的模型矩阵的倒数。我对 GLM 不熟悉,但我认为其中一定有一个 inverse() 函数:

    vec3 light_pos_object_space = inverse(model_matrix) * rm.light_pos;
    glVertexAttrib3fv(light_ID, &light_pos_object_space[0]);
    

    【讨论】:

    • 感谢您的回复。我最初将 light_pos 定义为制服,但将其更改为属性以查看是否有帮助。我已经把它改回原来的问题。至于不同的坐标空间,我不确定这会有所帮助,因为我正在绘制的顶点已经在世界空间中。由于一切都是从正方形绘制的,我不执行任何局部对象转换,一切都在世界空间(顶点和光线位置)中,我的模型矩阵只是单位矩阵。既然如此,不知道您的建议是否有帮助?
    • 如果您确定顶点和灯光位置都在同一个空间中(未应用平移/旋转/缩放),则不。单位矩阵的逆是单位矩阵。您可以尝试的另一件事是将布局(位置)限定符添加到顶点着色器输出。我过去有过这样的问题。确保在片段着色器中匹配它们。另外,如果您可以发布片段着色器,那将很有帮助:)
    • 根据您的要求添加了片段着色器。至于布局限定符,你的意思是我应该创建一个顶点数组来处理灯光位置吗?这似乎有点限制,因为我希望最终能够为每个房间定义任意数量的灯。不过我会试一试的
    • 我的目的是让您尝试将 layout() 限定符添加到着色器的输出/输入。例如。在VS中你有“out vec2 vs_uv;”,尝试“layout(location = 0) out vec2 vs_uv;”然后在片段着色器“vec2 vs_uv中的布局(位置= 0);”以此类推。我建议这样做是因为我曾经在着色器中遇到过类似的数据损坏问题,因为没有添加布局限定符。顺便说一句,你的碎片着色器看起来不错。
    • 我不认为我的问题是由损坏的数据进入片段着色器引起的。毕竟,片段着色器完美地完成了它的工作,它获取了顶点着色器发送给它的颜色并将它们添加到纹理中。它是错误地计算这些颜色的顶点着色器。如果数据损坏是一个问题,那么颜色不会全部混乱吗?
    【解决方案2】:

    找出我的问题。我正在调用这个函数:

    glUniform3fv(light_ID, 3, &rm.light_pos[0]);
    

    当我应该打电话给这个时:

    glUniform3fv(light_ID, 1, &rm.light_pos[0]);
    

    【讨论】:

      猜你喜欢
      • 2021-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      相关资源
      最近更新 更多