2010-07-20 6 views
2

Y a-t-il un moyen, dans le framework XNA, de rendre votre scène 2D à l'aide de la méthode SpriteBatch classique, puis d'appliquer l'effet à toute l'image après son rendu? Par exemple, le flou, la sépia ou même le fait de tout faire ressembler à un vieux film de film, avec du grain, de la poussière, des lignes, etc?Application de l'effet Post rendu à SpriteBatch dans XNA

Répondre

3

Oui - ce que vous allez faire est de définir la cible de rendu à de rendre à une texture au lieu de sortir votre matériel graphique. Ensuite, une fois que votre sortie est dans une texture, vous allez appliquer vos effets de pixel shader et l'envoyer.

Quelques grands effets de base sont disponibles exemples ici (je recommande vivement ce blog vous abonnant à aussi bien) http://blogs.msdn.com/b/shawnhar/archive/2007/05/23/transitions-part-four-rendertargets.aspx

+1

Il y a aussi un ensemble d'échantillons post-traitement dans le club des Créateurs: http://creators.xna.com/en- US/éducation/catalogue /? Devarea = 15 (Le Bl oom échantillon est un bon pour ce que vous voulez.) –

2

Voici mon code lumineux, je serais intéressé par des commentaires sur la façon de l'améliorer. Fondamentalement, j'ai des objets divisés en rougeoyant et normal. Je crée deux objets RenderTarget2D dans ma méthode Initialize, l'un d'entre eux avec un tampon de profondeur parce que je fais 3D:

GlowTarget = new RenderTarget2D(GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight, true, SurfaceFormat.Color, DepthFormat.Depth24Stencil8); 
GlowTarget2 = new RenderTarget2D(GraphicsDevice, pp.BackBufferWidth, pp.BackBufferHeight, true, SurfaceFormat.Color, DepthFormat.None); 

Dans ma méthode draw, rendre les objets normaux à mon GlowTarget puis effacer la couleur au noir avec zéro Alpha et dessine les objets lumineux. Je dessine ceci à GlowTarget2 avec un pixel shader d'effet personnalisé appliqué pour le flouter dans la direction X. Ensuite, j'efface la cible de rendu et dessine les objets normaux. Enfin, je dessine la texture GlowTarget2 sur le dessus avec un autre effet personnalisé à flou dans la direction Y.

/// <summary> 
/// This is called when the game should draw itself. 
/// </summary> 
/// <param name="gameTime">Provides a snapshot of timing values.</param> 
protected override void Draw(GameTime gameTime) 
{ 
    // draw clear GlowTarget and draw normal, non-glowing objects to set depth buffer 
    GraphicsDevice.SetRenderTarget(GlowTarget); 
    GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Stencil | ClearOptions.Target, Color.FromNonPremultiplied(0, 0, 0, 0), 1f, 0); 
    MyScene.DrawNormal(); 

    // clear target only and set color to black WITH ZERO ALPHA, then draw glowing objects 
    // so they will be the only ones that appear and they will be hidden by objects in front of them 
    GraphicsDevice.Clear(ClearOptions.Target, Color.FromNonPremultiplied(0, 0, 0, 0), 1f, 0); 
    MyScene.DrawGlow(); 

    // blur objects horizontally into GlowTarget2 
    GraphicsDevice.SetRenderTarget(GlowTarget2); 
    GraphicsDevice.Clear(Color.FromNonPremultiplied(0, 0, 0, 0)); 
    using (SpriteBatch sb = new SpriteBatch(GlowTarget2.GraphicsDevice)) 
    { 
     blurXEffect.Parameters["PixelSize"].SetValue((float)(1.0f/(float)GlowTarget.Width)); 
     sb.Begin(0, BlendState.Additive, SamplerState.PointWrap, DepthStencilState.Default, RasterizerState.CullNone, blurXEffect); 
     sb.Draw(GlowTarget, new Rectangle(GraphicsDevice.Viewport.X, GraphicsDevice.Viewport.Y, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), Color.White); 
     sb.End(); 
    } 

    // now reset context and clear for actual drawing 
    GraphicsDevice.SetRenderTarget(null); 
    GraphicsDevice.BlendState = BlendState.Opaque; 
    GraphicsDevice.Clear(Color.Black); 

    // TODO: Add your drawing code here 
    base.Draw(gameTime); 

    // draw scene to graphics card back buffer 
    MyScene.DrawNormal(); 

    using (SpriteBatch sprite = new SpriteBatch(GraphicsDevice)) 
    { 
     // draw glowing texture and blur Y this time 
     blurYEffect.Parameters["PixelSize"].SetValue((float)(1.0f/(float)GlowTarget.Height)); 
     sprite.Begin(0, BlendState.Additive, SamplerState.PointWrap, DepthStencilState.Default, RasterizerState.CullNone, blurYEffect); 

     //sprite.Draw(GlowTarget, new Vector2(0, 0), Color.White); 
     sprite.Draw(GlowTarget2, new Rectangle(GraphicsDevice.Viewport.X, GraphicsDevice.Viewport.Y, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), Color.White); 
     sprite.End(); 
    } 
} 

Si vous faites quelque chose de simple 2D comme l'application d'un effet unique, vous pouvez alors simplement définir un effet personnalisé dans votre SpriteBatch.Begin() appeler ... Voici mon Shader pour bluring X:

// texture we are rendering 
sampler2D tex : register(S0); 

float PixelSize; 

// pixel shader function 
float4 main(float2 uv : TEXCOORD) : COLOR 
{ 
    float4 c = 0; // will get max of each value for c 
    float alpha = 0; // alpha will be average 

    float2 myuv = uv; 
    for(int i = -7; i <= 7; i++) 
    { 
     myuv.x = uv.x + (i * PixelSize * 1.5); 
     float4 sample = tex2D(tex, myuv); 
     c = max(c, sample); 
     alpha += sample.a; 
    } 

    c.a = saturate(pow(abs(alpha/6), 0.4)); 
    return(c); 
} 

technique Technique1 
{ 
    pass Pass1 
    { 
     PixelShader = compile ps_2_0 main(); 
    } 
} 

est ici un exemple d'image, carrés verts et bleus rouges normaux avec les versions luisent au-dessus: les Glow Sample

Questions connexes