DYT/Source/resources/shaders/osgOcean_godrays.vert
2024-11-22 23:11:48 +08:00

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;
}