Sorry about the shader question. I made a slight change to this in order to update it with the camera's position. Ray, of course, is always the center of the ocean plane. All I get is a black plane in jpct. The first method is how I update the shader (once per gameloop iteration, naturally).

` public void update(SimpleVector cameraPosition) {`

shader.setUniform("iGlobalTime", (timeF+=.1f));

shader.setUniform("pos", cameraPosition);

}

`// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.`

uniform vec3 iResolution;

uniform vec3 iChannelResolution[4];

uniform vec3 pos;

uniform vec3 ray;

uniform float iGlobalTime;

uniform float iChannelTime[4];

uniform sampler2D iChannel0;

uniform sampler2D iChannel1;

uniform sampler2D iChannel2;

uniform sampler2D iChannel3;

const float tau = 6.28318530717958647692;

// Gamma correction

#define GAMMA (2.2)

vec3 ToLinear( in vec3 col ) {

// simulate a monitor, converting colour values into light values

return pow( col, vec3(GAMMA) );

}

vec3 ToGamma( in vec3 col ) {

// convert back into colour values, so the correct light will come out of the monitor

return pow( col, vec3(1.0/GAMMA) );

}

vec3 localRay;

// Set up a camera looking at the scene.

// origin - camera is positioned relative to, and looking at, this point

// distance - how far camera is from origin

// rotation - about x & y axes, by left-hand screw rule, relative to camera looking along +z

// zoom - the relative length of the lens

void CamPolar( out vec3 pos, out vec3 ray, in vec3 origin, in vec2 rotation, in float distance, in float zoom ) {

// get rotation coefficients

vec2 c = vec2(cos(rotation.x),cos(rotation.y));

vec4 s;

s.xy = vec2(sin(rotation.x),sin(rotation.y)); // worth testing if this is faster as sin or sqrt(1.0-cos);

s.zw = -s.xy;

// ray in view space

ray.xy = gl_FragCoord.xy - iResolution.xy*.5;

ray.z = iResolution.y*zoom;

ray = normalize(ray);

localRay = ray;

// rotate ray

ray.yz = ray.yz*c.xx + ray.zy*s.zx;

ray.xz = ray.xz*c.yy + ray.zx*s.yw;

// position camera

pos = origin - distance*vec3(c.x*s.y,s.z,c.x*c.y);

}

// Noise functions, distinguished by variable types

vec2 Noise( in vec3 x ) {

vec3 p = floor(x);

vec3 f = fract(x);

f = f*f*(3.0-2.0*f);

// vec3 f2 = f*f; f = f*f2*(10.0-15.0*f+6.0*f2);

vec2 uv = (p.xy+vec2(37.0,17.0)*p.z) + f.xy;

// hardware interpolation lacks precision

// vec4 rg = texture2D( iChannel0, (uv+0.5)/256.0, -100.0 );

vec4 rg = mix( mix(

texture2D( iChannel0, (floor(uv)+0.5)/256.0, -100.0 ),

texture2D( iChannel0, (floor(uv)+vec2(1,0)+0.5)/256.0, -100.0 ),

fract(uv.x) ),

mix(

texture2D( iChannel0, (floor(uv)+vec2(0,1)+0.5)/256.0, -100.0 ),

texture2D( iChannel0, (floor(uv)+1.5)/256.0, -100.0 ),

fract(uv.x) ),

fract(uv.y) );

return mix( rg.yw, rg.xz, f.z );

}

vec4 Noise( in vec2 x ) {

vec2 p = floor(x.xy);

vec2 f = fract(x.xy);

f = f*f*(3.0-2.0*f);

// vec3 f2 = f*f; f = f*f2*(10.0-15.0*f+6.0*f2);

vec2 uv = p.xy + f.xy;

return texture2D( iChannel0, (uv+0.5)/256.0, -100.0 );

}

vec4 Noise( in ivec2 x ) {

return texture2D( iChannel0, (vec2(x)+0.5)/256.0, -100.0 );

}

vec2 Noise( in ivec3 x ) {

vec2 uv = vec2(x.xy)+vec2(37.0,17.0)*float(x.z);

return texture2D( iChannel0, (uv+0.5)/256.0, -100.0 ).xz;

}

float Waves( vec3 pos ) {

pos *= .2*vec3(1,1,1);

const int octaves = 6;

float f = 0.0;

// need to do the octaves from large to small, otherwise things don't line up

// (because I rotate by 45 degrees on each octave)

pos += iGlobalTime*vec3(0,.1,.1);

for ( int i=0; i < octaves; i++ ) {

pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);

f = f*2.0+abs(Noise(pos).x-.5)*2.0;

pos *= 2.0;

}

f /= exp2(float(octaves));

return (.5-f)*1.0;

}

