TGE water upgrade
by Manoel Neto · 07/03/2006 (11:33 am) · 347 comments
Download Code File
This resource adds basic pixel shader and vertex shader support to the TGE waterblock, using CG, and support for drawing a reflected view of the world into a texture and using it in the waterblock. Right now it's windows-only, but there's nothing stopping you from making it work on OSX and Linux, since CG is also avaliable in those platforms.
Note: For those worrying about Cg being Nvidia-only, fear not, I've personally tested it in different ATI cards and it's compatible with no visible performance problems. Just make sure your drivers aren't ancient.
Note2:
Alex Scarborough (of the TLK DRL fame) is working on porting this resource to GLSL and making it work on OSX. Might get some news soon.
Installing the source changes:
First you'll need the CG toolkit. You can get it here:
developer.nvidia.com/object/cg_toolkit.html
After installing it you must modify the TGE project to include the Cg/lib and Cg/include folders to the library paths and the include paths, respectively.
Important: you also need to open cgGL.h in the "Cg/include" folder and replace this:
Included in the zip file are the modified source files. To install into a unmodified TGE 1.4, just replace the TGE files by the ones included. To install in modified TGE sources, use a merge tool, or copy the changes by hand (all changes are comment-tagged), then compile.
Script changes and usage:
The example folder in the ZIP contains the script files you need to actually see the water in the game. The "example/CG" folder must be copied to the same folder as your executable. It contains the vertex and fragment shaders. The filenames are very hardcoded into the source code, unfortunally.
In "example/starter.fps", you'll find a modified playGui.cs and a normal map for using with the water (it's actually one of TSE's water textures).
The modified playGui.cs is required to render the reflection texture. The GameTSCtrl control was modified and now features a flag called "isReflection". Turning it on will make the gameTsCtrl render the world using a reflected camera matrix, based on the first existing waterblock.
Waterblocks will search for a GameTSCtrl called "reflectionGui". If it's found, they'll grab the refleciton texture from it.
Waterblocks also have a new field, called NormalMaptexture. You need a suitable normal map there, otherwise the reflection texture coordinates will be badly displaced.
Known bugs/limitations:
- No refraction support;
- No specular;
- No fog (at most times it looks like the water is fogged, because the reflected scene is fogged);
- No proper support for using a static envornment map instead of a full reflection (it does use the texture, but it remains fixed, and won't rotate along the view, as the original did);
- Sometimes the reflection can go strange and "melt away". Something to do with clip planes;
This resource adds basic pixel shader and vertex shader support to the TGE waterblock, using CG, and support for drawing a reflected view of the world into a texture and using it in the waterblock. Right now it's windows-only, but there's nothing stopping you from making it work on OSX and Linux, since CG is also avaliable in those platforms.
Note: For those worrying about Cg being Nvidia-only, fear not, I've personally tested it in different ATI cards and it's compatible with no visible performance problems. Just make sure your drivers aren't ancient.
Note2:
Alex Scarborough (of the TLK DRL fame) is working on porting this resource to GLSL and making it work on OSX. Might get some news soon.
Installing the source changes:
First you'll need the CG toolkit. You can get it here:
developer.nvidia.com/object/cg_toolkit.html
After installing it you must modify the TGE project to include the Cg/lib and Cg/include folders to the library paths and the include paths, respectively.
Important: you also need to open cgGL.h in the "Cg/include" folder and replace this:
#include <GL/gl.h>By this:
#include <dgl/dgl.h>Otherwise you'll get loads of compile errors.
Included in the zip file are the modified source files. To install into a unmodified TGE 1.4, just replace the TGE files by the ones included. To install in modified TGE sources, use a merge tool, or copy the changes by hand (all changes are comment-tagged), then compile.
Script changes and usage:
The example folder in the ZIP contains the script files you need to actually see the water in the game. The "example/CG" folder must be copied to the same folder as your executable. It contains the vertex and fragment shaders. The filenames are very hardcoded into the source code, unfortunally.
In "example/starter.fps", you'll find a modified playGui.cs and a normal map for using with the water (it's actually one of TSE's water textures).
The modified playGui.cs is required to render the reflection texture. The GameTSCtrl control was modified and now features a flag called "isReflection". Turning it on will make the gameTsCtrl render the world using a reflected camera matrix, based on the first existing waterblock.
Waterblocks will search for a GameTSCtrl called "reflectionGui". If it's found, they'll grab the refleciton texture from it.
Waterblocks also have a new field, called NormalMaptexture. You need a suitable normal map there, otherwise the reflection texture coordinates will be badly displaced.
Known bugs/limitations:
- No refraction support;
- No specular;
- No fog (at most times it looks like the water is fogged, because the reflected scene is fogged);
- No proper support for using a static envornment map instead of a full reflection (it does use the texture, but it remains fixed, and won't rotate along the view, as the original did);
- Sometimes the reflection can go strange and "melt away". Something to do with clip planes;
About the author
#262
NormalMapTexture = "~/data/water/noise02";
In the waterblock. Here's my entire waterblock:
new WaterBlock() {
position = "-32 -752 159.5";
rotation = "1 0 0 0";
scale = "2048 2048 10";
UseDepthMask = "1";
surfaceTexture = "~/data/water/water_center";
ShoreTexture = "~/data/water/water_edge";
envMapOverTexture = "~/data/skies/storm_env";
specularMaskTex = "~/data/water/water_spec";
liquidType = "OceanWater";
NormalMapTexture = "~/data/water/noise02";
density = "0.5";
viscosity = "15";
waveMagnitude = "2";
surfaceOpacity = "0";
envMapIntensity = "10";
TessSurface = "0";
TessShore = "0";
SurfaceParallax = "0.0";
FlowAngle = "220";
FlowRate = "0.0";
DistortGridScale = "0.01";
DistortMag = "0.01";
DistortTime = "10";
ShoreDepth = "14";
DepthGradient = "1";
MinAlpha = "0.01";
MaxAlpha = "0.8";
tile = "1";
removeWetEdges = "0";
specularColor = "1 0.8 0.46 1";
specularPower = "10";
params1 = "0.63 -2.41 0.33 0.21";
locked = "true";
params2 = "0.39 0.39 0.2 0.133";
params3 = "1.21 -0.61 0.13 -0.33";
seedPoints = "0 0 1 0 1 1 0 1";
textureSize = "32 32";
params0 = "0.32 -0.67 0.066 0.5";
floodFill = "1";
Extent = "100 100 10";
};
** note: at the time of the screenshot I did above, my distortion was all set to 0 (trying to get a glassy lake look)
Thanks for the help :P
Edit: After a few hours of trial and error - found that my having tesselation settings of "0" caused the issue. When I set the tesselation to anything higher - the issues resolved and the water looked awesome. Again to all who have contributed to this resource - THANK YOU VERY MUCH!
James
08/11/2006 (1:35 pm)
I already did that - read through this whole post a couple of times ;) Should have mentioned that I did put the line: NormalMapTexture = "~/data/water/noise02";
In the waterblock. Here's my entire waterblock:
new WaterBlock() {
position = "-32 -752 159.5";
rotation = "1 0 0 0";
scale = "2048 2048 10";
UseDepthMask = "1";
surfaceTexture = "~/data/water/water_center";
ShoreTexture = "~/data/water/water_edge";
envMapOverTexture = "~/data/skies/storm_env";
specularMaskTex = "~/data/water/water_spec";
liquidType = "OceanWater";
NormalMapTexture = "~/data/water/noise02";
density = "0.5";
viscosity = "15";
waveMagnitude = "2";
surfaceOpacity = "0";
envMapIntensity = "10";
TessSurface = "0";
TessShore = "0";
SurfaceParallax = "0.0";
FlowAngle = "220";
FlowRate = "0.0";
DistortGridScale = "0.01";
DistortMag = "0.01";
DistortTime = "10";
ShoreDepth = "14";
DepthGradient = "1";
MinAlpha = "0.01";
MaxAlpha = "0.8";
tile = "1";
removeWetEdges = "0";
specularColor = "1 0.8 0.46 1";
specularPower = "10";
params1 = "0.63 -2.41 0.33 0.21";
locked = "true";
params2 = "0.39 0.39 0.2 0.133";
params3 = "1.21 -0.61 0.13 -0.33";
seedPoints = "0 0 1 0 1 1 0 1";
textureSize = "32 32";
params0 = "0.32 -0.67 0.066 0.5";
floodFill = "1";
Extent = "100 100 10";
};
** note: at the time of the screenshot I did above, my distortion was all set to 0 (trying to get a glassy lake look)
Thanks for the help :P
Edit: After a few hours of trial and error - found that my having tesselation settings of "0" caused the issue. When I set the tesselation to anything higher - the issues resolved and the water looked awesome. Again to all who have contributed to this resource - THANK YOU VERY MUCH!
James
#263
I made the changes to the exe code, compiled it without error, placed the CG folder where the exe, replaced the Playgui.gui, put the noise02 in the water folder, edited the waterblock and set the normalmap to noise02. But there are no changes to the water.
from the log:
CG:callback set
CG: no valid profile found...
My video card is a geforce6800GS
Anyone know what is causing it not to reflect?
08/13/2006 (10:42 am)
Hmm, I followed instructions exactly, but the water does not reflect at all, it just looks normal.I made the changes to the exe code, compiled it without error, placed the CG folder where the exe, replaced the Playgui.gui, put the noise02 in the water folder, edited the waterblock and set the normalmap to noise02. But there are no changes to the water.
from the log:
CG:callback set
CG: no valid profile found...
My video card is a geforce6800GS
Anyone know what is causing it not to reflect?
#264
08/13/2006 (10:36 pm)
maybe, you put the wrong directory. actually hit the ... button and browse for the file. and hit "apply". if it still doesnt work. then post a screen shot.
#265
I'm getting one error from gametsctrl.cc
if (!gClientSceneGraph->mCameraSubmerged) //<--- This line is added so we'll only reflect if we're over water.
camq->cameraMatrix = getCameraReflection(camq->cameraMatrix, plane);
It doesn't know what "plane" is, am I missing something?
08/16/2006 (1:45 am)
@Trond I'm getting one error from gametsctrl.cc
if (!gClientSceneGraph->mCameraSubmerged) //<--- This line is added so we'll only reflect if we're over water.
camq->cameraMatrix = getCameraReflection(camq->cameraMatrix, plane);
It doesn't know what "plane" is, am I missing something?
#266
This is the relevant code from the original resource:
As you can see, 'plane' is defined a little above the line you're getting an error on. Are you sure you have correctly merged the original resource with your code? What is the exact error you get?
EDIT: I see that I may have been a little inaccurate when I pasted the change to that file - I suspect you may have pasted the change at the top of the function? It should be where you see the 'getCameraReflection(camq->cameraMatrix, plane);' function call in the snippet above.
-Trond
08/16/2006 (2:36 am)
@Dion:This is the relevant code from the original resource:
//--------------------------------------
// PRLD_WATER_SHADER
//--------------------------------------
bool ok = GameProcessCameraQuery(camq);
// If we are reflecting, mirror the camera transform
if (mIsReflection)
{
SimpleQueryList sql;
gClientSceneGraph->getWaterObjectList(sql);
if (sql.mList.size()) //Only the first waterblock is used for reclection calculation
{
WaterBlock* pBlock = static_cast<WaterBlock*>(sql.mList[0]);
//Steal the texture
//mReflectionTexture = pBlock->getEnvMapTexture();
PlaneF plane;
Point3F norm;
pBlock->getRenderTransform().getColumn( 2, &norm );
norm.normalize();
plane.set( Point3F(0,0,pBlock->getSurfaceHeight()), norm );
camq->cameraMatrix = getCameraReflection(camq->cameraMatrix, plane);
gClientSceneGraph->mReflectPass = true;
//----------------------------------------
//Set water clip plane
// rotate clip plane into modelview space
norm.normalize();
mClipPlane.set( norm.x, norm.y, norm.z, -(pBlock->getSurfaceHeight()-0.5) );
}
}
return ok; //return GameProcessCameraQuery(camq);
//--------------------------------------
// PRLD_WATER_SHADER
//--------------------------------------As you can see, 'plane' is defined a little above the line you're getting an error on. Are you sure you have correctly merged the original resource with your code? What is the exact error you get?
EDIT: I see that I may have been a little inaccurate when I pasted the change to that file - I suspect you may have pasted the change at the top of the function? It should be where you see the 'getCameraReflection(camq->cameraMatrix, plane);' function call in the snippet above.
-Trond
#267
i don't know if this is mentioned or not, but walk into the building in the default demo level,
just a lil inside of the doorway... then look back at the water, and change the up/down angle
which you are looking...
i have the reflections sorta go a lil grazy...
everything seems to reset itself as soon as i exit out of the building... portals maybe?
... or just my imagination :)
--Mike
08/17/2006 (8:55 am)
has anyone noticed that the water resource works fine... until you enter an interior...i don't know if this is mentioned or not, but walk into the building in the default demo level,
just a lil inside of the doorway... then look back at the water, and change the up/down angle
which you are looking...
i have the reflections sorta go a lil grazy...
everything seems to reset itself as soon as i exit out of the building... portals maybe?
... or just my imagination :)
--Mike
#268
08/17/2006 (10:00 am)
Michael, see my posts above about looking through portals
#270
the second error is that with a low view angle and a large distance the shader seems to dissapear near objects or terrain (anything with shadow maybe?)
08/27/2006 (11:29 pm)
I have a error with the shader if player/camera is on a large distance (~200 meters) to the water surface..
the second error is that with a low view angle and a large distance the shader seems to dissapear near objects or terrain (anything with shadow maybe?)
#271
08/28/2006 (1:59 am)
Have you tried implementing all the fixes presented in this thread? They should fix these issues. Looks like clipping problems.
#272
08/29/2006 (7:47 am)
yes, have found it now, was a small pice of code i have overseen. Have added variables for fog and water color to the waterblock, at it seems to work now without errors.
#273
thx
--Mike
09/01/2006 (5:37 am)
new small problem i can't seem to figure out... the reflections only kick in after i've visited the editor (f11) and returned... any ideas...thx
--Mike
#274
09/01/2006 (8:16 am)
ya, its your playgui.cs read up through the post, i think there should be a solution somewhere.
#275
thx
--Mike
09/01/2006 (2:06 pm)
i've tried a couple of things here... could i impose upon you (or someone) to pop up a listing of their playgui.gui... is it the same as the one that's in the zip?thx
--Mike
#276
09/01/2006 (8:14 pm)
//--- OBJECT WRITE BEGIN ---
new GuiControl(PlayGui) {
Profile = "GuiContentProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "0 0";
Extent = "640 480";
MinExtent = "8 8";
Visible = "1";
Variable = "ap";
Command = "ap";
AltCommand = "ap";
Accelerator = "ap";
tooltip = "ap";
langTableMod = "ap";
applyFilterToChildren = "1";
noCursor = "1";
cameraZRot = "0";
helpTag = "0";
forceFOV = "0";
new GameTSCtrl(reflectionGui) {
Profile = "GuiContentProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "0 0";
Extent = "320 240";
MinExtent = "8 8";
Visible = "1";
applyFilterToChildren = "1";
cameraZRot = "0";
forceFOV = "0";
isReflection = "1";
reflection = "1";
noCursor = "1";
helpTag = "0";
};
new GameTSCtrl() {
Profile = "GuiContentProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "0 0";
Extent = "640 480";
MinExtent = "8 8";
Visible = "1";
applyFilterToChildren = "1";
cameraZRot = "0";
forceFOV = "0";
isReflection = "0";
noCursor = "1";
helpTag = "0";
new GuiBitmapCtrl(CenterPrintDlg) {
Profile = "CenterPrintProfile";
HorizSizing = "center";
VertSizing = "center";
position = "45 230";
Extent = "550 20";
MinExtent = "8 8";
Visible = "0";
bitmap = "./hudfill.png";
wrap = "0";
helpTag = "0";
new GuiMLTextCtrl(CenterPrintText) {
Profile = "CenterPrintTextProfile";
HorizSizing = "center";
VertSizing = "center";
position = "0 0";
Extent = "546 12";
MinExtent = "8 8";
Visible = "1";
lineSpacing = "2";
allowColorChars = "0";
maxChars = "-1";
helpTag = "0";
};
};
new GuiBitmapCtrl(BottomPrintDlg) {
Profile = "CenterPrintProfile";
HorizSizing = "center";
VertSizing = "top";
position = "45 375";
Extent = "550 20";
MinExtent = "8 8";
Visible = "0";
bitmap = "./hudfill.png";
wrap = "0";
helpTag = "0";
new GuiMLTextCtrl(BottomPrintText) {
Profile = "CenterPrintTextProfile";
HorizSizing = "center";
VertSizing = "center";
position = "0 0";
Extent = "546 12";
MinExtent = "8 8";
Visible = "1";
lineSpacing = "2";
allowColorChars = "0";
maxChars = "-1";
helpTag = "0";
};
};
new GuiBitmapCtrl(LagIcon) {
Profile = "GuiDefaultProfile";
HorizSizing = "right";
VertSizing = "bottom";
position = "572 3";
Extent = "32 32";
MinExtent = "8 8";
Visible = "0";
bitmap = "./lagIcon.png";
wrap = "0";
helpTag = "0";
};
new GuiShapeNameHud() {
Profile = "GuiDefaultProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "0 0";
Extent = "652 484";
MinExtent = "8 8";
Visible = "1";
fillColor = "0 0 0 0.25";
frameColor = "0 1 0 1";
textColor = "0 1 0 0.94426";
showFill = "0";
showFrame = "0";
verticalOffset = "0.2";
distanceFade = "0.1";
damageRect = "30 4";
helpTag = "0";
damageFrameColor = "1.000000 0.600000 0.000000 1.000000";
damageFillColor = "0.000000 1.000000 0.000000 1.000000";
};
new sgGuiFullScreenFilter() {
Profile = "GuiDefaultProfile";
HorizSizing = "relative";
VertSizing = "relative";
position = "0 0";
Extent = "372 480";
MinExtent = "8 2";
Visible = "0";
sgExposure = "0.5 0.5 0.5 1";
};
};
};
//--- OBJECT WRITE END ---
#277
being overlayed by the white spec mask texture, or something...
when i go into the editor, then immediately exit, everything looks right...
but i can't get it to show correctly when the mision first loads up...
i'm gonna retrace my install steps...
--Mike
09/02/2006 (7:11 am)
thx T... mine looks identical, but if the reflections are there, they arebeing overlayed by the white spec mask texture, or something...
when i go into the editor, then immediately exit, everything looks right...
but i can't get it to show correctly when the mision first loads up...
i'm gonna retrace my install steps...
--Mike
#278
09/05/2006 (1:30 pm)
Has anyone else had a problem with water explosions, especially surface detection for explosions. When I fire at the water, nothing happens on the surface.
#279
09/05/2006 (3:13 pm)
No, it works fine for me. its probably a scripting error.
#280
I can see the onEnterliquid function in the Player.cc but I can't find where the actual resistance is applied against the player. It seems to happen when the water gets above his knee, however, the engine doesn't seem to concerened with this aspect. It seems to only care if he is 90% covered ( mWaterCoverage >= 0.9).
Any tips?
AS it turned out, I just deleted the object and re-created it in the editor ... seemingly exactly the same. It now works. blah
09/06/2006 (9:24 pm)
I implemented the waterblock. It looks great but now my player and AIPlayers get stuck in it ... I can run a few feet but then I get stuck. It does not throw an onStuck event. If I lower the water with the editor ... I can run again. I can see the onEnterliquid function in the Player.cc but I can't find where the actual resistance is applied against the player. It seems to happen when the water gets above his knee, however, the engine doesn't seem to concerened with this aspect. It seems to only care if he is 90% covered ( mWaterCoverage >= 0.9).
Any tips?
AS it turned out, I just deleted the object and re-created it in the editor ... seemingly exactly the same. It now works. blah

Torque 3D Owner Thanhda Tie
Digital Shock Inc.