我知道网上有几个关于同样问题的线程,但我没有得到这些帮助,因为我的实现是不同的。
我渲染颜色,法线和深度在视图空间到纹理。其次,我绑定纹理与全屏四边形和计算照明。定向光似乎工作得很好,但点光随着相机移动。
我分享相应的着色器代码:
光照阶跃顶点着色器
in vec2 inVertex;
in vec2 inTexCoord;
out vec2 texCoord;
void main() {
gl_Position = vec4(inVertex, 0, 1.0);
texCoord = inTexCoord;
}
光照步骤片段着色器
float depth = texture2D(depthBuffer, texCoord).r;
vec3 normal = texture2D(normalBuffer, texCoord).rgb;
vec3 color = texture2D(colorBuffer, texCoord).rgb;
vec3 position;
position.z = -nearPlane / (farPlane - (depth * (farPlane - nearPlane))) * farPlane;
position.x = ((gl_FragCoord.x / width) * 2.0) - 1.0;
position.y = (((gl_FragCoord.y / height) * 2.0) - 1.0) * (height / width);
position.x *= -position.z;
position.y *= -position.z;
normal = normalize(normal);
vec3 lightVector = lightPosition.xyz - position;
float dist = length(lightVector);
lightVector = normalize(lightVector);
float nDotL = max(dot(normal, lightVector), 0.0);
vec3 halfVector = normalize(lightVector - position);
float nDotHV = max(dot(normal, halfVector), 0.0);
vec3 lightColor = lightAmbient;
vec3 diffuse = lightDiffuse * nDotL;
vec3 specular = lightSpecular * pow(nDotHV, 1.0) * nDotL;
lightColor += diffuse + specular;
float attenuation = clamp(1.0 / (lightAttenuation.x + lightAttenuation.y * dist + lightAttenuation.z * dist * dist), 0.0, 1.0);
gl_FragColor = vec4(vec3(color * lightColor * attenuation), 1.0);
我发送光属性到shader作为制服:
shader->set("lightPosition", (viewMatrix * modelMatrix).inverse().transpose() * vec4(0, 10, 0, 1.0));
viewmatrix是相机矩阵,modelmatrix是单位矩阵。
为什么点灯是翻译与相机而不是与模型?
欢迎提出任何建议!
除了Nobody的注释之外,你计算的所有向量都必须归一化,你必须确保它们都在同一个空间中。如果您使用视图空间位置作为视图向量,则法向量也必须在视图空间中(在第一次写入g缓冲区之前,必须通过逆转置模型视图矩阵进行变换)。光向量也必须在可视空间中。因此,你必须通过视图矩阵(或模型视图矩阵,如果光的位置不在世界空间中)来变换光的位置,而不是它的逆转置。
shader->set("lightPosition", viewMatrix * modelMatrix * vec4(0, 10, 0, 1.0));
编辑:对于定向光,如果您指定光的方向作为光的方向(例如指向-z方向的光的vec4(0, 1, 0, 0)
),则逆转置实际上是一个好主意。