我在场景中绘制多个点光源时遇到问题。我在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);
}
我的片段着色器看起来像这样(忽略&#34; vs_normal&#34;,它现在不用了):
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)处圈出了房间):
如您所见,看起来只有位置(0,0)的灯光会影响地图上的任何房间,其他灯光都会被忽略。我知道灯的位置正确,因为我用来显示位置的方框是正确的。我想虽然我设置了新的light_pos
,但由于某种原因它还没有通过。有什么想法吗?
答案 0 :(得分:0)
您正在做的一件事情(不常见)是将灯光位置作为顶点属性传递。最理想的情况是,您应该将它作为统一变量传递给着色器,就像对矩阵一样。但我怀疑这是问题所在。
我相信你的问题是你在不同的空间进行光计算。您绘制的曲面的顶点位于对象/模型空间中,而我猜测,您的光位于 world 空间中定义的点。尝试将您的灯光位置乘以您应用于顶点的模型矩阵的倒数。我不熟悉GLM,但我认为必须有一个 inverse()函数:
vec3 light_pos_object_space = inverse(model_matrix) * rm.light_pos;
glVertexAttrib3fv(light_ID, &light_pos_object_space[0]);
答案 1 :(得分:0)
弄清楚我的问题。我在调用这个函数:
glUniform3fv(light_ID, 3, &rm.light_pos[0]);
我什么时候应该这样说:
glUniform3fv(light_ID, 1, &rm.light_pos[0]);