Flowing Rivers

A place to show off your latest screenshots and for people to comment on them. Only start a new thread here if you have some nice images to show off!
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Friday or saturday, the code should be ready (together with a new movie)

- umpf
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

new video is ready!
watch it at http://www.youtube.com/watch?v=TeSuNYvXAiA&hd=1
(sorry for the Germans, it uses the same music, which is blocked in Germany)
Last edited by umpf on Fri Oct 22, 2010 9:03 pm, edited 1 time in total.
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Code: Select all

the boring part... the vertex shader (in this case for osgviewer)

//
// Vertex shader 

varying vec3  Normal;
varying vec3  EyeDir;


varying vec2 texNormal0Coord;
varying vec2 texColorCoord;
varying vec2 texFlowCoord;

uniform float osg_FrameTime;

varying float myTime;
void main(void)
{
	
    gl_Position    = ftransform();
    Normal         = normalize(gl_NormalMatrix * gl_Normal);
  
    vec4 pos       = gl_ModelViewMatrix * gl_Vertex;
    EyeDir         = pos.xyz;

    texNormal0Coord   = gl_MultiTexCoord1.xy;
    texColorCoord = gl_MultiTexCoord3.xy;
    texFlowCoord = gl_MultiTexCoord2.xy;

    myTime = 0.01 * osg_FrameTime;
}
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

and the interesting part... the fragment shader
I will pack everything (including osg example) into a zip file and make it available for download from somewhere.
I'll post the link here. But for now, get inspired by the source below ;-)

advantages of this shader:
- flow in any direction
- waves can rotate with the flow direction
- waves can be scaled (in this demo the waves are smaller on the inside)
- no visible tiling (even for very large surfaces like open sea)
- no pulsing effect


This shader creates animated water by transforming normalmaps.
The scaling and rotation of the normalmaps is done per tile
and is constant per tile. Each tile can have its own parameters
for rotation, scaling, and speed of translation
To hide the seams between the tiles, all seams have another tile
centered on top of the seam. The opacity of the tiles decreases towards the
edge of the tiles, so the edge isn't visible at all.
Basically, all points have four tiles (A,B,C and D), mixed together
(although at the edges the contribution of a tile to this mix is
reduced to zero).
The mixing of the tiles each with different parameters gives a nice
animated look to the water. It is no longer just sliding in one direction, but
appears to move more like real water.

The resulting sum of normalmaps, is used to calculate the refraction of the clouds
in a cube map and can also be used for other nice effects. In this example the
colormap of the material under water is distorted to fake some kind of refraction
(for this example the water is a bit too transparent, but it shows this refraction
better)

A flowmap determines in the red and green channel the normalized direction of the
flow and in the blue channel wavelength.
The alpha channel is used for the transparency of the water. Near the edge, the
water becomes less deep and more transparent. Also near the edge, the waves tend
to be smaller, so the same alpha channel also scales the height of the waves.
Currently the wavelength is in its own channel (blue), but could be pre-multiplied
to the red and green channels. This makes this channel available for changing the
speed of the waves per tile.

you can do whatever you want with this shader except claiming rights
you may sell it, but you cannot prevent others from selling it, giving it away
or use it as they please.

Having said that, it would be nice if you gave me some credit for it, when you use
it.
movie at youtube: http://www.youtube.com/watch?v=TeSuNYvXAiA

Thanks to Bart Campman, Pjotr Svetachov and Martijn Kragtwijk for their help.

Code: Select all

//
// Fragment shader, Tiled Directional Flow
//
// (c) 2010 frans van hoesel, university of groningen
//
uniform sampler2D normalMap;
uniform sampler2D colorMap;
uniform sampler2D flowMap;
uniform samplerCube cubeMap;
uniform float osg_FrameTime;
uniform mat4 osg_ViewMatrixInverse;

varying vec3  Normal;
varying vec3  EyeDir;
varying vec2 texNormal0Coord;
varying vec2 texColorCoord;
varying vec2 texFlowCoord;
varying float myTime;

