【问题标题】:Simple GLSL Spotlight Shader简单的 GLSL 聚光灯着色器
【发布时间】:2015-06-19 14:25:21
【问题描述】:

我需要一个简单的聚光灯着色器方面的帮助。 圆锥内的所有顶点都应该涂成黄色,圆锥外的所有顶点都应该涂成黑色。 我只是无法让它工作。我认为这与从世界到眼睛坐标的转换有关。

顶点着色器:

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;
}

编辑:
蒂姆是对的。这个

if(angle > radians(spotCutoff))

应该是:

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

新问题:
灯光似乎没有停留在场景中的固定位置,而是随着锥体变小或变大而相对于我的相机移动我向前或向后移动。

【问题讨论】:

  • 你的#version指令在哪里?
  • 我不会设置 gl_FrontColor,而是将颜色值作为varying 传递给片段着色器。再说一次,当我针对 GLSL 1.20 编写代码时,通常只是为了向后兼容 GLSL 3.30+ 着色器,我以同样的方式做事。我仍然认为它与 gl_FrontColor 相关,请看另一个问题:stackoverflow.com/questions/6430154/…

标签: opengl graphics glsl shader


【解决方案1】:

(设 spotDirection 为向量 A,lightDirection 为向量 B)

您正在分配;

angle = dot(A,B)

公式不应该是:

cos(angle) = dot(A,B)

angle = arccos(dot(A,B))

http://en.wikipedia.org/wiki/Dot_product#Geometric_interpretation

【讨论】:

  • 感谢您的努力!你能帮我解决我的第二个问题吗?
  • @Basti 为了将来参考,如果您有其他问题,您应该考虑发布一个单独的问题。此问题已标记为已解决,并且可能很少会引起您帖子底部的编辑的注意。话虽如此,我没有足够的信息来知道答案。如果你真的在对象坐标中定义你的光照位置,而不是移动对象,那么我不希望看到光照发生变化,所以上面可能没有显示出一些错误。尝试使用描述您的问题的图片链接发布新帖子。
【解决方案2】:

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

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;

与其将角度发送到着色器,不如发送这些角度的 Cos

【讨论】:

    【解决方案3】:

    要回答您的新问题,这里有一个类似问题的链接:GLSL point light shader moving with camera。 解决办法是去掉gl_NormalMatrix和gl_ModelViewMatrix。

    spotDirection  = normalize(spotDirectionOC * gl_NormalMatrix);
    

    会变成:

    spotDirection  = normalize(spotDirectionOC);
    

    【讨论】:

      【解决方案4】:

      https://code.google.com/p/jpcsp/source/browse/trunk/src/jpcsp/graphics/shader.vert?r=1639

      if (spotEffect >= cos(radians(uLightOuterCone[index])))
      

      //vec3 NSpotDir  = (uViewMatrix * vec4(uLightDirection[index],0)).xyz; //must do outside or become flashlight follow
          vec3 NSpotDir = normalize(uLightDirection[index]);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-05
        • 2011-08-31
        • 2012-04-04
        • 1970-01-01
        相关资源
        最近更新 更多