我知道网上有几个关于同样问题的线程,但我没有得到这些帮助,因为我的实现是不同的. 我将视图空间中的颜色,法线和深度渲染为纹理.第二,我用全屏四边形绑定纹理并计算光照.方向灯
我将视图空间中的颜色,法线和深度渲染为纹理.第二,我用全屏四边形绑定纹理并计算光照.方向灯似乎工作正常但点光源正在用相机移动.
我分享相应的着色器代码:
照明步骤顶点着色器
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->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)),则反向移调实际上是个好主意.