XNA Creators Club Online
Page 1 of 1 (8 items)
Sort Posts: Previous Next

Passing Multiple Textures to HLSL code

Last post 18/06/2009 16:37 by CutRock. 7 replies.
  • 11/06/2009 0:26

    Passing Multiple Textures to HLSL code

    I'm hoping to write a 2D fluid dynamics simulation using HLSL code, but can't really figure out a good way to access multiple textures (velocity, color and pressure). I'm able to access the colors being drawn each frame using "tex2D(ScreenSample, texCoord.xy)", which accesses the ScreenSample sample2D. Is there any way to add more samples so that I can access each frame's velocity and pressure? I've searched for quite a while and have only found remotely similar solutions in GLSL, and most access static textures. I hope there is a fairly straightforward solution!

    Thanks,
    Doug
  • 11/06/2009 0:33 In reply to

    Re: Passing Multiple Textures to HLSL code

    Unless you're doing something I'm unfamiliar with, you just have to add more texture samplers:

    texture Texture1;  
    texture Texture2;  
    texture Texture3;  
     
    sampler Sampler1 = sampler_state  
    {  
        Texture = (Texture1);  
     
        MinFilter = Linear;  
        MagFilter = Linear;  
        MipFilter = Linear;  
    };  
     
    sampler Sampler2 = sampler_state  
    {  
        Texture = (Texture2);  
     
        MinFilter = Linear;  
        MagFilter = Linear;  
        MipFilter = Linear;  
    };  
     
    //etc... 
    | QuadTerrain LOD |
    | My Current Project: Morph Target Animation |
  • 11/06/2009 0:51 In reply to

    Re: Passing Multiple Textures to HLSL code

    Check out the Sprite Effects sample (on this site) for some code to look at.
    XNA Framework Developer - blog - homepage
  • 12/06/2009 12:16 In reply to

    Re: Passing Multiple Textures to HLSL code

    One thing to watch out for.

    IF you are using spritebatch with your shaders, it will grab texture channel 0, so either make sure the texture you pass to spritebatch matches what is in your shader, or leave channel 0 alone.

    You specify shader channels by adding :register(s1) to the sampler definition.

    sampler ColorMapSampler : register (s1) = sampler_state

    Just one thing that has caught me out in the past.

    Information is not knowledge, knowledge is not wisdom, wisdom is not truth, truth is not beauty, beauty is not love, love is not music, music is the best! Wisdom is the domain of the Wis (which is extinct).
  • 17/06/2009 13:56 In reply to

    Re: Passing Multiple Textures to HLSL code

    Thanks a lot guys. I was traveling this weekend and then the forum was down last night, so I have only just now figured it all out. I haven't incorporated it yet, but judging by the sprite effects tutorial it should work fine for what I'm looking at doing.

    Thanks a ton,
    Doug
  • 18/06/2009 5:39 In reply to

    Re: Passing Multiple Textures to HLSL code

    I've spent quite a bit of time looking into coding for the diffusion in a shader, but have been hung up on saving the texture using floating point variables for colors. I believe that the floating point values are truncated to the closest 1/256th when the texture is saved, so I can't incrementally change the value by anything less than 1/256th of the maximum pressure. This makes the diffusion look clunky and doesn't allow for it to work with small diffusion rates or subtle diffusion between relatively similar values.

    Any insight or proposed solutions would be much appreciated.

    If you would like to look over my coder, here is the C# code used to incrementally change the pressure texture:
                    //Change RenderTarget2D to render to Pressure texture 
                    RenderTarget2D temp = (RenderTarget2D)GraphicsDevice.GetRenderTarget(0); 
                    GraphicsDevice.SetRenderTarget(0, PressureRenderTarget); 
     
                    //Begin SpriteBatch 
                    spriteBatch.Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.Immediate, SaveStateMode.None); 
     
                        //Set PressureTexture and VelocityTexture in Advection 
                        graphics.GraphicsDevice.Textures[1] = pressure; 
                        graphics.GraphicsDevice.Textures[2] = velocity; 
     
                        //Begin Effect 
                        Diffusion.Begin(); 
                        Diffusion.CurrentTechnique.Passes[0].Begin(); 
                            //Draw Scene 
                            spriteBatch.Draw(pressure, new Rectangle(0, 0, GraphicsDevice.Viewport.Width, GraphicsDevice.Viewport.Height), Color.White); 
                        //End Effect 
                        Diffusion.CurrentTechnique.Passes[0].End(); 
                        Diffusion.End(); 
     
                    //End SpriteBatch 
                    spriteBatch.End(); 
     
                    //Change back to original RenderTarget, retrieve texture for Pressure texture 
                    GraphicsDevice.SetRenderTarget(0, temp); 
                    pressure = PressureRenderTarget.GetTexture(); 


    And the HLSL code that is called:
    sampler InkSampler      : register(s0); 
    sampler PressureSampler : register(s1); 
    sampler VelocitySampler : register(s2); 
     
    float d = 0.001f; //DIFFUSIVITY CONSTANT 
    float2 size = float2(320.0f, 200.0f); //SIZE OF TEXTURE 
     
    float4 main(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : COLOR0 { 
        float newPressure; 
        newPressure = (tex2D(PressureSampler, texCoord).r + 
                  d * (tex2D(PressureSampler, texCoord - half2(1.0f / size.x, 0)).r + 
                       tex2D(PressureSampler, texCoord + half2(1.0f / size.x, 0)).r + 
                       tex2D(PressureSampler, texCoord - half2(0, 1.0f / size.y)).r + 
                       tex2D(PressureSampler, texCoord + half2(0, 1.0f / size.y)).r)) / (1 + 4 * d); 
         
        return float4(newPressure, newPressure, newPressure, 1.0f); 
     
    technique { 
        pass Pass0 { 
            PixelShader = compile ps_2_0 main(); 
        } 
     

  • 18/06/2009 15:48 In reply to

    Re: Passing Multiple Textures to HLSL code

    The precision of texture data depends what format you store that texture in. By default you are most likely using SurfaceFormat.Color, which has 8 bits per channel.

    If the values stored in this texture are all very small, or have a limited range, you could scale and/or bias the values in the texture to spread them over the full 0-1 range (which will obviously increase precision) then reverse that scaling before using the value in your shader.

    If you really need the full 0-1 range with >8 bit precision, you will have to use a texture format with more bits per channel. 16 bits per channel and floating point texture formats are supported on some of the more modern GPU's, but not universally on all hardware, so this really depends what cards you aim to run this program on.
    XNA Framework Developer - blog - homepage
  • 18/06/2009 16:37 In reply to

    Re: Passing Multiple Textures to HLSL code

    Thanks Shawn. I actually just solved the problem earlier today by encoding a 24bit floating point value into the R, G and B color values of the texture. Because this is a texture for the pressure at different points in the fluid I only need it to represent one value. For velocity, however, I'm going to probably have to use R and G for x velocity and B and A for y velocity. The problem with scaling over a 0-1 range was that, if I wanted to incrementally change the value by something less than 1/256, then the value would be reverted back to it's original value after I saved the texture again.

    Thanks for all the great advice!
    Doug
Page 1 of 1 (8 items) Previous Next