September 09, 2010, 05:49:58 AM
News: As promised, here is another update of the editor with improvements and bug fixes
Pages: [1]
Print
Author Topic: Animated 2d texture  (Read 1349 times)
Tamarin
Full Member
***
Posts: 208


View Profile
« on: April 04, 2009, 02:15:42 PM »

Hi,

I have created a series of 100 256x256 normal maps and arranged them into a single image. I want to tile a single 256x256 piece of the image onto an object and then cycle through the other 99 images. I have no idea how to do this, or if it would be part of the image loading code or the programmable  shader code. I am trying to create an animated displacement shader using 2d textures for water or clouds. I am attaching the image which cycles from bottom left to top right.

http://www.mediafire.com/file/cnjcmm3yuzr/water_animation_map.rar
Logged
Jochen Stier
Administrator
Sr. Member
*****
Posts: 498


Founder/Programmer

jochen.stier@gmail.com
View Profile
« Reply #1 on: April 04, 2009, 03:39:25 PM »

You can use the timer variable gs_Time in the vertex shader to cycle and clamp the texture coordinates. I have used your texture and gave it a try.

First create a tree view like so

--World
   -- Shader
   -- Texture
   -- Plane


Put the water_animation.jpg into the \textures directory and then assign it to the Texture node. Then double click the Shader node and copy the following into the vertex shader:

Code:
uniform float gs_Time;

void main()
{
float time = fract(gs_Time/10000.0);
float tile = floor(time*100.0);

gl_TexCoord[0] = vec4(tile/10.0,fmod(tile,10.0),1,1) + gl_MultiTexCoord0/10.0;
gl_Position = ftransform();
}

Then copy this into the fragment shader:

Code:
uniform sampler2D Texture;

void main (void)
{
gl_FragColor = texture2D (Texture,  gl_TexCoord[0].st );
}


That's it. You should see your texture cycling. You can change the speed by changing the denomiator in fract(gs_Time/10000.0);






Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #2 on: April 04, 2009, 04:33:00 PM »

Thanks Jochen, it is nice to just to have the answer!

I hope I will be able to pick a few things up along the way Roll Eyes I found a good method for creating these animated textures in Blender so I'm going to see what kind of effects I can get (mixing noise images).We should be able to use the normal values to displace the surface of an object(I think), and with a reflection texture  make a somewhat convincing water effect. I ordered a book on game math to try and understand how the lighting works a bit better (all that vector math).  I'm not sure what the best method for creating these animated effects are. I know a 3d texture is 256x256x256 and my 2d texture is 256x256x100, but the 3d texture is done in gray scale, while the texture is color(with normals built in). I think for my next animation I will make an image 256x256x50 or smaller. The texture might be faster because the values are stored like a look-up table rather than on the fly, but that is pure conjecture. I read somewhere that Half-Life 2 used animated textures for their water effects, so they can't be all-bad.
Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #3 on: April 04, 2009, 07:39:32 PM »

It seems to be skipping after 10 frames, so I'll have to change the image, or change the code.
Logged
Jochen Stier
Administrator
Sr. Member
*****
Posts: 498


Founder/Programmer

jochen.stier@gmail.com
View Profile
« Reply #4 on: April 04, 2009, 07:59:07 PM »

He Tamarin, if you are interested in 3D noise shaders, Geist3D already supports 3D noise textures. Just have look at the fragment shaders for the shuttle or the stargate in demo7. Or look at noise shader in demo6 which is under the “face node” in the treeview somewhere.  I am also using the same noise for the clouds. You should be looking for gs_Noise3D in the fragement shader.

This noise is produced by a really small 3D Perlin noise texture (32x32x32), but a few lookups are necessary to remove regularities. I got much of the code from a Graphics Gems article written by Perlin himself. Because the texture is so small it fits into the cache and the lookups are thus quite inexpensive. But, you need a lot of them, especially if you want to compute normals. I think in the future this will be the way to go though to generate procedural textures. The texture that you generated takes 6 Megs on the graphics card, but you can use the same one for all kinds of effects.

I just quickly whipped together the code in those shaders. I will try to get around tomorrow and see why it only cycles through 10 textures instead of all 100. It’s definitely not optimal.
Logged
Jochen Stier
Administrator
Sr. Member
*****
Posts: 498


Founder/Programmer

jochen.stier@gmail.com
View Profile
« Reply #5 on: April 06, 2009, 07:27:35 PM »

Use this one as the vertex shader... that should do the trick

Code:
uniform float gs_Time;

void main()
{
float tile = floor(gs_Time/100.0);

float x = fmod(tile,10.0)*0.1;
float y = floor(tile/10.0)*0.1;

gl_TexCoord[0] = vec4(x,1.0-y,1,1) + gl_MultiTexCoord0/10.0;
gl_Position = ftransform();
}


Looks very cool. With proper lighting this could turn into nice water.
« Last Edit: April 06, 2009, 07:31:18 PM by Jochen Stier » Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #6 on: April 06, 2009, 08:17:22 PM »

That works.
Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #7 on: April 06, 2009, 09:57:38 PM »

Code:
uniform sampler2D Texture;

void main (void)
{
vec3 noiseVec;
vec2 displacement;

displacement = gl_TexCoord[0].st;

noiseVec = normalize(texture2D(Texture, displacement.xy).xyz);
noiseVec = (noiseVec * 2.0 - 1.0) * 0.035;

gl_FragColor = texture2D(Texture, gl_TexCoord[0].st + noiseVec.xy);
}

Try that for a fragment shader.

I'm trying to get the current texture to affect normals only( I would also like to add some kind of reflection to the water.)

I also changed one line in the vertex shader.

