Archived

This topic is now archived and is closed to further replies.

Bump mapped water

This topic is 5630 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I was thinking of simulating a water surface with EMBM (environmental bump mapping). I am working on a GeForce2 MX and unfortunately it doesn''t support EMBM. The funny thing is that the color op is supported but the required texture formats aren''t. In any case, EMBM seems perfect because I generate the heightmap using perlin noise and I could just use the heightmap values to displace the environment map. Since I didn''t really need the base texture, just the diffuse water color I could do everything in one pass (I only have two texture units). Well, since EMBM idea is out I am trying to do it with DOT3 bumpmapping. I didn''t yet get to the environment map, but right now my water looks like one of those electromagnetic physics experiments where they take a piece of paper, put a magnet underneath and throw a lot of very small pieces of metal on top. This is due to a couple of reasons, mainly because I tile the fBm function and because my heightmaps/normal maps have relatively small resolution (it''s expensive to generate an fBm at runtime and then convert it to a normal map). Also, I''m not sure how to scale the altitude of the heightmap when generating the normals. Once I get the crappy tiled low resolution dot product texture I just modulate it with the backgroung color and I get an even crappier result Can anyone post some ideas/suggestions?

Share this post


Link to post
Share on other sites
Why are you using fractal surfaces to approximate water in the first place?

------------------------------------------------
The wind shear alone from a pink golfball can take the head off a 90-pound midget from 300 yards.

-Six String Samurai

Share this post


Link to post
Share on other sites
Depends on the scale you want. For large scale water (eg. oceans), a fractal system is appropriate, but I''m not sure about fBm in specific. I had good results using Fourier synthesis, fBm and Perlin noise seems a bit to random for that task.

If you are after a smaller water surface (lake, pool, puddle), which I guess since you are still after your 4E3 entry , I wouldn''t use noise. A full physical simulation is far more impressive, eg. a 2D NSE solver.

About the EMBM: You don''t really need it to get good looking water. And since you need texture shaders for real EMBM, you are screwed on a GF2. Just calculate a planar reflection around the water plane. Render it to a texture. Apply this as a projective texture to the water surface (with appropriate blending). Trace a reflection ray from each water mesh vertex through a ''virtual'' plane floating above the surface. Calculate the intersection point, and the displacement offsets in x/y from the original vertex. Shift the texcoords of the reflection texture by that amount. You''ll get incredibly realistic reflections with this method. If you have a GF3+, you can even EMBM into that view-dependend reflection texture.

A similar system can be applied to refraction.

/ Yann

Share this post


Link to post
Share on other sites
Yann:
I''ve seen some stuff using Fourier, and I''ve never really been impressed. It generally looks very nice for a while, but soon you realize that it really is just periodic. Unless the programmer sets it up so that the greatest wavelength is about twice the size of the body of water, there is an apparent pattern, which kills the whole effect.

Also, do you have any papers on projective texturing? I''ve read some articles that demonstrate it, but using four coordinates (u, v, s, t?) to specify textures just sort of confuses me. I''d like to see the math behind how it works.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by tsuraan
Yann:
I''ve seen some stuff using Fourier, and I''ve never really been impressed. It generally looks very nice for a while, but soon you realize that it really is just periodic. Unless the programmer sets it up so that the greatest wavelength is about twice the size of the body of water, there is an apparent pattern, which kills the whole effect.



Really? To me it''s not obvious, especially with correct reflection (Fresnel) and correct water color upwelling. Myself, I''ve never been too impressed with noise-based water. Maybe combining the two approaches could help satisfy us both.

<img src="http://www.people.fas.harvard.edu/~reichard/water/water.jpg">

Share this post


Link to post
Share on other sites
quote:

Yann:
I've seen some stuff using Fourier, and I've never really been impressed. It generally looks very nice for a while, but soon you realize that it really is just periodic. Unless the programmer sets it up so that the greatest wavelength is about twice the size of the body of water, there is an apparent pattern, which kills the whole effect.


You won't see a repeating pattern, if the synthesis is well balanced (frequency wise). And yes, you might see individual repeating waves, but this is exactly the effect that makes water realistic.

fBm and Perlin noise are both chaotic. Water surfaces in reality are not, they are superimposed waves, creating interference, they cancel each other out, etc. You can fully simulate this behaviour using the 3D Navier Stokes equations. That's way overkill for a simple water surface (the 2D NSE version is more appropriate) but it shows that a water surface can be mathematically defined. Fourier synthesis does exactly that: It creates overlayed wavepatterns that show interference and cancellation.

