【问题标题】:opengl - spot light moves when camera rotates when using a shaderopengl - 使用着色器时相机旋转时聚光灯移动
【发布时间】:2016-08-06 16:25:38
【问题描述】:

我为照明实现了一个简单的着色器;它有点工作,但是当相机旋转时(并且仅在它旋转时),灯光似乎会移动。

我正在尝试使用聚光灯,它的外观是这样的(它是中心的位置):

如果现在我旋转相机,光点会四处移动;例如,在这里我往下看(我根本没有动,只是往下看),它似乎在我的脚下:

我查了一下,发现在着色器中混合参考系统和/或在移动相机之前设置灯光位置时,这是一个常见错误。

问题是,我很确定我没有做这两件事,但显然我错了;就是找不到bug。

这是着色器:

顶点着色器

varying vec3 vertexNormal;
varying vec3 lightDirection;

void main()
{
    vertexNormal = gl_NormalMatrix * gl_Normal;

    lightDirection = vec3(gl_LightSource[0].position.xyz - (gl_ModelViewMatrix * gl_Vertex).xyz);

    gl_Position = ftransform();
}

片段着色器

uniform vec3 ambient;
uniform vec3 diffuse;
uniform vec3 specular;
uniform float shininess;

varying vec3 vertexNormal;
varying vec3 lightDirection;

void main()
{
    vec3 color = vec3(0.0, 0.0, 0.0);

    vec3 lightDirNorm;
    vec3 eyeVector;
    vec3 half_vector;
    float diffuseFactor;
    float specularFactor;
    float attenuation;
    float lightDistance;

    vec3 normalDirection = normalize(vertexNormal);

    lightDirNorm = normalize(lightDirection);

    eyeVector = vec3(0.0, 0.0, 1.0);
    half_vector = normalize(lightDirNorm + eyeVector);

    diffuseFactor = max(0.0, dot(normalDirection, lightDirNorm));

    specularFactor = max(0.0, dot(normalDirection, half_vector));
    specularFactor = pow(specularFactor, shininess);

    color += ambient * gl_LightSource[0].ambient;
    color += diffuseFactor * diffuse * gl_LightSource[0].diffuse;
    color += specularFactor * specular * gl_LightSource[0].specular;

    lightDistance = length(lightDirection[i]);

    float constantAttenuation = 1.0;
    float linearAttenuation = (0.02 / SCALE_FACTOR) * lightDistance;
    float quadraticAttenuation = (0.0 / SCALE_FACTOR) * lightDistance * lightDistance;

    attenuation = 1.0 / (constantAttenuation + linearAttenuation + quadraticAttenuation);

    // If it's a spotlight
    if(gl_LightSource[i].spotCutoff <= 90.0) 
    {
        float spotEffect = dot(normalize(gl_LightSource[0].spotDirection), normalize(-lightDirection));
        if (spotEffect > gl_LightSource[0].spotCosCutoff) 
        {
            spotEffect = pow(spotEffect, gl_LightSource[0].spotExponent);

            attenuation = spotEffect / (constantAttenuation + linearAttenuation + quadraticAttenuation);
        }
        else
            attenuation = 0.0;
    }

    color = color * attenuation;

    // Moltiplico il colore per il fattore di attenuazione
    gl_FragColor = vec4(color, 1.0);
}

现在,我无法向您展示我渲染这些东西的代码,因为它是一种集成了 opengl 的自定义语言,它旨在创建 3D 应用程序(它不会帮助您展示);但我所做的是这样的:

SetupLights();
UpdateCamera();
RenderStuff();

地点:

  • SetupLights 包含设置灯光及其位置的实际 opengl 调用;
  • UpdateCamera 使用语言的内置类更新相机的位置;我这里的权力不大;
  • RenderStuff 调用语言的内置函数来绘制场景;我这里也没有多少权力。

所以,要么是我在着色器中做错了什么,要么是语言中的某些东西“在幕后”破坏了一些东西。

你能指出我正确的方向吗?

【问题讨论】:

    标签: opengl glsl shader light


    【解决方案1】:

    你写的

    灯光的位置已经在世界坐标中,这就是我进行计算的地方

    但是,由于您将 gl_ModelViewMatrix 应用于您的顶点并将 gl_NormalMatrix 应用于您的法线,这些值可能在视图空间中,这可能会导致移动光。

    顺便说一句,您的眼睛矢量看起来应该在视图坐标中,但是,视图空间是右手坐标系,因此“向前”指向负 z 轴。此外,您的镜面反射计算可能会关闭,因为您对所有片段使用相同的眼睛矢量,但它可能应该指向该片段在近/远平面上的位置。

    【讨论】:

    • 我的错误,灯光的位置在着色器的视图空间中。我认为您对其他事情的看法是正确的,但仍然找不到真正的问题。
    • 如果您的灯光位置在视图空间中,则您必须在相机更改时更新它。您在UpdateCamera() 之前的SetupLights() 序列似乎在概念上是错误的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-25
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多