Add participating media
This commit is contained in:
parent
990b36d9eb
commit
3e90f7e7cd
68
hittable.c
68
hittable.c
@ -247,6 +247,24 @@ Hittable *hittable_create_y_rotation(Hittable *ptr, double angle,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Hittable *hittable_create_constant_medium(Hittable *boundary, double density,
|
||||||
|
const Texture *phase, Arena *arena) {
|
||||||
|
Hittable *result = arena_alloc(arena, sizeof(Hittable));
|
||||||
|
result->type = HITTABLE_CONSTANT_MEDIUM;
|
||||||
|
result->constant_medium.boundary = boundary;
|
||||||
|
result->constant_medium.neg_inv_density = -1.0 / density;
|
||||||
|
result->constant_medium.phase_function =
|
||||||
|
material_create_isotropic(phase, arena);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Hittable *hittable_create_constant_medium_color(Hittable *boundary,
|
||||||
|
double density, Color albedo,
|
||||||
|
Arena *arena) {
|
||||||
|
return hittable_create_constant_medium(
|
||||||
|
boundary, density, texture_create_solid_color(albedo, arena), arena);
|
||||||
|
}
|
||||||
|
|
||||||
/*===----------------------------------------------------------------------===*/
|
/*===----------------------------------------------------------------------===*/
|
||||||
|
|
||||||
static bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
static bool hittable_list_hit(const HittableList *list, Ray r, double t_min,
|
||||||
@ -469,6 +487,43 @@ static bool y_rotation_hit(const YRotation *rotation, Ray r, double t_min,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool constant_medium_hit(const ConstantMedium *constant_medium, Ray r,
|
||||||
|
double t_min, double t_max, HitRecord *record) {
|
||||||
|
/* TODO: Handle non-convex boundaries */
|
||||||
|
|
||||||
|
HitRecord record1, record2;
|
||||||
|
if (!hittable_hit(constant_medium->boundary, r, -DBL_MAX, DBL_MAX, &record1))
|
||||||
|
return false;
|
||||||
|
if (!hittable_hit(constant_medium->boundary, r, record1.t + 0.0001, DBL_MAX,
|
||||||
|
&record2))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (record1.t < t_min)
|
||||||
|
record1.t = t_min;
|
||||||
|
if (record2.t > t_max)
|
||||||
|
record2.t = t_max;
|
||||||
|
|
||||||
|
if (record1.t >= record2.t)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (record1.t < 0)
|
||||||
|
record1.t = 0;
|
||||||
|
|
||||||
|
double ray_length = vec3_length(r.direction);
|
||||||
|
double distance_inside_boundary = (record2.t - record1.t) * ray_length;
|
||||||
|
double hit_distance = constant_medium->neg_inv_density * log(random_double());
|
||||||
|
|
||||||
|
if (hit_distance > distance_inside_boundary)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Arbitrary values */
|
||||||
|
record->normal = (Vec3){1.0, 0.0, 0.0};
|
||||||
|
record->front_face = true;
|
||||||
|
|
||||||
|
record->material = constant_medium->phase_function;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
||||||
HitRecord *record) {
|
HitRecord *record) {
|
||||||
switch (hittable->type) {
|
switch (hittable->type) {
|
||||||
@ -492,6 +547,9 @@ bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
|||||||
return translation_hit(&hittable->translation, r, t_min, t_max, record);
|
return translation_hit(&hittable->translation, r, t_min, t_max, record);
|
||||||
case HITTABLE_Y_ROTATION:
|
case HITTABLE_Y_ROTATION:
|
||||||
return y_rotation_hit(&hittable->y_rotation, r, t_min, t_max, record);
|
return y_rotation_hit(&hittable->y_rotation, r, t_min, t_max, record);
|
||||||
|
case HITTABLE_CONSTANT_MEDIUM:
|
||||||
|
return constant_medium_hit(&hittable->constant_medium, r, t_min, t_max,
|
||||||
|
record);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -608,6 +666,13 @@ static bool y_rotation_bounding_box(const YRotation *rotation,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool constant_medium_bounding_box(const ConstantMedium *constant_medium,
|
||||||
|
double time_start, double time_end,
|
||||||
|
AABB *bounding_box) {
|
||||||
|
return hittable_bounding_box(constant_medium->boundary, time_start, time_end,
|
||||||
|
bounding_box);
|
||||||
|
}
|
||||||
|
|
||||||
bool hittable_bounding_box(const Hittable *hittable, double time_start,
|
bool hittable_bounding_box(const Hittable *hittable, double time_start,
|
||||||
double time_end, AABB *bounding_box) {
|
double time_end, AABB *bounding_box) {
|
||||||
switch (hittable->type) {
|
switch (hittable->type) {
|
||||||
@ -634,6 +699,9 @@ bool hittable_bounding_box(const Hittable *hittable, double time_start,
|
|||||||
time_end, bounding_box);
|
time_end, bounding_box);
|
||||||
case HITTABLE_Y_ROTATION:
|
case HITTABLE_Y_ROTATION:
|
||||||
return y_rotation_bounding_box(&hittable->y_rotation, bounding_box);
|
return y_rotation_bounding_box(&hittable->y_rotation, bounding_box);
|
||||||
|
case HITTABLE_CONSTANT_MEDIUM:
|
||||||
|
return constant_medium_bounding_box(&hittable->constant_medium, time_start,
|
||||||
|
time_end, bounding_box);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
13
hittable.h
13
hittable.h
@ -33,6 +33,7 @@ typedef enum HittableType {
|
|||||||
HITTABLE_BOX,
|
HITTABLE_BOX,
|
||||||
HITTABLE_TRANSLATION,
|
HITTABLE_TRANSLATION,
|
||||||
HITTABLE_Y_ROTATION,
|
HITTABLE_Y_ROTATION,
|
||||||
|
HITTABLE_CONSTANT_MEDIUM,
|
||||||
} HittableType;
|
} HittableType;
|
||||||
|
|
||||||
typedef struct Hittable Hittable;
|
typedef struct Hittable Hittable;
|
||||||
@ -96,6 +97,12 @@ typedef struct YRotation {
|
|||||||
AABB bounding_box;
|
AABB bounding_box;
|
||||||
} YRotation;
|
} YRotation;
|
||||||
|
|
||||||
|
typedef struct ConstantMedium {
|
||||||
|
const Hittable *boundary;
|
||||||
|
const Material *phase_function;
|
||||||
|
double neg_inv_density;
|
||||||
|
} ConstantMedium;
|
||||||
|
|
||||||
struct Hittable {
|
struct Hittable {
|
||||||
HittableType type;
|
HittableType type;
|
||||||
union {
|
union {
|
||||||
@ -109,6 +116,7 @@ struct Hittable {
|
|||||||
Box box;
|
Box box;
|
||||||
Translation translation;
|
Translation translation;
|
||||||
YRotation y_rotation;
|
YRotation y_rotation;
|
||||||
|
ConstantMedium constant_medium;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,6 +142,11 @@ Hittable *hittable_create_box(Point3 p0, Point3 p1, const Material *material,
|
|||||||
Arena *arena);
|
Arena *arena);
|
||||||
Hittable *hittable_create_translation(Hittable *ptr, Vec3 offset, Arena *arena);
|
Hittable *hittable_create_translation(Hittable *ptr, Vec3 offset, Arena *arena);
|
||||||
Hittable *hittable_create_y_rotation(Hittable *ptr, double angle, Arena *arena);
|
Hittable *hittable_create_y_rotation(Hittable *ptr, double angle, Arena *arena);
|
||||||
|
Hittable *hittable_create_constant_medium(Hittable *boundary, double density,
|
||||||
|
const Texture *phase, Arena *arena);
|
||||||
|
Hittable *hittable_create_constant_medium_color(Hittable *boundary,
|
||||||
|
double density, Color albedo,
|
||||||
|
Arena *arena);
|
||||||
|
|
||||||
bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
bool hittable_hit(const Hittable *hittable, Ray r, double t_min, double t_max,
|
||||||
HitRecord *record);
|
HitRecord *record);
|
||||||
|
|||||||
68
main.c
68
main.c
@ -23,9 +23,10 @@
|
|||||||
#define SCENE_EARTH 3
|
#define SCENE_EARTH 3
|
||||||
#define SCENE_SIMPLE_LIGHT 4
|
#define SCENE_SIMPLE_LIGHT 4
|
||||||
#define SCENE_CORNELL_BOX 5
|
#define SCENE_CORNELL_BOX 5
|
||||||
|
#define SCENE_CORNELL_BOX_SMOKE 6
|
||||||
|
|
||||||
#ifndef SCENE_SELECT
|
#ifndef SCENE_SELECT
|
||||||
#define SCENE_SELECT SCENE_CORNELL_BOX
|
#define SCENE_SELECT SCENE_CORNELL_BOX_SMOKE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static Color ray_color(Ray r, Color background_color, const Hittable *world,
|
static Color ray_color(Ray r, Color background_color, const Hittable *world,
|
||||||
@ -231,9 +232,60 @@ static Hittable *cornell_box(Arena *arena) {
|
|||||||
box2 = hittable_create_translation(box2, (Vec3){130, 0, 65}, arena);
|
box2 = hittable_create_translation(box2, (Vec3){130, 0, 65}, arena);
|
||||||
hittable_list_add(&world->list, box2, arena);
|
hittable_list_add(&world->list, box2, arena);
|
||||||
|
|
||||||
Hittable *bvh_root = hittable_create_bvh_node(
|
return world;
|
||||||
world->list.objects, 0, world->list.size, 0.0, 1.0, arena);
|
}
|
||||||
return bvh_root;
|
|
||||||
|
static Hittable *cornell_box_smoke(Arena *arena) {
|
||||||
|
Hittable *world = hittable_create_hittable_list(arena);
|
||||||
|
|
||||||
|
Material *red =
|
||||||
|
material_create_lambertian_color((Color){0.65, 0.05, 0.05}, arena);
|
||||||
|
Material *white =
|
||||||
|
material_create_lambertian_color((Color){0.73, 0.73, 0.73}, arena);
|
||||||
|
Material *green =
|
||||||
|
material_create_lambertian_color((Color){0.12, 0.45, 0.15}, arena);
|
||||||
|
Material *light =
|
||||||
|
material_create_diffuse_light_color((Color){7.0, 7.0, 7.0}, arena);
|
||||||
|
|
||||||
|
hittable_list_add(
|
||||||
|
&world->list,
|
||||||
|
hittable_create_yz_rectangle(0, 555, 0, 555, 555, green, arena), arena);
|
||||||
|
hittable_list_add(&world->list,
|
||||||
|
hittable_create_yz_rectangle(0, 555, 0, 555, 0, red, arena),
|
||||||
|
arena);
|
||||||
|
hittable_list_add(
|
||||||
|
&world->list,
|
||||||
|
hittable_create_xz_rectangle(113, 443, 127, 432, 554, light, arena),
|
||||||
|
arena);
|
||||||
|
hittable_list_add(
|
||||||
|
&world->list,
|
||||||
|
hittable_create_xz_rectangle(0, 555, 0, 555, 0, white, arena), arena);
|
||||||
|
hittable_list_add(
|
||||||
|
&world->list,
|
||||||
|
hittable_create_xz_rectangle(0, 555, 0, 555, 555, white, arena), arena);
|
||||||
|
hittable_list_add(
|
||||||
|
&world->list,
|
||||||
|
hittable_create_xy_rectangle(0, 555, 0, 555, 555, white, arena), arena);
|
||||||
|
|
||||||
|
Hittable *box1 = hittable_create_box((Point3){0, 0, 0},
|
||||||
|
(Point3){165, 330, 165}, white, arena);
|
||||||
|
box1 = hittable_create_y_rotation(box1, 15, arena);
|
||||||
|
box1 = hittable_create_translation(box1, (Vec3){265, 0, 295}, arena);
|
||||||
|
hittable_list_add(&world->list,
|
||||||
|
hittable_create_constant_medium_color(
|
||||||
|
box1, 0.01, (Color){0.0, 0.0, 0.0}, arena),
|
||||||
|
arena);
|
||||||
|
|
||||||
|
Hittable *box2 = hittable_create_box((Point3){0, 0, 0},
|
||||||
|
(Point3){165, 165, 165}, white, arena);
|
||||||
|
box2 = hittable_create_y_rotation(box2, -18, arena);
|
||||||
|
box2 = hittable_create_translation(box2, (Vec3){130, 0, 65}, arena);
|
||||||
|
hittable_list_add(&world->list,
|
||||||
|
hittable_create_constant_medium_color(
|
||||||
|
box2, 0.01, (Color){1.0, 1.0, 1.0}, arena),
|
||||||
|
arena);
|
||||||
|
|
||||||
|
return world;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
@ -318,6 +370,14 @@ int main(int argc, char *argv[]) {
|
|||||||
look_from = (Point3){278.0, 278.0, -800.0};
|
look_from = (Point3){278.0, 278.0, -800.0};
|
||||||
look_at = (Point3){278.0, 278.0, 0.0};
|
look_at = (Point3){278.0, 278.0, 0.0};
|
||||||
vfov = 40.0;
|
vfov = 40.0;
|
||||||
|
#elif SCENE_SELECT == SCENE_CORNELL_BOX_SMOKE
|
||||||
|
world = cornell_box_smoke(&arena);
|
||||||
|
aspect_ratio = 1.0;
|
||||||
|
image_width = 600;
|
||||||
|
samples_per_pixel = 200;
|
||||||
|
look_from = (Point3){278.0, 278.0, -800.0};
|
||||||
|
look_at = (Point3){278.0, 278.0, 0.0};
|
||||||
|
vfov = 40.0;
|
||||||
#else
|
#else
|
||||||
#error Unknown scene selected
|
#error Unknown scene selected
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
21
material.c
21
material.c
@ -70,6 +70,15 @@ static bool dielectric_scatter(const Dielectric *dielectric, Ray r,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isotropic_scatter(const Isotropic *isotropic, Ray r,
|
||||||
|
const struct HitRecord *record,
|
||||||
|
Color *attenuation, Ray *scattered) {
|
||||||
|
*scattered = (Ray){record->p, vec3_random_in_unit_sphere(), r.time};
|
||||||
|
*attenuation =
|
||||||
|
texture_value(isotropic->albedo, record->u, record->v, record->p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
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,
|
||||||
Ray *scattered) {
|
Ray *scattered) {
|
||||||
@ -84,6 +93,9 @@ bool material_scatter(const Material *material, Ray r,
|
|||||||
scattered);
|
scattered);
|
||||||
case MATERIAL_DIFFUSE_LIGHT:
|
case MATERIAL_DIFFUSE_LIGHT:
|
||||||
return false;
|
return false;
|
||||||
|
case MATERIAL_ISOTROPIC:
|
||||||
|
return isotropic_scatter(&material->isotropic, r, record, attenuation,
|
||||||
|
scattered);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -145,8 +157,13 @@ Material *material_create_diffuse_light(const Texture *emit, Arena *arena) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Material *material_create_diffuse_light_color(Color color, Arena *arena) {
|
Material *material_create_diffuse_light_color(Color color, Arena *arena) {
|
||||||
|
return material_create_diffuse_light(texture_create_solid_color(color, arena),
|
||||||
|
arena);
|
||||||
|
}
|
||||||
|
|
||||||
|
Material *material_create_isotropic(const Texture *albedo, Arena *arena) {
|
||||||
Material *result = arena_alloc(arena, sizeof(Material));
|
Material *result = arena_alloc(arena, sizeof(Material));
|
||||||
result->type = MATERIAL_DIFFUSE_LIGHT;
|
result->type = MATERIAL_ISOTROPIC;
|
||||||
result->diffuse_light.emit = texture_create_solid_color(color, arena);
|
result->isotropic.albedo = albedo;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,7 @@ typedef enum MaterialType {
|
|||||||
MATERIAL_METAL,
|
MATERIAL_METAL,
|
||||||
MATERIAL_DIELECTRIC,
|
MATERIAL_DIELECTRIC,
|
||||||
MATERIAL_DIFFUSE_LIGHT,
|
MATERIAL_DIFFUSE_LIGHT,
|
||||||
|
MATERIAL_ISOTROPIC,
|
||||||
} MaterialType;
|
} MaterialType;
|
||||||
|
|
||||||
typedef struct Lambertian {
|
typedef struct Lambertian {
|
||||||
@ -33,6 +34,10 @@ typedef struct DiffuseLight {
|
|||||||
const Texture *emit;
|
const Texture *emit;
|
||||||
} DiffuseLight;
|
} DiffuseLight;
|
||||||
|
|
||||||
|
typedef struct Isotropic {
|
||||||
|
const Texture *albedo;
|
||||||
|
} Isotropic;
|
||||||
|
|
||||||
typedef struct Material {
|
typedef struct Material {
|
||||||
MaterialType type;
|
MaterialType type;
|
||||||
union {
|
union {
|
||||||
@ -40,6 +45,7 @@ typedef struct Material {
|
|||||||
Metal metal;
|
Metal metal;
|
||||||
Dielectric dielectric;
|
Dielectric dielectric;
|
||||||
DiffuseLight diffuse_light;
|
DiffuseLight diffuse_light;
|
||||||
|
Isotropic isotropic;
|
||||||
};
|
};
|
||||||
} Material;
|
} Material;
|
||||||
|
|
||||||
@ -57,5 +63,6 @@ Material *material_create_metal_color(Color albedo, double fuzziness,
|
|||||||
Material *material_create_dielectric(double eta, Arena *arena);
|
Material *material_create_dielectric(double eta, Arena *arena);
|
||||||
Material *material_create_diffuse_light(const Texture *emit, Arena *arena);
|
Material *material_create_diffuse_light(const Texture *emit, Arena *arena);
|
||||||
Material *material_create_diffuse_light_color(Color color, Arena *arena);
|
Material *material_create_diffuse_light_color(Color color, Arena *arena);
|
||||||
|
Material *material_create_isotropic(const Texture *albedo, Arena *arena);
|
||||||
|
|
||||||
#endif /* INCLUDED_MATERIAL_H */
|
#endif /* INCLUDED_MATERIAL_H */
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user