diff options
-rw-r--r-- | src/modules/ray/Makefile.am | 2 | ||||
-rw-r--r-- | src/modules/ray/ray.c | 19 | ||||
-rw-r--r-- | src/modules/ray/ray_render.c (renamed from src/modules/ray/ray_scene.c) | 61 | ||||
-rw-r--r-- | src/modules/ray/ray_render.h | 15 | ||||
-rw-r--r-- | src/modules/ray/ray_scene.h | 20 |
5 files changed, 79 insertions, 38 deletions
diff --git a/src/modules/ray/Makefile.am b/src/modules/ray/Makefile.am index 872efb6..a0d7cb9 100644 --- a/src/modules/ray/Makefile.am +++ b/src/modules/ray/Makefile.am @@ -1,4 +1,4 @@ noinst_LIBRARIES = libray.a -libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray_light_emitter.h ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_scene.c ray_scene.h ray_surface.h +libray_a_SOURCES = ray_3f.h ray.c ray_camera.c ray_camera.h ray_color.h ray_euler.c ray_euler.h ray_light_emitter.h ray_object.h ray_object_light.h ray_object_plane.h ray_object_point.h ray_object_sphere.h ray_object_type.h ray_ray.h ray_render.c ray_render.h ray_scene.h ray_surface.h libray_a_CFLAGS = @ROTOTILLER_CFLAGS@ -ffast-math libray_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I@top_srcdir@/src diff --git a/src/modules/ray/ray.c b/src/modules/ray/ray.c index 5f6326d..bb9c042 100644 --- a/src/modules/ray/ray.c +++ b/src/modules/ray/ray.c @@ -8,6 +8,7 @@ #include "ray_camera.h" #include "ray_object.h" +#include "ray_render.h" #include "ray_scene.h" /* Copyright (C) 2016-2017 Vito Caputo <vcaputo@pengaru.com> */ @@ -118,6 +119,7 @@ static float r; typedef struct ray_context_t { + ray_render_t *render; } ray_context_t; @@ -142,6 +144,8 @@ static int ray_fragmenter(void *context, const fb_fragment_t *fragment, unsigned /* prepare a frame for concurrent rendering */ static void ray_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fragment, rototiller_fragmenter_t *res_fragmenter) { + ray_context_t *ctxt = context; + *res_fragmenter = ray_fragmenter; /* TODO: the camera doesn't need the width and height anymore, the fragment has the frame_width/frame_height */ @@ -169,14 +173,24 @@ static void ray_prepare_frame(void *context, unsigned n_cpus, fb_fragment_t *fra /* tilt camera pitch in time with up and down movements, phase shifted appreciably */ camera.orientation.pitch = -(sinf((M_PI * 1.5f) + r * 1.3f) * .6f + -.35f); #endif - ray_scene_prepare(&scene, &camera); + ctxt->render = ray_render_new(&scene, &camera); } /* ray trace a simple scene into the fragment */ static void ray_render_fragment(void *context, fb_fragment_t *fragment) { - ray_scene_render_fragment(&scene, fragment); + ray_context_t *ctxt = context; + + ray_render_trace_fragment(ctxt->render, fragment); +} + + +static void ray_finish_frame(void *context, fb_fragment_t *fragment) +{ + ray_context_t *ctxt = context; + + ray_render_free(ctxt->render); } @@ -185,6 +199,7 @@ rototiller_module_t ray_module = { .destroy_context = ray_destroy_context, .prepare_frame = ray_prepare_frame, .render_fragment = ray_render_fragment, + .finish_frame = ray_finish_frame, .name = "ray", .description = "Ray tracer (threaded)", .author = "Vito Caputo <vcaputo@pengaru.com>", diff --git a/src/modules/ray/ray_scene.c b/src/modules/ray/ray_render.c index 21a3bfa..bfa5112 100644 --- a/src/modules/ray/ray_scene.c +++ b/src/modules/ray/ray_render.c @@ -12,13 +12,20 @@ #define MAX_RECURSION_DEPTH 4 #define MIN_RELEVANCE 0.05f +typedef struct ray_render_t { + const ray_scene_t *scene; /* scene being rendered */ + const ray_camera_t *camera; /* camera rendering the scene */ + + ray_color_t ambient_light; + ray_camera_frame_t frame; +} ray_render_t; /* Determine if the ray is obstructed by an object within the supplied distance, for shadows */ -static inline int ray_is_obstructed(ray_scene_t *scene, unsigned depth, ray_ray_t *ray, float distance) +static inline int ray_is_obstructed(ray_render_t *render, unsigned depth, ray_ray_t *ray, float distance) { ray_object_t *object; - for (object = scene->objects; object->type; object++) { + for (object = render->scene->objects; object->type; object++) { float ood; if (ray_object_intersects_ray(object, depth, ray, &ood) && @@ -32,14 +39,14 @@ static inline int ray_is_obstructed(ray_scene_t *scene, unsigned depth, ray_ray_ /* shadow test */ -static inline int point_is_shadowed(ray_scene_t *scene, unsigned depth, ray_3f_t *light_direction, float distance, ray_3f_t *point) +static inline int point_is_shadowed(ray_render_t *render, unsigned depth, ray_3f_t *light_direction, float distance, ray_3f_t *point) { ray_ray_t shadow_ray; shadow_ray.direction = *light_direction; shadow_ray.origin = *point; - if (ray_is_obstructed(scene, depth + 1, &shadow_ray, distance)) + if (ray_is_obstructed(render, depth + 1, &shadow_ray, distance)) return 1; return 0; @@ -57,21 +64,21 @@ static inline float approx_powf(float x, float y) /* Determine the color @ distance on ray on object viewed from origin */ -static inline ray_color_t shade_intersection(ray_scene_t *scene, ray_object_t *object, ray_ray_t *ray, ray_3f_t *intersection, ray_3f_t *normal, unsigned depth, float *res_reflectivity) +static inline ray_color_t shade_intersection(ray_render_t *render, ray_object_t *object, ray_ray_t *ray, ray_3f_t *intersection, ray_3f_t *normal, unsigned depth, float *res_reflectivity) { ray_surface_t surface = ray_object_surface(object, intersection); - ray_color_t color = ray_3f_mult(&surface.color, &scene->_prepared.ambient_light); + ray_color_t color = ray_3f_mult(&surface.color, &render->ambient_light); ray_object_t *light; /* visit lights for shadows and illumination */ - for (light = scene->lights; light->type; light++) { + for (light = render->scene->lights; light->type; light++) { ray_3f_t lvec = ray_3f_sub(&light->light.emitter.point.center, intersection); float ldist = ray_3f_length(&lvec); float lvec_normal_dot; lvec = ray_3f_mult_scalar(&lvec, (1.0f / ldist)); /* normalize lvec */ #if 1 - if (point_is_shadowed(scene, depth, &lvec, ldist, intersection)) + if (point_is_shadowed(render, depth, &lvec, ldist, intersection)) continue; #endif lvec_normal_dot = ray_3f_dot(normal, &lvec); @@ -109,13 +116,13 @@ static inline ray_color_t shade_intersection(ray_scene_t *scene, ray_object_t *o } -static inline ray_object_t * find_nearest_intersection(ray_scene_t *scene, ray_object_t *reflector, ray_ray_t *ray, unsigned depth, float *res_distance) +static inline ray_object_t * find_nearest_intersection(ray_render_t *render, ray_object_t *reflector, ray_ray_t *ray, unsigned depth, float *res_distance) { ray_object_t *nearest_object = NULL; float nearest_object_distance = INFINITY; ray_object_t *object; - for (object = scene->objects; object->type; object++) { + for (object = render->scene->objects; object->type; object++) { float distance; /* Don't bother checking if a reflected ray intersects the object reflecting it, @@ -140,7 +147,7 @@ static inline ray_object_t * find_nearest_intersection(ray_scene_t *scene, ray_o } -static inline ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *primary_ray) +static inline ray_color_t trace_ray(ray_render_t *render, ray_ray_t *primary_ray) { ray_color_t color = { .x = 0.0f, .y = 0.0f, .z = 0.0f }; ray_3f_t intersection, normal; @@ -165,7 +172,7 @@ static inline ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *primary_ray) ray = &reflected_ray; } - nearest_object = find_nearest_intersection(scene, reflector, ray, depth, &nearest_distance); + nearest_object = find_nearest_intersection(render, reflector, ray, depth, &nearest_distance); if (nearest_object) { ray_3f_t more_color; ray_3f_t rvec; @@ -174,7 +181,7 @@ static inline ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *primary_ray) intersection = ray_3f_add(&ray->origin, &rvec); normal = ray_object_normal(nearest_object, &intersection); - more_color = shade_intersection(scene, nearest_object, ray, &intersection, &normal, depth, &reflectivity); + more_color = shade_intersection(render, nearest_object, ray, &intersection, &normal, depth, &reflectivity); more_color = ray_3f_mult_scalar(&more_color, relevance); color = ray_3f_add(&color, &more_color); } @@ -186,16 +193,16 @@ static inline ray_color_t trace_ray(ray_scene_t *scene, ray_ray_t *primary_ray) } -void ray_scene_render_fragment(ray_scene_t *scene, fb_fragment_t *fb_fragment) +void ray_render_trace_fragment(ray_render_t *render, fb_fragment_t *fb_fragment) { uint32_t *buf = fb_fragment->buf; ray_camera_fragment_t fragment; ray_ray_t ray; - ray_camera_fragment_begin(&scene->_prepared.frame, fb_fragment, &ray, &fragment); + ray_camera_fragment_begin(&render->frame, fb_fragment, &ray, &fragment); do { do { - *buf = ray_color_to_uint32_rgb(trace_ray(scene, &ray)); + *buf = ray_color_to_uint32_rgb(trace_ray(render, &ray)); buf++; } while (ray_camera_fragment_x_step(&fragment)); @@ -207,13 +214,29 @@ void ray_scene_render_fragment(ray_scene_t *scene, fb_fragment_t *fb_fragment) /* prepare the scene for rendering with camera, must be called whenever anything in the scene+camera pair has been changed. */ /* this is basically a time for the raytracer to precompute whatever it can which otherwise ends up occurring per-ray */ /* the camera is included so primary rays which all have a common origin may be optimized for */ -void ray_scene_prepare(ray_scene_t *scene, ray_camera_t *camera) +ray_render_t * ray_render_new(ray_scene_t *scene, ray_camera_t *camera) { + ray_render_t *render; ray_object_t *object; - scene->_prepared.ambient_light = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness); - ray_camera_frame_prepare(camera, &scene->_prepared.frame); + render = malloc(sizeof(ray_render_t)); + if (!render) + return NULL; + + render->scene = scene; + render->camera = camera; + + render->ambient_light = ray_3f_mult_scalar(&scene->ambient_color, scene->ambient_brightness); + ray_camera_frame_prepare(camera, &render->frame); for (object = scene->objects; object->type; object++) ray_object_prepare(object, camera); + + return render; +} + + +void ray_render_free(ray_render_t *render) +{ + free(render); } diff --git a/src/modules/ray/ray_render.h b/src/modules/ray/ray_render.h new file mode 100644 index 0000000..a6d6c67 --- /dev/null +++ b/src/modules/ray/ray_render.h @@ -0,0 +1,15 @@ +#ifndef _RAY_RENDER_H +#define _RAY_RENDER_H + +#include "fb.h" + +#include "ray_camera.h" +#include "ray_scene.h" + +typedef struct ray_render_t ray_render_t; + +ray_render_t * ray_render_new(ray_scene_t *scene, ray_camera_t *camera); +void ray_render_free(ray_render_t *render); +void ray_render_trace_fragment(ray_render_t *render, fb_fragment_t *fb_fragment); + +#endif diff --git a/src/modules/ray/ray_scene.h b/src/modules/ray/ray_scene.h index 5c7cd5e..ff9c440 100644 --- a/src/modules/ray/ray_scene.h +++ b/src/modules/ray/ray_scene.h @@ -1,28 +1,16 @@ #ifndef _RAY_SCENE_H #define _RAY_SCENE_H -#include "fb.h" - -#include "ray_camera.h" #include "ray_color.h" -#include "ray_ray.h" typedef union ray_object_t ray_object_t; typedef struct ray_scene_t { - ray_object_t *objects; - ray_object_t *lights; - - ray_color_t ambient_color; - float ambient_brightness; + ray_object_t *objects; + ray_object_t *lights; - struct { - ray_color_t ambient_light; - ray_camera_frame_t frame; - } _prepared; + ray_color_t ambient_color; + float ambient_brightness; } ray_scene_t; -void ray_scene_prepare(ray_scene_t *scene, ray_camera_t *camera); -void ray_scene_render_fragment(ray_scene_t *scene, fb_fragment_t *fb_fragment); - #endif |