Flame.fx (FIRE animation) - - SOLVED

Started by
41 comments, last by circlesoft 19 years, 3 months ago
Hi friend! I'm here with a new problem!!! I'm trying to use NVIDIA FX file Flame.fx in my game, but I can't find a good solution to load and use this effect... I think that the problem is about some missing stage or some other little thing... The .FX file is this:

/*
	Volumetric flame effect
	based on Yury Uralsky's "Volumetric Fire"
	http://www.cgshaders.org/shaders/show.php?id=39
	
	This revolves a cross section of a flame image around the Y axis to
	produce a cylindrical volume, and then perturbs the texture coordinates
	with 4 octaves of animated 3D procedural noise to produce the flame effect.
*/

string XFile = "slices_10y.x";
string description = "3D Flame";

float Script : STANDARDSGLOBAL <
    string UIWidget = "none";
    string ScriptClass = "object";
    string ScriptOrder = "standard";
    string ScriptOutput = "color";
    string Script = "Technique=ps20;";
> = 0.8;

float ticks : Time
<
 string units = "sec";
>;

/************* TWEAKABLES **************/

float noiseFreq
<
    string UIWidget = "slider";
    float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.01;
> = 0.1;

float noiseStrength
<
    string UIWidget = "slider";
    float UIMin = 0.0; float UIMax = 5.0; float UIStep = 0.01;
> = 1.0;

float timeScale
<
    string UIWidget = "slider";
    float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.01;
> = 1.0;

float3 noiseScale = { 0.5, 0.5, 0.5 };
float3 noiseAnim = { 0.4, -1.9, 0.8 };

float4 flameColor = { 0.3, 0.2, 0.2, 0.8 };
float3 flameScale = { 0.25, -0.18, 0.12};
float3 flameTrans = { 0.0, -0.1, 0.0 };

// Textures

#define VOLUME_SIZE 32

texture noiseTexture
<
    string Name = "noiseL8_32x32x32.dds";
    string ResourceType = "3D";
	string function = "GenerateNoise1f";
	float3 Dimensions = { VOLUME_SIZE, VOLUME_SIZE, VOLUME_SIZE};
>;

texture flameTexture
<
    string ResourceName = "flame.png";
    string ResourceType = "2D";
>;

// Vector-valued noise
float4 GenerateNoise4f(float3 Pos : POSITION) : COLOR
{
	float4 c;
	float3 P = Pos*VOLUME_SIZE;
	c.r = noise(P);
	c.g = noise(P + float3(11, 17, 23));
	c.b = noise(P + float3(57, 93, 65));
	c.a = noise(P + float3(77, 15, 111));
//	return c*0.5+0.5;
	return abs(c);
}

// Scalar noise
float GenerateNoise1f(float3 Pos : POSITION) : COLOR
{
	float3 P = Pos*VOLUME_SIZE;
//	return noise(P)*0.5+0.5;
	return abs(noise(P));
}

// Tracked matricies
float4x4 wvp : WorldViewProjection;
float4x4 world : World;

// Structures
struct appdata {
    float3 Position	: POSITION;
    float4 UV		: TEXCOORD0;
    float4 Tangent	: TANGENT0;
    float4 Binormal	: BINORMAL0;
    float4 Normal	: NORMAL;
};

struct vertexOutput {
    float4 HPosition	: POSITION;
    float3 NoisePos     : TEXCOORD0;
    float3 FlamePos     : TEXCOORD1;
    float2 UV           : TEXCOORD2;
};

