Monte Carlo integration and ray marching in a signed distance field (SDF) to render emissive circles.
// Use Monte Carlo integration and ray marching
// of signed distance field (SDF) to render emissive circles.
// Source: https://github.com/miloyip/light2d/blob/master/basic.c
int samples = chi('samples');
function float sd_circle(vector2 uv, pos; float radius){
float dist = distance(uv, pos) - radius;
return dist;
}
function float sd_scene(vector2 uv){
float d_0 = sd_circle(uv, {0.3, 0.18}, 0.12);
float d_1 = sd_circle(uv, {0.25, 0.18}, 0.12);
float d_2 = sd_circle(uv, {-0.3, -0.2}, 0.02);
float dist = min( max(d_0, -d_1), d_2);
return max(dist);
}
function float trace(vector2 uv, dist){
float t = 0.0;
for(int i = 0; i < 100 && t < 2.0; i++){
float sd = sd_scene(uv + dist * t);
if(sd < 1e-5) return 1.5;
t += sd;
}
return 0.0;
}
function float sample(vector2 uv; int samples){
float sum = 0.0;
for(int i = 0; i < samples; i++){
float a = 2.0 * PI * ((rand(uv) + i) / float(samples));
sum += trace(uv, set(cos(a), sin(a)));
}
return sum / float(samples);
}
vector2 uv = set(v@P.x, v@P.y);
f@d = sample(uv, samples);