Code:
float tile = floor(gs_Time/50.0);
« Last Edit: April 07, 2009, 11:20:52 AM by Jochen Stier » Logged
Jochen Stier
Administrator
Sr. Member
*****
Posts: 498


Founder/Programmer

jochen.stier@gmail.com
View Profile
« Reply #8 on: April 07, 2009, 06:15:47 PM »

if you want the texture to effect the normals, then you needs some kind of lighting model. The first step is to compute the eye, light and normal vectors in the vertex shader and then pass them to the fragment shader like so:


Code:
uniform float gs_Time;

varying vec3 lightVec;
varying vec3 normalVec;
varying vec3 eyeVec;

void main()
{
vec4 vertex =gl_ModelViewMatrix*gl_Vertex;
lightVec =  normalize(gl_LightSource[1].position.xyz - vertex.xyz);
normalVec = normalize(gl_NormalMatrix * gl_Normal);
eyeVec = -vertex;

float tile = floor(gs_Time/50.0);
float x = fmod(tile,10.0)*0.1;
float y = floor(tile/10.0)*0.1;
gl_TexCoord[0] = vec4(x,1.0-y,1,1) + gl_MultiTexCoord0/10.0;

gl_Position = ftransform();
}

Then, in the fragment shader you have to use these vectors to compute a lighting model. In this case it's phong, but there is a bunch of others, like gooch, which makes things look like plastic. There is also toon shading that looks like it's a cartoon drawing.  You then perturb the normal vector with the ones from your map like so:

Code:
uniform sampler2D Texture;

varying vec3 lightVec;
varying vec3 normalVec;

void main (void)
{
vec3 noiseVec;
noiseVec = normalize(texture2D(Texture, gl_TexCoord[0].st).xyz);
noiseVec = (noiseVec * 2.0 - 1.0) ;

vec3 N = normalize(normalVec + noiseVec);
vec3 L = normalize(lightVec);

float Kd = max(dot(N, L), 0.0);
vec4 diffuse  = Kd * gl_LightSource[1].diffuse;
vec4 ambient  =  gl_LightSource[1].ambient;

gl_FragColor = diffuse + ambient;
}


There is no secular reflection component in here yet, so you don't get the bright highlights. Also, if you want the water to reflect the environment then things get real complicated, but also much more realistic.

Don't forget to insert a light node into the scene. I.e, first add a transform, and under the transform add a light node. This will then be gl_LightSource[1] in the shader. You can move the light by selecting the transform in the treeview. As you can see in the code, the shader is using the ambient and diffuse component of the light. You can change those when you select the light node in the tree view.





« Last Edit: April 07, 2009, 07:10:07 PM by Jochen Stier » Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #9 on: April 07, 2009, 07:00:55 PM »

I'm guessing for reflecting the environment you would need to make a texture cubemap from the environment or some such thing, probably have to update it all the time, might be interesting shader to put on a spaceship.

I get a compile error when I try this code. Thanks for explaining it, I'm starting to understand some of it.
Logged
Jochen Stier
Administrator
Sr. Member
*****
Posts: 498


Founder/Programmer

jochen.stier@gmail.com
View Profile
« Reply #10 on: April 07, 2009, 07:51:23 PM »

Yeah exactly, you need a cubemap. Most games just use a fixed cubemap of the sky and the mountains. You can also create a new cubemap for each rendering step, but that takes 9 (!) additional rendering steps.

I just tried the shaders again. It works for me ... make sure the first one is the vertex shader and the second one is the fragment shader.
Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #11 on: April 10, 2009, 01:19:21 AM »

Here is a new Shader to try out. This one uses less resources I think. I'm using a 256x256 for the displace.



Vertex:
Quote
void main()
{   
   gl_TexCoord[0] = gl_MultiTexCoord0;
   gl_Position = ftransform();      
}

Pixel:
Quote
uniform sampler2D Texture_d;
uniform sampler2D Texture_n;
uniform float gs_Time;

void main (void)
{
   vec3 noiseVec;
   vec2 displacement;
   float scaledTimer;

   displacement = gl_TexCoord[0].st;

   scaledTimer = (gs_Time/10000.0)*0.1;

   displacement.x += scaledTimer;
   displacement.y -= scaledTimer;

   noiseVec = normalize(texture2D(Texture_n, displacement.xy).xyz);
   noiseVec = (noiseVec * 2.0 - 1.0) * 0.035;
   
   gl_FragColor = texture2D(Texture_d, gl_TexCoord[0].st + noiseVec.xy);
}
I found this shader on the web and I really like it Grin
Logged
Jochen Stier
Administrator
Sr. Member
*****
Posts: 498


Founder/Programmer

jochen.stier@gmail.com
View Profile
« Reply #12 on: April 12, 2009, 01:15:37 PM »

You got two textures here, Texture_d and Texture_n. What does your diffuse texture look like? I like this shader too.... I think I can actually use some of this for the planet water.
Logged
Tamarin
Full Member
***
Posts: 208


View Profile
« Reply #13 on: April 12, 2009, 03:24:47 PM »

I'm using _d for diffuse, _n for normal.  The attached image is the one I was using for the effect. The diffuse could be any other texture.

Also, while talking about shaders. I was thinking about getting rid of the tiled effect on the land. What if we tiled the ground twice with different textures and threw a noise alpha map between them. More texture calls but maybe a nice effect.

If you could write a small demo that shows a shader variable connected to a slider through lua that might be cool.

gl_MultiTexCoord0 would be whatever uv mapping comes with a model, is that correct? I'm thinking of adding multiple uv maps to some of the larger objects, so we might be able to use gl_MultiTexCoord1, etc.

How difficult is it to add some spice to the windows in the game client?

These are all things I'm currently thinking about Smiley
Logged
Pages: [1]
Print
Jump to: