0

ピクセル シェーダーを作成しようとしています。Texture.Sample が使用されていないループ構成で使用できるので、Texture.SampleCmpLevelZero を使用したいと思います。

テクスチャを構築し、Texture.Sample で正常にサンプリングできますが、SampleCmpLevelZero への切り替えは最初の数フレームで機能し、その後空白になり、まれに断続的に正しくレンダリングされます。

私のシーンは静的です (テクスチャ データも) - 1 つのクワッドをレンダリングしていますが、カメラの動きは一切ありません - PS シェーダー関数の 1 行を変更するだけで、これを確実に再現できます。

誰もこれを見たことがありますか?

ありがとう

SamplerState sampPointClamp
{
    Filter = MIN_MAG_MIP_POINT;
    AddressU = Clamp;
    AddressV = Clamp;
};

SamplerComparisonState ShadowSampler
{
   // sampler state
   Filter = MIN_MAG_MIP_POINT;
   AddressU = Clamp;
   AddressV = Clamp;

   // sampler comparison state
   ComparisonFunc = LESS;
   //ComparisonFilter = COMPARISON_MIN_MAG_MIP_POINT;
};

texture2D tex;

//on the fly full screen quad
PS_IN VS(uint id : SV_VertexID)
{
    PS_IN ret;
    ret.uv = float2( id & 1, (id & 2) >> 1 );
    ret.pos = float4( ret.uv * float2( 2.0f, -2.0f ) + float2( -1.0f, 1.0f), 0.0f, 1.0f );
    return ret;
}

float4 PS( PS_IN input ) : SV_Target
{
    //return float4(tex.SampleCmpLevelZero(ShadowSampler, input.uv, 0), 0, 0, 1); // Does not work properly
    return float4(tex.Sample(sampPointClamp, input.uv).x, 0, 0, 1); // Works fine
}
4

2 に答える 2

3

サンプルはループで問題なく動作するはずです。

float4 PSColUV(COLUV_PIXEL input) : SV_Target
{
    float4 output;
    for (int i = 0; i < 4; i++)
    {
        float f = float(i) / 256.0;
        float2 uv = input.UV + float2(i,i);

        output += g_txDiffuse.Sample(g_samLinear, uv);
    }
    return input.Col * output/4.0;
}

生成:

      ps_4_0
      dcl_sampler s0, mode_default
      dcl_resource_texture2d (float,float,float,float) t0
      dcl_input_ps linear v1.xyzw
      dcl_input_ps linear v2.xy
      dcl_output o0.xyzw
      dcl_temps 3
   0: mov r0.xyzw, l(0,0,0,0)
   1: mov r1.x, l(0)
   2: loop
   3:   ige r1.y, r1.x, l(4)
   4:   breakc_nz r1.y
   5:   itof r1.y, r1.x
   6:   add r1.yz, r1.yyyy, v2.xxyx
   7:   sample r2.xyzw, r1.yzyy, t0.xyzw, s0
   8:   add r0.xyzw, r0.xyzw, r2.xyzw
   9:   iadd r1.x, r1.x, l(1)
  10: endloop
  11: mul r0.xyzw, r0.xyzw, v1.xyzw
  12: mul o0.xyzw, r0.xyzw, l(0.250000, 0.250000, 0.250000, 0.250000)
  13: ret

また、通常のテクスチャサンプルではなくPCFルックアップを実行していること、およびこれではテクスチャ内のデータが得られないことを認識していますが、すべてのテクセルサブサンプル(たとえば、バイリニアの8)を比較します。参照値(0)を使用して、参照値に対してLESSまたはGREATEREQUALのどちらであるかに応じて、0または1を計算し、これらのブール値を0から1までの数値にフィルター処理します。

コメントへの返信:

ありがとう-サンプルは、可変長またはコンパイル時(?)で不明な長さのループに入ることができないと思います。私が得たエラーは、「エラーX4014:ループ内で発散勾配演算を行うことはできませんエラー:式のコンパイル中にエラーが発生しました」でした。他の点では-正確なサンプルが必要です-それが私が得ているものだと思いました-値のテーブルとしてテクスチャバッファを使用して手続き型テクスチャ生成を実行し、真のテクセル値を計算できるようにしようとしています(u、v)などに基づく。– AnonDev

http://msdn.microsoft.com/en-gb/library/windows/desktop/bb219848%28v=vs.85%29.aspx 「ピクセルごとのフロー制御と画面のグラデーションの相互作用」

ピクセルは(少なくとも)2x2ブロックで実行されることに注意してください。一部のピクセルをサンプリングし、他のピクセルをサンプリングしない制御フローを設定することはできません。また、制御フロー内で、サンプル操作で異なるグラデーションを取得する計算を行うこともできません。

(まあ、できますが、そのためにはSampleGradを使用する必要があります。しかし!この場合、それはあなたが望むものではありません。)

あなたは「正確な」サンプルと言います。リソースにミップマップが1つしかないため、フィルタリングせずにリソース内の各テクセルを取得したいということですか?(つまり、ポイントフィルターを実行していましたか?)テクスチャが値のテーブルであるという説明を考えると、テクスチャをmipchainにする必要がある理由がわかりません。また、トップレベルにのみ有用な情報が含まれています。この場合、LODが0のSampleLevel()を使用できます。これは、サンプルopが​​導関数を使用していないため、導関数に発散がないことを意味します。

これは、SampleCmpLevelZeroが機能するのと同じ理由ですが、SampleCmpは機能しません:)ポイントサンプリングの場合、別の適切な候補はLoad()です。これは、バッファーで使用できるように正確なテクセル位置を指定するためです。したがって、テクスチャのルックアップ位置がたとえばピクセル(X、Y)に基づいている場合は、これらを直接Loadに渡すことができます(半分のテクセルオフセットを考慮した後)。

とにかく、あなたは本当にSampleCmp/LevelZeroを使いたくありません。それはあなたが求めている間違ったことをします!シャドウマップなどに使用されます。代わりに、LODが0のSampleLevelを使用してください。

于 2013-03-19T15:34:04.133 に答える
0

問題は次のとおりです。

SamplerComparisonState ShadowSampler
{
   // sampler state
   Filter = MIN_MAG_MIP_POINT;
   AddressU = Clamp;
   AddressV = Clamp;

   // sampler comparison state
   ComparisonFunc = LESS;
   //ComparisonFilter = COMPARISON_MIN_MAG_MIP_POINT;
};

ComparisonFilter が属性として存在していた時期があったようです (ドキュメントに記載されているように) 。 bb509644(v=vs.85).aspx ですが、存在する場合はコンパイルされません。

Filter 属性の値を COMPARISON_MIN_MAG_MIP_POINT に変更することで、上記の動作を修正しました。その時点で、すべてが機能していました。

于 2013-03-17T17:00:39.987 に答える