2012-07-11 152 views
0

如何讓該着色器在聚光燈上具有光滑邊緣而不是硬光線?另外,着色器必須處理GL_SPOT_CUTOFF的變量值。請注意,並非所有燈都是聚光燈--GL_LIGHT0是一盞點燈。着眼於聚光燈

varying vec3 N; 
varying vec3 v; 
#define MAX_LIGHTS 2 
void main (void) 
{ 
    vec4 finalColour; 
    float spotEffect; 

    for (int i=0; i<MAX_LIGHTS; i++) 
    { 
     vec3 L = normalize(gl_LightSource[i].position.xyz - v); 
     vec3 E = normalize(-v); 
     vec3 R = normalize(-reflect(L,N)); 

     spotEffect = dot(normalize(gl_LightSource[i].spotDirection), 
         normalize(-L)); 
     if (spotEffect > gl_LightSource[i].spotCosCutoff) { 
      vec4 Iamb = gl_FrontLightProduct[i].ambient;  
      vec4 Idiff = gl_FrontLightProduct[i].diffuse * max(dot(N,L), 0.0); 
      Idiff = clamp(Idiff, 0.0, 1.0);  
      vec4 Ispec = gl_FrontLightProduct[i].specular 
         * pow(max(dot(R,E),0.0),0.3*gl_FrontMaterial.shininess); 
      Ispec = clamp(Ispec, 0.0, 1.0); 
      finalColour += Iamb + Idiff + Ispec; 
     } 
    } 
    gl_FragColor = gl_FrontLightModelProduct.sceneColor + finalColour; 

}

場景是這樣的:

enter image description here

+0

您是否在談論衰減,其中光線的強度隨着距離中心越遠而減弱?如果是這樣,那麼這看起來像一個很好的教程:http://www.ozone3d.net/tutorials/glsl_lighting_phong_p4.php – beaker 2012-07-11 17:00:31

回答

3

這個shader從http://www.ozone3d.net/tutorials/glsl_lighting_phong_p3.php生產軟邊你之後的焦點。

[Pixel_Shader] 

varying vec3 normal, lightDir, eyeVec; 

const float cos_outer_cone_angle = 0.8; // 36 degrees 

void main (void) 
{ 
    vec4 final_color = 
    (gl_FrontLightModelProduct.sceneColor * gl_FrontMaterial.ambient) + 
    (gl_LightSource[0].ambient * gl_FrontMaterial.ambient); 

    vec3 L = normalize(lightDir); 
    vec3 D = normalize(gl_LightSource[0].spotDirection); 

    float cos_cur_angle = dot(-L, D); 

    float cos_inner_cone_angle = gl_LightSource[0].spotCosCutoff; 

    float cos_inner_minus_outer_angle = 
      cos_inner_cone_angle - cos_outer_cone_angle; 

    //**************************************************** 
    // Don't need dynamic branching at all, precompute 
    // falloff(i will call it spot) 
    float spot = 0.0; 
    spot = clamp((cos_cur_angle - cos_outer_cone_angle)/
      cos_inner_minus_outer_angle, 0.0, 1.0); 
    //**************************************************** 

    vec3 N = normalize(normal); 

    float lambertTerm = max(dot(N,L), 0.0); 
    if(lambertTerm > 0.0) 
    { 
     final_color += gl_LightSource[0].diffuse * 
      gl_FrontMaterial.diffuse * 
      lambertTerm * spot; 

     vec3 E = normalize(eyeVec); 
     vec3 R = reflect(-L, N); 

     float specular = pow(max(dot(R, E), 0.0), 
      gl_FrontMaterial.shininess); 

     final_color += gl_LightSource[0].specular * 
      gl_FrontMaterial.specular * 
      specular * spot; 
    } 
    gl_FragColor = final_color; 
+0

可悲的是,這不適應變量GL_SPOT_CUTOFF變量。問題已更新。 – Sardathrion 2012-07-12 09:45:57

+0

我不確定你的意思。上面的着色器允許你設置外錐角,這是聚光燈的邊緣,內錐角是聚光燈完全照亮部分的邊緣,由gl_LightSource [0] .spotCosCutoff派生。這意味着着色器負責處理GL_SPOT_CUTOFF值爲 – StuGrey 2012-07-14 14:57:19

+0

的所有內容,我嘗試了它,它僅適用於小GL_SPOT_CUTOFF。如果該天使變得太大(> 60),則着色器反轉:只有外部亮起。 – Sardathrion 2012-07-15 13:00:12