aboutsummaryrefslogtreecommitdiffstats
path: root/shaders/compute.comp
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2021-01-04 23:47:59 +0100
committerladevieq <ladevie.quentin@gmail.com>2021-01-04 23:47:59 +0100
commit8c3376c49f803e1d28e76ed100d4d417394df41f (patch)
tree2288bd6b2364953cd491345d8be4790fb415183b /shaders/compute.comp
parent5c66c6673590323b2f875b77a353cd852565b4d1 (diff)
Dielectric materials
Diffstat (limited to 'shaders/compute.comp')
-rw-r--r--shaders/compute.comp44
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 {