void main (void)
{

    float texScale = 35.0;
    float texScale2 = 10.0;
    float myangle;
    float transp;
    vec3 myNormal;
    vec2 mytexFlowCoord = texFlowCoord * texScale;
    // ff is the factor that blends the tiles.
    vec2 ff =  abs(2*(frac(mytexFlowCoord)) - 1) -0.5; 	  
    // take a third power, to make the area with more or less equal contribution
    // of more tile bigger
    ff = 0.5-4*ff*ff*ff;
    // ffscale is a scaling factor that compensates for the effect that
    // adding normal vectors together tends to get them closer to the average normal
    // which is a visible effect. For more or less random waves, this factor
    // compensates for it 
    vec2 ffscale = sqrt(ff*ff + (1-ff)*(1-ff));
    vec2 Tcoord = texNormal0Coord  * texScale2;
    
    // offset makes the water move
    vec2 offset = vec2(myTime,0);
    
    // I scale the texFlowCoord and floor the value to create the tiling
    // This could have be replace by an extremely lo-res texture lookup
    // using NEAREST pixel.
    vec4 sample = texture2D( flowMap, floor(mytexFlowCoord)/ texScale);
    
    // flowdir is supposed to go from -1 to 1 and the line below
    // used to be sample.xy * 2.0 - 1.0, but saves a multiply by
    // moving this factor two to the sample.b
    vec2 flowdir = sample.xy -0.5;    
   
    // sample.b is used for the inverse length of the wave
    // could be pre-multiplied in sample.xy, but this is easier for editing flowtexture
    flowdir *= sample.b;
    
    // build the rotation matrix that scales and rotates the complete tile
    mat2 rotmat = mat2(flowdir.x, -flowdir.y, flowdir.y ,flowdir.x);
    
    // this is the normal for tile A
    vec2 NormalT0 = texture2D(normalMap, rotmat * Tcoord - offset).rg;
    
    // for the next tile (B) I shift by half the tile size in the x-direction
    sample = texture2D( flowMap, floor((mytexFlowCoord + vec2(0.5,0)))/ texScale );
    flowdir = sample.b * (sample.xy - 0.5);
    rotmat = mat2(flowdir.x, -flowdir.y, flowdir.y ,flowdir.x);
    // and the normal for tile B...
    // multiply the offset by some number close to 1 to give it a different speed
    // The result is that after blending the water starts to animate and look
    // realistic, instead of just sliding in some direction.
    // This is also why I took the third power of ff above, so the area where the
    // water animates is as big as possible
    // adding a small arbitrary constant isn't really needed, but helps to show
    // a bit less tiling in the beginning of the program. After a few seconds, the
    // tiling cannot be seen anymore so this constant could be removed.
    // For the quick demo I leave them in. In a simulation that keeps running for
    // some time, you could just as well remove these small constant offsets
    vec2 NormalT1 = texture2D(normalMap, rotmat * Tcoord - offset*1.06+0.62).rg ; 
	  
    // blend them together using the ff factor
    // use ff.x because this tile is shifted in the x-direction 
    vec2 NormalTAB = ff.x * NormalT0 + (1-ff.x) * NormalT1;
   
    // the scaling of NormalTab and NormalTCD is moved to a single scale of
    // NormalT later in the program, which is mathematically identical to
    // NormalTAB = (NormalTAB - 0.5) / ffscale.x + 0.5;
	  
    // tile C is shifted in the y-direction 
    sample = texture2D( flowMap, floor((mytexFlowCoord + vec2(0.0,0.5)))/ texScale );
    flowdir = sample.b * (sample.xy - 0.5);
    rotmat = mat2(flowdir.x, -flowdir.y, flowdir.y ,flowdir.x);	      
    NormalT0 = texture2D(normalMap, rotmat * Tcoord - offset*1.33+0.27).rg;
	   
    // tile D is shifted in both x- and y-direction
    sample = texture2D( flowMap, floor((mytexFlowCoord + vec2(0.5,0.5)))/ texScale );
    flowdir = sample.b * (sample.xy - 0.5);
    rotmat = mat2(flowdir.x, -flowdir.y, flowdir.y ,flowdir.x);
    NormalT1 = texture2D(normalMap, rotmat * Tcoord - offset*1.24).rg ;
	   
    vec2 NormalTCD = ff.x * NormalT0 + (1-ff.x) * NormalT1;
    // NormalTCD = (NormalTCD - 0.5) / ffscale.x + 0.5;
    
    // now blend the two values together
    vec2 NormalT = ff.y * NormalTAB + (1-ff.y) * NormalTCD;
	  
    // this line below used to be here for scaling the result
    //NormalT = (NormalT - 0.5) / ffscale.y + 0.5;

    // below the new, direct scaling of NormalT
    NormalT = (NormalT - 0.5) / (ffscale.y * ffscale.x);
    // scaling by 0.3 is arbritrary, and could be done by just
    // changing the values in the normal map
    // without this factor, the waves look very strong
    NormalT *= 0.3; 
     // to make the water more transparent 
    transp = texture2D( flowMap, texFlowCoord ).a;
    // and scale the normals with the transparency
    NormalT *= transp*transp;
 
    // assume normal of plane is 0,0,1 and produce the normalized sum of adding NormalT to it
    myNormal = vec3(NormalT,sqrt(1-NormalT.x*NormalT.x - NormalT.y*NormalT.y));

    vec3 myEye = vec3(osg_ViewMatrixInverse*vec4(EyeDir,0));
    vec3 reflectDir = reflect(myEye, myNormal);
    vec3 envColor = vec3 (textureCube(cubeMap, -reflectDir)); 
    
    // very ugly version of fresnel effect
    // but it gives a nice transparent water, but not too transparent
    myangle = dot(myNormal,normalize(myEye));
    myangle = 0.95-0.6*myangle*myangle;
    
    // blend in the color of the plane below the water	
    
    // add in a little distortion of the colormap for the effect of a refracted
    // view of the image below the surface. 
    // (this isn't really tested, just a last minute addition
    // and perhaps should be coded differently
    vec3 base = vec3 (texture2D(colorMap,texColorCoord + myNormal/texScale2*0.07*transp));
    gl_FragColor = vec4 (mix(base,envColor,myangle*transp),1.0 );

    // note that smaller waves appear to move slower than bigger waves
    // one could use the tiles and give each tile a different speed if that
    // is what you want 
}

