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

編集:
ティムは正しいです。これ

if(angle > radians(spotCutoff))

次のようにする必要があります。

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

新しい質問:
ライトはシーン内の固定位置にとどまらないように見えます。代わりに、前方または後方に移動するときにコーンが小さくまたは大きくなるにつれて、カメラに対して相対的に移動するように見えます。

4

4 に答える 4

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

于 2012-05-17T03:24:07.347 に答える
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;

Anglesをシェーダーに送信する代わりに、それらのAnglesのCosを送信することをお勧めします

于 2012-05-17T10:38:03.320 に答える
1

新しい質問に答えるために、同様の質問へのリンクを次に示します: GLSL point light shader moving with camera . 解決策は、gl_NormalMatrix と gl_ModelViewMatrix を削除することです。

spotDirection  = normalize(spotDirectionOC * gl_NormalMatrix);

次のようになります。

spotDirection  = normalize(spotDirectionOC);
于 2015-06-19T06:25:21.523 に答える
0

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]);
于 2015-02-11T17:53:14.607 に答える