-
|
|
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
|
|
-
|
|
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... |
|
|
-
-
- (10849)
-
Team XNA
-
Posts
8.007
|
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
|
|
-
-
- (1115)
-
premium membership
-
Posts
859
|
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).
|
|
-
|
|
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
|
|
-
|
|
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(); |
| } |
| } |
| |
|
|
-
-
- (10849)
-
Team XNA
-
Posts
8.007
|
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
|
|
-
|
|
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
|
|
|