User avatar
bernie
Gnoblar
Posts: 3
Joined: Sun Oct 03, 2010 2:38 pm

Re: Flowing Rivers

Post by bernie »

Thanks,that is just fantastic.
Last edited by bernie on Fri Oct 22, 2010 3:28 pm, edited 1 time in total.
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Flowing Rivers

Post by jacmoe »

Let's hand the torch to the OP, shall we? :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
Crashy
Google Summer of Code Student
Google Summer of Code Student
Posts: 1005
Joined: Wed Jan 08, 2003 9:15 pm
Location: Lyon, France
x 49
Contact:

Re: Flowing Rivers

Post by Crashy »

That's great!
It's a bit different from my technique because you use flowmap, but it's a cool and good looking implementation! :) Especially the fact that you have no pulse effect and the seamless normal mapping :!:
Let's hand the torch to the OP, shall we?
What do you mean? (if the "OP" is myself :D )
Follow la Moustache on Twitter or on Facebook
Image
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Flowing Rivers

Post by jacmoe »

Umpf stole your thunder - now you take it back. :mrgreen:

Two really cool implementations in one topic - that's awesome! :)
/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Crashy wrote:That's great!
It's a bit different from my technique because you use flowmap, but it's a cool and good looking implementation! :) Especially the fact that you have no pulse effect and the seamless normal mapping :!:
I do use a flowmap, because I need it in a harbor, with open sea. In the harbor the waves can have very different directions.
But if you have a landscape, and the water flows simply downhill, you could easily calculate the flow from the normal vectors of the landscape. Once you have the flow, you can use this technique to make it look really good ;-)
Last edited by umpf on Fri Oct 22, 2010 5:51 pm, edited 2 times in total.
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

a visual version of 'how to go with the flow' is at http://www.youtube.com/watch?v=wdcvPegJ1lw&hd=1
(no sound, so the Germans are not blocked by MGM)
Last edited by umpf on Fri Oct 22, 2010 9:02 pm, edited 1 time in total.
User avatar
jacmoe
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 20570
Joined: Thu Jan 22, 2004 10:13 am
Location: Denmark
x 179
Contact:

Re: Flowing Rivers

Post by jacmoe »

That video is just too awesome not to be inlined! :D

/* Less noise. More signal. */
Ogitor Scenebuilder - powered by Ogre, presented by Qt, fueled by Passion.
OgreAddons - the Ogre code suppository.
User avatar
aguru
Goblin
Posts: 236
Joined: Tue Feb 26, 2008 5:48 pm
x 3

Re: Flowing Rivers

Post by aguru »

aaah, this is nice! :)
Rhynedahll
Halfling
Posts: 77
Joined: Thu Jan 08, 2009 2:03 am
x 1

Re: Flowing Rivers

Post by Rhynedahll »

This is truly amazing! :o

If I understand correctly, the riverbed is not modeled but rather a texture on a plane?
The Key to Magic -- Book One: ORPHAN
An epic fantasy by H. Jonas Rhynedahll available on Kindle.
The Key to Magic
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Rhynedahll wrote:This is truly amazing! :o

If I understand correctly, the riverbed is not modeled but rather a texture on a plane?
yes that is true. The whole scene is just one square. Not that it needs to be, it is just me being lazy and not modeling any mountains, riverbed or whatever. The whole thing is a bit artificial, but made this way to show the possibilities of the algorithm.
Rhynedahll
Halfling
Posts: 77
Joined: Thu Jan 08, 2009 2:03 am
x 1

Re: Flowing Rivers

Post by Rhynedahll »

Another question:

How does it look up close? Would it be suitable, for instance, for a 3d game where characters are close to the ground?
Or is it best suited to flight sims and the like?
The Key to Magic -- Book One: ORPHAN
An epic fantasy by H. Jonas Rhynedahll available on Kindle.
The Key to Magic
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Rhynedahll wrote:Another question:

