Created
August 24, 2024 19:33
-
-
Save matthewjberger/b6e89845b0f06613e2de6e1c4a15ad71 to your computer and use it in GitHub Desktop.
cube shader for shadertoy
This file contains hidden or 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
#define MAX_STEPS 100 | |
#define MAX_DIST 100.0 | |
#define SURF_DIST 0.001 | |
// Camera variables | |
vec3 cameraPos; | |
vec3 cameraTarget; | |
float cameraZoom = 5.0; | |
mat3 getCameraRotation(vec2 angle) { | |
vec2 c = cos(angle); | |
vec2 s = sin(angle); | |
return mat3( | |
c.y, 0.0, -s.y, | |
s.y * s.x, c.x, c.y * s.x, | |
s.y * c.x, -s.x, c.y * c.x | |
); | |
} | |
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 getDist(vec3 p) { | |
return sdBox(p, vec3(1.0)); | |
} | |
float getLightDist(vec3 p, vec3 lightPos) { | |
return sdBox(p - lightPos, vec3(0.1)); // Small cube for light source | |
} | |
vec3 getNormal(vec3 p) { | |
float d = getDist(p); | |
vec2 e = vec2(0.001, 0); | |
vec3 n = d - vec3( | |
getDist(p - e.xyy), | |
getDist(p - e.yxy), | |
getDist(p - e.yyx)); | |
return normalize(n); | |
} | |
float rayMarch(vec3 ro, vec3 rd, vec3 lightPos, bool isForLight) { | |
float dO = 0.0; | |
for(int i = 0; i < MAX_STEPS; i++) { | |
vec3 p = ro + rd * dO; | |
float dS = isForLight ? getLightDist(p, lightPos) : getDist(p); | |
dO += dS; | |
if(dO > MAX_DIST || abs(dS) < SURF_DIST) break; | |
} | |
return dO; | |
} | |
// Sky shader | |
vec3 getSkyColor(vec3 rd) { | |
float t = 0.5 * (rd.y + 1.0); | |
vec3 skyColor = mix(vec3(0.2, 0.4, 0.6), vec3(0.7, 0.9, 1.0), t); | |
return skyColor; | |
} | |
void mainImage( out vec4 fragColor, in vec2 fragCoord ) | |
{ | |
vec2 uv = (fragCoord - 0.5 * iResolution.xy) / iResolution.y; | |
vec3 col = vec3(0.0); | |
// Camera controls | |
vec2 mouseUV = iMouse.xy / iResolution.xy; | |
vec2 cameraAngle = vec2(0.0, 0.0); | |
if (iMouse.z > 0.0) { | |
cameraAngle = vec2((mouseUV.y - 0.5) * 3.14159, (mouseUV.x - 0.5) * 6.28318); | |
} | |
mat3 cameraRotation = getCameraRotation(cameraAngle); | |
// Adjust zoom with mouse wheel (iMouse.w) | |
cameraZoom = max(2.0, min(10.0, cameraZoom - 0.1 * iMouse.w)); | |
// Camera setup | |
cameraPos = vec3(0.0, 0.0, cameraZoom); | |
cameraTarget = vec3(0.0, 0.0, 0.0); | |
vec3 cameraDir = normalize(cameraTarget - cameraPos); | |
vec3 cameraRight = normalize(cross(vec3(0.0, 1.0, 0.0), cameraDir)); | |
vec3 cameraUp = cross(cameraDir, cameraRight); | |
vec3 ro = cameraPos * cameraRotation; | |
vec3 rd = normalize(uv.x * cameraRight + uv.y * cameraUp + cameraDir) * cameraRotation; | |
// Point light position (rotating around the cube) | |
vec3 lightPos = vec3(3.0 * sin(iTime), 2.0, 3.0 * cos(iTime)); | |
// Check if the ray hits the main object | |
float d = rayMarch(ro, rd, lightPos, false); | |
if(d < MAX_DIST) { | |
vec3 p = ro + rd * d; | |
vec3 n = getNormal(p); | |
// Light calculations | |
vec3 l = normalize(lightPos - p); | |
float diff = max(dot(n, l), 0.0); | |
vec3 h = normalize(l - rd); | |
float spec = pow(max(dot(n, h), 0.0), 32.0); | |
// Colors | |
vec3 objectColor = vec3(0.5, 0.8, 0.9); | |
vec3 lightColor = vec3(1.0, 0.9, 0.7); | |
vec3 ambientColor = vec3(0.1, 0.1, 0.2); | |
// Combine lighting components | |
col = ambientColor * objectColor + | |
diff * objectColor * lightColor + | |
spec * lightColor; | |
// Add distance attenuation | |
float distanceToLight = length(lightPos - p); | |
col /= 1.0 + 0.1 * distanceToLight * distanceToLight; | |
} else { | |
// Check if the ray hits the light source cube | |
float dLight = rayMarch(ro, rd, lightPos, true); | |
if(dLight < MAX_DIST) { | |
// Light source color (white) | |
col = vec3(1.0); | |
} else { | |
// Background sky color | |
col = getSkyColor(rd); | |
} | |
} | |
// Gamma correction | |
col = pow(col, vec3(0.4545)); | |
fragColor = vec4(col, 1.0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment