fixed reverse pathtracing image link and misplaced src files

This commit is contained in:
Sven Vogel 2024-03-02 14:26:51 +01:00
parent d2ee54070c
commit 4e7b4b63e3
4 changed files with 1 additions and 254 deletions

View File

@ -1,7 +1,7 @@
# Reverse Path Tracing # Reverse Path Tracing
<p align="center"> <p align="center">
<img src="https://git.montehaselino.de/servostar/shadertoy-shaders/src/branch/main/pathtracing/reverse/overview.png"/> <img src="https://git.montehaselino.de/servostar/Shadertoy-Shaders/src/branch/main/pathtracing/reverse/overview.png"/>
</p> </p>
SDF based ray marching reverse path tracer. Capable of direct and indirect diffuse, specular and refractive ray bounces. SDF based ray marching reverse path tracer. Capable of direct and indirect diffuse, specular and refractive ray bounces.

View File

@ -1,215 +0,0 @@
const int DEPTH = 32;
const int AA = 8;
const vec2 epsilon = vec2(1e-3, 0);
const float planeNear = 1e-3;
const float planeFar = 1e2;
const float fov = 82.0;
const float PI = 3.141592653589793;
const float pdf = 2.0 * PI;
#define UNION(a, b) ((a.x) < (b.x) ? (a) : (b))
#define SDF vec2
#define MATERIAL_WHITE 0
#define MATERIAL_RED 1
#define MATERIAL_GREEN 2
#define MATERIAL_BLUE 3
#define MATERIAL_MIRROR 10
#define MATERIAL_GLASS 20
#define MATERIAL_EMISSION 255
SDF sdfScene(in vec3 pos)
{
vec3 q = abs(pos - vec3(0,0.99,-1)) - vec3(0.5, 0.01, 0.5);
SDF li0 = SDF(length(max(q, 0.0)) + min(max(q.x, max(q.y, q.z)), 0.0), MATERIAL_EMISSION);
SDF sp1 = SDF(length(pos + vec3( 0.5, 0.5, 1)) - 0.5, MATERIAL_WHITE);
SDF sp2 = SDF(abs(length(pos + vec3(-0.5, 0.75, 1)) - 0.25) - epsilon[0], MATERIAL_GLASS);
SDF sp3 = SDF(length(pos + vec3( 0.5,-0.25, 1)) - 0.25, MATERIAL_MIRROR);
SDF pl0 = SDF( pos.y + 1.0, MATERIAL_WHITE);
SDF pl1 = SDF(-pos.y + 1.0, MATERIAL_WHITE);
SDF pl2 = SDF( pos.x + 1.0, MATERIAL_RED);
SDF pl3 = SDF(-pos.x + 1.0, MATERIAL_GREEN);
SDF pl4 = SDF(-pos.z, MATERIAL_BLUE);
SDF pl5 = SDF( pos.z + 4.1, MATERIAL_WHITE);
SDF box = UNION(pl0, pl1);
box = UNION(box, pl2);
box = UNION(box, pl3);
box = UNION(box, pl4);
box = UNION(box, pl5);
box = UNION(box, sp1);
box = UNION(box, sp2);
box = UNION(box, sp3);
return UNION(li0, box);
}
vec3 sceneNormal(in vec3 pos)
{
return normalize(sdfScene(pos)[0] - vec3(
sdfScene(pos + epsilon.xyy)[0],
sdfScene(pos + epsilon.yxy)[0],
sdfScene(pos + epsilon.yyx)[0]
));
}
// project vector b onto vector a
vec3 project(in vec3 a, in vec3 b)
{
return a * (dot(a, b) / dot(a, a));
}
// construct a 3D coordinate system with the input up being the "upwards" facing vector
// which will be directly stored in w.
// Mathematically this function will create two non linear vectors of up and generate an orthonormal
// basis using gram-schmidt.
// This function assumes "up" being already normalized
void construct_orthonormal_basis(in vec3 up, out vec3 u, out vec3 v, out vec3 w)
{
w = up;
vec3 n2 = normalize(cross(w, vec3(0, 1.0, 1.0))); // build perpendicular vector from w
vec3 n3 = cross(w, n2); // create 2nd vector perpendicular to w and n2
// gram schmidt
u = n2 - (project(w, n2));
v = n3 - project(w, n3) - project(u, n3);
}
// generate a normalized vector within the bounds of the hemisphere with radius of 1.
// Z-Coordinate will be "upwards".
// radius determines the maximum radius the output vector will have.
// NOTE: shrinkin radius will still result in the output to be normalized
vec3 cosine_weighted_hemisphere()
{
float u1 = random();
float u2 = random();
float r = sqrt(u1);
float theta = 2.0 * PI * u2;
float x = r * cos(theta);
float y = r * sin(theta);
return vec3(x, y, sqrt(1.0 - u1));
}
vec3 generate_brdf_ray_direction(in vec3 normal, in vec3 incident) {
vec3 hemisphere = cosine_weighted_hemisphere();
vec3 u, v, w;
construct_orthonormal_basis(normal, u, v, w);
return u * hemisphere.x + v * hemisphere.y + w * hemisphere.z;
}
vec3 tracePath(in vec3 ro, in vec3 rd)
{
vec3 col = vec3(0);
vec3 thr = vec3(1);
for (int k = 0; k < DEPTH; k++)
{
vec3 pos = ro + rd * planeNear;
float t = planeNear;
for (int i = 0; i < 256 && t < planeFar; i++)
{
SDF h = sdfScene(pos);
if (h[0] < epsilon[0])
{
vec3 nor = sceneNormal(pos);
switch(int(h[1]))
{
case MATERIAL_MIRROR:
rd = reflect(rd, nor);
ro = pos - nor * epsilon[0];
break;
case MATERIAL_GLASS:
if (dot(nor, rd) > random())
{
rd = refract(rd, -nor, 0.2);
ro = pos + nor * epsilon[0] * 4.0;
}
else
{
rd = reflect(rd, nor);
ro = pos - nor * epsilon[0];
}
break;
default:
rd = -generate_brdf_ray_direction(nor, rd);
ro = pos - nor * epsilon[0];
break;
}
float cosTheta = abs(dot(nor, -rd)) * pdf / PI * 0.6667;
switch(int(h[1]))
{
case MATERIAL_EMISSION:
col += thr * 10.0;
break;
case MATERIAL_WHITE:
thr *= cosTheta;
break;
case MATERIAL_RED:
thr *= vec3(0.9, 0.1, 0.1) * cosTheta;
break;
case MATERIAL_GREEN:
thr *= vec3(0.1, 0.9, 0.1) * cosTheta;
break;
case MATERIAL_BLUE:
thr *= vec3(0.1, 0.1, 0.9) * cosTheta;
break;
default:
break;
}
break;
}
t += h[0];
pos += rd * h[0];
}
float m = max(thr.x, max(thr.y, thr.z));
if (random() > m)
break;
}
return col;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
SEED = (fragCoord.x * fragCoord.y)/iResolution.y + iTime;
vec3 col = vec3(0);
vec3 ro = vec3(0,0,-3.999);
// take multiple samples per pixel
// offset each ray direction slightly inside pixel
// in order to anti aliase
for (int i = 0; i < AA; i++, SEED++)
{
vec2 off = vec2(random(), random()) * 0.5;
vec2 uv = (fragCoord + off -0.5 * iResolution.xy) / iResolution.y;
vec3 rd = normalize(vec3(uv, 1.0/tan(fov * 0.008726646259971648)));
col += tracePath(ro, rd);
}
col /= float(AA);
vec3 prev = texture(iChannel0, fragCoord.xy/iResolution.xy).rgb;
col = mix(prev, col, 1.0/max(float(iFrame), 1.0));
fragColor = vec4(col, 1.0);
}

View File

@ -1,8 +0,0 @@
float SEED = 0.0;
float random()
{
SEED ++;
return fract(cos(SEED) * 2474.0);
}

View File

@ -1,30 +0,0 @@
float luminance(vec3 v)
{
return dot(v, vec3(0.2126f, 0.7152f, 0.0722f));
}
vec3 reinhard_jodie(vec3 v)
{
float l = luminance(v);
vec3 tv = v / (1.0f + v);
return mix(v / (1.0f + l), tv, tv);
}
float tentKernel(in vec2 xy, in float r)
{
return (1.0 - abs(xy.x/r)) * (1.0 - abs(xy.y/r)) / (r*r);
}
float gaussianWeight(in float delta, in float sigma)
{
return exp(-delta*delta/(2.0 * sigma * sigma)) * 2.5 * sigma;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord)
{
vec2 uv = fragCoord.xy/iResolution.xy;
vec3 color = texture(iChannel0, uv).rgb;
fragColor = vec4(reinhard_jodie(color), 1);
}