From Shaders to Scenes
Raymarching SDFs Friendly Optimizations
Main MacOS Programmer
(Since 2024)
Lead Engine Programmer
(Since 2021)
Inspired By Inigo Quilez
What Is It?
Rays are shot from a camera's viewpoint through each pixel of the screen
Determines what object, if any, the ray hits first
The color of that object is used for that specific pixel
Let's see the simplest example
I got lazy so I'mma freestyle the explanation
That's why it's called
"Signed Distance Function"
#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}#define N 80
// Sphere constants
const vec3 c = vec3(0., 0., 0.)
const float R = 1.0;
float scene(vec3 p) {
return length(p - c) - R; // function `f(p)`
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
vec2 uv = (fragCoord * 2. - iResolution.xy) / iResolution.y;
vec3 ro = vec3(0, 0, -3); // Ray Origin
vec3 rd = normalize(vec3(uv, -1)); // Ray Direction
float t = 0.; // Total distance travelled
for(int i = 0; i < N; i++){
vec3 p = ro + rd * t;
float dt = scene(p); // ds = 1
t += dt;
if(dt < 0.001) { // Exit Epsilon
fragColor = vec4(1., 0., 0., 1.); // If hit, then red
return;
}
}
fragColor = vec4(0., 0., 0., 1.);
}Squeeze Theorem!
(For Art Purposes)
(For Art Purposes)
(For Art Purposes)
C'mon. Don't Be Shy.
#define MAX_STEPS 100
float raymarch(vec3 ray_origin, vec3 ray_direction) {
float offset_size = 10.0;
float t = 0.0;
int iter = 0;
float t_j = cam_block.far;
float min_dist = cam_block.far;
int i = int((MAX_STEPS & 1) == 0);
#if (MAX_STEPS & 1) == 0
{
t = scene(ray_origin + t * ray_direction, 2.0, offset_size);
if(t < cam_block.near) {
return t;
}
}
#endif
while(i <= (MAX_STEPS >> 1)) {
vec3 p_i = ray_origin + t * ray_direction;
float dist_i = scene(p_i, 2.0, offset_size);
if(dist_i < cam_block.near) {
return t;
}
if(t > cam_block.far) {
return -1.0;
}
if(dist_i - min_dist > MIN_GROWTH) {
vec3 p_j = ray_origin + t_j * ray_direction;
float dist_j = scene(p_j, 2.0, offset_size);
if(abs(dist_i - dist_j) <= abs(t_j - t)
&& (dist_i + dist_j) >= abs(t_j - t)) {
return -1.0;
}
t_j -= dist_j;
}else {
t += dist_i;
dist_i = scene(ray_origin + t * ray_direction, 2.0, offset_size);
if(dist_i < cam_block.near) {
return t;
}
if(t > cam_block.far) {
return -1.0;
}
}
min_dist = min(min_dist, dist_i);
t += dist_i;
i++;
}
return t;
}