float WavesDetail( vec3 pos ) {

pos *= .2*vec3(1,1,1);

const int octaves = 8;

float f = 0.0;

// need to do the octaves from large to small, otherwise things don't line up

// (because I rotate by 45 degrees on each octave)

pos += iGlobalTime*vec3(0,.1,.1);

for ( int i=0; i < octaves; i++ ) {

pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);

f = f*2.0+abs(Noise(pos).x-.5)*2.0;

pos *= 2.0;

}

f /= exp2(float(octaves));

return (.5-f)*1.0;

}

float WavesSmooth( vec3 pos ) {

pos *= .2*vec3(1,1,1);

const int octaves = 2;

float f = 0.0;

// need to do the octaves from large to small, otherwise things don't line up

// (because I rotate by 45 degrees on each octave)

pos += iGlobalTime*vec3(0,.1,.1);

for ( int i=0; i < octaves; i++ ) {

pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);

//f = f*2.0+abs(Noise(pos).x-.5)*2.0;

f = f*2.0+sqrt(pow(Noise(pos).x-.5,2.0)+.01)*2.0;

pos *= 2.0;

}

f /= exp2(float(octaves));

return (.5-f)*1.0;

}

float WaveCrests( vec3 ipos ) {

vec3 pos = ipos;

pos *= .2*vec3(1,1,1);

const int octaves1 = 6;

const int octaves2 = 16;

float f = 0.0;

// need to do the octaves from large to small, otherwise things don't line up

// (because I rotate by 45 degrees on each octave)

pos += iGlobalTime*vec3(0,.1,.1);

vec3 pos2 = pos;

for ( int i=0; i < octaves1; i++ ) {

pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);

f = f*1.5+abs(Noise(pos).x-.5)*2.0;

pos *= 2.0;

}

pos = pos2 * exp2(float(octaves1));

pos.y = -.05*iGlobalTime;

for ( int i=octaves1; i < octaves2; i++ ) {

pos = (pos.yzx + pos.zyx*vec3(1,-1,1))/sqrt(2.0);

f = f*1.5+pow(abs(Noise(pos).x-.5)*2.0,1.0);

pos *= 2.0;

}

f /= 1500.0;

f -= Noise(ivec2(gl_FragCoord.xy)).x*.01;

return pow(smoothstep(.4,-.1,f),6.0);

}

vec3 Sky( vec3 ray ) {

return vec3(.4,.45,.5);

}

float OceanDistanceField( vec3 pos ) {

return pos.y - Waves(pos);

}

float OceanDistanceFieldDetail( vec3 pos ) {

return pos.y - WavesDetail(pos);

}

vec3 OceanNormal( vec3 pos ) {

vec3 norm;

vec2 d = vec2(.01*length(pos),0);

norm.x = OceanDistanceFieldDetail( pos+d.xyy )-OceanDistanceFieldDetail( pos-d.xyy );

norm.y = OceanDistanceFieldDetail( pos+d.yxy )-OceanDistanceFieldDetail( pos-d.yxy );

norm.z = OceanDistanceFieldDetail( pos+d.yyx )-OceanDistanceFieldDetail( pos-d.yyx );

return normalize(norm);

}

float TraceOcean( vec3 pos, vec3 ray ) {

float h = 1.0;

float t = 0.0;

for ( int i=0; i < 100; i++ ) {

if ( h < .01 || t > 100.0 )

break;

h = OceanDistanceField( pos+t*ray );

t += h;

}

if ( h > .1 )

return 0.0;

return t;

}

vec3 ShadeOcean( vec3 pos, vec3 ray ) {

vec3 norm = OceanNormal(pos);

float ndotr = dot(ray,norm);

float fresnel = pow(1.0-abs(ndotr),5.0);

vec3 reflectedRay = ray-2.0*norm*ndotr;

vec3 refractedRay = ray+(-cos(1.33*acos(-ndotr))-ndotr)*norm;

refractedRay = normalize(refractedRay);

const float crackFudge = .0;

// reflection

vec3 reflection = Sky(reflectedRay);

vec3 col = vec3(0,.04,.04); // under-sea colour

col = mix( col, reflection, fresnel );

// foam

col = mix( col, vec3(1), WaveCrests(pos) );

return col;

}

void main(void) {

// vec2 camRot = vec2(.5,.5)+vec2(-.35,4.5)*(iMouse.yx/iResolution.yx);

// vec3 pos, ray;

// CamPolar( pos, ray, vec3(0), camRot, 3.0, 1.0 );

float to = TraceOcean( pos, ray );

vec3 result;

if ( to > 0.0 )

result = ShadeOcean( pos+ray*to, ray );

else result = Sky( ray );

// vignette effect

result *= 1.1*smoothstep( .35, 1.0, localRay.z );

gl_FragColor = vec4(ToGamma(result),1.0);

}