From 2abc2ba697721ea661bbb36f62f59556cc3912ce Mon Sep 17 00:00:00 2001 From: Jean-Michel Gorius Date: Sat, 12 Nov 2022 16:17:42 +0100 Subject: [PATCH] Cleanup the API --- hittable.c | 11 ++++++++ hittable.h | 2 ++ main.c | 83 ++++++++++++++++++------------------------------------ material.c | 23 +++++++++++++++ material.h | 4 +++ 5 files changed, 68 insertions(+), 55 deletions(-) diff --git a/hittable.c b/hittable.c index 808d41c..4ddc7cd 100644 --- a/hittable.c +++ b/hittable.c @@ -1,4 +1,5 @@ #include "hittable.h" +#include "arena.h" #include "point3.h" #include "vec3.h" @@ -60,6 +61,16 @@ bool hittable_list_hit(const HittableList *list, Ray r, double t_min, return hit_anything; } +Sphere *sphere_create(Point3 center, double radius, const Material *material, + Arena *arena) { + Sphere *sphere = arena_alloc(arena, sizeof(Sphere)); + sphere->type = HITTABLE_SPHERE; + sphere->center = center; + sphere->radius = radius; + sphere->material = material; + return sphere; +} + bool sphere_hit(const Sphere *sphere, Ray r, double t_min, double t_max, HitRecord *record) { Vec3 oc = point3_sub(r.origin, sphere->center); diff --git a/hittable.h b/hittable.h index 9539894..bd64755 100644 --- a/hittable.h +++ b/hittable.h @@ -51,6 +51,8 @@ typedef struct Sphere { double radius; } Sphere; +Sphere *sphere_create(Point3 center, double radius, const Material *material, + Arena *arena); bool sphere_hit(const Sphere *sphere, Ray r, double t_min, double t_max, HitRecord *record); diff --git a/main.c b/main.c index 600a5ac..aa5bc99 100644 --- a/main.c +++ b/main.c @@ -37,20 +37,14 @@ static Color ray_color(Ray r, const Hittable *world, int depth) { static const Hittable *generate_random_scene(Arena *arena) { static HittableList world = {.type = HITTABLE_LIST}; - static Lambertian ground_material = {.type = MATERIAL_LAMBERTIAN, - .albedo = (Color){0.5, 0.5, 0.5}}; - Sphere *ground_sphere = arena_alloc(arena, sizeof(Sphere)); - ground_sphere->type = HITTABLE_SPHERE; - ground_sphere->center = (Point3){0.0, -1000.0, 0.0}; - ground_sphere->radius = 1000.0; - ground_sphere->material = (const Material *)&ground_material; + const Lambertian *ground_material = + lambertian_create((Color){0.5, 0.5, 0.5}, arena); + const Sphere *ground_sphere = + sphere_create((Point3){0.0, -1000.0, 0.0}, 1000.0, + (const Material *)ground_material, arena); hittable_list_add(&world, (const Hittable *)ground_sphere, arena); - static Lambertian lambertian = {.type = MATERIAL_LAMBERTIAN, - .albedo = {0.4, 0.2, 0.1}}; - static Metal metal = { - .type = MATERIAL_METAL, .albedo = {0.7, 0.6, 0.5}, .fuzziness = 0.0}; - static Dielectric glass = {.type = MATERIAL_DIELECTRIC, .eta = 1.5}; + const Dielectric *glass = dielectric_create(1.5, arena); for (int a = -11; a < 11; ++a) { for (int b = -11; b < 11; ++b) { @@ -60,60 +54,39 @@ static const Hittable *generate_random_scene(Arena *arena) { if (vec3_length(point3_sub(center, (Point3){4.0, 0.2, 0.0})) > 0.9) { if (choose_material < 0.8) { - Color albedo = color_mul(color_random(), color_random()); - Lambertian *material = arena_alloc(arena, sizeof(Lambertian)); - material->type = MATERIAL_LAMBERTIAN; - material->albedo = albedo; - - Sphere *sphere = arena_alloc(arena, sizeof(Sphere)); - sphere->type = HITTABLE_SPHERE; - sphere->center = center; - sphere->radius = 0.2; - sphere->material = (const Material *)material; + const Lambertian *material = lambertian_create( + color_mul(color_random(), color_random()), arena); + const Sphere *sphere = + sphere_create(center, 0.2, (const Material *)material, arena); hittable_list_add(&world, (const Hittable *)sphere, arena); } else if (choose_material < 0.95) { - Color albedo = color_random_in_range(0.5, 1); - double fuzziness = random_double_in_range(0.5, 1.0); - Metal *material = arena_alloc(arena, sizeof(Metal)); - material->type = MATERIAL_METAL; - material->albedo = albedo; - material->fuzziness = fuzziness; - - Sphere *sphere = arena_alloc(arena, sizeof(Sphere)); - sphere->type = HITTABLE_SPHERE; - sphere->center = center; - sphere->radius = 0.2; - sphere->material = (const Material *)material; + const Metal *material = + metal_create(color_random_in_range(0.5, 1), + random_double_in_range(0.5, 1.0), arena); + const Sphere *sphere = + sphere_create(center, 0.2, (const Material *)material, arena); hittable_list_add(&world, (const Hittable *)sphere, arena); } else { - Sphere *sphere = arena_alloc(arena, sizeof(Sphere)); - sphere->type = HITTABLE_SPHERE; - sphere->center = center; - sphere->radius = 0.2; - sphere->material = (const Material *)&glass; + const Sphere *sphere = + sphere_create(center, 0.2, (const Material *)glass, arena); hittable_list_add(&world, (const Hittable *)sphere, arena); } } } } - Sphere *sphere1 = arena_alloc(arena, sizeof(Sphere)); - sphere1->type = HITTABLE_SPHERE; - sphere1->center = (Point3){0.0, 1.0, 0.0}; - sphere1->radius = 1.0; - sphere1->material = (const Material *)&glass; + const Lambertian *lambertian = + lambertian_create((Color){0.4, 0.2, 0.1}, arena); + const Metal *metal = metal_create((Color){0.7, 0.6, 0.5}, 0.0, arena); + + const Sphere *sphere1 = sphere_create((Point3){0.0, 1.0, 0.0}, 1.0, + (const Material *)glass, arena); hittable_list_add(&world, (const Hittable *)sphere1, arena); - Sphere *sphere2 = arena_alloc(arena, sizeof(Sphere)); - sphere2->type = HITTABLE_SPHERE; - sphere2->center = (Point3){-4.0, 1.0, 0.0}; - sphere2->radius = 1.0; - sphere2->material = (const Material *)&lambertian; + const Sphere *sphere2 = sphere_create((Point3){-4.0, 1.0, 0.0}, 1.0, + (const Material *)lambertian, arena); hittable_list_add(&world, (const Hittable *)sphere2, arena); - Sphere *sphere3 = arena_alloc(arena, sizeof(Sphere)); - sphere3->type = HITTABLE_SPHERE; - sphere3->center = (Point3){4.0, 1.0, 0.0}; - sphere3->radius = 1.0; - sphere3->material = (const Material *)&metal; + const Sphere *sphere3 = sphere_create((Point3){4.0, 1.0, 0.0}, 1.0, + (const Material *)metal, arena); hittable_list_add(&world, (const Hittable *)sphere3, arena); return (const Hittable *)&world; @@ -134,7 +107,7 @@ int main(void) { const double aspect_ratio = 3.0 / 2.0; const int image_width = 1200; const int image_height = (int)(image_width / aspect_ratio); - const int samples_per_pixel = 500; + const int samples_per_pixel = 2; const int max_depth = 50; /* World */ diff --git a/material.c b/material.c index b329a19..ec63ce6 100644 --- a/material.c +++ b/material.c @@ -1,4 +1,5 @@ #include "material.h" +#include "arena.h" #include "hittable.h" #include "utils.h" #include "vec3.h" @@ -23,6 +24,13 @@ bool material_scatter(const Material *material, Ray r, return false; } +Lambertian *lambertian_create(Color albedo, Arena *arena) { + Lambertian *lambertian = arena_alloc(arena, sizeof(Lambertian)); + lambertian->type = MATERIAL_LAMBERTIAN; + lambertian->albedo = albedo; + return lambertian; +} + bool lambertian_scatter(const Lambertian *lambertian, Ray r, const HitRecord *record, Color *attenuation, Ray *scattered) { @@ -38,6 +46,14 @@ bool lambertian_scatter(const Lambertian *lambertian, Ray r, return true; } +Metal *metal_create(Color albedo, double fuzziness, Arena *arena) { + Metal *metal = arena_alloc(arena, sizeof(Metal)); + metal->type = MATERIAL_METAL; + metal->albedo = albedo; + metal->fuzziness = fuzziness; + return metal; +} + bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record, Color *attenuation, Ray *scattered) { Vec3 reflected = vec3_reflect(vec3_normalize(r.direction), record->normal); @@ -51,6 +67,13 @@ bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record, return vec3_dot(scattered->direction, record->normal) > 0; } +Dielectric *dielectric_create(double eta, Arena *arena) { + Dielectric *dielectric = arena_alloc(arena, sizeof(Dielectric)); + dielectric->type = MATERIAL_DIELECTRIC; + dielectric->eta = eta; + return dielectric; +} + static double schlick_reflectance(double cosine, double eta) { double r0 = (1 - eta) / (1 + eta); r0 *= r0; diff --git a/material.h b/material.h index f9d3a78..b6e12bd 100644 --- a/material.h +++ b/material.h @@ -1,6 +1,7 @@ #ifndef INCLUDED_MATERIAL_H #define INCLUDED_MATERIAL_H +#include "arena.h" #include "color.h" #include "ray.h" @@ -27,6 +28,7 @@ typedef struct Lambertian { Color albedo; } Lambertian; +Lambertian *lambertian_create(Color albedo, Arena *arena); bool lambertian_scatter(const Lambertian *lambertian, Ray r, const struct HitRecord *record, Color *attenuation, Ray *scattered); @@ -37,6 +39,7 @@ typedef struct Metal { double fuzziness; } Metal; +Metal *metal_create(Color albedo, double fuzziness, Arena *arena); bool metal_scatter(const Metal *metal, Ray r, const struct HitRecord *record, Color *attenuation, Ray *scattered); @@ -45,6 +48,7 @@ typedef struct Dielectric { double eta; } Dielectric; +Dielectric *dielectric_create(double eta, Arena *arena); bool dielectric_scatter(const Dielectric *dielectric, Ray r, const struct HitRecord *record, Color *attenuation, Ray *scattered);