Skip to content

Commit

Permalink
Smallpt OGL
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaisiero committed Dec 28, 2024
1 parent 513ef76 commit 8e35f76
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 22 deletions.
14 changes: 9 additions & 5 deletions samples/demos/custom_shader_pt/custom_shader_pt.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ SHADER pathtracer
COMPUTE
LAYOUT 8 8 1
// texture unit 0: UAV albedo
UNIFORMS texuavw0
UNIFORM uint frame_count
UNIFORM uint frame_accum
UNIFORMS texfuav0
// texture unit 0: UAV albedo
UNIFORMS texfuavw1
UNIFORM int frame_count
UNIFORM int frame_accum
UNIFORM mat2x3 m_ray
UNIFORM mat2x3 lens
UNIFORM ivec2 window_size
Expand All @@ -28,6 +30,8 @@ SHADER pathtracer
cy*( ( (1.0 + dy)/2.0 + uv.y)/window_size.y - .5) + cam.d;
d = normalize(d);

vec3 r = radiance(Ray(cam.o+d*140.0, d), 0);
vec3 r = radiance(Ray(cam.o+d*140.0, d), 0, seed);
iuv.y = window_size.y - iuv.y - 1;
imageStore(texuavw0, iuv, vec4(r, 1.0));
vec4 prev = imageLoad(texfuav0, iuv);
vec4 average = vec4((prev.xyz * float(frame_accum) + r) / float(frame_accum + 1), 1.0);
imageStore(texfuavw1, iuv, average);
7 changes: 5 additions & 2 deletions samples/demos/custom_shader_pt/custom_shader_pt.lobster
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct Ray:
d:float3


let rgba32f = texture_format_float | texture_format_clamp | texture_format_nomipmap
let rgba32f = texture_format_float | texture_format_clamp | texture_format_nomipmap | texture_format_compute | texture_format_readwrite

let albedo_tex_format = rgba32f
var last_window_size = int2{800, 600}
Expand Down Expand Up @@ -43,6 +43,7 @@ SHADER screen

fatal(gl.load_materials(mats, true))
var albedo_tex = gl.create_blank_texture(int3(last_window_size, 0), albedo_tex_format)
var albedo_text_db = gl.create_blank_texture(int3(last_window_size, 0), albedo_tex_format)
var window_size_changed_last_frame = false
var frame_count = 0
var frame_accum = 0 // for averaging
Expand All @@ -63,6 +64,7 @@ while(gl.frame()):
++frame_accum
if window_size_changed_last_frame:
albedo_tex = gl.create_blank_texture(int3(last_window_size, 0), albedo_tex_format)
albedo_text_db = gl.create_blank_texture(int3(last_window_size, 0), albedo_tex_format)
frame_accum = 0
cx = float3_x * (last_window_size.x * .5135 / last_window_size.y)
cy = normalize(cx.cross(cam.d)) * .5135
Expand All @@ -73,7 +75,8 @@ while(gl.frame()):
gl.set_uniform_matrix("m_ray", cam_vector, true)
gl.set_uniform_matrix("lens", lens_matrix, true)
gl.set_uniform("window_size", last_window_size)
gl.set_image_texture(0, albedo_tex, 0, texture_format_writeonly)
gl.set_image_texture(0, if frame_count % 2 == 0: albedo_tex else: albedo_text_db, 0)
gl.set_image_texture(1, if frame_count % 2 == 0: albedo_text_db else: albedo_tex, 0)
let groups = (last_window_size + 7) / 8
gl.dispatch_compute(int3(groups, 1))
gl.blend(blend_none)
Expand Down
109 changes: 96 additions & 13 deletions samples/demos/custom_shader_pt/helper_functions.glsl
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ const float lrad = 100.0;

