Created
January 22, 2025 23:23
-
-
Save CharStiles/a9206b677a555b6c050833cba7f36546 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef GL_ES | |
precision highp float; | |
#endif | |
uniform float time; | |
uniform vec2 resolution; | |
uniform vec2 mouse; | |
uniform vec3 spectrum; | |
uniform sampler2D texture0; | |
uniform sampler2D texture1; | |
uniform sampler2D texture2; | |
uniform sampler2D texture3; | |
uniform sampler2D prevFrame; | |
uniform sampler2D prevPass; | |
varying vec3 v_normal; | |
varying vec2 v_texcoord; | |
float rand(vec2 co){ | |
return fract(sin(dot(co, vec2(12.9898, 78.233))) * 43758.5453); | |
} | |
// Same, but mirror every second cell at the diagonal as well | |
vec2 pModGrid2(inout vec2 p, vec2 size) { | |
vec2 c = floor((p + size*0.5)/size); | |
p = mod(p + size*0.5, size) - size*0.5; | |
p *= mod(c,vec2(2))*2. - vec2(1); | |
p -= size/2.; | |
if (p.x > p.y) p.xy = p.yx; | |
return floor(c/2.); | |
} | |
vec2 pModMirror2(inout vec2 p, vec2 size) { | |
vec2 halfsize = size*0.5; | |
vec2 c = floor((p + halfsize)/size); | |
p = mod(p + halfsize, size) - halfsize; | |
p *= mod(c,vec2(2))*2. - vec2(1); | |
return c; | |
} | |
void pR(inout vec2 p, float a) { | |
p = cos(a)*p + sin(a)*vec2(p.y, -p.x); | |
} | |
// Maximum/minumum elements of a vector | |
float vmax(vec2 v) { | |
return max(v.x, v.y); | |
} | |
float vmax(vec3 v) { | |
return max(max(v.x, v.y), v.z); | |
} | |
float vmax(vec4 v) { | |
return max(max(v.x, v.y), max(v.z, v.w)); | |
} | |
// Box: correct distance to corners | |
float fBox(vec3 p, vec3 b) { | |
vec3 d = abs(p) - b; | |
return length(max(d, vec3(0))) + vmax(min(d, vec3(0))); | |
} | |
// Smooth minimum function for rounding | |
// Smooth minimum function for rounding | |
float smin(float a, float b, float k) { | |
float h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0); | |
return mix(b, a, h) - k * h * (1.0 - h); | |
} | |
// Smooth maximum function for rounding | |
float smax(float a, float b, float k) { | |
return -smin(-a, -b, k); | |
} | |
// Rounded box function | |
float fBoxRound(vec3 p, vec3 b, float r) { | |
vec3 q = abs(p) - b + vec3(r); | |
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0) - r; | |
} | |
// Domain repetition with offset | |
vec3 opRep(vec3 p, vec3 c) { | |
return mod(p + 0.5 * c, c) - 0.5 * c; | |
} | |
// Box SDF | |
float sdBox(vec3 p, vec3 b) { | |
vec3 q = abs(p) - b; | |
return length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0); | |
} | |
float scene(vec3 p) { | |
float result = 1e10; | |
// Create infinite grid with smoother transitions | |
vec3 cell = floor(p / vec3(20.0, 40.0, 10.0)); | |
vec3 localPos = opRep(p, vec3(40.0, 30.0, 40.0)); | |
// Soften the rotation variation | |
float rotAngle = sin(dot(cell.xz, vec2(12.9898, 78.233))) * 3.14159; | |
pR(localPos.xz, rotAngle); | |
// Smooth height variation | |
float baseHeight = 15.0 + 10.0 * (0.5 + 0.5 * sin(dot(cell.xz, vec2(0.3, 0.7)))); | |
// Main tower with rounded edges | |
float tower = fBoxRound(localPos * 0.95, vec3(4.0, baseHeight, 4.0),.1); | |
// Smoother bridges | |
float bridgeThickness = 2.5; // Slightly thicker | |
float bridgeLength = 10.0; | |
float bridgeX = fBoxRound(localPos - vec3(bridgeLength, baseHeight * 0.7, 0.0), | |
vec3(bridgeLength, bridgeThickness, bridgeThickness),2.); | |
float bridgeZ = fBoxRound(localPos - vec3(0.0, baseHeight * 0.4, bridgeLength), | |
vec3(bridgeThickness, bridgeThickness, bridgeLength),2.2); | |
// Connected structures with gradual blending | |
vec3 offsetPos = localPos; | |
float finalTower = tower; | |
for (int i = 0; i < 3; i++) { | |
float blend = float(i) * 0.333; | |
float h = baseHeight * (0.5 + 0.3 * sin(dot(cell.xz + float(i), vec2(1.1, 0.9)))); | |
// Smooth position offset | |
vec2 offset = vec2( | |
8.0 * sin(dot(cell.xz + float(i), vec2(0.5, 0.7))), | |
8.0 * sin(dot(cell.xz + float(i), vec2(0.9, 0.3))) | |
); | |
offsetPos.xz += offset; | |
float smallTower = fBoxRound(offsetPos * (0.95 + float(i) * 0.02), vec3(3.0, h, 3.0),1.); | |
finalTower = smin(finalTower, smallTower, 4.0 + float(i)); // Progressive smoothing | |
} | |
// Combine elements with varying smooth factors | |
result = smin(finalTower, smin(bridgeX, bridgeZ, 3.0), 2.0); | |
// Architectural details with softer edges | |
vec3 windowPos = localPos; | |
windowPos.y = mod(windowPos.y + time * 2.0, 5.0) - 2.5; | |
float windows = sdBox(windowPos * 1.1, vec3(2.0, 0.5, 0.5)); | |
result = smax(result, -windows, 0.8); | |
return result * 0.9; // Slightly scale down the entire SDF for smoother results | |
} | |
vec3 estimateNormal(vec3 p) { | |
float d = 0.001; | |
return normalize(vec3( | |
scene(p + vec3(d, 0, 0)) - scene(p - vec3(d, 0, 0)), | |
scene(p + vec3(0, d, 0)) - scene(p - vec3(0, d, 0)), | |
scene(p + vec3(0, 0, d)) - scene(p - vec3(0, 0, d)) | |
)); | |
} | |
vec4 lighting(vec3 ray, vec3 rd, vec2 id){ | |
vec3 norm = estimateNormal(ray); | |
vec3 light = vec3(1., 0., 0.); | |
float dif = max(dot(norm, light), 0.0); // Add max to prevent negative values | |
vec4 retCol = vec4(dif); | |
// Add ambient light to prevent pure black | |
float ambient = 0.9621; | |
retCol += vec4(ambient); | |
vec3 lightRayDir = normalize(light - ray); | |
return retCol * vec4(norm, 1.0) + rand(ray.xy); | |
} | |
vec4 trace(vec3 rayO, vec3 dir) { | |
vec3 ray = rayO; | |
float dist = 0.0; | |
float totalDist = 0.0; | |
float glow = 0.0; | |
// Adaptive stepping for smoother results | |
float precis = 0.001; | |
float t = precis * 2.0; | |
for(int i = 0; i < 128; ++i) { | |
dist = scene(ray); | |
// Accumulate glow based on how close we are to the surface | |
glow += max(0.0, 0.05 - dist) * 0.5; | |
// Adaptive step size | |
float step = max(dist * 0.8, precis); | |
totalDist += step; | |
ray += dir * step; | |
// Enhanced hit detection with smooth transition | |
if(dist < precis * totalDist) { | |
vec4 retCol = vec4(1.0 - (totalDist /100.)); // Smoother distance falloff | |
vec4 lit = lighting(ray, dir, dir.xy); | |
// Blend between lit surface and atmosphere | |
float fade = smoothstep(0.0, 100.0, totalDist); | |
vec4 atmosColor = vec4(0.6, 0.7, 0.8, 1.0); | |
return mix(lit * retCol, atmosColor,1.- fade) +glow*glow + (rand(ray.xy)-0.25); | |
} | |
// Distance-based early termination | |
if(totalDist > 200.0) break; | |
} | |
return vec4(0);//glow ; // Sky color with subtle glow | |
} | |
// | |
// vec4 trace(vec3 rayO, vec3 dir){ | |
// vec3 ray = rayO; | |
// float dist = 0.; | |
// float totalDist = 0.; | |
// | |
// for(int i = 0; i < 128; ++i){ | |
// dist = scene(ray); | |
// totalDist += dist; | |
// ray += dist * dir; | |
// | |
// if(dist < 0.01){ | |
// vec4 retCol = 1.0 - (vec4(totalDist) / 5.0); | |
// return lighting(ray, dir,dir.xy) * retCol + rand(ray.xy ); | |
// } | |
// } | |
// return vec4(0.0); | |
//} | |
void main() { | |
vec2 uv = (2.0 * gl_FragCoord.xy - resolution.xy) / min(resolution.x, resolution.y); | |
// Camera setup | |
float camHeight = 3.0 + 20.0 * tan(time * 0.2); | |
vec3 ro = vec3(15.0 * cos(time * 0.2), camHeight, 20.0 * sin(time * 0.2)); | |
vec3 lookAt = vec3(0.0, 20.0, 0.0); | |
vec3 forward = normalize(lookAt - ro); | |
vec3 right = normalize(cross(vec3(0.0, 1.0, 0.0), forward)); | |
vec3 up = cross(forward, right); | |
vec3 rd = normalize(forward + right * uv.x + up * uv.y); | |
vec4 col = trace(ro, rd); | |
// Output final color | |
gl_FragColor = col.gggg ; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment