Sign in to follow this  
h3ro

XNA - Render to texture

Recommended Posts

Hallo, I am very new to shaders and im trying to get started by writing a class that applies a blur shader to what ever sprite I send to it, but I am getting some un-expected results. The sprite is rendered correctly (no shader is applied), but from what I understand, the sprite should never show up as it is being rendered to a texture, and that texture is never added to the screen. Also, all the other sprites have now disappeared from the screen. (This sprite is the last to render) My spriteBatch.draw is like this: m_spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); My code that is causing problems: Rectangle spriteRect = m_sprite.getRect(); Texture2D texture = DataManager.Instance.getSprite(m_sprite.getSpriteID()); RenderTarget2D renderTarget = new RenderTarget2D(m_device, spriteRect.Width, spriteRect.Height, 1, m_format); Rectangle renderTargetRect = new Rectangle(0, 0, renderTarget.Width, renderTarget.Height); m_device.SetRenderTarget(0, renderTarget); m_render.getSpriteBatch().Draw(texture, renderTargetRect, spriteRect, Color.White); m_device.SetRenderTarget(0, null); Regards,

Share this post


Link to post
Share on other sites

It's a bit of a guess, but you probably want to Begin() and End() your spritebatch while you're rendering to your target. Something like this:


m_device.SetRenderTarget(0, renderTarget);
m_render.getSpriteBatch().Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None);
m_render.getSpriteBatch().Draw(texture, renderTargetRect, spriteRect, Color.White);
m_render.getSpriteBatch().End();
m_device.SetRenderTarget(0, null);

Share this post


Link to post
Share on other sites
You were correct, I needed to change where I did my begin/end calls.

I still have the problem of everything else disappearing though. Any ideas what that might be?

// Get the data from the sprite
Rectangle spriteRect = m_sprite.getRect();
Texture2D texture = DataManager.Instance.getSprite(m_sprite.getSpriteID());

// Create a render target the same size as the sprite
RenderTarget2D renderTarget = new RenderTarget2D(m_device, spriteRect.Width, spriteRect.Height, 1, m_format);
Rectangle renderTargetRect = new Rectangle(0, 0, renderTarget.Width, renderTarget.Height);

// Change the render target to the sprite and begin drawing. When done drawing, change the render target
// back to the screen
m_device.SetRenderTarget(0, renderTarget);
m_render.getSpriteBatch().Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.None);
m_render.getSpriteBatch().Draw(texture, renderTargetRect, spriteRect, Color.White);
m_render.getSpriteBatch().End();
m_device.SetRenderTarget(0, null);

// Draw the texture to the screen
m_render.getSpriteBatch().Begin();
m_render.getSpriteBatch().Draw(renderTarget.GetTexture(), new Vector2(100, 100), Color.White);
m_render.getSpriteBatch().End();


Edit:
If I want to create a generic BlurTexture function, am I better of creating one big texture and store in that class as a static and always use that or is it better to create a texture each time I do a Blue() call? I am guessing that its not a good idea to have the each instance of the class have a separate render target that it creates when the class is created as it will consume a lot of render memory?

Share this post


Link to post
Share on other sites
Quote:
Original post by h3ro
I still have the problem of everything else disappearing though. Any ideas what that might be?


From your code I can't seem to tell where or how you're drawing 'everything else'. I did notice you're not clearing your render target and you're using the same depthbuffer for both your backbuffer and your target, which can be problematic. I don't use sprite batches much though, so those are just guesses.

Quote:
If I want to create a generic BlurTexture function, am I better of creating one big texture and store in that class as a static and always use that or is it better to create a texture each time I do a Blue() call? I am guessing that its not a good idea to have the each instance of the class have a separate render target that it creates when the class is created as it will consume a lot of render memory?


It depends a bit on what you want to do. If you want to permanently blur a static texture as a one-time preprocessing step before you render anything, you could opt to create a new blurred texture. This is definitely not something you want to be doing every frame though.

Blurring like this, using shaders and render targets, is typically applied as a post-processing step to the entire scene. First you render all sprites you want to blur to a render target so you can access the scene as a texture (alternatively your could resolve the backbuffer). Then you render this texture containing your scene back to the backbuffer/screen using the blur shader. This will in effect make the scene you rendered so far appear blurred and you can continue rendering the non-blurred parts or move on to the next frame.

In this latter setup, the blurring typically isn't implemented as Class.Blur(texture), but rather as additional code in your Game.Draw() method. This can be tidied up by sticking this additional code in a GameComponent.Draw() which is called after everything that should be blurred has been drawn. The bloom sample provides a good example how that can be done.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this