// Vertex shader
vertexOutput flameVS(appdata IN,
					uniform float4x4 WorldViewProj,
					uniform float4x4 World,
					uniform float3 noiseScale,					
					uniform float noiseFreq,
					uniform float3 noiseAnim,
					uniform float3 flameScale,
					uniform float3 flameTrans,
					uniform float timeScale
					)
{
    vertexOutput OUT;
    float4 objPos = float4(IN.Position.x,IN.Position.y,IN.Position.z,1.0);
    float3 worldPos = mul(objPos, World).xyz;
 
    OUT.HPosition = mul(objPos, WorldViewProj);
    float time = fmod(ticks, 10.0);	// avoid large texcoords
    OUT.NoisePos = worldPos*noiseScale*noiseFreq + time*timeScale*noiseAnim;
	OUT.FlamePos = worldPos*flameScale + flameTrans;
	
	OUT.UV = IN.UV;
    return OUT;
}

// Pixel shaders
half4 noise3D(uniform sampler3D NoiseMap, float3 P)
{
//	return tex3D(NoiseMap, P)*2-1;
	return tex3D(NoiseMap, P);
}

half4 turbulence4(uniform sampler3D NoiseMap, float3 P)
{
	half4 sum = noise3D(NoiseMap, P)*0.5 +
 				noise3D(NoiseMap, P*2)*0.25 +
 				noise3D(NoiseMap, P*4)*0.125 +
				noise3D(NoiseMap, P*8)*0.0625;
	return sum;
}

half4 flamePS(vertexOutput IN,
			  uniform sampler3D NoiseMap,
			  uniform sampler2D FlameTex,
			  uniform half noiseStrength,
			  uniform half4 flameColor
			  ) : COLOR
{
//	return tex3D(NoiseMap,IN.NoisePos) * flameColor;
//  return turbulence4(NoiseMap, IN.NoisePos) * flameColor;

	half2 uv;
	uv.x = length(IN.FlamePos.xz);	// radial distance in XZ plane
	uv.y = IN.FlamePos.y;
	
//	uv.y += turbulence4(NoiseMap, IN.NoisePos) * noiseStrength;
	uv.y += turbulence4(NoiseMap, IN.NoisePos) * noiseStrength / uv.x;

	return tex2D(FlameTex, uv) * flameColor;
}

/****************************************************/
/********** SAMPLERS ********************************/
/****************************************************/

sampler3D noiseTextureSampler = sampler_state
{
	Texture = <noiseTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
};

sampler2D flameTextureSampler = sampler_state
{
	Texture = <flameTexture>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
	AddressU = Clamp;
	AddressV = Clamp;	
};


/****************************************************/
/********** TECHNIQUES ******************************/
/****************************************************/

technique ps20 <
	string Script = "Pass=p1d;";
> {
    pass p1d <
		string Script = "Draw=geometry;";
    > {		
	VertexShader = compile vs_1_1 flameVS(wvp, world,
										  noiseScale, noiseFreq, noiseAnim,
										  flameScale, flameTrans, timeScale
										  );

	ZEnable = true;
	ZWriteEnable = true;
	CullMode = None;

	AlphaBlendEnable = true;
	BlendOp = Add;		
	SrcBlend = One;
	DestBlend = One;
	
	PixelShader = compile ps_2_0 flamePS(noiseTextureSampler, flameTextureSampler, noiseStrength, flameColor);
    }
}

/***************************** eof ***/









