aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/vk-renderer.hpp6
-rw-r--r--shaders/compute.comp44
-rw-r--r--src/main.cpp9
3 files changed, 48 insertions, 11 deletions
diff --git a/include/vk-renderer.hpp b/include/vk-renderer.hpp
index afd5019..2e996c8 100644
--- a/include/vk-renderer.hpp
+++ b/include/vk-renderer.hpp
@@ -9,6 +9,7 @@
enum MATERIAL_TYPE: uint32_t {
LAMBERTIAN,
METAL,
+ DIELECTRIC,
};
struct input_data {
@@ -29,12 +30,13 @@ struct input_data {
struct material {
color albedo;
float fuzz;
+ float ior;
uint32_t type;
- uint32_t padding[2];
+ uint32_t padding;
} material;
float radius;
float padding[3];
- } spheres[4];
+ } spheres[5];
uint32_t max_bounce;
float padding[3];
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 {
diff --git a/src/main.cpp b/src/main.cpp
index 7ba2b47..66b1f6a 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -103,10 +103,11 @@ int main() {
.viewport_height = 2.f,
.proj_plane_distance = 1.f,
.spheres = {
- { { -1.f, 0.f, -1.f }, { { 0.8f, 0.8f, 0.8f }, 0.3, MATERIAL_TYPE::METAL }, 0.5f },
- { { 0.f, 0.f, -1.f }, { { 0.7f, 0.3f, 0.3f }, MATERIAL_TYPE::LAMBERTIAN }, 0.5f },
- { { 1.f, 0.f, -1.f }, { { 0.8f, 0.6f, 0.2f }, 1.0, MATERIAL_TYPE::METAL }, 0.5f },
- { { 0.f, -100.5f, -1.f }, { { 0.8f, 0.8f, 0.f }, MATERIAL_TYPE::LAMBERTIAN }, 100.f }
+ { { -1.f, 0.f, -1.f }, { { 0.8f, 0.8f, 0.8f }, 0.3, 1.5, MATERIAL_TYPE::DIELECTRIC }, 0.5f },
+ { { -1.f, 0.f, -1.f }, { { 0.8f, 0.8f, 0.8f }, 0.3, 1.5, MATERIAL_TYPE::DIELECTRIC }, -0.4f },
+ { { 0.f, 0.f, -1.f }, { { 0.7f, 0.3f, 0.3f }, 0.0, 1.5, MATERIAL_TYPE::DIELECTRIC }, 0.5f },
+ { { 1.f, 0.f, -1.f }, { { 0.8f, 0.6f, 0.2f }, 1.0, 0.0, MATERIAL_TYPE::METAL }, 0.5f },
+ { { 0.f, -100.5f, -1.f }, { { 0.8f, 0.8f, 0.f }, 0.0, 0.0, MATERIAL_TYPE::LAMBERTIAN }, 100.f }
},
.max_bounce = max_depth,
};