如何修复错误的Blinn-Phong照明

测试人员

我正在尝试为Vulkan着色器中的单个光源实施Blinn-Phong着色,但是我得到的结果不是我期望的。

输出如下所示: 照明不正确

灯光位置应位于相机右侧的后方,该位置正确地显示在头上,而不是圆圈上。我不希望圆圈中间有高强度的点。

灯光位置在坐标(10、10、10)处。

圆中间的高强度点是(0,0,0)。

顶点着色器:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 0) uniform MVP {
    mat4 model;
    mat4 view;
    mat4 proj;
} mvp;

layout(location = 0) in vec3 inPosition;
layout(location = 1) in vec3 inColor;
layout(location = 2) in vec2 inTexCoord;
layout(location = 3) in vec3 inNormal;

layout(location = 0) out vec3 fragColor;
layout(location = 1) out vec2 fragTexCoord;
layout(location = 2) out vec3 Normal;
layout(location = 3) out vec3 FragPos;
layout(location = 4) out vec3 viewPos;

void main() {
    gl_Position = mvp.proj * mvp.view * mvp.model * vec4(inPosition, 1.0);
    fragColor = inColor;
    fragTexCoord = inTexCoord;
    Normal = inNormal;
    FragPos = inPosition;
    viewPos = vec3(mvp.view[3][0], mvp.view[3][1], mvp.view[3][2]);
}

片段着色器:

#version 450
#extension GL_ARB_separate_shader_objects : enable

layout(binding = 1) uniform sampler2D texSampler;
layout(binding = 2) uniform LightUBO{
    vec3 position;
    vec3 color;
} Light;

layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 2) in vec3 Normal;
layout(location = 3) in vec3 FragPos;
layout(location = 4) in vec3 viewPos;

layout(location = 0) out vec4 outColor;

void main() {
    vec3 color = texture(texSampler, fragTexCoord).rgb;
    // ambient
    vec3 ambient = 0.2 * color;

    // diffuse
    vec3 lightDir = normalize(Light.lightPos - FragPos);
    vec3 normal = normalize(Normal);
    float diff = max(dot(lightDir, normal), 0.0);
    vec3 diffuse = diff * color;

    // specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, normal);
    float spec = 0.0;
    vec3 halfwayDir = normalize(lightDir + viewDir);  
    spec = pow(max(dot(normal, halfwayDir), 0.0), 32.0);

    vec3 specular = vec3(0.25) * spec;
    outColor = vec4(ambient + diffuse + specular, 1.0);
}

注意:我正在尝试将教程中的着色器实现到Vulkan中。

迈克尔·肯泽尔

这似乎只是使用正确的坐标系的问题。由于您的问题中缺少一些重要信息,因此我必须做一些假设。首先,基于您拥有一个模型矩阵并且场景中显然有多个对象这一事实,我将假定您的世界空间和对象空间通常并不相同。此外,我将假设您的model矩阵从对象空间转换为世界空间,您的view矩阵从世界空间转换为视图空间,并且您的proj矩阵从视图空间转换为剪辑空间。我还将假设您的inPositioninNormal属性位于对象空间坐标中。

基于所有这些,您viewPos只需要获取视图矩阵的最后一列,其中将包含相机在世界空间中的位置。最后一行也不会。视图矩阵从世界空间转换为视图空间。从相机的角度看,它的最后一列对应于指向世界空间原点的向量。您的FragPosNormal将在对象空间中。而且,根据您在问题中所说的,您的照明位置位于世界空间中。因此,最后,您只是将所有相对于完全不同的坐标系的坐标混在一起。例如:

vec3 lightDir = normalize(Light.lightPos - FragPos);

在这里,您要从世界空间位置减去对象空间位置,这将产生完全无意义的结果。然后将此无意义的结果归一化并用对象空间方向标出

float diff = max(dot(lightDir, normal), 0.0);

另外,即使viewPos是世界相机位置

vec3 viewDir = normalize(viewPos - FragPos);

仍然是没有意义的,因为FragPos是在对象空间坐标中给出的。

仅当涉及的所有矢量都相对于同一坐标系时,才对坐标矢量进行运算。选择哪种坐标系并不重要。但是您必须选择一个。确保所有矢量实际上都相对于该坐标系,例如世界空间。如果某些矢量尚未恰好位于该坐标系中,则必须将其转换为该坐标系。只有所有向量都在同一坐标系中,阴影计算才有意义。

要获取viewPos,您可以取反视图矩阵的最后一列(如果由于某种原因碰巧已经在某个地方放置了该列),或者只是将相机位置作为附加制服传递。另外,不要对每个顶点一次又一次地乘以模型视图和投影矩阵,而应该考虑将组合的模型视图-投影矩阵传递给着色器...

除此之外:请注意,如果表面实际上朝向光,则很可能只希望具有镜面反射分量。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

OpenGL Phong照明:镜面反射高光错误

来自分类Dev

OpenGL网站中的Phong照明

来自分类Dev

使用Phong方法照明不良

来自分类Dev

OpenGL网站中的Phong照明

来自分类Dev

OpenGL:在着色器中实现的 Blinn-Phong 模型给出错误的结果

来自分类Dev

顶点着色器中的Phong照明

来自分类Dev

Phong阴影/插值与Phong照明模型之间的区别是什么?

来自分类Dev

HLSL和D3D11的Blinn-Phong阴影:点光源

来自分类Dev

RealityKit –如何编辑或添加照明?

来自分类Dev

如何使用phong阴影实现凹凸贴图

来自分类Dev

OpenGL照明照亮了错误的表面

来自分类Dev

平行表面上的漫射照明错误

来自分类Dev

如何参与照明事件Laravel 5.3

来自分类Dev

法线贴图和照明出现错误,无法正确显示

来自分类Dev

如何在opencv python中更改图像照明

来自分类Dev

如何在不同的照明条件下检测颜色

来自分类Dev

如何在Three.js中使用延迟照明

来自分类Dev

OpenGL:我如何影响纹理平面上的照明?

来自分类Dev

如何访问并可能修改子照明元素组件的属性?

来自分类Dev

如何在OpenGL中使2D照明更好

来自分类Dev

如何从移动物体获取照明的坐标?WebGL

来自分类Dev

如何将谷歌地图添加到照明元素?

来自分类Dev

如何在 WebGl 中使用漫射照明进行 Gouraud 着色?

来自分类Dev

如何修复语言错误

来自分类Dev

如何修复distcc错误

来自分类Dev

如何修复NullPointerException错误?

来自分类Dev

如何修复此段错误?

来自分类Dev

如何修复语言错误

来自分类Dev

如何修复NullPointerException错误