I've loaded my effect and passed to it values and matrices...

	dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;
	dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;
	dwShaderFlags |= D3DXSHADER_NO_PRESHADER;

	if( FAILED( D3DXCreateEffectFromFile( g_pD3DDevice, PathFlameEffect, 
					NULL, // CONST D3DXMACRO* pDefines,
					NULL, // LPD3DXINCLUDE pInclude,
					dwShaderFlags, NULL, &g_pEffect, NULL )))
					OutputDebugString( "Error in Flame_OK.fx\n" );

	D3DXCreateTextureFromFile(g_pD3DDevice, PathFlameTexture1 , &g_FlameTexture1 );
	D3DXCreateTextureFromFile(g_pD3DDevice, PathFlameTexture2 , &g_FlameTexture2 );


		D3DXHANDLE Tecn = g_pEffect->GetTechnique( 0 );
		if (FAILED(g_pEffect->SetTechnique(Tecn)))
			OutputDebugString( "Impossibile settare la Technique ps20\n" );

		g_pEffect->SetFloat( "ticks", (float)QuantoVeloce );
		g_pEffect->SetFloat( "noiseFreq", 0.1f );
		g_pEffect->SetFloat( "noiseStrength", 1.0f );
		g_pEffect->SetFloat( "timeScale", 1.0f );

		g_pEffect->SetValue( "noiseScale", D3DXVECTOR3(0.5, 0.5, 0.5), sizeof(D3DXVECTOR3) );
		g_pEffect->SetValue( "noiseAnim", D3DXVECTOR3(0.4, -1.9, 0.8), sizeof(D3DXVECTOR3) );

		g_pEffect->SetValue( "flameColor", D3DXVECTOR4(0.3, 0.2, 0.2, 1.0), sizeof(D3DXVECTOR4) );
		g_pEffect->SetValue( "flameScale", D3DXVECTOR3(0.25, -0.18, 0.12), sizeof(D3DXVECTOR3) );
		g_pEffect->SetValue( "flameTrans", D3DXVECTOR3(0.0, -0.1, 0.0), sizeof(D3DXVECTOR3) );

		
		g_pD3DDevice->GetTransform( D3DTS_WORLD, &mWorld );
		g_pD3DDevice->GetTransform( D3DTS_VIEW, &mView );
		g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &mProj );
		mWorldViewProjection = mWorld * mView * mProj;

		g_pEffect->SetMatrix( "wvp", &mWorldViewProjection );
		g_pEffect->SetMatrix( "world", &mWorld );
		
		if( FAILED( g_pEffect->SetTexture( "noiseTexture", g_FlameTexture1 ) ))
			OutputDebugString( "Impossibile assegnare noiseTexture\n" );

		if( FAILED( g_pEffect->SetTexture( "flameTexture", g_FlameTexture2 ) ))
			OutputDebugString( "Impossibile assegnare flameTexture\n" );









and then I run the effect in the usual way:

    UINT cPasses=0; 
	// Apply the technique contained in the effect 
	g_pEffect->Begin(&cPasses, 0);

	for (iPass = 0; iPass < cPasses; iPass++)
	{

	    g_pEffect->BeginPass(iPass);
	
		g_pD3DDevice->SetTexture( 0, g_FlameTexture1 );		
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );

		g_pD3DDevice->SetTexture( 0, g_FlameTexture2 );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP );
		g_pD3DDevice->SetSamplerState( 0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP );

		g_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
		g_pD3DDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
		g_pD3DDevice->SetRenderState( D3DRS_CULLMODE,  D3DCULL_NONE );
		g_pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE , TRUE );
		g_pD3DDevice->SetRenderState( D3DRS_BLENDOP, D3DBLENDOP_ADD );
		g_pD3DDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
		g_pD3DDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );

		g_pEffect->CommitChanges();

	    // Render the mesh with the applied technique
		Flame.Update();
		g_FlameMesh->MeshData.pMesh->DrawSubset(0);
	
	    g_pEffect->EndPass();
	}
	g_pEffect->End();









After that, when I run my app, I could only see my "g_FlameMesh" onto the screen with only one STATIC texture applied without any animated effect... Where is the problem in my code?! I've missed something?! Where I'm wrong?! Is it a bad way to use effect files?! THANKS for help!!! Bye, [Edited by - GENTS on January 9, 2005 10:47:57 AM]
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
Advertisement
You need to increment the time and assign it to the "ticks" variable. I don't see that you are doing this in your posted code.
-dizzyGame Institute InternPlease rate me. :)
I've added the code you said but it still doesn't work...

Seems I need something strange as SamplerStage or TextureStage or probably I miss something important...

Help me please!!! ^__^

Byez,
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
Could it be an error in VERTEX declaration of my mesh or in device's FVF ?!?

How should I declare VERTEX and FVF for my mesh?!

