SsaoEffect.fx à partir de l'espace d'écran Occlusion ambiante xna 3.1 Exemple ne fonctionne pas dans XNA 4.0

StackOverflow https://stackoverflow.com/questions/5484542

Question

J'essaie de convertir l'exemple d'occlusion ambiant de l'espace d'écran de XNA 3.1 en XNA 4.0. J'ai résolu tous les problèmes de la source, sauf cet étrange problème dans un fichier shader. J'ai traversé et résolu tous les problèmes évidents avec le shader tel que guidé par le blog de Shawn Hargreaves, mais lorsqu'il compile, il utilise 620 emplacements d'instructions, ce qui est bien sur la limite des emplacements d'instructions 512. Comment cela aurait-il pu fonctionner dans XNA 3.1, mais pas dans XNA 4.0?

Les modifications par rapport à la copie 3.1 du fichier sont très minimes et consistaient uniquement à renommer quelques fonctions. Vous trouverez ci-dessous la source complète du shader dans sa forme actuelle. Je serai très reconnaissant de toute aide pour réduire le nombre de créneaux d'instructions que cela compile.


float sampleRadius;
float distanceScale;
float4x4 Projection;

float3 cornerFustrum;

struct VS_OUTPUT
{
    float4 pos              : POSITION;
    float2 TexCoord         : TEXCOORD0;
    float3 viewDirection    : TEXCOORD1;
}; 

VS_OUTPUT VertexShaderFunction(
    float4 Position : POSITION, float2 TexCoord : TEXCOORD0)
{
    VS_OUTPUT Out = (VS_OUTPUT)0;

    Out.pos = Position;
    Position.xy = sign(Position.xy);
    Out.TexCoord = (float2(Position.x, -Position.y) + float2( 1.0f, 1.0f ) ) * 0.5f;
    float3 corner = float3(-cornerFustrum.x * Position.x,
            cornerFustrum.y * Position.y, cornerFustrum.z);
    Out.viewDirection =  corner;

    return Out;
}


texture depthTexture;
texture randomTexture;

sampler2D depthSampler = sampler_state
{
    Texture = <depthTexture>;
    ADDRESSU = CLAMP;
    ADDRESSV = CLAMP;
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
};

sampler2D RandNormal = sampler_state
{
    Texture = <randomTexture>;
    ADDRESSU = WRAP;
    ADDRESSV = WRAP;
    MAGFILTER = LINEAR;
    MINFILTER = LINEAR;
};

float4 PixelShaderFunction(VS_OUTPUT IN) : COLOR0
{
    float4 samples[16] =
    {
        float4(0.355512,    -0.709318,  -0.102371,  0.0 ),
        float4(0.534186,    0.71511,    -0.115167,  0.0 ),
        float4(-0.87866,    0.157139,   -0.115167,  0.0 ),
        float4(0.140679,    -0.475516,  -0.0639818, 0.0 ),
        float4(-0.0796121,  0.158842,   -0.677075,  0.0 ),
        float4(-0.0759516,  -0.101676,  -0.483625,  0.0 ),
        float4(0.12493,     -0.0223423, -0.483625,  0.0 ),
        float4(-0.0720074,  0.243395,   -0.967251,  0.0 ),
        float4(-0.207641,   0.414286,   0.187755,   0.0 ),
        float4(-0.277332,   -0.371262,  0.187755,   0.0 ),
        float4(0.63864,     -0.114214,  0.262857,   0.0 ),
        float4(-0.184051,   0.622119,   0.262857,   0.0 ),
            float4(0.110007,    -0.219486,  0.435574,   0.0 ),
        float4(0.235085,    0.314707,   0.696918,   0.0 ),
        float4(-0.290012,   0.0518654,  0.522688,   0.0 ),
        float4(0.0975089,   -0.329594,  0.609803,   0.0 )
    };

    IN.TexCoord.x += 1.0/1600.0;
    IN.TexCoord.y += 1.0/1200.0;

    normalize (IN.viewDirection);
    float depth = tex2D(depthSampler, IN.TexCoord).a;
    float3 se = depth * IN.viewDirection;

    float3 randNormal = tex2D( RandNormal, IN.TexCoord * 200.0 ).rgb;

    float3 normal = tex2D(depthSampler, IN.TexCoord).rgb;
    float finalColor = 0.0f;

    for (int i = 0; i < 16; i++)
    {
        float3 ray = reflect(samples[i].xyz,randNormal) * sampleRadius;

        //if (dot(ray, normal) < 0)
        //  ray += normal * sampleRadius;

        float4 sample = float4(se + ray, 1.0f);
        float4 ss = mul(sample, Projection);

        float2 sampleTexCoord = 0.5f * ss.xy/ss.w + float2(0.5f, 0.5f);

        sampleTexCoord.x += 1.0/1600.0;
        sampleTexCoord.y += 1.0/1200.0;
        float sampleDepth = tex2D(depthSampler, sampleTexCoord).a;

        if (sampleDepth == 1.0)
        {
            finalColor ++;
        }
        else
        {       
            float occlusion = distanceScale* max(sampleDepth - depth, 0.0f);
            finalColor += 1.0f / (1.0f + occlusion * occlusion * 0.1);
        }
    }

    return float4(finalColor/16, finalColor/16, finalColor/16, 1.0f);
}


technique SSAO
{
    pass P0
    {          
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader  = compile ps_3_0 PixelShaderFunction();
    }
}
Était-ce utile?

La solution

XNA 4.0 applique la limite d'instructions 512 (dont la Xbox360 a et le profil Hidef applique comme un minimum), alors que XNA3.1 ne l'a pas fait.

Du côté positif, toute carte graphique qui peut exécuter le profil XNA Hidef ne doit pas tomber, où, comme XNA avait permis un certain nombre d'instructions, il peut avoir fait.

Étant donné que vous avez une boucle dans votre code, vous pouvez essayer de forcer le compilateur à utiliser des instructions de boucle si elle la déroute actuellement (pas familière avec cela moi-même).

Autres conseils

Si vous recherchez un XNA 4 SSAO qui a une source open source, consultez ce lien: Rendu différé avec les normales SSAO

réduire le nombre d'échantillons dans le shader de 16 à 8

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top