1

XNAで使用しているピクセルシェーダー(下)があります。私のラップトップ(くだらないグラフィックカード)では、少しぎくしゃくしますが、大丈夫です。xboxで実行してみたところ、ひどいです!

ゲームには何もありません(フラクタルレンダラーです)ので、問題の原因となるピクセルシェーダーである必要があります。また、反復を減らして問題がないので、PSコードだと思います。私もチェックしましたが、GCデルタはゼロです。

xboxにno-noのHLSL関数はありますか?私ここで何か間違ったことをしているに違いありません、パフォーマンスはそれほど悪くはありません!

#include "FractalBase.fxh"

float ZPower;

float3 Colour;
float3 ColourScale;

float ComAbs(float2 Arg)
{
    return sqrt(Arg.x * Arg.x + Arg.y * Arg.y);
}

float2 ComPow(float2 Arg, float Power)
{
    float Mod = pow(Arg.x * Arg.x + Arg.y * Arg.y, Power / 2);
    float Ang = atan2(Arg.y, Arg.x) * Power;

    return float2(Mod * cos(Ang), Mod * sin(Ang));
}

float4 FractalPixelShader(float2 texCoord : TEXCOORD0, uniform float Iterations) : COLOR0
{
    float2 c = texCoord.xy;
    float2 z = 0;

    float i;

    float oldBailoutTest = 0;
    float bailoutTest = 0;

    for(i = 0; i < Iterations; i++)
    {
        z = ComPow(z, ZPower) + c;

        bailoutTest = z.x * z.x + z.y * z.y;

        if(bailoutTest >= ZPower * ZPower)
        {
            break;
        }

        oldBailoutTest = bailoutTest;
    }

    float normalisedIterations = i / Iterations;
    float factor = (bailoutTest - oldBailoutTest) / (ZPower * ZPower - oldBailoutTest);

    float4 Result = normalisedIterations + (1 / factor / Iterations);

    Result = (i >= Iterations - 1) ? float4(0.0, 0.0, 0.0, 1.0) : float4(Result.x * Colour.r * ColourScale.x, Result.y * Colour.g * ColourScale.y, Result.z * Colour.b * ColourScale.z, 1);

    return Result;
}

technique Technique1
{
    pass
    {
        VertexShader = compile vs_3_0 SpriteVertexShader();
        PixelShader = compile ps_3_0 FractalPixelShader(128);
    }
}

以下はFractalBase.fxhです。

float4x4 MatrixTransform : register(vs, c0);

float2 Pan;
float Zoom;
float Aspect;

void SpriteVertexShader(inout float4 Colour    : COLOR0,
                        inout float2 texCoord : TEXCOORD0,
                        inout float4 position : SV_Position)
{
    position = mul(position, MatrixTransform);

    // Convert the position into from screen space into complex coordinates
    texCoord = (position) * Zoom * float2(1, Aspect) - float2(Pan.x, -Pan.y);
}

編集私はたくさんのlerpを使用して条件付きを削除しようとしましたが、それを実行すると、大量のアーティファクトが発生しました(「美術館に属する」種類ではありません!)。状況を変えて、いくつかの論理エラーを修正しましたが、重要なのは、0.9999 = 0(整数)になる丸め誤差を考慮して、GreaterThanの結果に1+イプシロンを掛けることでした。以下の修正コードを参照してください。

#include "FractalBase.fxh"

float ZPower;

float3 Colour;
float3 ColourScale;

float ComAbs(float2 Arg)
{
    return sqrt(Arg.x * Arg.x + Arg.y * Arg.y);
}

float2 ComPow(float2 Arg, float Power)
{
    float Mod = pow(Arg.x * Arg.x + Arg.y * Arg.y, Power / 2);
    float Ang = atan2(Arg.y, Arg.x) * Power;

    return float2(Mod * cos(Ang), Mod * sin(Ang));
}

float GreaterThan(float x, float y)
{
    return ((x - y) / (2 * abs(x - y)) + 0.5) * 1.001;
}

float4 FractalPixelShader(float2 texCoord : TEXCOORD0, uniform float Iterations) : COLOR0
{
    float2 c = texCoord.xy;
    float2 z = 0;

    int i;

    float oldBailoutTest = 0;
    float bailoutTest = 0;

    int KeepGoing = 1;

    int DoneIterations = Iterations;

    int Bailout = 0;

    for(i = 0; i < Iterations; i++)
    {
        z = lerp(z, ComPow(z, ZPower) + c, KeepGoing);

        bailoutTest = lerp(bailoutTest, z.x * z.x + z.y * z.y, KeepGoing);

        Bailout = lerp(Bailout, GreaterThan(bailoutTest, ZPower * ZPower), -abs(Bailout) + 1);

        KeepGoing = lerp(KeepGoing, 0.0, Bailout);
        DoneIterations = lerp(DoneIterations, min(i, DoneIterations), Bailout);

        oldBailoutTest = lerp(oldBailoutTest, bailoutTest, KeepGoing);
    }

    float normalisedIterations = DoneIterations / Iterations;
    float factor = (bailoutTest - oldBailoutTest) / (ZPower * ZPower - oldBailoutTest);

    float4 Result = normalisedIterations + (1 / factor / Iterations);

    Result = (DoneIterations >= Iterations - 1) ? float4(0.0, 0.0, 0.0, 1.0) : float4(Result.x * Colour.r * ColourScale.x, Result.y * Colour.g * ColourScale.y, Result.z * Colour.b * ColourScale.z, 1);

    return Result;
}

technique Technique1
{
    pass
    {
        VertexShader = compile vs_3_0 SpriteVertexShader();
        PixelShader = compile ps_3_0 FractalPixelShader(128);
    }
}
4

1 に答える 1

1

xboxのブロックサイズはかなり大きいため、xboxでの分岐は必ずしも優れているとは限りません。また、コンパイラは、コードが使用していると思われる動的ブランチを生成するのに常に最も効果的であるとは限りません。

ブランチ属性を調べます:http://msdn.microsoft.com/en-us/library/bb313972%28v=xnagamestudio.31%29.aspx

また、早期のベイルアウトを移動した場合、PCはXboxに似たものになりますか?

最近のグラフィックカードは、実際にはキセノンユニットよりもかなり高速であることに注意してください。

于 2011-05-25T20:22:21.190 に答える