(I've undeclared anything special for VERTEX or FVF 'cause in my .X file the Effect result just applied so, I think, vertex information should be correct)

I still can't find a working solution!!!
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
That what I can see on my screen:

Flame Effect
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
Hi,

Remove all the code that changes the device states inside the BeginPass/Endpass. Your code should look like:

//Load your effect, textures and meshes. Do it as in your code... then set the parameters that will never change for this effect during this execution

g_pEffect->SetFloat( "noiseFreq", 0.1f );
g_pEffect->SetFloat( "noiseStrength", 1.0f );
g_pEffect->SetFloat( "timeScale", 1.0f );

g_pEffect->SetValue( "noiseScale", D3DXVECTOR3(0.5, 0.5, 0.5), sizeof(D3DXVECTOR3) );
g_pEffect->SetValue( "noiseAnim", D3DXVECTOR3(0.4, -1.9, 0.8), sizeof(D3DXVECTOR3) );

g_pEffect->SetValue( "flameColor", D3DXVECTOR4(0.3, 0.2, 0.2, 1.0), sizeof(D3DXVECTOR4) );
g_pEffect->SetValue( "flameScale", D3DXVECTOR3(0.25, -0.18, 0.12), sizeof(D3DXVECTOR3) );
g_pEffect->SetValue( "flameTrans", D3DXVECTOR3(0.0, -0.1, 0.0), sizeof(D3DXVECTOR3) );

if( FAILED( g_pEffect->SetTexture( "noiseTexture", g_FlameTexture1 ) ))
OutputDebugString( "Impossibile assegnare noiseTexture\n" );

if( FAILED( g_pEffect->SetTexture( "flameTexture", g_FlameTexture2 ) ))
OutputDebugString( "Impossibile assegnare flameTexture\n" );



//Once everyting is loaded, use the windows loop to call a render function
void Render()
{
//Compute the current time
time=GetTickCount();

//Clear your color and back buffer.

//Update the effect params that should be updated each frame

g_pEffect->SetFloat( "ticks", (float)QuantoVeloce );
g_pD3DDevice->GetTransform( D3DTS_WORLD, &mWorld );
g_pD3DDevice->GetTransform( D3DTS_VIEW, &mView );
g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &mProj );
mWorldViewProjection = mWorld * mView * mProj;
g_pEffect->SetMatrix( "wvp", &mWorldViewProjection );
g_pEffect->SetMatrix( "world", &mWorld );


//Call the render loop, no additional changes required because shading is done in PS2.0
UINT cPasses=0;
// Apply the technique contained in the effect
g_pEffect->Begin(&cPasses, 0);
for (iPass = 0; iPass < cPasses; iPass++)
{
g_FlameMesh->MeshData.pMesh->DrawSubset(0);
g_pEffect->EndPass();
}
g_pEffect->End();

//Flip


}



Try this

Luck!
Guimo
I've tried your code, but it still doesn't work!!!

This is my code:

