diff options
| author | ladevieq <ladevie.quentin@gmail.com> | 2021-01-04 23:47:59 +0100 |
|---|---|---|
| committer | ladevieq <ladevie.quentin@gmail.com> | 2021-01-04 23:47:59 +0100 |
| commit | 8c3376c49f803e1d28e76ed100d4d417394df41f (patch) | |
| tree | 2288bd6b2364953cd491345d8be4790fb415183b /shaders/compute.comp | |
| parent | 5c66c6673590323b2f875b77a353cd852565b4d1 (diff) | |
Dielectric materials
Diffstat (limited to 'shaders/compute.comp')
| -rw-r--r-- | shaders/compute.comp | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/shaders/compute.comp b/shaders/compute.comp index 7763538..92fae9d 100644 --- a/shaders/compute.comp +++ b/shaders/compute.comp @@ -3,11 +3,16 @@ struct ray { vec3 direction; }; +const uint LAMBERTIAN_MATERIAL = 0; +const uint METAL_MATERIAL = 1; +const uint DIELECTRIC_MATERIAL = 2; + struct material { vec4 albedo; float fuzz; + float ior; uint type; - uint[2] padding; + uint padding; }; struct hit_info { @@ -39,7 +44,7 @@ layout(set = 0, binding = 0) buffer Inputs { vec4[1000] random_in_sphere; - sphere[4] spheres; + sphere[5] spheres; uint max_bounce; float [3] padding; @@ -100,7 +105,7 @@ bool hit_spheres(ray r, float min_t, float max_t, out hit_info info) { float closest_t = max_t; hit_info temp_info; bool hit = false; - for (uint sphere_index = 0; sphere_index < 4; sphere_index++) { + for (uint sphere_index = 0; sphere_index < 5; sphere_index++) { if (hit_sphere(spheres[sphere_index], r, min_t, closest_t, temp_info)) { info = temp_info; closest_t = temp_info.t; @@ -130,6 +135,34 @@ bool metal_scattering(material mat, ray incident, vec2 seed, hit_info info, out return (dot(scattered.direction, info.normal) > 0.0); } +float reflectance(float cosine, float eta) { + // Use Schlick's approximation for reflectance. + float r0 = (1 - eta) / (1 + eta); + r0 = r0 * r0; + return r0 + (1 - r0) * pow((1 - cosine), 5); +} + +bool dielectric_scattering(material mat, ray incident, vec2 seed, hit_info info, out vec4 attenuation, out ray scattered) { + attenuation = vec4(1.0); + + vec3 unit_dir = normalize(incident.direction); + float cos_theta = min(dot(-unit_dir, info.normal), 1.0); + float sin_theta = sqrt(1.0 - cos_theta*cos_theta); + + float eta = info.front_face ? 1.0 / mat.ior : mat.ior; + vec3 direction; + + if (eta * sin_theta > 1.0 || reflectance(cos_theta, eta) > rand(seed)) { + direction = reflect(unit_dir, info.normal); + } else { + direction = refract(unit_dir, info.normal, eta); + } + + scattered = ray(info.point, direction); + + return true; +} + vec4 ray_color(ray r, uint sample_index) { hit_info info; uint bounces = 0; @@ -140,8 +173,9 @@ vec4 ray_color(ray r, uint sample_index) { vec2 seed = vec2(info.point.x * sample_index, info.point.y * bounces) * gl_GlobalInvocationID.xy; ray scattered; vec4 attenuation; - if (info.mat.type == 0 && lambertian_scattering(info.mat, current_ray, seed, info, attenuation, scattered) || - info.mat.type == 1 && metal_scattering(info.mat, current_ray, seed, info, attenuation, scattered)) { + if (info.mat.type == LAMBERTIAN_MATERIAL && lambertian_scattering(info.mat, current_ray, seed, info, attenuation, scattered) || + info.mat.type == METAL_MATERIAL && metal_scattering(info.mat, current_ray, seed, info, attenuation, scattered) || + info.mat.type == DIELECTRIC_MATERIAL && dielectric_scattering(info.mat, current_ray, seed, info, attenuation, scattered)) { final_color *= attenuation; current_ray = scattered; } else { |
