The new shader example is about how to simulate a shock-wave over a texture.
It is really useful for my explosion. The result is pretty cool. It looks like a transparent shock-wave, and I think I could use it for water wave. If you can make a better version of it, I'll appreciate to get it :)
I could have used 2 textures (the real texture + a normal-like map) to implement it. However I'm not sure if the multi-texture is part of all the almost recent devices, I use a distance algorithm.
Video from YouTube to show the effect of the shockwaves :
The goal is to make like a circle around a point and to get the texture displaced at this point (and around). Instead of using the whole map texture which would limit the number of explosion to 1 (or to loop inside the shader which is, I think not a good idea), I create a square of the size of the shock-wave for each explosion with the map texture applied on it.
- For each of those explosions, I get the distance of the pixel (in the pixel shader) from the center of the explosion.
- I compare is the distance is ~ equal to time ( an increasing value from 0 to the size of the shock-wave ) and I apply a algorithm to generate a displacement (This one needs to be improved)
This is all.
To get a good result, don't hesitate to try different values/algorithms. I wrote different ones before choosing one.
The values used are for a shock-wave with a size of 3 units... Adapt the values depending of your scale (1 unit = the size of a case in my map)
It is really a simple one.
uniform sampler2D tex;
uniform float posX;
uniform float posY;
uniform float time;
uniform sampler2D tex;
uniform vec2 center;
uniform float time;
void main (void)
{
float distance = distance(gl_TexCoord[0].st,center);
if (distance <= time + 0.025 && distance >= time - 0.025) {
float ecart = (distance - time); // value between -0.02 & 0.02
float powEcart = 1.0-pow(abs(ecart*40.0),0.4); // value between -1 & 1 (because 0.02 * 50 = 1)
float ecartTime = ecart * powEcart; // value between -0.02 & 0.02
vec2 diff = normalize(gl_TexCoord[0].st - center); // get the direction
vec2 newTexCoord = gl_TexCoord[0].st + (diff * ecartTime);
gl_FragColor = texture2D(tex, newTexCoord.st) * gl_Color;
} else {
discard; //gl_FragColor = texture2D(tex, gl_TexCoord[0].st) * gl_Color;
}
}Just the basic one
uniform vec2 center;
uniform float time;
void main(void)
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
}This was just a example of how to generate a shock-wave, you can easily improve it.
I upload an image with a grid to see the shockwave but to see the real result, look at the video.
Comments
Normal map
Someone asked me on facebook why I don't use a normal map and a light to generate a better 3D effect ?
I'll try to answer it.
First of all, my game is using 2D texture in a projection mode, not a perspective mode (why ? because I don't have 3D objects), and there is no light ( why ? because I don't have 3D objects, but I'll add simple spot light later to simulate the shadow parts of the map).
In the other hand, The normal map generation requires the same algorithm as the one I use to make the wave actually. For each pixel I have to calculate the normal. And the question is, how the normal map could be useful ? It is really useful to generate the light impact on a 3D texture, but on a shock-wave (which is supposed to be transparent) I don't see any interest. Maybe to get the height of the map and then displace the map depending of this value. Whatever... It seems too complex to use this techniques.
About the 2nd texture I wrote in the post, I thought about a simple ring with a pow (x,04) gradient black->white from the ring (circle) to the border of the ring (as shown on the picture). The goal was to increase the size of the texture when the shock-wave is far. The shader algorithm would be simpler but the result is :
- farther the shock-wave is, bigger it is (remember, I have to increase the texture size, so the ring of the texture will be bigger too).
- It is dependent of the zoom (If I get too close to the texture, i'll be a "pixelized" effect.... My shader is like a vectorial image, you can zoom into the texture, the result is always perfect)
I hope those explanations are useful