From 475ddb1fd6107ff6bb95f4994558f1279a529f02 Mon Sep 17 00:00:00 2001 From: Lukas Jiriste Date: Fri, 3 Jan 2025 16:18:48 +0100 Subject: [PATCH] Try to implement sphere self obstruction inside The sphere was completely lit inside by the lights outside. I cannot stop ignoring at least parts of the objects else planes would render with shadow acne. So I tried to ignore the object if it obstructs itself very close from the rendered place - this should prevent shadow acne. The sphere however ignores the distant intersection when the close one needs to be ignored. This manifests as "light acne" - some part are correctly in shadow, while others cause the object to be ignored and light passes through. --- src/scene.c | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/src/scene.c b/src/scene.c index 475002d..b8d3ed4 100644 --- a/src/scene.c +++ b/src/scene.c @@ -11,7 +11,9 @@ # error "This platform does not support NAN macro!" #endif // NAN -static const t_color DEFAULT_COLOR = {0, 0, 0}; +static const t_color DEFAULT_COLOR = {0, 0, 0}; + +static const double SELF_OBSTRUCTION_MULTIPLIER = 1e-8; static int is_bounded(const t_object *object) { @@ -53,26 +55,38 @@ int is_behind_ray(const t_ray *ray, t_vec3 point) return (0 > vec_scalar_mul(ray->direction, vec_diff(point, ray->start))); } -int intersects_circumsphere(const t_ray *ray, const t_object *object) +t_sphere get_circumsphere(const t_object *object) { - double radius; - t_vec3 center; - double distance; + t_sphere circumsphere; if (object->type == SPHERE) { - radius = object->object.sphere.radius; - center = object->object.sphere.center; + circumsphere.radius = object->object.sphere.radius; + circumsphere.center = object->object.sphere.center; } else if (object->type == CYLINDER) { - radius = get_cylinder_circumsphere_radius(&object->object.cylinder); - center = object->object.cylinder.center; + circumsphere.radius = get_cylinder_circumsphere_radius(&object->object.cylinder); + circumsphere.center = object->object.cylinder.center; + } + else if(object->type == PLANE) + { + circumsphere.radius = INFINITY; + circumsphere.center = object->object.plane.point; } - if (is_behind_ray(ray, center)) + return (circumsphere); +} + +int intersects_circumsphere(const t_ray *ray, const t_object *object) +{ + t_sphere circumsphere; + double distance; + + circumsphere = get_circumsphere(object); + if (is_behind_ray(ray, circumsphere.center)) return (0); - distance = dist_point_from_line(ray, center); - return (distance < radius); + distance = dist_point_from_line(ray, circumsphere.center); + return (distance < circumsphere.radius); } double get_intersection_arg_plane(const t_ray *ray, const t_plane *plane) @@ -208,7 +222,7 @@ double get_intersection_arg(const t_ray *ray, const t_object *object) } const t_object *find_nearest_object(const t_ray *ray, const t_vec *objects, - const t_object *ignored) + const t_object *ignored, double ignored_dist) { size_t i; const t_object *object_found; @@ -222,9 +236,9 @@ const t_object *find_nearest_object(const t_ray *ray, const t_vec *objects, while (i < objects->size) { object = ft_vec_caccess(objects, i++); - if (object == ignored) - continue ; distance = get_intersection_arg(ray, object); + if (object == ignored && distance > 0 && distance < ignored_dist) + continue ; if (0 < distance && distance < distance_found) { distance_found = distance; @@ -278,6 +292,11 @@ t_vec3 get_object_normal(const t_object *object, t_vec3 point) return ((t_vec3){.x = 0, .y = 0, .z = 0}); } +double get_self_obstruction_limit(const t_object *object) +{ + return (get_circumsphere(object).radius * SELF_OBSTRUCTION_MULTIPLIER); +} + t_color get_light_contribution(t_ray normal, const t_object *object, const t_light *light, const t_scene *scene) { t_ray new_ray; @@ -289,7 +308,7 @@ t_color get_light_contribution(t_ray normal, const t_object *object, const t_lig new_ray.direction = vec_diff(light->position, new_ray.start); distance = vec_norm(new_ray.direction); new_ray.direction = vec_real_mul(new_ray.direction, 1 / distance); - obstruction = find_nearest_object(&new_ray, &scene->objects, object); + obstruction = find_nearest_object(&new_ray, &scene->objects, object, get_self_obstruction_limit(object)); angle_multiplier = vec_scalar_mul(normal.direction, new_ray.direction) / (vec_norm(normal.direction) * vec_norm(new_ray.direction)); if (object->type == PLANE) @@ -335,7 +354,7 @@ t_color trace_ray(const t_ray *ray, const t_scene *scene) { const t_object *object_found; - object_found = find_nearest_object(ray, &scene->objects, NULL); + object_found = find_nearest_object(ray, &scene->objects, NULL, 0); if (object_found) return (get_object_color(ray, object_found, scene)); else -- 2.30.2