example. ray marching (naïve) [ag-0019]
example. ray marching (naïve) [ag-0019]
The following renders a scene with a unit sphere at the origin, the camera at \((0,0,8)\) and looking at the origin, through a screen of height 1.0, centered at 5.0 from the camera.
The color of pixels are adjusted so that they are brighter the closer they are to the camera, as if there is a light source at the camera. As it takes a fixed step size of 0.1 (not small enough), the sphere is not rendered smoothly, and clearly shows the stepping artifacts.
/* The SDF for a sphere with radius r */ float sdSphere(vec3 p, float r) { return length(p) - r; } /* The SDF for a scene with a unit sphere at the origin */ float sdScene(in vec3 pos) { return sdSphere(pos, 1.0); } #define EPSILON 0.01 #define T_MAX 10.0 #define DELTA_T 0.1 #define SDF_FUNCTION sdScene /* Ray marching (naïve) */ float rayMarch(in vec3 ro, in vec3 rd) { float t = 0.0; while(t < T_MAX) { vec3 rt = ro + t * rd; float ft = SDF_FUNCTION(rt); if(ft < EPSILON) return t; t += DELTA_T; } return T_MAX; } /* The main function to render the scene per pixel */ void mainImage(out vec4 pixelColor, in vec2 pixelCoordinate) { // set up uv coordinates on the screen float aspect = iResolution.x/iResolution.y; vec2 uv = pixelCoordinate/iResolution.xy; uv -= vec2(0.5, 0.5); uv *= 2.0 * vec2(aspect, 1.0); // set up camera and view ray float observerDistance = 8.0; vec3 ro = vec3(0.0, 0.0, observerDistance); vec3 ta = ro - vec3(uv, 5.0); vec3 rd = normalize(ta - ro); // ray march float t = rayMarch(ro, rd); float hit = t != T_MAX ? 1.0 : 0.0; // adjust the color to look just bright enough float baseRatio = 0.65; // the closer, the brighter float distRatio = baseRatio + smoothstep(0.0, 1.0 - baseRatio, 1.0 - t / observerDistance); vec3 col = distRatio * vec3(1.0); // transparent if not hit pixelColor = vec4(col, hit); }
Code
/* The SDF for a sphere with radius r */
float sdSphere(vec3 p, float r)
{
return length(p) - r;
}
/* The SDF for a scene with a unit sphere at the origin */
float sdScene(in vec3 pos) {
return sdSphere(pos, 1.0);
}
#define EPSILON 0.01
#define T_MAX 10.0
#define DELTA_T 0.1
#define SDF_FUNCTION sdScene
/* Ray marching (naïve) */
float rayMarch(in vec3 ro, in vec3 rd) {
float t = 0.0;
while(t < T_MAX) {
vec3 rt = ro + t * rd;
float ft = SDF_FUNCTION(rt);
if(ft < EPSILON) return t;
t += DELTA_T;
}
return T_MAX;
}
/* The main function to render the scene per pixel */
void mainImage(out vec4 pixelColor, in vec2 pixelCoordinate) {
// set up uv coordinates on the screen
float aspect = iResolution.x/iResolution.y;
vec2 uv = pixelCoordinate/iResolution.xy;
uv -= vec2(0.5, 0.5);
uv *= 2.0 * vec2(aspect, 1.0);
// set up camera and view ray
float observerDistance = 8.0;
vec3 ro = vec3(0.0, 0.0, observerDistance);
vec3 ta = ro - vec3(uv, 5.0);
vec3 rd = normalize(ta - ro);
// ray march
float t = rayMarch(ro, rd);
float hit = t != T_MAX ? 1.0 : 0.0;
// adjust the color to look just bright enough
float baseRatio = 0.65;
// the closer, the brighter
float distRatio = baseRatio + smoothstep(0.0, 1.0 - baseRatio, 1.0 - t / observerDistance);
vec3 col = distRatio * vec3(1.0);
// transparent if not hit
pixelColor = vec4(col, hit);
}