0

私はシェーダー プログラムに取り組んでいますが、最も奇妙なことが起こっています。私は PositionLightPS と呼ばれるメソッドを持っています。これは基本的に位置ライト (オムニ ライトとスポット ライト) の計算を実行し、ライトの強度と拡散色の両方を含む構造体を返します。

以前のバージョンのプログラムでは動作していましたが、何らかの理由で動作しなくなりました...

理由を説明しましょう。まず、PositionPS メソッドのコードを示します。この方法の計算が正しいことに疑いの余地はありませんが、それについては後で詳しく説明します。

struct LightFragment {
    float4 diffuse;
    float intensity;
};

LightFragment PositionLightPS(PositionLightVOut pin, float3 lightToPixelVec)
{
    LightFragment result;

    pin.normal = normalize(pin.normal);

    float4 diffuse = shaderTexture.Sample( textureSampler, pin.tex0 );
    float3 finalDiffuse = float3(0.0f, 0.0f, 0.0f);

    float d = length(lightToPixelVec);
    if( d > plRange )
    {
        result.diffuse = float4(finalDiffuse, 0);
        result.intensity = 0; 
        return result;
    }

    lightToPixelVec /= d; 

    result.intensity = dot(lightToPixelVec, pin.normal);

    if( result.intensity > 0.0f )
    {   
        finalDiffuse = result.intensity * diffuse.xyz;
        finalDiffuse.xyz *= clColour.xyz;
        finalDiffuse.xyz *= clColour.w;

        finalDiffuse /= plAttenuation[0] + (plAttenuation[1] * d) + (plAttenuation[2] * (d*d));
    }   

    result.diffuse = float4(finalDiffuse, diffuse.a) * diffuseColour;
    return result;
}

これがオムニ ライト ピクセル シェーダです。

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    return = PositionLightPS(pin, lightToPixelVec).diffuse;
}

長い間そうでしたが、何らかの理由でこれが機能しません。しかし、これは私の質問の焦点では​​ありません。明らかに奇妙なのは、これら 2 つの方法で異なる結果が得られることです。

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    //return float4(1,1,1,1);
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec);
    return float4(1,1,1,1);
}

これは黒いピクセルを返します

float4 OmniLightDiffusePS(PositionLightVOut pin) : SV_TARGET0
{
    return float4(1,1,1,1);
    float3 lightToPixelVec = plPosition.xyz - pin.worldPos.xyz;
    LightFragment fragment = PositionLightPS(pin, lightToPixelVec);
    //return float4(1,1,1,1);
}

これは白いピクセルを返します

これは、PositionLightPS メソッドを呼び出すと、返される値に影響があることを意味します...しかし、なぜでしょうか? なぜでしょうか?何が起こっている?メモリエラーですか?

(注: OmniLightDiffuse メソッドに直接 PositionLightPS メソッド コードをコピーすると、問題が解決し、ライトが正常に表示されます。これは、PositionLightPS で実行された計算が正しいことを意味します。問題は、LightFragment 構造体を使用すると、シェーダー プログラムに影響があるかどうかです。どういうわけか?)

4

3 に答える 3

2

問題の原因がわかりました。私のコンピューターは CUDA を使用しており、知らないうちに統合グラフィックス チップを使用するようにロックされています。NVidia カードを強制すると問題が解決しました。

ただし、本質的に私の問題が何であるかを詳しく説明しているこの非常に役立つブログ投稿を見つけました。2 つの特定のコンパイラ フラグが同時にアクティブな場合、ユーザー定義関数を呼び出すと、コンパイラによるインライン化により、処理するピクセルが削除されます。統合グラフィックス チップがこのエラーを正確に再現したかどうかはわかりませんが、症状は完全に対応しているように見えました (つまり、戻り値に関係なく関数を呼び出すと、返されるものが変わります)。

詳細については、Nico Shertler によるブログ投稿へのリンクを次に示します。 /

于 2012-12-07T20:40:33.213 に答える
1

Typically, this is due to a divide-by-zero error. ATI and NVIDIA may differ in their handling of this NaN. Check the length of your input vector, or add some epsilon.

于 2012-12-07T02:06:46.983 に答える