89 lines
3.2 KiB
GLSL
89 lines
3.2 KiB
GLSL
|
const int NUM_WAVES = 16;
|
||
|
|
||
|
uniform vec3 osgOcean_Origin; // central position of vertices - sun position on water surface
|
||
|
uniform vec3 osgOcean_Extinction_c; // extinction coefficient
|
||
|
uniform vec3 osgOcean_Eye; // Eye position in world space
|
||
|
uniform vec3 osgOcean_SunDir; // sunlight direction
|
||
|
uniform float osgOcean_Spacing; // spacing between vertices
|
||
|
uniform float osgOcean_Waves[NUM_WAVES * 5]; // wave constants
|
||
|
|
||
|
varying vec3 vIntensity;
|
||
|
|
||
|
float fastFresnel(vec3 I, vec3 N, float r0)
|
||
|
{
|
||
|
return r0 + (1.0-r0) * pow(1.0-dot(I, N), 5.0);
|
||
|
}
|
||
|
|
||
|
vec3 calculateWaterNormal(float x0, float y0)
|
||
|
{
|
||
|
vec3 t1 = vec3(1.0,0.0,0.0);
|
||
|
vec3 t2 = vec3(0.0,1.0,0.0);
|
||
|
|
||
|
int itr = NUM_WAVES/4;
|
||
|
|
||
|
for (int i = 0, j = 0; i < itr; i++, j += 20)
|
||
|
{
|
||
|
vec4 kx = vec4( osgOcean_Waves[j+0], osgOcean_Waves[j+1], osgOcean_Waves[j+2], osgOcean_Waves[j+3] );
|
||
|
vec4 ky = vec4( osgOcean_Waves[j+4], osgOcean_Waves[j+5], osgOcean_Waves[j+6], osgOcean_Waves[j+7] );
|
||
|
vec4 Ainvk = vec4( osgOcean_Waves[j+8], osgOcean_Waves[j+9], osgOcean_Waves[j+10], osgOcean_Waves[j+11] );
|
||
|
vec4 A = vec4( osgOcean_Waves[j+12], osgOcean_Waves[j+13], osgOcean_Waves[j+14], osgOcean_Waves[j+15] );
|
||
|
vec4 wt = vec4( osgOcean_Waves[j+16], osgOcean_Waves[j+17], osgOcean_Waves[j+18], osgOcean_Waves[j+19] );
|
||
|
vec4 phase = (kx*x0 + ky*y0 - wt);
|
||
|
vec4 sinp, cosp;
|
||
|
|
||
|
#if 1
|
||
|
sinp = sin(phase);
|
||
|
cosp = cos(phase);
|
||
|
#else
|
||
|
sincos(phase, sinp, cosp);
|
||
|
#endif
|
||
|
|
||
|
// Update tangent vector along x0
|
||
|
t1.x -= dot(Ainvk, kx*cosp*kx);
|
||
|
t1.y -= dot(Ainvk, ky*cosp*kx);
|
||
|
t1.z += dot(A, (-sinp)*(kx));
|
||
|
|
||
|
// Update tangent vector along y0
|
||
|
t2.x -= dot(Ainvk, kx*cosp*ky);
|
||
|
t2.y -= dot(Ainvk, ky*cosp*ky);
|
||
|
t2.z += dot(A, (-sinp)*(ky));
|
||
|
}
|
||
|
|
||
|
// Calculate and return normal
|
||
|
return normalize( cross(t1, t2) );
|
||
|
}
|
||
|
|
||
|
void main(void)
|
||
|
{
|
||
|
gl_TexCoord[0] = gl_MultiTexCoord0;
|
||
|
|
||
|
// Scale and translate the vertex on the water surface
|
||
|
vec3 worldPos = gl_Vertex.xyz * vec3(osgOcean_Spacing,osgOcean_Spacing,1.0);
|
||
|
worldPos += osgOcean_Origin;
|
||
|
|
||
|
// Calculate the water normal at this point
|
||
|
vec3 normal = calculateWaterNormal(worldPos.x, worldPos.y);
|
||
|
|
||
|
// Calculate transmittance
|
||
|
// BUG: makes intensity too small not sure why.
|
||
|
float transmittance = 1.0-fastFresnel(-osgOcean_SunDir, normal, 0.0204);
|
||
|
|
||
|
// Extrude bottom vertices along the direction of the refracted
|
||
|
// sunlight
|
||
|
if (gl_TexCoord[0].s > 0.0)
|
||
|
{
|
||
|
// Calculate refraction vector and extrude polygon
|
||
|
vec3 refr = refract(osgOcean_SunDir, normal, 0.75);
|
||
|
worldPos += refr*gl_TexCoord[0].s;
|
||
|
}
|
||
|
// Set intensity so that the further away you go from the surface
|
||
|
float totalDist = gl_TexCoord[0].s + length(worldPos-osgOcean_Eye);
|
||
|
vIntensity = exp(-totalDist*osgOcean_Extinction_c)*transmittance;
|
||
|
vIntensity = clamp(vIntensity, 0.0, 0.06);
|
||
|
|
||
|
// Transform position from world to clip space
|
||
|
gl_Position = gl_ModelViewProjectionMatrix * vec4(worldPos, 1.0 );
|
||
|
// Tweak z position not to clip shafts very close to the viewer
|
||
|
gl_Position.z = 0.01;
|
||
|
}
|