EXPLOSION SHADER

A geometry shader in hlsl using FX composer to resemble an explosion. This shader can be used on any object you put the shader on.

This is the source code of the shader.

 
//GLOBAL VARIABLES
//****************
float4x4 gMatrixWorldViewProj : WORLDVIEWPROJECTION;
float4 gColorDiffuse : COLOR = float4(1.0, 1.0, 1.0, 1.0);
float4x4 gMatrixWorld : WORLD;

float3 gLightDirection:DIRECTION
<
	string UIName = "Light Direction";
	string Object = "TargetLight";
> = float3(0.577f, 0.577f, 0.577f);

float gTimer<
	string UIName = "Timer Elapsed";
	string UIWidget = "Slider";
	float UIMin = 0.0f;
	float UIMax = 5.0f;
	float UIStep = 0.01f;
> = 0.0f;

float gThickness<
	string UIName = "Thickness";
	string UIWidget = "Slider";
	float UIMin = 0.0f;
	float UIMax = 0.5f;
	float UIStep = 0.01f;
> = 0.0f;

float gSpeed<
	string UIName = "Explosion Speed";
	string UIWidget = "Slider";
	float UIMin = 0.0f;
	float UIMax = 1.0f;
	float UIStep = 0.01f;
> = 0.0f;

float gExplosionForce<
	string UIName = "Explosion Force";
	string UIWidget = "Slider";
	float UIMin = 0.0f;
	float UIMax = 10.0f;
	float UIStep = 0.01f;
> = 0.0f;

float gBreakability<
	string UIName = "Strength";
	string UIWidget = "Slider";
	float UIMin = 0.0f;
	float UIMax = 10.0f;
	float UIStep = 0.01f;
> = 0.0f;

//float3 gEyePos
//<
//string UIName = "Eye Position"
//>=float3(10,5,0);

float3 gGravity
<
	string UIName = "Gravity Vector";
> = float3(0.577f, 0.577f, 0.577f);

float3 gExplosionLocation
<
	string UIName = "Explosion Location";
> = float3(0.0f, 0.0f, 0.0f);

float gExplosionFalloffTime<
	string UIName = "Falloff Time";
	string UIWidget = "Slider";
	float UIMin = 0.0f;
	float UIMax = 10.0f;
	float UIStep = 0.01f;
> = 0.0f;
//STATES
//******
RasterizerState gRasterizerState 
{ 
	FillMode = SOLID;
	CullMode = NONE; 
};

SamplerState samLinear
{
    Filter = MIN_MAG_MIP_LINEAR;
    AddressU = Wrap;// of Mirror of Clamp of Border
    AddressV = Wrap;// of Mirror of Clamp of Border
};

BlendState EnableBlending
{
	BlendEnable[0] = TRUE;
	SrcBlend = SRC_ALPHA;
	DestBlend = INV_SRC_ALPHA;
};

DepthStencilState EnableDepth
{
	DepthEnable = TRUE;
	DepthWriteMask = ALL;
};

//**********
// STRUCTS *
//**********
struct VS_INPUT
{
	float3 Position : POSITION;
	float4 Color : COLOR;
	float3 Normal : NORMAL;
};

struct VS_OUTPUT
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR;
	float3 Normal : NORMAL;
};

struct GS_DATA
{
	float4 Position : SV_POSITION;
	float4 Color : COLOR;
	float3 Normal : NORMAL;
};

//MAIN VERTEX SHADER
//******************
VS_OUTPUT MainVS(VS_INPUT input){
	VS_OUTPUT output = (VS_OUTPUT)0;
	
	//Set the variables
	output.Position = float4(input.Position,1.0f);
	output.Color = gColorDiffuse;
	output.Normal = normalize(input.Normal);
	
	return output;
}

//GEOMETRY SHADER
//*****************
void CreateVertex(inout TriangleStream<GS_DATA> triStream, float3 pos, float3 normal, float4 color)
{
	GS_DATA output = (GS_DATA)0;
	output.Position = mul(float4(pos, 1), gMatrixWorldViewProj);
	output.Normal = mul(normal, (float3x3)gMatrixWorld);
	output.Color = color;
	triStream.Append(output);
}

