Add glass material
This commit is contained in:
parent
21b3d0e713
commit
7e6ba7d445
15
main.c
15
main.c
@ -47,13 +47,11 @@ int main(void) {
|
||||
Lambertian material_ground = {.type = MATERIAL_LAMBERTIAN,
|
||||
.albedo = (Color){0.8, 0.8, 0.0}};
|
||||
Lambertian material_center = {.type = MATERIAL_LAMBERTIAN,
|
||||
.albedo = (Color){0.7, 0.3, 0.3}};
|
||||
Metal material_left = {.type = MATERIAL_METAL,
|
||||
.albedo = (Color){0.8, 0.8, 0.8},
|
||||
.fuzziness = 0.3};
|
||||
.albedo = (Color){0.1, 0.2, 0.5}};
|
||||
Dielectric material_left = {.type = MATERIAL_DIELECTRIC, .eta = 1.5};
|
||||
Metal material_right = {.type = MATERIAL_METAL,
|
||||
.albedo = (Color){0.8, 0.6, 0.2},
|
||||
.fuzziness = 1.0};
|
||||
.fuzziness = 0.0};
|
||||
|
||||
Sphere sphere_ground = {
|
||||
.type = HITTABLE_SPHERE,
|
||||
@ -73,6 +71,12 @@ int main(void) {
|
||||
.radius = 0.5,
|
||||
.material = (const Material *)&material_left,
|
||||
};
|
||||
Sphere sphere_inside_left = {
|
||||
.type = HITTABLE_SPHERE,
|
||||
.center = (Point3){-1.0, 0.0, -1.0},
|
||||
.radius = -0.4,
|
||||
.material = (const Material *)&material_left,
|
||||
};
|
||||
Sphere sphere_right = {
|
||||
.type = HITTABLE_SPHERE,
|
||||
.center = (Point3){1.0, 0.0, -1.0},
|
||||
@ -82,6 +86,7 @@ int main(void) {
|
||||
hittable_list_add(&world, (const Hittable *)&sphere_ground);
|
||||
hittable_list_add(&world, (const Hittable *)&sphere_center);
|
||||
hittable_list_add(&world, (const Hittable *)&sphere_left);
|
||||
hittable_list_add(&world, (const Hittable *)&sphere_inside_left);
|
||||
hittable_list_add(&world, (const Hittable *)&sphere_right);
|
||||
|
||||
/* Camera */
|
||||
|
||||
36
material.c
36
material.c
@ -1,8 +1,10 @@
|
||||
#include "material.h"
|
||||
#include "hittable.h"
|
||||
#include "utils.h"
|
||||
#include "vec3.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
|
||||
bool material_scatter(const Material *material, Ray r,
|
||||
const struct HitRecord *record, Color *attenuation,
|
||||
@ -14,6 +16,9 @@ bool material_scatter(const Material *material, Ray r,
|
||||
case MATERIAL_METAL:
|
||||
return metal_scatter((const Metal *)material, r, record, attenuation,
|
||||
scattered);
|
||||
case MATERIAL_DIELECTRIC:
|
||||
return dielectric_scatter((const Dielectric *)material, r, record,
|
||||
attenuation, scattered);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -45,3 +50,34 @@ bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
||||
*attenuation = metal->albedo;
|
||||
return vec3_dot(scattered->direction, record->normal) > 0;
|
||||
}
|
||||
|
||||
static double schlick_reflectance(double cosine, double eta) {
|
||||
double r0 = (1 - eta) / (1 + eta);
|
||||
r0 *= r0;
|
||||
return r0 + (1 - r0) * pow(1 - cosine, 5);
|
||||
}
|
||||
|
||||
bool dielectric_scatter(const Dielectric *dielectric, Ray r,
|
||||
const struct HitRecord *record, Color *attenuation,
|
||||
Ray *scattered) {
|
||||
*attenuation = (Color){1.0, 1.0, 1.0};
|
||||
double refraction_ratio =
|
||||
record->front_face ? (1.0 / dielectric->eta) : dielectric->eta;
|
||||
|
||||
Vec3 unit_direction = vec3_normalize(r.direction);
|
||||
double cos_theta =
|
||||
fmin(vec3_dot(vec3_neg(unit_direction), record->normal), 1.0);
|
||||
double sin_theta = sqrt(1.0 - cos_theta * cos_theta);
|
||||
|
||||
bool cannot_refract = refraction_ratio * sin_theta > 1.0;
|
||||
|
||||
Vec3 direction;
|
||||
if (cannot_refract ||
|
||||
schlick_reflectance(cos_theta, refraction_ratio) > random_double())
|
||||
direction = vec3_reflect(unit_direction, record->normal);
|
||||
else
|
||||
direction = vec3_refract(unit_direction, record->normal, refraction_ratio);
|
||||
|
||||
*scattered = (Ray){record->p, direction};
|
||||
return true;
|
||||
}
|
||||
|
||||
10
material.h
10
material.h
@ -11,6 +11,7 @@ struct HitRecord;
|
||||
typedef enum MaterialType {
|
||||
MATERIAL_LAMBERTIAN,
|
||||
MATERIAL_METAL,
|
||||
MATERIAL_DIELECTRIC,
|
||||
} MaterialType;
|
||||
|
||||
typedef struct Material {
|
||||
@ -39,4 +40,13 @@ typedef struct Metal {
|
||||
bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
||||
Color *attenuation, Ray *scattered);
|
||||
|
||||
typedef struct Dielectric {
|
||||
MaterialType type;
|
||||
double eta;
|
||||
} Dielectric;
|
||||
|
||||
bool dielectric_scatter(const Dielectric *dielectric, Ray r,
|
||||
const struct HitRecord *record, Color *attenuation,
|
||||
Ray *scattered);
|
||||
|
||||
#endif /* INCLUDED_MATERIAL_H */
|
||||
|
||||
9
vec3.c
9
vec3.c
@ -73,3 +73,12 @@ bool vec3_is_near_zero(Vec3 v) {
|
||||
Vec3 vec3_reflect(Vec3 v, Vec3 n) {
|
||||
return vec3_sub(v, vec3_mul(2 * vec3_dot(v, n), n));
|
||||
}
|
||||
|
||||
Vec3 vec3_refract(Vec3 uv, Vec3 n, double refraction_ratio) {
|
||||
double cos_theta = fmin(vec3_dot(vec3_neg(uv), n), 1.0);
|
||||
Vec3 r_out_perpendicular =
|
||||
vec3_mul(refraction_ratio, vec3_add(uv, vec3_mul(cos_theta, n)));
|
||||
Vec3 r_out_parallel =
|
||||
vec3_mul(-sqrt(fabs(1.0 - vec3_length2(r_out_perpendicular))), n);
|
||||
return vec3_add(r_out_perpendicular, r_out_parallel);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user