简单的GLSL聚光灯着色器

4
我可以帮助您进行简单的聚光灯着色器翻译。 锥体内的所有顶点应该被染成黄色,锥体外的所有顶点应该被染成黑色。 我无法让它工作。我认为这与从世界坐标系到视角坐标系的转换有关。
顶点着色器:
uniform vec4  lightPositionOC;   // in object coordinates
uniform vec3  spotDirectionOC;   // in object coordinates
uniform float spotCutoff;        // in degrees

void main(void)
{
   vec3 lightPosition;
   vec3 spotDirection;
   vec3 lightDirection;
   float angle;

    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

    // Transforms light position and direction into eye coordinates
    lightPosition  = (lightPositionOC * gl_ModelViewMatrix).xyz;
    spotDirection  = normalize(spotDirectionOC * gl_NormalMatrix);

    // Calculates the light vector (vector from light position to vertex)
    vec4 vertex = gl_ModelViewMatrix * gl_Vertex;
    lightDirection = normalize(vertex.xyz - lightPosition.xyz);

    // Calculates the angle between the spot light direction vector and the light vector
    angle = dot( normalize(spotDirection),
                -normalize(lightDirection));
    angle = max(angle,0);   

   // Test whether vertex is located in the cone
   if(angle > radians(spotCutoff))
       gl_FrontColor = vec4(1,1,0,1); // lit (yellow)
   else
       gl_FrontColor = vec4(0,0,0,1); // unlit(black)   
}

片元着色器:

void main(void)
{
   gl_FragColor = gl_Color;
}

编辑:
Tim 是正确的。这个

if(angle > radians(spotCutoff))

应该是:

if(acos(angle) < radians(spotCutoff))

新问题:
光似乎不停留在场景的固定位置,相反,当我向前或向后移动时,它似乎随着圆锥体的变小或变大而相对于我的相机移动。


您的#version指令在哪里? - genpfault
不设置gl_FrontColor,我只需将颜色值作为“varying”传递到片段着色器中。然而,当我编写针对GLSL 1.20的代码时,通常只是为了向后兼容GLSL 3.30+着色器,并且我以相同的方式处理事情。我仍然认为它与gl_FrontColor有关,可以看看这个问题:https://dev59.com/Lmw15IYBdhLWcg3wu-M9 - Robert Rouhani
4个回答

5

谢谢您的努力!您能帮我回答我的第二个问题吗? - Basti
2
@Basti 为了以后的参考,如果您有另一个问题,应该考虑发布一个单独的问题。这个问题已经标记为已解决,很可能不会引起人们对您帖子底部的编辑的注意。话虽如此,我没有足够的信息来知道答案。如果您真的在对象坐标中定义了光源位置,并且没有移动对象,那么我不会期望看到光照的变化,因此可能存在一些未显示的错误。尝试发布一个新帖子,并附上描述您问题的图像链接。 - Tim

1
为了回答你的新问题,这里有一个类似问题的链接:GLSL点光源着色器随相机移动。解决方案是删除gl_NormalMatrix和gl_ModelViewMatrix。
spotDirection  = normalize(spotDirectionOC * gl_NormalMatrix);

会变成:

spotDirection  = normalize(spotDirectionOC);

1

在我的旧着色器中,我使用了这段代码:

float spotEffect = dot(normalize(gl_LightSource[0].spotDirection.xyz), 
                       normalize(-light));
if (spotEffect < gl_LightSource[0].spotCosCutoff) 
{
    spotEffect = smoothstep(gl_LightSource[0].spotCosCutoff-0.002,     
                            gl_LightSource[0].spotCosCutoff, spotEffect);
}
else spotEffect = 1.0;

与其将角度发送到着色器,不如发送这些角度的余弦值更好。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接