[maxvertexcount(24)]
void Explosiongenerator(triangle VS_OUTPUT vertices[3], inout TriangleStream<GS_DATA> triStream)
{
	
	//----------------
	//GEOMETRY SHADER
	//----------------
	float3 triCenter, explosionVector, offset, gravity;
	
	//CALCULATE VECTOR AWAY FROM EXPLOSION CENTER
	triCenter = (vertices[0].Position + vertices[1].Position + vertices[2].Position) / 3;
	float3 fromCenter = normalize(triCenter-gExplosionLocation);
	
	float explosionForce = gExplosionForce-(distance(triCenter,gExplosionLocation));
	if(explosionForce<=gBreakability)	
	{
		
		explosionForce = 0;
	}
	
	//CREATE THE OFFSET FROM THE STARTLOCATION
	if(gTimer*gSpeed>=explosionForce)
	{
		offset = fromCenter*explosionForce*explosionForce + 0.5*-fromCenter*pow(explosionForce,2);
	}else{
		offset = fromCenter*gTimer*gSpeed*explosionForce + 0.5*-fromCenter*pow(gTimer*gSpeed,2);
	}

	 //GRAVITY
	 gravity = 0.5*gGravity*pow(gTimer*gSpeed,2);
	 
	if(explosionForce==0)
	{
		offset = float3(0,0,0);
		gravity = float3(0,0,0);
	}
	 
	 //CALCULATE THE FINAL POSITIONS OF THE CENTER
	 float3 point1, point2, point3;
	 point1 = vertices[0].Position+offset+gravity;
	 point2 = vertices[1].Position+offset+gravity;
	 point3 = vertices[2].Position+offset+gravity;
	 
	 if(point1.y <= 0)
	 {
		 point1.y = 0;
	 }
	 if(point2.y <= 0)
	 {
		 point2.y = 0;
	 }
	 if(point3.y <= 0)
	 {
		 point3.y = 0;
	 }
	
	 //CALCULATE OTHER POINTS FOR THICKNESS
	 float3 point4, point5, point6;
	 if(gThickness > 0) 
	 {
		 point4 = point1-(vertices[0].Normal*gThickness);
		 point5 = point2-(vertices[1].Normal*gThickness);
		 point6 = point3-(vertices[2].Normal*gThickness);
	 }

	 
	 
	//RECALCULATE NORMALS
	float3 normal1,normal2,normal3;
	float3 normalAll;
	
	if(gTimer*gSpeed>0 && explosionForce>0)
	{
		
		//if(acos(dot(triCenter-)))
		//{
		//}
		normal1 = -normalize(cross(point3-point1,point2-point1));
		normal2 = normal1;
		normal3 = normal1;
	}else{
		normal1=vertices[0].Normal;
		normal2=vertices[1].Normal;
		normal3=vertices[2].Normal;
	}
	//Create Existing Geometry
	CreateVertex(triStream,point1,normal1,vertices[0].Color);
	CreateVertex(triStream,point2,normal2,vertices[1].Color);
	CreateVertex(triStream,point3,normal3,vertices[2].Color);
	

		
	//Create other side (thickness)
	if(gThickness > 0) 
	 {
		triStream.RestartStrip();
		CreateVertex(triStream,point4,-normal1,vertices[0].Color);
		CreateVertex(triStream,point5,-normal2,vertices[1].Color);
		CreateVertex(triStream,point6,-normal3,vertices[2].Color);	 
		if(gTimer*gSpeed>0)
		{
	 //SIDES OF THICKNESS (6 times)
	 //FIRST	
	 	normalAll = normalize(cross(point3-point1,point4-point1));
	 	triStream.RestartStrip();		
		CreateVertex(triStream,point1,normalAll,vertices[0].Color);
		CreateVertex(triStream,point3,normalAll,vertices[1].Color);
		CreateVertex(triStream,point4,normalAll,vertices[2].Color);
	 //SECOND
		normalAll = normalize(cross(point3-point4,point6-point4));
	 	triStream.RestartStrip();		
		CreateVertex(triStream,point4,normalAll,vertices[0].Color);
		CreateVertex(triStream,point3,normalAll,vertices[1].Color);
		CreateVertex(triStream,point6,normalAll,vertices[2].Color);
	 //THIRD
	 	normalAll = normalize(cross(point2-point3,point5-point3));
	 	triStream.RestartStrip();		
		CreateVertex(triStream,point3,normalAll,vertices[0].Color);
		CreateVertex(triStream,point2,normalAll,vertices[1].Color);
		CreateVertex(triStream,point5,normalAll,vertices[2].Color);
	 //FOURTH
	 	normalAll = normalize(cross(point6-point5,point3-point5));
	 	triStream.RestartStrip();		
		CreateVertex(triStream,point5,normalAll,vertices[0].Color);
		CreateVertex(triStream,point6,normalAll,vertices[1].Color);
		CreateVertex(triStream,point3,normalAll,vertices[2].Color);
	 //FIFTH
	 	normalAll = normalize(cross(point1-point2,point4-point2));
	 	triStream.RestartStrip();		
		CreateVertex(triStream,point2,normalAll,vertices[0].Color);
		CreateVertex(triStream,point1,normalAll,vertices[1].Color);
		CreateVertex(triStream,point4,normalAll,vertices[2].Color);
	 //SIXTH
	 	normalAll = normalize(cross(point5-point4,point2-point4));
	 	triStream.RestartStrip();		
		CreateVertex(triStream,point4,normalAll,vertices[0].Color);
		CreateVertex(triStream,point5,normalAll,vertices[1].Color);
		CreateVertex(triStream,point2,normalAll,vertices[2].Color);
		}	 
	 }
}

//MAIN PIXEL SHADER
//*****************
float4 MainPS(GS_DATA input) : SV_TARGET {
	
	input.Normal=-normalize(input.Normal);
	float alpha = input.Color.a;
	float3 color = input.Color.rgb;
	float s = max(dot(gLightDirection,input.Normal), 0.4f);

	return float4(color*s,alpha);
}


//TECHNIQUES
//**********
technique10 DefaultTechnique {
	pass p0 {
		SetRasterizerState(gRasterizerState);
		SetDepthStencilState(EnableDepth, 0);
		SetBlendState(EnableBlending, float4(0.0f, 0.0f, 0.0f, 0.0f), 0xFFFFFFFF);
		
		SetVertexShader(CompileShader(vs_4_0, MainVS()));
		SetGeometryShader(CompileShader(gs_4_0, Explosiongenerator()));
		SetPixelShader(CompileShader(ps_4_0, MainPS()));
	}
}