About passing 3D texture to Pixel Shader

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
williamlai3a
Posts: 13
Joined: Wed Sep 19, 2007 11:57 am

About passing 3D texture to Pixel Shader

Post by williamlai3a »

I am trying to put the fire: Lava example from RenderMonkey into Irrlicht Engine 1.31. Unfortunately, in that example, there is a 128 x 128 x 128 Noise Map in .dds format. I know that irr engine cannot support .dds format. So, I converted the dds file into 128 pieces of .jpg files with each 128 x 128. The HLSL code that I am using is as below:

Code: Select all

float noiseScale;
float morphRate;
float bubbleRate;
float bubbleScale;
float time_0_X;
float scale;
float bias;

sampler Flame : register(s0);
sampler Noise : register(s1);

float4x4 mWorldViewProj;  // World * View * Projection transformation
float4x4 mInvWorld;       // Inverted world matrix
float4x4 mTransWorld;     // Transposed world matrix
float3 mLightPos;         // Light position
float4 mLightColor;       // Light color


// Vertex shader output structure
struct VS_OUTPUT
{
	float4 Position   : POSITION;   // vertex position 
	float4 Diffuse    : COLOR0;     // vertex diffuse color
	float2 TexCoord   : TEXCOORD0;  // tex coords
};


VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
                      in float3 vNormal   : NORMAL,
                      float2 texCoord     : TEXCOORD0 )
{
	VS_OUTPUT Output;

	// transform position to clip space 
	Output.Position = mul(vPosition, mWorldViewProj);
	
	// transform normal 
	float3 normal = mul(vNormal, mInvWorld);
	
	// renormalize normal 
	normal = normalize(normal);
	
	// position in world coodinates
	float3 worldpos = mul(mTransWorld, vPosition);
	
	// calculate light vector, vtxpos - lightpos
	float3 lightVector = worldpos - mLightPos;
	
	// normalize light vector 
	lightVector = normalize(lightVector);
	
	// calculate light color 
	float3 tmp = dot(-lightVector, normal);
	tmp = lit(tmp.x, tmp.y, 1.0);
	
	tmp = mLightColor * tmp.y;
	Output.Diffuse = float4(tmp.x, tmp.y, tmp.z, 0);
	Output.TexCoord = texCoord;
	
	return Output;
}

// We use noise as our base texture. Then we use more noisy to
// bubble in that noise. Both the base noise and bubble noise is
// animated, though the bubbling at a higher rate.

float4 pixelMain(float2 pos: TEXCOORD0) : COLOR 
{
   // Bubble coords
   float3 coord;
   coord.xy = pos * bubbleScale;
   coord.z = bubbleRate * time_0_X;

   // Sample noise for x and y
   float noiseX = tex3D(Noise, coord).r - 0.5;
   float noiseY = tex3D(Noise, coord + 0.5).r - 0.5;

   // Offset our base noise with the bubble noise
   coord.x = pos.x + noiseX * noiseScale;
   coord.y = pos.y + noiseY * noiseScale;
   coord.z = time_0_X * morphRate;

   // Sample the base noise
   float base = tex3D(Noise, coord).r;

   // Assign a firey color from the base noise
   return tex1D(Flame, scale * base + bias);
}
I know that the problem is on the tex3D() function.
Is there way that I can pass the 128 pieces of Noise Map to the shader? Or letting the shader know which pieces I need this time?
Or any other suggestion that I can solve this problem??

Thank you very much.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

depends on the noise, is the noise vectorised or not? if you just want single floats from it you can use the rgb channels as a 3D texture. As for the 128 peices, that wont work unless you have 128 texture stages.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
Kriolyth
Posts: 26
Joined: Wed Mar 26, 2008 6:59 pm
Location: Moscow, Russia

Re: About passing 3D texture to Pixel Shader

Post by Kriolyth »

williamlai3a wrote:

Code: Select all

   // Bubble coords
   float3 coord;
   coord.xy = pos * bubbleScale;
   coord.z = bubbleRate * time_0_X;

   // Sample noise for x and y
   float noiseX = tex3D(Noise, coord).r - 0.5;
   float noiseY = tex3D(Noise, coord + 0.5).r - 0.5;

   // Offset our base noise with the bubble noise
   coord.x = pos.x + noiseX * noiseScale;
   coord.y = pos.y + noiseY * noiseScale;
   coord.z = time_0_X * morphRate;

   // Sample the base noise
   float base = tex3D(Noise, coord).r;
3D Texture lookup basically interpolates between two 3D slices, sampled at (x,y), so your shader can be rewritten to using several (not all 128) slices.
A call to tex3D(Noise, coord).x can be replaced with
float c1 = tex2D( slice0, coord.xy ).x;
float c2 = tex2D( slice1, coord.xy ).x;
float out = lerp( c1, c2, frac( coord.z ) );

Note the use of coord.z. First time, it is initialized with bubbleRate * time_0_X, and then offseted by 0.5. This gives at least two, at most three slices, e.g.:

Code: Select all

|........|........|   <- z axis in vilume texture; slices are vertical bars
  #   #            <- sampling1, two slices used
       #   #       <- sampling2, three slices used
We take these samples from slices and do a lerp(#1, #2, frac(z)).

Second time, coord.z is initialized with time_0_X * morphRate. So we have two more slices to sample from.

This said, you need 5 texture samplers, all textures have to be set every frame depending on time_0_X, bubbleRate and morphRate. And you get an increased shader complexity (6 2D texture lookups, 3 lerps) while conserving some video memory (no 3D texture, only several slices) - and it should work with Irrlicht ;)

EDIT: messed up c1 and c2 in lerp :oops:
Last edited by Kriolyth on Wed Apr 02, 2008 1:14 am, edited 1 time in total.
The cake is a lie.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

A call to tex3D(Noise, coord).x can be replaced with
float c1 = tex2D( slice0, coord.xy ).x;
float c2 = tex2D( slice1, coord.xy ).x;
float out = lerp( c2, c1, frac( coord.z ) );
Oh Thats very useful :D

Nice to see omaremad around :P
ShadowMapping for Irrlicht!: Get it here
Need help? Come on the IRC!: #irrlicht on irc://irc.freenode.net
Post Reply