From f38e7d808111374ce914e6e949410a640ddbf1ca Mon Sep 17 00:00:00 2001 From: Rokas Puzonas Date: Wed, 29 Nov 2023 23:16:50 +0200 Subject: [PATCH] add glass like material --- src/main.cu | 11 ++++----- src/material.cpp | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/main.cu b/src/main.cu index e034139..2ea1323 100644 --- a/src/main.cu +++ b/src/main.cu @@ -95,10 +95,11 @@ __global__ void render(vec3 *fb, __global__ void create_world(hitable **d_list, int d_list_size, hitable **d_world, camera **d_camera) { if (threadIdx.x == 0 && blockIdx.y == 0) { - d_list[0] = new sphere(vec3( 0, 0 , -1), 0.5, new lambertian(vec3(0.8, 0.3, 0.3))); - d_list[1] = new sphere(vec3( 0, -100.5, -1), 100, new lambertian(vec3(0.8, 0.8, 0.0))); - d_list[2] = new sphere(vec3( 1, 0 , -1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 1.0)); - d_list[3] = new sphere(vec3(-1, 0 , -1), 0.5, new metal(vec3(0.8, 0.8, 0.8), 0.3)); + d_list[0] = new sphere(vec3( 0, 0 , -1), 0.5, new lambertian(vec3(0.1, 0.2, 0.5))); + d_list[1] = new sphere(vec3( 0, -100.5, -1), 100, new lambertian(vec3(0.8, 0.8, 0.0))); + d_list[2] = new sphere(vec3( 1, 0 , -1), 0.5, new metal(vec3(0.8, 0.6, 0.2), 0.0)); + d_list[3] = new sphere(vec3(-1, 0 , -1), 0.5, new dielectric(1.5)); + d_list[4] = new sphere(vec3(-1, 0 , -1), -0.45, new dielectric(1.5)); *d_world = new hitable_list(d_list, d_list_size); *d_camera = new camera(); } @@ -137,7 +138,7 @@ int main() { // populate world hitable **d_list; - int d_list_size = 4; + int d_list_size = 5; checkCudaErrors(cudaMalloc((void **)&d_list, d_list_size*sizeof(hitable *))); hitable **d_world; checkCudaErrors(cudaMalloc((void **)&d_world, sizeof(hitable *))); diff --git a/src/material.cpp b/src/material.cpp index 0cf9c3f..07ee248 100644 --- a/src/material.cpp +++ b/src/material.cpp @@ -21,6 +21,24 @@ __device__ vec3 reflect(const vec3& v, const vec3& n) { return v - 2.0f*dot(v,n)*n; } +__device__ float schlick(float cosine, float ref_idx) { + float r0 = (1.0 - ref_idx) / (1.0f+ref_idx); + r0 = r0*r0; + return r0 + (1.0f - r0)*pow((1.0f - cosine), 5.0f); +} + +__device__ bool refract(const vec3& v, const vec3& n, float ni_over_nt, vec3& refracted) { + vec3 uv = unit_vector(v); + float dt = dot(uv, n); + float discriminant = 1.0f - ni_over_nt*ni_over_nt*(1-dt*dt); + if (discriminant > 0) { + refracted = ni_over_nt*(uv - n*dt) - n*sqrt(discriminant); + return true; + } else { + return false; + } +} + class material { public: __device__ virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered, curandState *local_rand_state) const = 0; @@ -58,3 +76,43 @@ public: vec3 albedo; float fuzz; }; + +class dielectric : public material { +public: + __device__ dielectric(float ri) : ref_idx(ri) {} + __device__ virtual bool scatter(const ray& r_in, const hit_record& rec, vec3& attenuation, ray& scattered, curandState *local_rand_state) const { + vec3 outward_normal; + vec3 reflected = reflect(r_in.direction(), rec.normal); + float ni_over_nt; + attenuation = vec3(1.0, 1.0, 1.0); + vec3 refracted; + float reflect_prob; + float cosine; + if (dot(r_in.direction(), rec.normal) > 0.0f) { + outward_normal = -rec.normal; + ni_over_nt = ref_idx; + cosine = dot(r_in.direction(), rec.normal) / r_in.direction().length(); + cosine = sqrt(1.0f - ref_idx*ref_idx*(1-cosine*cosine)); + } else { + outward_normal = rec.normal; + ni_over_nt = 1 / ref_idx; + cosine = -dot(r_in.direction(), rec.normal) / r_in.direction().length(); + } + + if (refract(r_in.direction(), outward_normal, ni_over_nt, refracted)) { + reflect_prob = schlick(cosine, ref_idx); + } else { + reflect_prob = 1.0; + } + + if (curand_uniform(local_rand_state) < reflect_prob) { + scattered = ray(rec.p, reflected); + } else { + scattered = ray(rec.p, refracted); + } + + return true; + } + + float ref_idx; +};