Jump to content

  • Log In with Google      Sign In   
  • Create Account

codymanix

Member Since 08 Mar 2005
Offline Last Active Feb 03 2013 01:12 PM

Posts I've Made

In Topic: XNA Generate Mip Maps with Texture.FromStream()

03 February 2013 - 12:49 PM

I found the problem: Rendertagets loose their contents on backbuffer change and normally need to be recreated, so needed to copy the data to a new texture.

 

I managed it to create a normal mip mapped Texture2D from a file with the following code.

It uses 3 Steps:

 

1. Load file with Texture2D.FromStream

2. Create mipmapped RenderTarget2D and render texture as sprite on it

3. Copy rendertarget texture to new Texture2D using GetData(mipLevel, ..)/SetData(mipLevel, ...)

 

It is unbelievable unefficient but I fear there is no better way to do it in XNA:

      MemoryStream ms = new MemoryStream();
                s.CopyTo(ms, 1024);
                ms.Seek(0, SeekOrigin.Begin);

                // load texture from file
                using (Texture2D intermediateTexture = Texture2D.FromStream(Graphics, ms))
                {
                    // create mip mapped texture
                    using (RenderTarget2D renderTarget = new RenderTarget2D(
                        Graphics,
                        intermediateTexture.Width,
                        intermediateTexture.Height,
                        mipMap: true,
                        preferredFormat: SurfaceFormat.Color,
                        preferredDepthFormat: DepthFormat.None,
                        preferredMultiSampleCount: 0,
                        usage: RenderTargetUsage.PreserveContents))
                    {
                        SamplerState oldSS = Graphics.SamplerStates[0];
                        RasterizerState oldrs = Graphics.RasterizerState;

                        SamplerState newss = SamplerState.LinearClamp; // todo which is best?

                        Graphics.SetRenderTarget(renderTarget);

                        spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.Opaque, newss, DepthStencilState.None, RasterizerState.CullNone, effect: null);
                        spriteBatch.Draw(intermediateTexture, new Vector2(0, 0), Color.White);
                        spriteBatch.End();

                        Graphics.SetRenderTarget(null);
                        Graphics.DepthStencilState = DepthStencilState.Default;
                        Graphics.BlendState = BlendState.Opaque;
                        Graphics.SamplerStates[0] = oldSS;
                        Graphics.RasterizerState = oldrs;

                        // since rendertarget textures are volatile (contents get lost on device) we have to copy data in new texture
                        Texture2D mergedTexture = new Texture2D(Graphics, intermediateTexture.Width, intermediateTexture.Height, true, SurfaceFormat.Color);
                        Color[] content = new Color[intermediateTexture.Width * intermediateTexture.Height];

                        for (int i = 0; i < renderTarget.LevelCount; i++)
                        {
                            int n = renderTarget.Width * renderTarget.Height / ((1 << i) * (1 << i));
                            renderTarget.GetData<Color>(i, null, content, 0, n);
                            mergedTexture.SetData<Color>(i, null, content, 0, n);
                        }

                        t = mergedTexture;
                    }                   
                }
 

In Topic: XNA Generate Mip Maps with Texture.FromStream()

03 February 2013 - 08:54 AM

// Input Image is a byte[] from your Png
System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(this.InputImage);
memoryStream.Seek(0, System.IO.SeekOrigin.Begin);
Texture2D intermediateTexture = Texture2D.FromStream(deviceAccessor.GetCurrentGraphicsDevice(), memoryStream);

Texture2D texture = null;
RenderTarget2D renderTarget = new RenderTarget2D(deviceAccessor.GetCurrentGraphicsDevice(), InputImageSize.Width, InputImageSize.Height, mipMap: true, preferredFormat: surfaceFormat, preferredDepthFormat: DepthFormat.None);

BlendState blendState = BlendState.Opaque;

currentGraphicsDevice.SetRenderTarget(renderTarget);
using (SpriteBatch sprite = new SpriteBatch(currentGraphicsDevice))
{
sprite.Begin(SpriteSortMode.Immediate, blendState, samplerState, DepthStencilState.None, RasterizerState.CullNone,
effect: null);
sprite.Draw(this.IntermediateTexture, new Vector2(0, 0), Color.White);
sprite.End();
}

texture = (Texture2D)renderTarget;
currentGraphicsDevice.SetRenderTarget(null);
intermediateTexture.Dispose();
return texture;

 

Thank you for the Code. It first seemed to work, it creates textures which also look mip mapped.

But now if I switch during the running game to fullscreen or activate multisampling (Anything that needs

 

GraphicsDeviceManager.ApplyChanges()
 

 

to be called), then things go mad.

My textures seem to be exchanged and sometimes I see nothing at all. When I use the original texture loading mechanism through content pipeline, it works again.

 

My first thought was passing

 

RenderTargetUsage.PreserveContents
 

 

when creating the rendertarget, but this didn't help.

 

Do you have an idea what the problem could be?


In Topic: Trouble with AlphaState

20 January 2013 - 12:27 PM

Hi thanks for the answer!
 

Yes I draw the quads in arbitrary order and with enabled Z-Buffer. Due to the (potentially) huge number of transparent objects I have sorting is no option for me.

But I searched a bit and found out that I can use the AlphaTestEffect or the HLSL Instruction clip().

Is HLSL portable to XBox or Windows Phone?


In Topic: XNA Generate Mip Maps with Texture.FromStream()

10 January 2013 - 02:50 PM

Thank you for the reply!

 

I also found out that I could use new Texture2D(device,w,h,true,format) and then call SetData() on it. Would this be possible? Will it automatically create a valid mip map too?

 

I believe that there is a performance penalty on writeable textures (RenderTarget2D). Is this true?


In Topic: Centering skybox around camera

20 March 2005 - 06:45 AM

> Isn't centering the skybox just as simple as this:
> skybox.position = camera.position;

Isn't that the same as

device.Transform.World = Matrix.Scaling(40f, 40f, 40f) * Matrix.Translation(camPos);

?

To Roquqkie: I already turned depth writing off.

PARTNERS