2012-05-17 80 views
4

我需要一个简单聚光灯着色器的帮助。 锥体内的所有顶点都应为黄色,锥体外的所有顶点应为黑色。 我只是不能得到它的工作。我认为它与从世界到眼坐标的转变有关。简单GLSL聚光灯着色器

顶点着色器:

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)) 

新问题:
的光似乎并没有留在现场的固定位置,而似乎是相对于移动当我向前或向后移动时,作为锥体的相机变得更小或更大。

+0

哪里是你的'#version'指令? – genpfault

+0

而不是设置gl_FrontColor我只是将一个颜色值作为变量传递给片段着色器。再次,当我写GLSL 1.20时,通常只是为了向后兼容GLSL 3.30+着色器,并且我以同样的方式做事。我仍然认为它与gl_FrontColor有关,但看看这个问题:http://stackoverflow.com/questions/6430154/what-is-the-relationship-between-gl-color-and-gl-frontcolor-in-both -vertex-and -f –

回答

5

(让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

+0

谢谢你的努力!你能帮我解答我的第二个问题吗? – Basti

+2

@Basti为了将来的参考,如果你有其他问题,你应该考虑发布一个单独的问题。这个问题被标记为已解决,并且很可能不会引起您在帖子底部的修改。话虽如此,我没有足够的信息来知道答案。如果你真的在对象坐标中定义光照位置,而不是移动对象,那么我不希望看到光照有变化,所以可能有错误的地方没有在上面显示。尝试制作一个新帖子,其中包含指向描述问题的图片的链接 – Tim

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; 

而不是发送角度着色器最好是发送这些角度

1

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

spotDirection = normalize(spotDirectionOC * gl_NormalMatrix); 

将成为:

spotDirection = normalize(spotDirectionOC);