Imagine a large lake on a day with a slight breeze coming from a constant direction. What does that water surface look like ? Long repeating wave patterns, moving synchroneously in the direction of the wind. You can perfectly simulate that effect using Fourier synthesis. It looks really nice.

The AP mentioned another extremely important point: the Fresnel term. If you want realistic water, you have to include it, there is no way around it. It can easily be approximated by a lookup texture and some simple vertex/pixelshaders on the GPU.

quote:

Also, do you have any papers on projective texturing? I've read some articles that demonstrate it, but using four coordinates (u, v, s, t?) to specify textures just sort of confuses me. I'd like to see the math behind how it works.


It actually is very easy, once you get the idea behind it. Just imagine a slide projector shining on your scene: it perspectively projects the texture onto it. Normally, you simple load your combined modelview/projection matrices (for OGL, same thing for D3D, but slightly different terminology) into the texture matrix. You feed the 3D coordinates of each vertex as a 4 component texture coordinate. They will get transformed by the texture matrix, just as 3D coordinates get transformed by the standard view camera.

It's a bit hard to explain, nVidia has some nice papers on their site.

/ Yann

[edited by - Yann L on June 25, 2002 12:53:55 PM]

Share this post


Link to post
Share on other sites
Some googling:

Perlin''s ''85 siggraph paper has a nice distant view of the ocean, although it looks quite expensive. He uses circular wave fronts to avoid any repeating patterns.

This isn''t exactly relevant, but I just ran across http://www.cs.umbc.edu/~bsmith15/799/ which looks to be a real-time implementation of Fournier & Reeves breaking waves model. It looks nice. I''d like to see this model integrated with Tessendorf''s deep-water waves.

Share this post


Link to post
Share on other sites
I am working on a large ocean. I have an island in the middle and the ocean goes as far into horizon as the player can see. As far as I see it, it doesn''t matter whether I use noise, NSE or Fourier synthesis, I would still have to tile my results because there is no way I can make a large enough texture with any of the methods.

Unfortunately tiling the heightmap looks like crap I''m not sure how to handle that. Since I have the most experience with noise and I am short on time I decided to use it because I thought I''ll be able to play around with some parameters to make tiling look less obvious. So far, I can''t seem to get it to look nice. How is this usually handled when generating large bodies of water?

quote:

Just calculate a planar reflection around the water plane. Render it to a texture. Apply this as a projective texture to the water surface (with appropriate blending). Trace a reflection ray from each water mesh vertex through a ''virtual'' plane floating above the surface. Calculate the intersection point, and the displacement offsets in x/y from the original vertex. Shift the texcoords of the reflection texture by that amount. You''ll get incredibly realistic reflections with this method.



Please excuse my ignorant self but I can''t help to ask for a little bit more details.

Calculate a planar reflection around the water plane. I have no idea what that means
Apply this as a projective texture to the water surface This is almost clear. Am I supposed to project the texture from a lightsource onto the plane or from a camera onto the plane?
with appropriate blending Should I use DOT3 at all to simulate lighting or the pertrubation of texture coordinates should be enough?

Everything else is pretty clear. Yann, if I win the contest (which I most likely won''t because unfortunately I don''t have enough time) it will only be fair to send the video card to you

Share this post


Link to post
Share on other sites
quote:

Unfortunately tiling the heightmap looks like crap I'm not sure how to handle that. Since I have the most experience with noise and I am short on time I decided to use it because I thought I'll be able to play around with some parameters to make tiling look less obvious. So far, I can't seem to get it to look nice. How is this usually handled when generating large bodies of water?


Normally nothing is tiled, since everything is procedurally computed (except bumpmaps, if you use them). That's the beauty of procedural modeling, you can just get data up into infinity without tiling anything.

First thing you need is a LOD system. Your water needs to be highly tesselated near the camera, but you only need a few triangles out at the horizon. If you don't use a water simulator that requires a fixed space grid (eg. an NSE solver), then ditch the heightmap. You need to apply your fBm, Perlin or Fourier system on the fly to every vertex created by the tesselator. This will eliminate any need for tiling heightmaps.

Tiling bumpmaps are no problem, since they are pretty high-frequency anyway, and won't generate visible repeating patterns.

quote:

Calculate a planar reflection around the water plane. I have no idea what that means


Simply rephrased: make your water surface act like a planar mirror. You know, those standard stencil-buffer reflections everybody seems to do these days. The only difference is that you don't even need a stencil buffer. Flip your geometry around the water plane. Create a clipping plane at the water surface level, to remove any reflected geometry that is above the water. Render the whole thing into a texture. Repeat for the refracted geometry, if you want to include refraction.

