我在着色器中的照明功能有什么问题?
What's wrong with my lighting function in the shader?
我正在努力寻找我的顶点着色器中超简单光照函数的错误:
in vec4 position; /* Homogenized input vertex position. */
in vec4 color; /* Input color information. */
in vec3 normal; /* Normal vector to the surface. */
uniform mat4 ortho; /* Orthographic matrix. */
uniform mat4 model; /* Modelling matrix. */
uniform mat4 view; /* View transformation. */
uniform mat4 project; /* Projection matrix. */
out vec4 color_out; /* Color passed to the fragment shader. */
float light()
{
mat3 normat = transpose(inverse(mat3(view * model)));
vec3 norm = normalize(normat * normalize(normal));
vec3 light = normalize(vec3(1.0f, 1.0f, 1.0f));
return max(dot(norm, light), 0.0f);
}
void main()
{
gl_Position = ortho * project * view * model * position;
color_out = vec4(color.rgb * light(), color.a);
}
此函数用于照亮旋转的 icosphere 的表面。因为我已经手动生成了 icosphere 的顶点并且我可以随时访问它们,所以我尝试在 CPU 代码中复制相同的操作来显示一张脸的结果,例如:
Normal Matrix: Normal vectors for face 10:
[ 0.08 0.59 -0.81] { 3936}[-0.58 0.61 -0.54] --> light: 0.694
[-0.00 0.81 0.59] { 3937}[-0.58 0.61 -0.54] --> light: 0.694
[ 1.00 -0.04 0.06] { 3938}[-0.58 0.61 -0.54] --> light: 0.694
无论法向量是否正确,光值确实会随着球体的旋转而变化。但是,如果我 运行 代码(并让着色器计算值),生成的三角形面会完全变暗。
这是我将顶点数据复制到缓冲区以及指向属性的方式:
/* (...) Bind shader, and get attribute locations. */
/* (...) Create VBO. */
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_DYNAMIC_DRAW);
/* (...) */
glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(color_id, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)sizeof(glm::vec3));
glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(sizeof(glm::vec3) + sizeof(glm::vec4)));
/* For reference: vertices is a std::vector<Vertex>, where Vertex
* is defined as:
*
* struct Vertex {
* glm::vec3 p; ---> Position.
* glm::vec4 c; ---> Color.
* glm::vec3 n; ---> Normal.
* };
**/
愚蠢的我,我忘了启用 normal 顶点属性...这是我缺少的行:
glEnableVertexAttribArray(normal_id);
其中 normal_id
之前已与 glGetAttribLocation
绑定。
我正在努力寻找我的顶点着色器中超简单光照函数的错误:
in vec4 position; /* Homogenized input vertex position. */
in vec4 color; /* Input color information. */
in vec3 normal; /* Normal vector to the surface. */
uniform mat4 ortho; /* Orthographic matrix. */
uniform mat4 model; /* Modelling matrix. */
uniform mat4 view; /* View transformation. */
uniform mat4 project; /* Projection matrix. */
out vec4 color_out; /* Color passed to the fragment shader. */
float light()
{
mat3 normat = transpose(inverse(mat3(view * model)));
vec3 norm = normalize(normat * normalize(normal));
vec3 light = normalize(vec3(1.0f, 1.0f, 1.0f));
return max(dot(norm, light), 0.0f);
}
void main()
{
gl_Position = ortho * project * view * model * position;
color_out = vec4(color.rgb * light(), color.a);
}
此函数用于照亮旋转的 icosphere 的表面。因为我已经手动生成了 icosphere 的顶点并且我可以随时访问它们,所以我尝试在 CPU 代码中复制相同的操作来显示一张脸的结果,例如:
Normal Matrix: Normal vectors for face 10:
[ 0.08 0.59 -0.81] { 3936}[-0.58 0.61 -0.54] --> light: 0.694
[-0.00 0.81 0.59] { 3937}[-0.58 0.61 -0.54] --> light: 0.694
[ 1.00 -0.04 0.06] { 3938}[-0.58 0.61 -0.54] --> light: 0.694
无论法向量是否正确,光值确实会随着球体的旋转而变化。但是,如果我 运行 代码(并让着色器计算值),生成的三角形面会完全变暗。
这是我将顶点数据复制到缓冲区以及指向属性的方式:
/* (...) Bind shader, and get attribute locations. */
/* (...) Create VBO. */
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_DYNAMIC_DRAW);
/* (...) */
glVertexAttribPointer(position_id, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
glVertexAttribPointer(color_id, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)sizeof(glm::vec3));
glVertexAttribPointer(normal_id, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(sizeof(glm::vec3) + sizeof(glm::vec4)));
/* For reference: vertices is a std::vector<Vertex>, where Vertex
* is defined as:
*
* struct Vertex {
* glm::vec3 p; ---> Position.
* glm::vec4 c; ---> Color.
* glm::vec3 n; ---> Normal.
* };
**/
愚蠢的我,我忘了启用 normal 顶点属性...这是我缺少的行:
glEnableVertexAttribArray(normal_id);
其中 normal_id
之前已与 glGetAttribLocation
绑定。