0

ターゲットスポットライトを実装しています。ライトコーン、フォールオフ、その他すべてがダウンしており、正常に動作しています。問題は、カメラを空間のある点で回転させると、照明がそれに追従しているように見えることです。つまり、カメラがどこにあるかに関係なく、光は常にカメラに対して同じ角度になります。

頂点シェーダーで行っていることは次のとおりです。

void main()
{
    // Compute vertex normal in eye space.

    attrib_Fragment_Normal = (Model_ViewModelSpaceInverseTranspose * vec4(attrib_Normal, 0.0)).xyz;

    // Compute position in eye space.

    vec4 position = Model_ViewModelSpace * vec4(attrib_Position, 1.0);

    // Compute vector between light and vertex.

    attrib_Fragment_Light = Light_Position - position.xyz;

    // Compute spot-light cone direction vector.

    attrib_Fragment_Light_Direction = normalize(Light_LookAt - Light_Position);

    // Compute vector from eye to vertex.

    attrib_Fragment_Eye = -position.xyz;

    // Output texture coord.

    attrib_Fragment_Texture = attrib_Texture;

    // Return position.

    gl_Position = Camera_Projection * position;
}

Light_Position と Light_LookAt で定義されたターゲット スポットライトがあります (look-at はもちろん、スポットライトが見ている空間内のポイントです)。position と lookAt の両方が既に目の空間にあります。両方からカメラの位置を差し引いて、CPU 側のアイ スペースを計算しました。

次に、頂点シェーダーで、ライトの位置からライトの lookAt ポイントまでのライト コーン ベクターを作成します。これにより、ライト コーンの主軸がどこにあるかがピクセル シェーダーに通知されます。

この時点で、ベクトルも変換する必要があるかどうか疑問に思っています。ビューマトリックスの逆転置を試みましたが、うまくいきませんでした。

誰かが私をこれに連れて行くことができますか?

完全を期すために、ピクセル シェーダーを次に示します。

void main(void)
{   
    // Compute N dot L.

    vec3 N = normalize(attrib_Fragment_Normal);
    vec3 L = normalize(attrib_Fragment_Light);  
    vec3 E = normalize(attrib_Fragment_Eye);
    vec3 H = normalize(L + E);

    float NdotL = clamp(dot(L,N), 0.0, 1.0);
    float NdotH = clamp(dot(N,H), 0.0, 1.0);

    // Compute ambient term.

    vec4 ambient = Material_Ambient_Colour * Light_Ambient_Colour;

    // Diffuse.

    vec4 diffuse = texture2D(Map_Diffuse, attrib_Fragment_Texture) * Light_Diffuse_Colour * Material_Diffuse_Colour * NdotL;

    // Specular.

    float specularIntensity = pow(NdotH, Material_Shininess) * Material_Strength;

    vec4 specular = Light_Specular_Colour * Material_Specular_Colour * specularIntensity;

    // Light attenuation (so we don't have to use 1 - x, we step between Max and Min).

    float d = length(-attrib_Fragment_Light);

    float attenuation = smoothstep( Light_Attenuation_Max, 
                                    Light_Attenuation_Min, 
                                    d);

    // Adjust attenuation based on light cone.

    vec3 S = normalize(attrib_Fragment_Light_Direction);

    float LdotS = dot(-L, S);
    float CosI = Light_Cone_Min - Light_Cone_Max;

    attenuation *= clamp((LdotS - Light_Cone_Max) / CosI, 0.0, 1.0);

    // Final colour.

    Out_Colour = (ambient + diffuse + specular) * Light_Intensity * attenuation;    
}

以下の回答に感謝します。私はまだこれを解決できません。私は今、光を目の空間の CPU 側に変換しています。したがって、光の変換は必要ありませんが、それでも機能しません。

// Compute eye-space light position.

Math::Vector3d eyeSpacePosition = MyCamera->ViewMatrix() * MyLightPosition;

MyShaderVariables->Set(MyLightPositionIndex, eyeSpacePosition);



// Compute eye-space light direction vector.

Math::Vector3d eyeSpaceDirection = Math::Unit(MyLightLookAt - MyLightPosition);

MyCamera->ViewMatrixInverseTranspose().TransformNormal(eyeSpaceDirection);

MyShaderVariables->Set(MyLightDirectionIndex, eyeSpaceDirection);

...そして、頂点シェーダーでは、これを行っています (以下)。私が見る限り、光は目の空間にあり、頂点は目の空間に変換され、照明ベクトル (attrib_Fragment_Light) は目の空間にあります。それでもベクトルは変わらない。少し太くてすみません!

// Transform normal from model space, through world space and into eye space (world * view * normal = eye).

attrib_Fragment_Normal = (Model_WorldViewInverseTranspose * vec4(attrib_Normal, 0.0)).xyz;

// Transform vertex into eye space (world * view * vertex = eye)

vec4 position = Model_WorldView * vec4(attrib_Position, 1.0);

// Compute vector from eye space vertex to light (which has already been put into eye space).

attrib_Fragment_Light = Light_Position - position.xyz;

// Compute vector from the vertex to the eye (which is now at the origin).

attrib_Fragment_Eye = -position.xyz;

// Output texture coord.

attrib_Fragment_Texture = attrib_Texture;
4

2 に答える 2

1

ここでは、目の空間のベクトルであるから、を減算しているように見えます。Light_Positionこれは、世界空間の座標になりたいと思います(現在、目の空間にあることに失望しているように見えるため) 。position

// Compute vector between light and vertex.
attrib_Fragment_Light = Light_Position - position.xyz;

2つのベクトルを減算する場合は、両方が同じ座標空間にある必要があります。ワールドスペースで照明の計算を行う場合は、ビュースペースの位置ベクトルではなく、ワールドスペースの位置ベクトルを使用する必要があります。

これは、attrib_Position変数にModelView行列ではなく、Model行列を乗算し、このベクトルを光の計算の基礎として使用することを意味します。

于 2012-12-10T15:29:10.267 に答える
1

カメラの位置を差し引くだけでは目の位置を計算することはできません。モデルビューの行列を掛ける必要があります。

于 2012-12-10T13:55:11.823 に答える