Skip to content

Instantly share code, notes, and snippets.

@bolducke
Created February 14, 2026 03:30
Show Gist options
  • Select an option

  • Save bolducke/00805ddf144ed53fdfc191ff354036d9 to your computer and use it in GitHub Desktop.

Select an option

Save bolducke/00805ddf144ed53fdfc191ff354036d9 to your computer and use it in GitHub Desktop.
Uniform Sampling of Surfaces
#define SELF iChannel0
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
if (iFrame < 3) {
ivec2 seed = ivec2(fragCoord.xy);
vec3 ro_sample;
vec3 rd_sample;
random_sample_ray(seed, ro_sample, rd_sample);
float[] t_rec = raymarch(ro_sample, rd_sample);
fragColor = vec4(t_rec[0], t_rec[1], t_rec[2], t_rec[3]);
}
else {
fragColor = texelFetch(SELF, ivec2(gl_FragCoord.xy), 0);
}
}
void random_sample_ray(ivec2 seed, inout vec3 ro, inout vec3 rd)
{
vec3 pcenter_disk = point_on_sphere(seed, 1.);
rd = normalize(vec3(0.) - pcenter_disk);
ro = point_on_disk(seed/2, pcenter_disk, rd, 1.);
}
//
// Invariant
//
#define PI 3.14159265359
#define TAU 2.*PI
#define RAYMARCH_MAX_INTERSECTION 4
//
// Variant
//
#define RAYMARCH_STEP 100
#define RAYMARCH_MAX_LENGTH 10.0
#define RAYMARCH_TOLERANCE 0.001
// MAX_DRAW_SAMPLES includes rejected points so the total displayed will be equal or lower
#define MAX_DRAW_SAMPLES 3000 // MAX: iResolution.x * iResolution.y
#define SAMPLE_RADIUS 0.02
#define RADIUS_CAMERA 3.
#define SDF_COLOR vec3(1.0, 0.5, 0.3)
#define LIGHT_DIR normalize(vec3(-0.5, 0.8, -1.0))
// ------------------------------------------------------------
// Random functions
// ------------------------------------------------------------
vec2 hash22(vec2 p) {
vec3 p3 = fract(vec3(p.xyx) * vec3(.1031, .1030, .0973));
p3 += dot(p3, p3.yzx+33.33);
return fract((p3.xx+p3.yz)*p3.zy);
}
vec3 point_on_disk(ivec2 seed, vec3 center, vec3 normal, float radius) {
vec2 uv = hash22(vec2(seed));
vec3 u = normalize(cross(normal, abs(normal.x) > 0.99 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0)));
vec3 v = normalize(cross(normal, u));
float r = sqrt(uv.x) * radius;
float theta = TAU * uv.y;
return center + r * cos(theta) * u + r * sin(theta) * v;
}
vec3 point_on_sphere(ivec2 seed, float radius) {
vec2 u = hash22(vec2(seed));
float z = 1.0 - 2.0 * u.x;
float a = TAU * u.y;
float r = sqrt(1.0 - z * z);
return radius * vec3(r * cos(a), r * sin(a), z);
}
// ------------------------------------------------------------
// SDF Primitives
// ------------------------------------------------------------
float sdSphere(vec3 p, float r) {
return length(p) - r;
}
float sdTorus(vec3 p, vec2 t) {
vec2 q = vec2(length(p.xz)-t.x, p.y);
return length(q)-t.y;
}
// ------------------------------------------------------------
// Scene
// ------------------------------------------------------------
float sdScene(vec3 p) {
return sdTorus(p, vec2(0.5, 0.3));
}
vec3 nScene(vec3 p) {
float h = 0.001;
vec2 k = vec2(1,-1);
return normalize(
k.xyy * sdScene(p + k.xyy*h) +
k.yyx * sdScene(p + k.yyx*h) +
k.yxy * sdScene(p + k.yxy*h) +
k.xxx * sdScene(p + k.xxx*h)
);
}
float[RAYMARCH_MAX_INTERSECTION] raymarch(vec3 ro, vec3 rd) {
float t = 0.0;
int index_insert = 0;
float[] store_t = float[4](-1., -1., -1., -1.);
for(int i = 0;
i < RAYMARCH_STEP &&
index_insert < RAYMARCH_MAX_INTERSECTION &&
t < RAYMARCH_MAX_LENGTH;
i++)
{
vec3 p = ro + t * rd;
float d = abs(sdScene(p));
if(d < RAYMARCH_TOLERANCE) {
store_t[index_insert] = t;
index_insert += 1;
}
while(d < RAYMARCH_TOLERANCE) {
t += max(RAYMARCH_TOLERANCE, d);
p = ro + t * rd;
d = abs(sdScene(p));
}
t += d;
}
return store_t;
}
// ------------------------------------------------------------
// Utilities
// ------------------------------------------------------------
vec2 intersect_line_sphere(vec3 ro, vec3 rd, vec3 sc, float sr) {
vec3 oc = ro - sc;
float a = dot(rd, rd);
float b = 2.0 * dot(oc, rd);
float c = dot(oc, oc) - sr * sr;
float discriminant = b * b - 4.0 * a * c;
if (discriminant < 0.0) return vec2(-1.0);
float sqrtD = sqrt(discriminant);
float t0 = (-b - sqrtD) / (2.0 * a);
float t1 = (-b + sqrtD) / (2.0 * a);
return vec2(t0, t1);
}
vec3 orbital_position(float yaw, float pitch, float radius, vec3 target) {
float x = radius * cos(pitch) * sin(yaw);
float y = radius * sin(pitch);
float z = radius * cos(pitch) * cos(yaw);
return target + vec3(x, y, z);
}
float remap(float uv, float omin, float omax, float nmin, float nmax) {
float t = (uv - omin) / (omax - omin);
return t * (nmax - nmin) + nmin;
}
#define TEX_REC_INTERSECTION iChannel0
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 mouse = iMouse.xy / iResolution.xy;
vec2 aspect_ratio = vec2(iResolution.xy / iResolution.yy);
vec2 uv_centered = ((gl_FragCoord.xy / iResolution.xy) - vec2(0.5)) * aspect_ratio;
vec3 ro_camera;
vec3 rd_camera;
{
float yaw = TAU * mouse.x;
float pitch = PI * mouse.y;
const vec3 target = vec3(0.);
ro_camera = orbital_position(yaw, pitch, RADIUS_CAMERA, target);
vec3 forward = normalize(target - ro_camera);
vec3 right = normalize(cross(vec3(0.0, 1.0, 0.0), forward));
vec3 up = cross(forward, right);
vec3 plane_center = ro_camera + forward * 1.0;
vec3 target_ray = plane_center + uv_centered.x * right + uv_centered.y * up;
rd_camera = normalize(target_ray - ro_camera);
}
float t = raymarch(ro_camera, rd_camera)[0];
vec3 col = vec3(0.0);
if (t > 0.0) {
vec3 p = ro_camera + rd_camera * t;
vec3 n = nScene(p);
float diffuse = clamp(dot(n, LIGHT_DIR), 0.0, 1.0);
diffuse = remap(diffuse, 0., 1., 0.2, 1.);
col = SDF_COLOR * diffuse;
for (int i = 0; i < MAX_DRAW_SAMPLES; i++) {
ivec2 seed = ivec2(i % int(iResolution.x),
i / int(iResolution.x));
vec3 ro_sample;
vec3 rd_sample;
random_sample_ray(seed, ro_sample, rd_sample);
vec4 t_rec = texelFetch(TEX_REC_INTERSECTION, seed, 0);
for (int c = 0; c < RAYMARCH_MAX_INTERSECTION; c++) {
float t_c = t_rec[c];
if (t_c >= 0.) {
vec3 p_tc = ro_sample + rd_sample * t_c;
vec2 t_inter = intersect_line_sphere(
ro_camera,
rd_camera,
p_tc,
SAMPLE_RADIUS
);
if ((t_inter.x > 0. && t_inter.x < t) ||
(t_inter.y > 0. && t_inter.y < t))
{
col = vec3(0.8, 0.4, 1.);
}
}
}
}
}
fragColor = vec4(col, 1.0);
}
@bolducke

bolducke commented Feb 14, 2026

Copy link
Copy Markdown
Author

Original implementation here: https://www.shadertoy.com/view/WfcXWB
Code extacted with LLM since shadertoy code is unavailable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment