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,
|
Lambertian material_ground = {.type = MATERIAL_LAMBERTIAN,
|
||||||
.albedo = (Color){0.8, 0.8, 0.0}};
|
.albedo = (Color){0.8, 0.8, 0.0}};
|
||||||
Lambertian material_center = {.type = MATERIAL_LAMBERTIAN,
|
Lambertian material_center = {.type = MATERIAL_LAMBERTIAN,
|
||||||
.albedo = (Color){0.7, 0.3, 0.3}};
|
.albedo = (Color){0.1, 0.2, 0.5}};
|
||||||
Metal material_left = {.type = MATERIAL_METAL,
|
Dielectric material_left = {.type = MATERIAL_DIELECTRIC, .eta = 1.5};
|
||||||
.albedo = (Color){0.8, 0.8, 0.8},
|
|
||||||
.fuzziness = 0.3};
|
|
||||||
Metal material_right = {.type = MATERIAL_METAL,
|
Metal material_right = {.type = MATERIAL_METAL,
|
||||||
.albedo = (Color){0.8, 0.6, 0.2},
|
.albedo = (Color){0.8, 0.6, 0.2},
|
||||||
.fuzziness = 1.0};
|
.fuzziness = 0.0};
|
||||||
|
|
||||||
Sphere sphere_ground = {
|
Sphere sphere_ground = {
|
||||||
.type = HITTABLE_SPHERE,
|
.type = HITTABLE_SPHERE,
|
||||||
@ -73,6 +71,12 @@ int main(void) {
|
|||||||
.radius = 0.5,
|
.radius = 0.5,
|
||||||
.material = (const Material *)&material_left,
|
.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 = {
|
Sphere sphere_right = {
|
||||||
.type = HITTABLE_SPHERE,
|
.type = HITTABLE_SPHERE,
|
||||||
.center = (Point3){1.0, 0.0, -1.0},
|
.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_ground);
|
||||||
hittable_list_add(&world, (const Hittable *)&sphere_center);
|
hittable_list_add(&world, (const Hittable *)&sphere_center);
|
||||||
hittable_list_add(&world, (const Hittable *)&sphere_left);
|
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);
|
hittable_list_add(&world, (const Hittable *)&sphere_right);
|
||||||
|
|
||||||
/* Camera */
|
/* Camera */
|
||||||
|
|||||||
36
material.c
36
material.c
@ -1,8 +1,10 @@
|
|||||||
#include "material.h"
|
#include "material.h"
|
||||||
#include "hittable.h"
|
#include "hittable.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "vec3.h"
|
#include "vec3.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
bool material_scatter(const Material *material, Ray r,
|
bool material_scatter(const Material *material, Ray r,
|
||||||
const struct HitRecord *record, Color *attenuation,
|
const struct HitRecord *record, Color *attenuation,
|
||||||
@ -14,6 +16,9 @@ bool material_scatter(const Material *material, Ray r,
|
|||||||
case MATERIAL_METAL:
|
case MATERIAL_METAL:
|
||||||
return metal_scatter((const Metal *)material, r, record, attenuation,
|
return metal_scatter((const Metal *)material, r, record, attenuation,
|
||||||
scattered);
|
scattered);
|
||||||
|
case MATERIAL_DIELECTRIC:
|
||||||
|
return dielectric_scatter((const Dielectric *)material, r, record,
|
||||||
|
attenuation, scattered);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -45,3 +50,34 @@ bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
|||||||
*attenuation = metal->albedo;
|
*attenuation = metal->albedo;
|
||||||
return vec3_dot(scattered->direction, record->normal) > 0;
|
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 {
|
typedef enum MaterialType {
|
||||||
MATERIAL_LAMBERTIAN,
|
MATERIAL_LAMBERTIAN,
|
||||||
MATERIAL_METAL,
|
MATERIAL_METAL,
|
||||||
|
MATERIAL_DIELECTRIC,
|
||||||
} MaterialType;
|
} MaterialType;
|
||||||
|
|
||||||
typedef struct Material {
|
typedef struct Material {
|
||||||
@ -39,4 +40,13 @@ typedef struct Metal {
|
|||||||
bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record,
|
||||||
Color *attenuation, Ray *scattered);
|
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 */
|
#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) {
|
Vec3 vec3_reflect(Vec3 v, Vec3 n) {
|
||||||
return vec3_sub(v, vec3_mul(2 * vec3_dot(v, n), 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);
|
||||||
|
}
|
||||||
|
|||||||
1
vec3.h
1
vec3.h
@ -29,5 +29,6 @@ Vec3 vec3_random_unit_vector(void);
|
|||||||
bool vec3_is_near_zero(Vec3 v);
|
bool vec3_is_near_zero(Vec3 v);
|
||||||
|
|
||||||
Vec3 vec3_reflect(Vec3 v, Vec3 n);
|
Vec3 vec3_reflect(Vec3 v, Vec3 n);
|
||||||
|
Vec3 vec3_refract(Vec3 uv, Vec3 n, double refraction_ratio);
|
||||||
|
|
||||||
#endif /* INCLUDED_VEC3_H */
|
#endif /* INCLUDED_VEC3_H */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user