#version 330 core #include "ring-world-common.glsl" #include "camera-ray.glsl" in vec2 vUv; uniform float uFar; uniform int uWaterEnabled; uniform float uWaterLevel; uniform vec3 uWaterDeep; uniform vec3 uWaterShallow; uniform vec3 uWaves; out vec4 fragColor; float best=1e10; vec3 normal; int material=0; void candidate(float t,vec3 n,int m) {if(t>.00000001&&t=y0&&p.y<=y1)candidate(t,normalize(vec3(p.x,0,p.z))*signNormal,m); } } void disk(vec3 o,vec3 d,float y,float inner,float outer,float signNormal) { if(abs(d.y)<1e-12)return; float t=(y-o.y)/d.y;float r=length((o+d*t).xz); if(r>=inner&&r<=outer)candidate(t,vec3(0,signNormal,0),0); } void main() { vec3 worldRay=cameraRay(vUv),d=mat3(uWorldToBody)*worldRay,o=uCameraBody; float w=uRingSize.x,ow=w+uRingSize.z,outer=1.0+uRingSize.y,rim=1.0-uAirHeight; tube(o,d,outer,-ow,ow,1.0,0); tube(o,d,rim,w,ow,-1.0,0);tube(o,d,rim,-ow,-w,-1.0,0); disk(o,d,w,rim,outer,-1.0);disk(o,d,-w,rim,outer,1.0); disk(o,d,ow,rim,outer,1.0);disk(o,d,-ow,rim,outer,-1.0); if(uWaterEnabled!=0)tube(o,d,1.0-uWaterLevel,-w,w,-1.0,1); if(best>1e9)discard; vec3 p=o+d*best; vec3 world=worldRay*(best*uRadius); vec3 color; if(material==1) { vec3 direction=ringDirection(p);float map; float h=mappedElevation(direction,map); float wet=uHasOceanMask!=0?oceanMaskValue(direction):float(h=uWaterLevel)discard; float a=atan(p.z,p.x)*uRadius,across=p.y*uRadius; float k=6.2831853/max(1.0,uWaves.y),time=uTime*uWaves.z; vec3 tangent=normalize(vec3(-p.z,0,p.x)); float waveFilter=1.0-smoothstep(.5,3.0,max(fwidth(a*k),fwidth(across*k))); normal=normalize(normal+(tangent*cos(a*k+time)*uWaves.x*k*.5+vec3(0,1,0)*sin(across*k*.73-time)*uWaves.x*k*.4)*waveFilter); float fresnel=.02+.98*pow(1.0-max(0.0,dot(normal,-d)),5.0); color=mix(uWaterShallow,uWaterDeep,smoothstep(.05,.8,wet))*ringLight(p,normal,world); color=mix(color,vec3(.16,.32,.50),fresnel*.8); for(int i=0;i<2;i++){if(i>=uLightCount)break;color+=uLightColors[i]*pow(max(0.0,dot(reflect(d,normal),uLightDirections[i])),160.0)*uLightFlux[i]*1.7*ringEnvironmentShadow(p,uLightDirections[i])*vegetationShadow(world,i);} color+=vec3(.5)*pow(1.0-wet,8.0)*.2; } else { float longitude=atan(p.z,p.x)/6.2831853; float panels=step(.04,fract(longitude*600.0))*step(.04,fract(p.y*uRadius/8000.0)); color=mix(vec3(.055,.07,.085),vec3(.16,.20,.23),panels)*ringLight(p,normal,world); color+=vec3(.015,.07,.09)*(1.0-panels)*.25; } fragColor=vec4(color,1); float forwardDistance=best*uRadius*max(.0001,dot(worldRay,uForward)); gl_FragDepth=log2(1.0+forwardDistance)/log2(uFar+1.0); }