quote:

Apply this as a projective texture to the water surface This is almost clear. Am I supposed to project the texture from a lightsource onto the plane or from a camera onto the plane?


In this case, the reflect/refract texture will be projected from the players POV. Simply use the same transformation and projection matrices you use in your viewing camera, and load them into the texture matrix.

quote:

with appropriate blending Should I use DOT3 at all to simulate lighting or the pertrubation of texture coordinates should be enough?


Hmm. Water is different than standard solid materials. So if you use standard rendering techniques (eg. diffuse bump), your water will look solid, a kind of (ugly) plastic look. Everybody who tried to do an advanced water system has surely run into that problem.

You need a special treatment for water surfaces:

* In the real-world, water has no diffuse component. Applying a standard diffuse DOT3 will give a weird look. Particles suspended in the water (eg. muddy water) can sometimes create pseudo-diffuse properties. Those can be simulated by fogging underwater geometry, based on the distance between a vertex and the water surface.

* Water has a reflective and transmissive colour. Both can be different. Your pixelshader can take them into account, you'll have to include them as constant colour modulators onto the result of the Fresnel term: c = const_col(transmissive) * current_col(refractive) * Fresnel(refractive component) + const_col(reflective) * current_col(reflection) * Fresnel(reflective component). current_col(reflection) is the colour from your projected (and distorted) reflection texture, current_col(refractive) the respective colour from the refracted texture. All this can be done with standard GF2 register combiners.

* Water has a very strong specular term. Now you can use your DOT3: bumpmap the specular term only. This will give you additional pixel detail, and make your waves look sharp and full of turbulences. A GF2 can do that pretty well, although you're somewhat limited in the specular exponentiation (only two general combiners + final combiner available). If you want nice results, you have to use a normalization cubemap in that pass. Add the result onto your water surface using additive blending.

* EMBM (if you have a GF3+): don't use the cheesy offset displace EMBM. It looks like crap. Use the real thing, by calculating the reflection vector perpixel (needs a 3x3 matrix transform perpixel, that can be done using a 4 stage texture shader). Displace your (already per-vertex distorted) texcoords into the projected reflection/refraction map using the perpixel vector.

quote:

Everything else is pretty clear. Yann, if I win the contest (which I most likely won't because unfortunately I don't have enough time) it will only be fair to send the video card to you


Thanks, but I already have a GF4

/ Yann

[edited by - Yann L on June 25, 2002 8:36:53 PM]

Share this post


Link to post
Share on other sites
Arghhhh. I wish I could target a GeForce3. I have to pertrub the water texture coordinates but I have to send the data over the bus. And why? Why?!!!! Why can''t vertex shaders by supported on a GeForce2. Whyyyyyy?!!!!!!!!!!

*Ahem* Excuse me.

Yann, thank you very much for your help. I''ll post screenshots whenever I get to the "screenshot" stage.

Share this post


Link to post
Share on other sites
For really good water you need to evaluate reflection vectors, Snell's law, etc. per vertex. You can't really do all that in today's vertex programs. So you have to stream even on a GF3+ (although VPs help to increase performance, of course). It's pretty fast, if you use VAR/NVfence, and since a water surface doesn't take too much faces either, your AGP bus won't be saturated.

BTW: to nVidia engineers that read this board (and I know at least one does !): I demand looping and conditional jumps in vertex programs now. Oh, and I want to be able to address system memory through VP opcodes. Thank you.
(It's too late, I must already be dreaming... )

/ Yann

[edited by - Yann L on June 25, 2002 11:06:39 PM]

Share this post


Link to post
Share on other sites
I just looked at my schedule, the amount of things to do and the amount of time I have. It isn''t looking good

The problem is that right now everything runs at 20 FPS on my GeForce2 MX. My terrain is totally wasteful because I render it fully as many times as the number of texture layers I have. I don''t have any level of detail set up and I don''t use any occlusion culling algorithms. I don''t even have simple frustum culling. I really don''t have enough horsepower right now to render my geometry into a texture again and implementing an LOD system will take out some of the time and I would prefer to use it for other purposes.

I am wondering if I can implement a dirty hack and use a sphere map instead of a projective texture. I will obviously not be able to accurately reflect the island but the sky should be enough. And since the demo will not be interactive I''ll be able to hide a lot of ugly artifacts with clever camera work

Also, how can I go about generating the sphere map?

Share this post


Link to post
Share on other sites
Here''s a water rendering test i did a while ago:



Basically it more or less uses Yann''s description. A LOD solution is used to keep the polycount low (around 2000 polys in that shot); it generates the waves animations with Perlin noise (i''m working on botter methods) and uploads animated bumpmaps every frame. Pixel shaders are used to compute the per-pixel fresnel term as well as the reflection vector. The refraction vector is still per-vertex (working on that too!).

Y.

Share this post


Link to post
Share on other sites
I started looking into the lighting system. My idea is the following.

Use simple diffuse vertex colors as the first color argument. Use the reflection texture as the second argument. Calculate the fresnel term per vertex and based on that balance the alpha value of the vertex. Based on the alpha value I will either have full diffuse color and none of the texture, full texture and none of the diffuse color or something in between. There''s obviously no refraction calculated, no per pixel calculations etc. but I will get to all that later. Do I have the right idea?

Share this post


Link to post
Share on other sites
Yes, you''ve got the idea right, but i''m afraid you''ll get ugly texturing artifacts (due to linear interpolation of texture coordinates) over the water surface. I didn''t find a way to solve it when i was doing everything per-vertex. Maybe tesselating a lot the surface would do the trick, but then, forget 2km-wide horizons.

Y.

Share this post


Link to post
Share on other sites
I tested it yesterday. Impossible to do per vertex, the water looks VERY ugly (and barely like water). Even tesselating the water much more did not help.

Share this post


Link to post
Share on other sites
What exactly did you do per vertex ? And what kind of reflection texture did you use (projected or spheremap) ?

The reflection vector distortion can be done per vertex, and it looks very good. But the Fresnel term should be done perpixel.

/ Yann

Share this post


Link to post
Share on other sites
I used a simple cubemap (it's upper part ). The reflection technique that you described worked perfectly. It's not too good with the cube map, would be MUCH better with a perspective texture, but still pretty good. Since I have no pixel shaders I calculated the Fresnel term per vertex. No matter how I changed things around it looked horrible. Very high tesselation gives much better results, but I can't use that in realtime so I gave up the Fresnel term idea. I will just use a cheap dirty hack for water and when I'm through with the deadline I'll start improving upon the current features.

[edited by - kill on June 27, 2002 11:38:04 PM]

Share this post


Link to post
Share on other sites
quote:
Original post by Alload
Does anyone know good papers on nowadays water rendering techniques?


The most recent paper is the siggraph 2002 paper by Fedkiw et al, "Animation and rendering of complex water surfaces," http://graphics.stanford.edu/papers/water-sg02/ . They discuss rendering in section 3.5, and reference earlier papers. Their animation of a glass of water is brilliant, although their ocean waves don't look so good.

Real-time rendering is discussed by Jensen & Golias in a GDCE article, http://www.swrendering.com/papers.html . This is based largely on Tessendorf's paper "Simulating ocean water" at http://home1.gte.net/tssndrf/index.html , which includes a basic ocean water Renderman shader. Also see "Towards real-time visual simulation of water surfaces" by Schneider & Westermann, http://www.vis.rwth-aachen.de/Research/research.html .

More links you should definitely check out
http://www.cs.utah.edu/~michael/water/ -- "Rendering natural waters" by Premoze & Ashikhmin
http://meshuggah.4fo.de/OceanScene.htm -- Nice rendering implementation
http://nis-lab.is.s.u-tokyo.ac.jp/~nis/pub_nis.html -- "Method of displaying optical effects within water using accumulation buffer" by Nishita & Nakamae -- equations 1-4 can be evaluated in closed form if you assume the ocean is flat; there is also a very good approximation (play around using Mathematica to find it) which is very fast; this improves looks dramatically
http://www.cs.umbc.edu/~bsmith15/799/ -- Nice implementation of breaking waves (more about modeling than rendering, though)

[Edit: UBB code for the links doesn't seem to be working, sorry]

[edited by - greeneggs on June 28, 2002 6:56:51 PM]

Share this post


Link to post
Share on other sites
Ysaneya, your effect seems very well done, however, it may be a good idea to tone down the reflective quality of the water if possible.

And even at the low polycount you described, ive seen water effects simaler with a higher framerate than 6 fps

Share this post


Link to post
Share on other sites
If I have well understood what I have read so far, to render a water surface we need a planar surface and a frame updated bump map and we will use reflection and refraction to render the quad?

Or is it better to reflect the scene in a texture and to deform this texture on the water surface?

Share this post


Link to post
Share on other sites