How does it look up close? Would it be suitable, for instance, for a 3d game where characters are close to the ground?
Or is it best suited to flight sims and the like?
I think it looks great up close. It is still flat of course. Tomorrow or the day after tomorrow I will release the complete data. I'll try to include a tiny bit of osg, but if you want to be sure you can see it immediately, make sure you have installed the osg binaries http://www.openscenegraph.org/projects/ ... /Downloads. With that comes a bin directory with a demo called osgviewer. I if you can run that, you should be able to zoom in as much as you like :-)
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

JustBoo wrote: I'm curios. I'm familiar with OSG. Are you saying that you are rendering with Ogre, but you are using OSG as the underlying scenegraph that drives the rendering? If so, could you explain that? If not, then I don't understand how you would be using OSG. Could you explain that? :-)
I know I'm going to disappoint you, but I'm not using ogre at all. Just osg. So if anyone wants to make a nice river in Ogre, feel free to adapt the shader so it works with ogre. That should be easy enough, I asume.
Rhynedahll
Halfling
Posts: 77
Joined: Thu Jan 08, 2009 2:03 am
x 1

Re: Flowing Rivers

Post by Rhynedahll »

umpf wrote: I'm I know I'm going to disappoint you, but I'm not using ogre at all. Just osg. So if anyone wants to make a nice river in Ogre, feel free to adapt the shader so it works with ogre. That should be easy enough, I asume.
Lol! :lol:

It's still nice work, but certainly dissapointing. But, no worries from me!
The Key to Magic -- Book One: ORPHAN
An epic fantasy by H. Jonas Rhynedahll available on Kindle.
The Key to Magic
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Finally :D, the complete source including images can be downloaded from our website http://www.rug.nl/cit/hpcv, but more directly from http://www.rug.nl/cit/hpcv/publications/watershader. This should get you going and enable you to write your own shader for use with Ogre.

Instructions are in the readme file.
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

now lets wait and see if Crashy likes it too and tries to build his river using my shader. I would love to see it. :D He never said he would do so, but anyway it would be cool to see the shader being used outside the purpose I wrote it for.
Crashy
Google Summer of Code Student
Google Summer of Code Student
Posts: 1005
Joined: Wed Jan 08, 2003 9:15 pm
Location: Lyon, France
x 49
Contact:

Re: Flowing Rivers

Post by Crashy »

Your shader is really nice, I think I may grab some little things to improve mine. But reminds that rivers in my game are made in the terrain shader, so there are a lot of instructions for the texture splatting and I cannot add a complex implementation for the river stuff. As it is for an aircraft-shooting game I do not need a top notch quality because most of time the player will be far from rivers. But I'm really interested in the normal mapping without tiling you've done ;)

I'm going to investigate this in the next days, stay tuned :)
Follow la Moustache on Twitter or on Facebook
Image
umpf
Gnoblar
Posts: 17
Joined: Tue Oct 12, 2010 7:08 pm

Re: Flowing Rivers

Post by umpf »

Crashy wrote:Your shader is really nice, I think I may grab some little things to improve mine.
if you are going to borrow little things, I suggest you look at my scaling (ffscale in the sourcecode) as this prevents the pulsing effect... at least I assume it will in you case as well.
User avatar
tuan kuranes
OGRE Retired Moderator
OGRE Retired Moderator
Posts: 2653
Joined: Wed Sep 24, 2003 8:07 am
Location: Haute Garonne, France
x 4
Contact:

Re: Flowing Rivers

Post by tuan kuranes »

You might be interested in GPU-based water flow simulator (binary+source+Dx9)
User avatar
mikeInside
Kobold
Posts: 37
Joined: Thu Apr 26, 2007 5:46 pm
Location: Sydney, Australia
Contact:

Re: Flowing Rivers

Post by mikeInside »

tuan kuranes wrote:You might be interested in GPU-based water flow simulator (binary+source+Dx9)

Oh wow I've been periodically checking in on that topic for years waiting for him to post the explanation, great find Tuan!

It's fantastic that we now have two really interesting solutions to the problem. I think DavlexDesign has also been working on flowing rivers, so the count may increase once again real soon.

Big thanks Umpf for your hard work :) And looking forward to seeing the results of your experimentation Crashy.
menglixiaoyi
Gnoblar
Posts: 2
Joined: Sun Jul 04, 2010 1:53 pm

Re: Flowing Rivers

Post by menglixiaoyi »

umpf wrote:Friday or saturday, the code should be ready (together with a new movie)

- umpf
Thank you for you code. But I want to know only the .osg and shader is enough? You code contain two .osg, what is another?

I want to do it in ogre, How to do just like you said it's easy? The terrain is from ?What is the .osg file corresponding to in OGRE? Please give an hint,thanks!
Post Reply