Saturday, June 9, 2012

Explosion Shader V2.


So, from my last post with my "explosion" shader, I have made it a bit more controllable and "realistic". 

Here's a video of 3 explosions with varying "weights" of the object.
The shader isn't really that complex in it's nature and has some easily tweaked values to make it so you can determine a few things about the explosion.

As far as how it's written, I'm going to assume that if you were searching for this kind of shader that you have either been taught or know the basic pipline for Shaders (Vertex -> Optional Geometry -> Pixel) and would also like to say that I'm by no means an expert in shader writing either so if you happen to see something I could improve, feel free to leave a comment, it's always appreciated.  On to the code Snippets!

K, so this shader uses a few things that really help to determine the explosion.
1 - float SpeedVariation; This will help to create differences in how much speed the exploded material will gain at explode time with 1 being a very small explosion and 5 being the kind that I used in the video.

2 - float MaterialWeight; This is what determines how fast your exploded pieces will fall after they have been propelled out.

3 - float ExplosionViolence; This is an extra parameter to help make the explosion either big or small. Smaller the EV, the smaller the explosion. (It also gives some weird explosions if you use numbers closer to 0 like 1 or 2. Greater than 3 is usually a safe bet for a decent looking explosion.

I have 3 random float2 's that I use to get some more randomness in the texture coord look up and my speed calculation as well. rand1 = 0.09, 0.05 rand2 = 0.075, 0.05 rand3 = 0.09, 0.04

Those variables coupled with a Time variable help to make it propel and fall with some realism.
//Sampler States
I use 2 sampler states for this as well, one that is used for the diffuse and the other for sampling the gradient/noise.

SamplerState samGradient
 Address U and V are both Clamp
 and the diffuse one is just AddressU and V with Wrap;

There are also 3 texture2D's that I use for this which are as follows.

1 - Diffuse - just whatever you want your object to have for it's regular texture

2- Noise - This you put in a noise texture to get some randomness for the distance the exploded pieces will travel

3 - Gradient  - I use a gradient of 1 X 256 that is white to black.

We sample the Noise and Gradient in the Geometry shader to help give just a touch more randomness.

I use triangle as my Geometry input as we only need the 3 verts per tri and the [maxvertexcount] is 3 as well since we only do the calculations for movement per tri.

//Geometry Shader

So the way I did this shader was to make it so the pieces fly in a somewhat up and out movement (Outwards explosion from the center) the way I do this is by grabbing all the normals of the tri and adding them then taking the average (divide by 3) and saving this in a float3.

I then take the average of the texture coordinates and use them to do a SampleLevel on the noise and gradient textures.

float Noise = 2.0f * m_TextureNoise.SampleLevel(samGradient, (aveTextureCoord +  m_random),0).r - 1.0f;

and same but a different randomvalue for the gradient one.
One of my math teachers loved the word Lerp and Slerp, now I never really bothered to use them that often but I figured this would be a good time to use a lerp go get a bit of randomness.

for my "speed" calculation I do a float3 (0, lerp( Noise, Gradient, m_SpeedVariation), 0);

Gravity is the negative of the "MaterialWeight" * time (only in the Y direction obviously).

Now the first bit that I was trying to get the variations to work I didn't have this calculation, this came from a friend of mine Jay Heggerud that said if I wanted to get some more variation on the speeds/distances the pieces travel to maybe try making my initial speed based on the min speed I wanted + the speed variation * random value for differences. 

So this puts my vi calculation at something like this (to get a random minimum speed on the initial we use the Noise and put it like this.

float3 vInitial = float3(Noise * m_SpeedVar , Noise * m_SpeedVar , Noise * m_SpeedVar);

Now we're pretty much at the end of the shader. The only part left is to plug things into some equations from Frank Luna's Intro to DirectX book (where I also got the idea to make an explosion shader)

So it's a somewhat basic Physics equation we put into make the triangles travel and fall kinda realistically.

 0.5 t^2 a + t vi + p0;  so this more or less translates into 0.5f * accel * time squared + vinital * time + the inital position;

for the initial Position we use another formula to represent the explosion, also from Frank Luna

p(i) = p(i) + tn where i = each vertex 1,2,3

so if we shove that in there as well we get

 0.5 t^2 a + t vi +(p + tn);

Now I deviate from the equation in the name of randomness and threw some other calculations into it as well.

The full calculation for the position of one vertex  is

pos[0] = 0.5f * gravity * (m_Time * m_Time) + (vInitial * m_Time) + ((vertices[0].Position -vertices[2].Normal * m_Time)+(normals * (m_Time*(m_ExplosionViolence * sin(cos((m_SpeedVariation * speed )))))));

Output each vertex with it's respective normals and texture coords and bam, you're done really.

Hope this has possibly helped or at least been somewhat of an interesting read, I'm gonna go write my paper for this now haha.


No comments:

Post a Comment

Hey, I love to have feedback about either how the post was or if there's even a topic you want me to talk about/tutorial, so let me know and I'll see what I can do. We only grow if we grow together.