bättre ringworld

This commit is contained in:
2026-11-03 20:32:59 +01:00
parent f447fe8e51
commit 6ea397a9e5
39 changed files with 2141 additions and 54 deletions

View File

@@ -0,0 +1,66 @@
#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);
}