INIT FUNCTION()
	D3DXCreateTextureFromFile(g_pD3DDevice, PathFlameTexture1 , &g_FlameTexture1 );	D3DXCreateTextureFromFile(g_pD3DDevice, PathFlameTexture2 , &g_FlameTexture2 );	// Load the collection of meshes used for demo	LoadMesh(&g_FlameMesh, g_pD3DDevice, PathFlames, "..\\Data\\flame\\" );	Flame.AddObject( g_FlameMesh );	Flame.ScaleMesh( g_FlameMesh, 10.0f );	Flame.SetPosition( -350, 200, -10 );		Flame.SetYaw( pi );	Flame.SetPitch( pi/3 );	dwShaderFlags |= D3DXSHADER_FORCE_VS_SOFTWARE_NOOPT;	dwShaderFlags |= D3DXSHADER_FORCE_PS_SOFTWARE_NOOPT;	dwShaderFlags |= D3DXSHADER_NO_PRESHADER;	if( FAILED( D3DXCreateEffectFromFile( g_pD3DDevice, PathFlameEffect, 					NULL, // CONST D3DXMACRO* pDefines,					NULL, // LPD3DXINCLUDE pInclude,					dwShaderFlags, NULL, &g_pEffect, NULL )))					OutputDebugString( "Errore nel caricamento del file Flame_OK.fx\n" );			D3DXHANDLE Tecn = g_pEffect->GetTechnique( 0 );		if (FAILED(g_pEffect->SetTechnique(Tecn)))			OutputDebugString( "Impossibile settare la Technique ps20\n" );		g_pEffect->SetFloat( "noiseFreq", 0.1f );		g_pEffect->SetFloat( "noiseStrength", 1.0f );		g_pEffect->SetFloat( "timeScale", 1.0f );		g_pEffect->SetValue( "noiseScale", D3DXVECTOR3(0.5, 0.5, 0.5), sizeof(D3DXVECTOR3) );		g_pEffect->SetValue( "noiseAnim", D3DXVECTOR3(0.4, -1.9, 0.8), sizeof(D3DXVECTOR3) );		g_pEffect->SetValue( "flameColor", D3DXVECTOR4(0.3, 0.2, 0.2, 1.0), sizeof(D3DXVECTOR4) );		g_pEffect->SetValue( "flameScale", D3DXVECTOR3(0.25, -0.18, 0.12), sizeof(D3DXVECTOR3) );		g_pEffect->SetValue( "flameTrans", D3DXVECTOR3(0.0, -0.1, 0.0), sizeof(D3DXVECTOR3) );		if( FAILED( g_pEffect->SetTexture( "noiseTexture", g_FlameTexture1 ) ))			OutputDebugString( "Impossibile assegnare noiseTexture\n" );		if( FAILED( g_pEffect->SetTexture( "flameTexture", g_FlameTexture2 ) ))			OutputDebugString( "Impossibile assegnare flameTexture\n" );


RENDER FUNCTION()
ThisTime = timeGetTime();    Flame.Update();		g_pEffect->SetFloat( "ticks", (float)ThisTime );		g_pD3DDevice->GetTransform( D3DTS_WORLD, &mWorld );		g_pD3DDevice->GetTransform( D3DTS_VIEW, &mView );		g_pD3DDevice->GetTransform( D3DTS_PROJECTION, &mProj );		mWorldViewProjection = mWorld * mView * mProj;		g_pEffect->SetMatrix( "wvp", &mWorldViewProjection );		g_pEffect->SetMatrix( "world", &mWorld );    UINT cPasses=0; 	// Apply the technique contained in the effect 	g_pEffect->Begin(&cPasses, 0);	for (iPass = 0; iPass < cPasses; iPass++)	{	    g_pEffect->BeginPass(iPass);	    // Render the mesh with the applied technique		g_FlameMesh->MeshData.pMesh->DrawSubset(0);		    g_pEffect->EndPass();	}	g_pEffect->End();


Result is always the same...

I'm beginning to think that I load in a wrong way the mesh undeclaring Vertex type or FVF...

THANKS for help!!!
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
Even if I change color (flameColor) my g_FlameMesh still remains white!!!

How can I solve all my problems?!

[Edited by - GENTS on January 6, 2005 9:39:54 AM]
----------------------------------------------- - GENTS -"Every man dies, not every man really lives"[William Wallace] - visit my website: GENTS.it -- Using Effect files with DirectX 9 Basics Tutorial -- MilkShape 3D models and OpenGL ES Tutorial -
MMMMMMMM... have you tried FXComposer in order to get correct values for the parameters? Maybe some colors aren't ok.

Also, do do you have the flame.png file. Some people reported it missing. I'd suggest you to convert the flame FX into another format like flame.png and add some alpha information in order to mask transparent areas (black areas).

Also, I'd suggest to use FX default values while you are testing it.

Luck!
Guimo
Whick texture are you using for the flame?

This topic is closed to new replies.

Advertisement