Simple Ray marcher with smooth union
script:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Ray Marching</title>
<style> body { margin: 0; overflow: hidden; } canvas { display: block; } </style>
</head>
<body>
<canvas id="glCanvas"></canvas>
<script id="fragShader" type="x-shader/x-fragment">
precision highp float;
uniform vec2 u_resolution;
uniform float u_time;
float sdSphere(vec3 p, float r) { return length(p) - r; }
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 smoothMin(float a, float b, float k) { float h = max(k - abs(a - b), 0.0) / k; return min(a, b) - h * h * k * 0.25; }
float map(vec3 p) {
float sphere = sdSphere(p - vec3(0.0, sin(u_time) * 0.5 + 0.5, 0.0), 0.3);
float cube = sdBox(p - vec3(0.0, -0.2, 0.0), vec3(0.4));
return smoothMin(sphere, cube, 0.2);
}
vec3 getNormal(vec3 p) {
vec2 e = vec2(0.001, 0.0);
return normalize(vec3(map(p + e.xyy) - map(p), map(p + e.yxy) - map(p), map(p + e.yyx) - map(p)));
}
vec3 rayMarch(vec3 ro, vec3 rd) {
float t = 0.0;
for (int i = 0; i < 100; i++) {
vec3 p = ro + rd * t;
float d = map(p);
if (d < 0.001) return mix(vec3(0.0, 1.0, 0.0), vec3(1.0), step(0.5, p.y)) * dot(getNormal(p), vec3(0.0, 1.0, 0.0)) * 0.5 + 0.5;
if ((t += d) > 10.0) break;
}
return vec3(0.0);
}
void main() {
vec2 uv = (gl_FragCoord.xy - u_resolution * 0.5) / u_resolution.y;
gl_FragColor = vec4(rayMarch(vec3(0.0, 0.0, 2.0), normalize(vec3(uv, -1.0))), 1.0);
}
</script>
<script>
const gl = (c => (c.width = innerWidth, c.height = innerHeight, c.getContext("webgl")))(document.getElementById("glCanvas"));
const vsSource = "attribute vec4 position; void main() { gl_Position = position; }";
const fsSource = document.getElementById("fragShader").textContent;
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return gl.getShaderParameter(shader, gl.COMPILE_STATUS) ? shader : console.error(gl.getShaderInfoLog(shader));
}
const program = gl.createProgram();
gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vsSource));
gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fsSource));
gl.linkProgram(program);
gl.useProgram(program);
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]), gl.STATIC_DRAW);
const position = gl.getAttribLocation(program, "position");
gl.enableVertexAttribArray(position);
gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
const resolutionLocation = gl.getUniformLocation(program, "u_resolution");
const timeLocation = gl.getUniformLocation(program, "u_time");
function render(time) {
gl.uniform2f(resolutionLocation, gl.canvas.width, gl.canvas.height);
gl.uniform1f(timeLocation, time * 0.001);
gl.drawArrays(gl.TRIANGLES, 0, 6);
requestAnimationFrame(render);
}
requestAnimationFrame(render);
window.addEventListener("resize", () => (gl.canvas.width = innerWidth, gl.canvas.height = innerHeight, gl.viewport(0, 0, gl.canvas.width, gl.canvas.height)));
</script>
</body>
</html>
Status | Released |
Platforms | HTML5 |
Author | G Magma JavaScript |
Leave a comment
Log in with itch.io to leave a comment.