WaterRenderPass (now in CVS)

Finally got my priorities right and ported the waterstuff to jME, putting things like marriage, vacation and my daughter on hold s :wink:



Alot of time went into making the watereffect handle arbitrary up axis, using a plane as equation for solving camera vector reflection etc etc. Also did alot of decoupling of the water and the mesh to apply the effect to.

Changes made while i ported:

  • The water effect is a stand alone render pass, and has no hardcoded connection to what kind of mesh it uses for rendering
  • You register the mesh you want to use as water-surface to the water effect pass. so now you can use a quad or a grid or anything you like with simple changes
  • The projected grid is a stand alone trimesh extension, and can be used to whatever you wish, not just water rendering. could be moved to jme's shape package
  • The projected grid uses a height generator class to generate it's heights, so you can plugin whatever nice water movement algorithms you wish.



    A first try at explaining what's in the cvs checkin at the moment:

    jmex.effects.water package:
  • WaterRenderPass

    The actual renderpass. Renders reflection, refraction and depth maps based on all settings and sets up shaders to use.
  • Projected grid

    A trimesh implementing parts of the projected grid thesis. A grid that is displaced in projective space based on the camera frustum.
  • HeightGenerator / WaterHeightGenerator(sample implementation of the interface)

    Returns heights based on x/z coordinates and time. Used by the projected grid to animate/displace the grid.
  • ImprovedNoise

    Perlin noise implementation by Ken Perlin, used by the sample heightgenerator implementation.



    jmetest.effects.water package:
  • TestProjectedGrid

    Simple test of the projected grid mesh itself
  • TestProjectedWater

    Test for the waterrenderpass with a projected grid mesh as watersurface
  • TestQuadWater

    Test for the waterrenderpass with a quad as watersurface. The quad is automatically moved along with the camera to simulate an infinite waterplane.
  • TestSimpleQuadWater

    Test for the waterrenderpass with a simple quad that uses the z-axis as up vector. To show how to use another plane equation than default y-up.



    Basic usage:
  1. Use a pass-enabled type of program(eg. extend the SimplePassGame)
  2. Create a WaterRenderPass and add to the pass manager before the main scene renderpass. Choose what type of watershader to use and if you want refraction or not.
  3. Create the mesh to use as watersurface and register it to the waterrenderpass with setWaterEffectOnSpatial()
  4. Create and register a node containing all objects that should be reflected/refracted in the water with setReflectedScene()
  5. Create and register a skybox to the waterrenderpass with setSkybox(). (this will later be extended for skydome usage etc)
  6. Try out all waterrenderpass settings (or projected grid settings)



    Some of the TODO's:
  • The watersurface mesh needs to have correctly hardcoded vertices and normals, no rotation/translation of the mesh is allowed. This was done to ease the burden of the shaders but i'll have a go at making a version where you supply a modelmatrix and so on.
  • The projected grid i y-axis up only at the moment. This is a limitation of the projected grid mesh and not of the waterrenderpass. There are many things to polish on the grid implementation that will allow for arbitrary up-axis and remove alot of artifacts(also allowing for lower resolution grids)
  • Make the water easier to use and understand (and add documentation)
  • Extract alot of settings and magic numbers from the shaders so they can be set by the user.
  • Add specular lighting
  • Make the normalmap and dudvmap used by the water user definable. To allow for other characteristics of the water part from just changing colors etc
  • Make a water editor similar to renanse's renparticleeditor
  • Find a way to get rid of some surface-object edge artifacts



    That's it for the moment. The source will be updated pretty much but i felt it was better to get it in the cvs now so that you can help me improve and test it :slight_smile:



    Gimme feedback on what sucks!

MrCoder, Absolutely beautiful water effect!!  :slight_smile:



I'll try and play around wiith it some more this week, and give you any feedback I have!!



Awesome work!

MrCoder said:

Gimme feedback on what sucks!


what sucks is that i waited so long for this one and now i only have a geforce 4ti and can't test it  :'(
but i'm still glad it's finally made public. thank you mr coder  ;)

WOW, just wow!  :-o this is really awesome! thanks a lot!

however it seems to be pretty ressource demading. i always get 70something fps, no matter what resolution i use or if i run it fullscreen or not. is it more limited by the gpu, or the cpu? very impressive work nonetheless!!!

ProjectedWater is very CPU limited (at least on my system) due to the expensive math for calculating the waves. However, mrCoder was ever so kind to make this pluggable. I hope someone with a bit of physics skills can build a better (not that the current one doesn't look good, but a bit better performing) HeightGenerator than WaterHeightGenerator.



The water effect itself is probably GPU limitedā€¦ that on it own doesn't say much though. GPUs can do many things concurrently. It's configurable though, you can make it have more and less of those pretty effects.



@sfera: I guess your card doesn't have the needed shader support (yours is PS1.3/VS1.1 I believe)ā€¦ maybe a low tech version is still possible?

thanks all!



yes it's pretty resource heavy, but i haven't gotten to profiling and optimization yet, so hopefully we can improve on that togetherā€¦

llama is correct about projected-cpu and watereffect-gpu limitedā€¦



@sfera: that sucksā€¦it's really hard to know what shader versions your shaders comply with. do you know what the problem is? and does anyone know of an easy way of getting info on what minimum version your shader programs need?

thank you for your condoleances  :expressionless: i previously had a geforce fx 5200 but i changed ist for a geforce ti 4200 (the geforce 4 ti was 3x faster in 3dmark). so i traded GLSL and higher vertex/pixel shader language versions for speed.

here's a list of what nvidia cards can and cannot do:

http://en.wikipedia.org/wiki/Comparison_of_NVIDIA_Graphics_Processing_Units



and for completeness here's the ati list:

http://en.wikipedia.org/wiki/Comparison_of_ATI_GPUs

aha, glsl is opengl 1.5+ only wich came with the geforce fx seriesā€¦not for the Ti'sā€¦a port to the old vertex/pixel assembly programs anyone? :slight_smile:

I'm not sure if it would even be possible to translate the GLSL code to old school vertex/fragment assembly. The programs rely heavily on passing data from the vertex shader to the fragment shader (using "varying"), but there really isn't a mechanism to do that with GL_ARB_vertex/fragment_program. You could potentially (ab)use the various texture units to do it, but they're all occupied with other information. I think we're stuck in GLSL-land, unless of course I'm missing something obvious.

Here is entire log output, Im in linux and my desktop is set to 24 and Im using a 9800pro.

Aug 10, 2006 3:00:59 PM com.jme.app.BaseGame start

INFO: Application started.

Aug 10, 2006 3:00:59 PM com.jme.system.PropertiesIO <init>

INFO: PropertiesIO created

Aug 10, 2006 3:00:59 PM com.jme.system.PropertiesIO load

INFO: Read properties

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:107: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:129: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:200: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:257: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:309: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:361: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:398: Engine "smooth" is unsupported, ignoring

/usr/share/themes/Nuvola/gtk-2.0/gtkrc:429: Engine "smooth" is unsupported, ignoring

Aug 10, 2006 3:01:07 PM com.jme.input.joystick.DummyJoystickInput <init>

INFO: Joystick support is disabled

Aug 10, 2006 3:01:07 PM com.jme.system.lwjgl.LWJGLDisplaySystem <init>

INFO: LWJGL Display System created.

Aug 10, 2006 3:01:07 PM com.jme.system.PropertiesIO save

INFO: Saved properties

Aug 10, 2006 3:01:07 PM com.jme.app.BaseSimpleGame initSystem

INFO: jME version 0.11 beta

Aug 10, 2006 3:01:07 PM com.jme.app.BaseSimpleGame initSystem

INFO: Running on: null

Driver version: null

Aug 10, 2006 3:01:09 PM com.jme.renderer.lwjgl.LWJGLRenderer <init>

INFO: LWJGLRenderer created. W:  640H: 480

Aug 10, 2006 3:01:09 PM com.jme.renderer.AbstractCamera <init>

INFO: Camera created.

Aug 10, 2006 3:01:09 PM com.jme.util.lwjgl.LWJGLTimer <init>

INFO: Timer resolution: 1000 ticks per second

Aug 10, 2006 3:01:09 PM com.jme.scene.Node <init>

INFO: Node created.

Aug 10, 2006 3:01:09 PM com.jme.scene.Node <init>

INFO: Node created.

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (FPS label) attached to this node (FPS node)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (Text) attached to this node (FPS node)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (Text) attached to this node (FPS node)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node <init>

INFO: Node created.

Aug 10, 2006 3:01:09 PM com.jme.scene.Node <init>

INFO: Node created.

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (north) attached to this node (skybox)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (south) attached to this node (skybox)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (east) attached to this node (skybox)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (west) attached to this node (skybox)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (up) attached to this node (skybox)

Aug 10, 2006 3:01:09 PM com.jme.scene.Node attachChild

INFO: Child (down) attached to this node (skybox)

Aug 10, 2006 3:01:12 PM com.jme.scene.Node attachChild

INFO: Child (skybox) attached to this node (reflectNode)

Aug 10, 2006 3:01:12 PM com.jme.scene.Node <init>

INFO: Node created.

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (Torus) attached to this node (objects)

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (box1) attached to this node (objects)

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (box2) attached to this node (objects)

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (box3) attached to this node (objects)

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (box4) attached to this node (objects)

******** REUSING TEXTURE ******** Texture with id: 0

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (box5) attached to this node (objects)

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (objects) attached to this node (reflectNode)

Aug 10, 2006 3:01:13 PM com.jme.scene.Node attachChild

INFO: Child (reflectNode) attached to this node (rootNode)

java.lang.NullPointerException

   at com.jmex.effects.water.WaterRenderPass.<init>(WaterRenderPass.java:199)

   at jmetest.effects.water.TestProjectedWater.simpleInitGame(TestProjectedWater.java:115)

   at com.jme.app.BaseSimpleGame.initGame(BaseSimpleGame.java:474)

   at com.jme.app.SimplePassGame.initGame(SimplePassGame.java:95)

   at com.jme.app.BaseGame.start(BaseGame.java:56)

   at jmetest.effects.water.TestProjectedWater.main(TestProjectedWater.java:73)

Aug 10, 2006 3:01:13 PM com.jme.app.BaseSimpleGame cleanup

INFO: Cleaning up resources.

Exception in thread "main" java.lang.NullPointerException

   at jmetest.effects.water.TestProjectedWater.cleanup(TestProjectedWater.java:78)

   at com.jme.app.BaseGame.start(BaseGame.java:81)

   at jmetest.effects.water.TestProjectedWater.main(TestProjectedWater.java:73)




using the texture units would be a fully working solution, at least for the flat water shader with only 4 varying(or three if packed together). the projected water shader would need 7 or 5 if packedā€¦

Im getting a null pointer exception in this line

tRenderer.getCamera().setFrustum( cam.getFrustumNear(), cam.getFrustumFar(), cam.getFrustumLeft(), cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom() );

         



I just updated from cvs. I got exceptions running all the water tests except TestProjectedGrid

On my 6800 I got this originally. My problem was my desktop was set at 16bits on accident (I was playing something and it crashed causing the desktop to not reset properly). However, in TextureRenderer the bpp field was set to 32 (as this is what the card supports). Those two items caused Texture renderer to bomb. Changing the desktop to 32 fixed the problem. Not sure the best way to handle this in jME.

can i get the complete log output? sounds more like it's the texturerenderer that doesnt get setup cause of your card not supporting it. the testprojectedgrid is not really water related so it's definitely something with the waterrenderpassā€¦



anyone else getting that error?

Sorry to but into your debugging issue, but I've been playing around with this and man is it cool! 



Does anyone good at math know the formula we can use to have the waves roll in concentric circles instead of sin waves?  Would be awesome to have them close in on an island.  The form would be something like this: (mrcoders code)



projectedGrid = new ProjectedGrid( "ProjectedGrid", cam, 50, 50, 0.01f, new WaterHeightGenerator() {
         public float getHeight( float x, float z, float time ) {
            return FastMath.sin(z*0.1f+time*4.0f)*2+FastMath.cos(z*0.05f+time*2.0f)*2;  //sin waves from x and z colliding with eachother
         }
      } );


in terms of x, z and time, as said above.



EDIT:

I asked a math whiz I know and got the formula:

return FastMath.sin(FastMath.sqrt((z*z*0.01f)+(x*x*0.01f))+time*4.0f)*4.0f;

Iā€™ll try to webstart enable this later tonight, (new lwjgl verison for the watertest means i have to re-sign all my jars, etc)

but check out a screenshot of the spherical waves using above formula, with a terrainblock thrown in:



By the way, disabling refraction on the WaterRenderPass boosts my framerate (modest system) from 5-6 to 24-25

still probably too slow for a game at this point, but looks damn good :slight_smile:



nice one! you should add the terrainblock to the reflection hierarchy so that it reflects in the waterā€¦



i'll go through the waterrenderpass and add a log output and fallback if the texturerenderer fails to initializeā€¦

nice effect beamanbr tried it myself the wave however are bet to close together and a bitā€¦consistent/uniformed and tend to arc out toward the island in a  broken fashion (multiple arcs) , then thats what I see in my part of the world, lived in the caribbean all 29 years of my life :),sort of

You can always make a very simple HeightGenerator that averages or adds two others. Shouldn't be more than a few lines of code.

redrew my island a bit, and enabled your reflection on the terrainblock.  Note that I can only run this locally, webstart crashes due to the terrainblock for some reason.  Still trying to figure that out, have an open thread in troubleshooting.



I could webstart just the water, however.