const uint num_spheres = 9;
const Sphere spheres[num_spheres] = Sphere[](
Sphere(50.0, vec3(50.0, lrad + 81.6 - 1.0, 81.6), vec3(12.0), vec3(0), DIFF), // Lite
Sphere(lrad, vec3(50.0, lrad + 81.6 - 1.0, 81.6), vec3(12.0), vec3(0), DIFF), // Lite
Sphere(16.5, vec3(73.0, 16.5, 78.0), vec3(0.0), vec3(0.999), REFR), // Glas
Sphere(16.5, vec3(27.0, 16.5, 47.0), vec3(0.0), vec3(0.999), SPEC), // Mirr
Sphere(bigrad, vec3(50.0, -bigrad + 81.6, 81.6), vec3(0.0), vec3(0.75), DIFF), // Top
Expand All @@ -79,17 +79,100 @@ const Sphere spheres[num_spheres] = Sphere[](
);


vec3 radiance(Ray r, uint depth) {
float t = 1000000000000.0; // distance to intersection
int id = -1; // id of intersected object
for (int i = 0; i < num_spheres; ++i) {
float d = intersect(spheres[i], r);
if (d > 0.0 && d < t) {
t = d;
id = i;
vec3 radiance(Ray initial_ray, uint initial_depth, inout uint seed) {
vec3 result = vec3(0.0); // Final accumulated color
vec3 attenuation = vec3(1.0); // Tracks the accumulated reflectance along the path
uint depth = initial_depth;

Ray ray = initial_ray;

while (true) {
float t = 1000000000000.0; // Distance to intersection
int id = -1; // ID of the intersected object

// Find the closest sphere intersection
for (int i = 0; i < num_spheres; ++i) {
float d = intersect(spheres[i], ray);
if (d > 0.0 && d < t) {
t = d;
id = i;
}
}

// If no intersection, terminate and return the accumulated color
if (id == -1) {
result += attenuation * vec3(0.0); // Add black if no hit
break;
}

// Intersection found
Sphere s = spheres[id];
vec3 x = ray.o + ray.d * t; // Hit position
vec3 n = normalize(x - s.p); // Surface normal
vec3 nl = dot(n, ray.d) < 0.0 ? n : -n; // Properly oriented normal
vec3 f = s.c; // Object color
result += attenuation * s.e; // Add emitted light

// Russian Roulette for termination
float p = max(max(f.x, f.y), f.z); // Maximum reflectance
if (++depth > 5) {
if (random_float(seed) >= p) {
break; // Terminate if not reflected
}
f *= 1.0 / p; // Scale reflectance
}

// Update attenuation
attenuation *= f;

// Determine next ray direction based on material type
if (s.refl == DIFF) { // Diffuse reflection
float r1 = 360.0* random_float(seed);
float r2 = random_float(seed);
float r2s = sqrt(r2);
vec3 w = nl;
vec3 u = normalize(abs(w.x) > 0.1 ? vec3(0.0, 1.0, 0.0) : vec3(1.0, 0.0, 0.0));
vec3 v = cross(w, u);
vec3 d = normalize(u * cos(r1) * r2s + v * sin(r1) * r2s + w * sqrt(1.0 - r2));
ray = Ray(x, d); // Update the ray
} else if (s.refl == SPEC) { // Specular reflection
ray = Ray(x, ray.d - n * 2.0 * dot(n, ray.d)); // Reflect ray
} else { // Dielectric refraction
Ray reflRay = Ray(x, ray.d - n * 2.0 * dot(n, ray.d));
bool into = dot(n, nl) > 0.0; // Ray entering?
float nc = 1.0;
float nt = 1.5;
float nnt = into ? nc / nt : nt / nc;
float ddn = dot(ray.d, nl);
float cos2t = 1.0 - nnt * nnt * (1.0 - ddn * ddn);

if (cos2t < 0.0) { // Total internal reflection
ray = reflRay; // Reflect ray
continue;
}

vec3 tdir = normalize(ray.d * nnt - n * ((into ? 1.0 : -1.0) * (ddn * nnt + sqrt(cos2t))));
float a = nt - nc;
float b = nt + nc;
float R0 = a * a / (b * b);
float c = 1.0 - (into ? -ddn : dot(tdir, n));
float Re = R0 + (1.0 - R0) * c * c * c * c * c;
float Tr = 1.0 - Re;
float P = 0.25 + 0.5 * Re;
float RP = Re / P;
float TP = Tr / (1.0 - P);

if (random_float(seed) < P) {
attenuation *= RP;
ray = reflRay;
} else {
attenuation *= TP;
ray = Ray(x, tdir);
}
}

ray.o += ray.d * 0.001; // Offset the origin to avoid self-intersection
}
if (id == -1) return vec3(0.0); // if miss, return black
return spheres[id].c; // the hit object
// return vec3(1.0); // the hit object
}

return result;
}
4 changes: 2 additions & 2 deletions samples/demos/smallpt.lobster
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ def radiance(r:Ray, depth) -> float3:
radiance(reflRay,depth)*Re+radiance(Ray { x, tdir },depth)*Tr
return obj.e + f*temp

let w = 64
let h = 48
let w = 800
let h = 600

let cam = Ray { float3 { 50.0,50.0,290.0 }, normalize(float3 { 0.0,-0.042612,-1.0 }) } // cam pos, dir
let cx = float3_x * (w*.5135/h)
Expand Down

0 comments on commit 8e35f76

Please sign in to comment.