Water Shader Physics Synchronisation

mkolb

15-11-2006 08:15:09

Hi all,

I know, buoyancy has been discussed so many times, but I'm stuck with the buoyancy results(not the feature itself).

I've implemented a water shader which generates water waves and reflections as well. Since I'm working on a ship simulator I need a ship swimming on the water. So far I've written the function for the water wave for the CPU to let the ship interact with the water according the vertex displacement in the shader program.

My problem is now, that it seems to behave correctly but not as fast as it should, causing very odd looking intersections between the water plane and the ship.

I post my code as well:
Shader code

#define NWAVES 2
Wave wave[NWAVES] = {
{ 1.0, 1.0, 0.5, float2(-1, 0) },
{ 2.0, 0.5, 1.7, float2(-0.7, 0.7) }
};

wave[0].freq = waveFreq;
wave[0].amp = waveAmp;
wave[0].dir = waveDirections.xy;

wave[1].freq = waveFreq * 3.0;
wave[1].amp = waveAmp * 0.33;
wave[1].dir = waveDirections.zw;

float4 P = IN.Position;

// sum waves
float ddx = 0.0, ddy = 0.0;
float deriv;
float angle;

// wave synthesis using two sine waves at different frequencies and phase shift
for(int i = 0; i<NWAVES; ++i)
{
angle = dot(wave[i].dir, P.xz) * wave[i].freq + time * wave[i].phase;
P.y += wave[i].amp * sin( angle );
// calculate derivate of wave function
deriv = wave[i].freq * wave[i].amp * cos(angle);
ddx += deriv * wave[i].dir.x;
ddy += deriv * wave[i].dir.y;
}


and the C++ code:

Wave wave[2];

wave[0].freq = 0.001f * Math::Sqr(selLevel.Windkraft);
wave[0].amp = 1.5f * selLevel.Windkraft;
wave[0].dir = Vector2(WindDirectionShaderConstant.x,WindDirectionShaderConstant.y);

wave[1].freq = wave[0].freq * 3.0f;
wave[1].amp = wave[0].amp * 0.33f;
wave[1].dir = Vector2(WindDirectionShaderConstant.z,WindDirectionShaderConstant.w);

Real P = waterLevel;

// sum waves
float deltax = 0.0, deltay = 0.0;
float deriv;
float angle;

WaveTime += evt.timeSinceLastFrame;
if (WaveTime >= 100)
WaveTime = 0.0f;

WaveParam->setNamedConstant("time",WaveTime);

// wave synthesis using two sine waves at different frequencies and phase shift
for(int i = 0; i < 2; ++i) {
//float dotprod = Vector2(Position.x,Position.z).dotProduct(wave[i].dir);
float dotprod = wave[i].dir.dotProduct(Vector2(Position.x,Position.z));
angle = dotprod * wave[i].freq + WaveTime * wave[i].phase;
P += wave[i].amp * Math::Sin(angle);
// calculate derivate of wave function
deriv = wave[i].freq * wave[i].amp * Math::Cos(angle);
deltax += deriv * wave[i].dir.x;
deltay += deriv * wave[i].dir.y;
}

Vector3 deltaVector = Vector3(-deltax, 1.0f, -deltay);
//Vector3 normalVector = deltaVector.normalisedCopy(); // Normal
Vector3 normalVector = Vector3(0.0f,1.0f,0.0f);
Ogre::Plane ret = Plane(normalVector,P);


ret is the buoyancy plane after all. Another question: If I use the correct normalVector which is commented out in the C++ code, the ship floats up, with the 0,1,0 normal vector the ship floats on the water.
How can I make the ship react more directly to the waves of the water?
Thanks in advance!!!