67 lines
3.1 KiB
GLSL
67 lines
3.1 KiB
GLSL
#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<best){best=t;normal=n;material=m;}}
|
|
void tube(vec3 o,vec3 d,float radius,float y0,float y1,float signNormal,int m) {
|
|
vec2 times=cylinder(o,d,radius);
|
|
for(int i=0;i<2;i++) {
|
|
float t=i==0?times.x:times.y;
|
|
vec3 p=o+d*t;
|
|
if(p.y>=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);
|
|
// Keep shallow generated coastlines covered too; the terrain depth test clips water on dry land.
|
|
if(wet<=.0001&&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);
|
|
}
|