OpenGL中的镜面光不稳定

Posted

技术标签:

【中文标题】OpenGL中的镜面光不稳定【英文标题】:Specular light erratic in OpenGL 【发布时间】:2021-02-10 17:04:39 【问题描述】:

我正在开发一个片段着色器应该在切线空间中工作的着色器。它对环境光和漫射光都按预期工作,但镜面光很奇怪。似乎附近的碎片在没有明显原因的情况下可能有很多光或没有光。

顶点着色器是:

#version 330 core
layout (location = 0) in vec3 inVertex;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inTexture;
layout (location = 3) in vec3 inTangent;
layout (location = 4) in vec3 inBitangent;

out vec3 FragmentPosition;
out vec2 TextureCoordinate;
out vec3 TangentLightDirection;
out vec3 TangentViewPosition;
out vec3 TangentFragmentPosition;


void main()

    FragmentPosition = vec3(inVertex);
    vec3 normal = normalize(inNormal);
    gl_Position = vec4( inVertex, 1 );
    TextureCoordinate = inTexture;

    vec3 tangent = normalize(inTangent);
    vec3 biTangent = normalize(inBitangent);

    mat3 toTangentSpaceTransformation = transpose(mat3(tangent,biTangent,normal));
    TangentFragmentPosition = toTangentSpaceTransformation * FragmentPosition;
    TangentLightPosition = toTangentSpaceTransformation * vec3(0,1,1);
    TangentFragmentPosition = toTangentSpaceTransformation * vec3(0,0,3);

片段着色器是:

#version 330 core
out vec4 FragColor;

in vec3 FragmentPosition;
in vec2 TextureCoordinate;
in vec3 TangentLightDirection;
in vec3 TangentViewPosition;
in vec3 TangentFragmentPosition;

uniform sampler2D Texture;
uniform sampler2D normalTexture;


void main() 
    vec3 normal = vec3(0,0,1);

    float shininess = 4;
    vec3 phongVector = vec3(0.3,0.7,1);
    vec4 color = texture(Texture,TextureCoordinate);
    vec4 ambientLightColor = vec4(1,1,1,1);//vec4(normalOffset,1);

    // Calculation of ambient light
    vec4 sunLightColor = vec4(1,1,1,1);
    vec3 sunLightDirection = normalize(TangentLightPosition);
    vec4 ambientLight = phongVector[0] * ambientLightColor;

    // Calculation of diffuse light
    float diffuseConst = max(dot(normal,sunLightDirection),0.0);
    vec4 diffuseLight = phongVector[1] * diffuseConst * sunLightColor;

    // Calculation of specular light
    vec3 viewDirection = normalize(TangentViewPosition - TangentFragmentPosition);
    vec3 reflectionDirection = reflect(-sunLightDirection,normal);
    float spec = pow(max(dot(reflectionDirection,viewDirection),0),shininess);
    vec4 specularLight = phongVector[2] * spec * sunLightColor;

    FragColor = (specularLight)*color;

【问题讨论】:

您不应该将切线和双切线值作为顶点属性传递。将位置、法线和纹理值发送到您的顶点着色器,并将一个统一的相机位置发送到您的片段着色器,然后计算反射和片段中的所有其他内容。这样一来,插值就不会产生任何伪影。 这些不是插值工件......这看起来像使用未初始化的变量。调试此问题的一个好方法是逐个渲染失败方程中使用的每个单独的术语,以检查值是否符合您的预期。很可能是您没有正确设置切线和双切线的属性指针。 【参考方案1】:

这是一个错字。 tangentFragmentPosition 被初始化了两次,而 tangentViewPosition 根本没有被初始化。初始化 tangentViewPosition 得到了预期的结果。

【讨论】:

以上是关于OpenGL中的镜面光不稳定的主要内容,如果未能解决你的问题,请参考以下文章

过多的镜面光opengl

镜面高光故障 OpenGL

OpenGL 光照变化:环境到漫反射或镜面反射有效,但不是相反

GLM 不断提供不稳定的转换和旋转

OpenGL编程 基础篇OpenGL中几种光照参数

directx和opengl哪个好?