dump state
This commit is contained in:
parent
fca2c54ab3
commit
fc39ee66df
|
@ -1,6 +1,7 @@
|
|||
/* Main command line executable. */
|
||||
|
||||
#include <defocus/defocus.h>
|
||||
#include <defocus/df_math.h>
|
||||
|
||||
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
#include <stb_image_write.h>
|
||||
|
@ -49,17 +50,43 @@ int main(int argc, char **argv) {
|
|||
|
||||
df_image_handle input_image = df_load_image("../test_image.png", &image_width, &image_height);
|
||||
float aspect = (float)image_width / (float)image_height;
|
||||
df_plane plane = get_image_filling_plane(image_width, image_height, input_image, focal_length);
|
||||
|
||||
|
||||
df_plane plane;
|
||||
plane.base_x = 0.f;
|
||||
plane.base_y = 0.f;
|
||||
plane.base_z = -2;
|
||||
plane.normal_x = 0.f;
|
||||
plane.normal_y = 0.f;
|
||||
plane.normal_z = 1.f;
|
||||
plane.img_p0_x = -aspect;
|
||||
plane.img_p0_y = -1.f;
|
||||
plane.img_p0_z = plane.base_z;
|
||||
plane.img_w = 2.f * aspect;
|
||||
plane.img_h = 2.f;
|
||||
plane.img_ax0_x = 1.f;
|
||||
plane.img_ax0_y = 0.f;
|
||||
plane.img_ax0_z = 0.f;
|
||||
plane.img_ax1_x = 0.f;
|
||||
plane.img_ax1_y = 1.f;
|
||||
plane.img_ax1_z = 0.f;
|
||||
plane.image = input_image;
|
||||
|
||||
uint8_t *image = NULL;
|
||||
|
||||
df_thin_lense_camera_data camera_data = df_create_thin_lense_camera_data(image_width, image_height, 42.f, focal_length);
|
||||
df_v3 look_from = {1, 1.5, 5};
|
||||
df_v3 look_at = {0, 0, -2};
|
||||
df_v3 up = {0, 1, 0};
|
||||
|
||||
float dist_to_focus = df_len_v3(df_sub_v3(look_at, look_from));
|
||||
|
||||
df_thin_lense_camera_data camera_data = df_create_thin_lense_camera_data(look_from, look_at, up, 45.f, aspect, 2.0, dist_to_focus);
|
||||
|
||||
df_trace_rays((df_trace_rays_settings){
|
||||
.image_width = image_width,
|
||||
.image_height = image_height,
|
||||
.samples_per_pixel = 64,
|
||||
.camera = df_thin_lense_camera,
|
||||
.camera = df_pinhole_camera,
|
||||
.camera_data = &camera_data,
|
||||
},
|
||||
spheres, 0,
|
||||
|
|
|
@ -26,6 +26,9 @@
|
|||
#define DF_PIF32 3.1415926f
|
||||
#define DF_PI_OVER_4F32 (DF_PIF32 / 4.f)
|
||||
#define DF_PI_OVER_2F32 (DF_PIF32 / 2.f)
|
||||
#define DF_PI_OVER_180F32 (DF_PIF32 / 180.f)
|
||||
|
||||
#define DF_DEGREES_TO_RADIANS(deg) ((deg) * DF_PI_OVER_180F32)
|
||||
|
||||
#define DF_ARRAY_COUNT(A) (sizeof((A)) / sizeof((A)[0]))
|
||||
#define DF_UNUSED(x) ((void)sizeof((x)))
|
||||
|
@ -58,6 +61,12 @@ DF_API df_image_handle df_load_image(const char *path, int *w, int *h);
|
|||
|
||||
/* cameras */
|
||||
|
||||
/* The camera data structs (df_pinhole_camera_data etc.) are defined here
|
||||
* to enable you to store these on the stack.
|
||||
* However - unless you know what you are doing (-: - you should treat these
|
||||
* structs as opaque.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
df_v3 origin;
|
||||
|
@ -70,25 +79,31 @@ typedef df_ray (*df_camera_fn)(float u, float v, unsigned int sample_idx, void *
|
|||
|
||||
typedef struct
|
||||
{
|
||||
df_v2 viewport_size;
|
||||
df_v3 horizontal;
|
||||
df_v3 vertical;
|
||||
df_v3 lower_left;
|
||||
df_v3 origin;
|
||||
} df_pinhole_camera_data;
|
||||
|
||||
DF_API df_pinhole_camera_data df_create_pinhole_camera_data(int image_width, int image_height, float focal_length);
|
||||
/* Creates data for a pinhole camera.
|
||||
* The vertical fov (vfov) is given in degrees.
|
||||
*/
|
||||
DF_API df_pinhole_camera_data df_create_pinhole_camera_data(df_v3 look_from, df_v3 look_at, df_v3 up,
|
||||
float vfov, float aspect);
|
||||
|
||||
DF_API df_ray df_pinhole_camera(float u, float v, unsigned int sample_idx, void *camera_data);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
df_v2 viewport_size;
|
||||
df_v3 horizontal;
|
||||
df_v3 vertical;
|
||||
df_v3 lower_left;
|
||||
df_v3 origin;
|
||||
float lens_radius;
|
||||
} df_thin_lense_camera_data;
|
||||
|
||||
DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(int image_width,
|
||||
int image_height,
|
||||
float aperture,
|
||||
float focal_distance);
|
||||
DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(df_v3 look_from, df_v3 look_at, df_v3 up,
|
||||
float vfov, float aspect, float aperture, float focal_distance);
|
||||
|
||||
DF_API df_ray df_thin_lense_camera(float u, float v, unsigned int sample_idx, void *camera_data);
|
||||
|
||||
|
@ -100,6 +115,9 @@ typedef struct
|
|||
int image_height;
|
||||
int samples_per_pixel;
|
||||
|
||||
df_v3 look_from;
|
||||
df_v3 look_at;
|
||||
|
||||
df_camera_fn camera;
|
||||
void *camera_data;
|
||||
} df_trace_rays_settings;
|
||||
|
|
BIN
include/defocus/df_math.h
Normal file
BIN
include/defocus/df_math.h
Normal file
Binary file not shown.
BIN
lib/df_math.c
Normal file
BIN
lib/df_math.c
Normal file
Binary file not shown.
164
lib/raytracer.c
164
lib/raytracer.c
|
@ -1,4 +1,5 @@
|
|||
#include <defocus/defocus.h>
|
||||
#include <defocus/df_math.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -9,23 +10,6 @@
|
|||
|
||||
#include "pcg/pcg_basic.h"
|
||||
|
||||
/* ************* *
|
||||
* *
|
||||
* Vectors *
|
||||
* *
|
||||
* ************* */
|
||||
|
||||
static df_v3 normalize(df_v3 v)
|
||||
{
|
||||
float l = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
|
||||
return (df_v3){v.x / l, v.y / l, v.z / l};
|
||||
}
|
||||
|
||||
static float dot(df_v3 a, df_v3 b) { return a.x * b.x + a.y * b.y + a.z * b.z; }
|
||||
|
||||
static float v2_len(df_v2 v) { return sqrtf(v.x * v.x + v.y * v.y); }
|
||||
|
||||
|
||||
/* ********************* *
|
||||
* *
|
||||
* Image functions *
|
||||
|
@ -72,22 +56,32 @@ DF_API df_image_handle df_load_image(const char *path, int *w, int *h)
|
|||
* *
|
||||
* *************************** */
|
||||
|
||||
DF_API df_pinhole_camera_data df_create_pinhole_camera_data(int image_width, int image_height, float focal_length)
|
||||
DF_API df_pinhole_camera_data
|
||||
df_create_pinhole_camera_data(df_v3 look_from, df_v3 look_at, df_v3 up, float vfov, float aspect)
|
||||
{
|
||||
float aspect_ratio = (float)image_width / (float)image_height;
|
||||
float viewport_height = 2.f;
|
||||
float viewport_width = aspect_ratio * viewport_height;
|
||||
float theta = DF_DEGREES_TO_RADIANS(vfov);
|
||||
float h = tanf(theta * .5f);
|
||||
float viewport_height = 2.f * h;
|
||||
float viewport_width = aspect * viewport_height;
|
||||
|
||||
/* Simple perspective projection.
|
||||
* The lens is placed at (0, 0, 0)
|
||||
*/
|
||||
float lower_left_x = -viewport_width / 2.f;
|
||||
float lower_left_y = -viewport_height / 2.f;
|
||||
float lower_left_z = -focal_length;
|
||||
df_v3 view_vec = df_sub_v3(look_from, look_at);
|
||||
df_v3 w = df_normalize_v3(view_vec);
|
||||
df_v3 u = df_normalize_v3(df_cross(up, w));
|
||||
df_v3 v = df_cross(w, u);
|
||||
|
||||
df_v3 horizontal = df_mul_v3(viewport_width, u);
|
||||
df_v3 vertical = df_mul_v3(viewport_height, v);
|
||||
df_v3 lower_left = {
|
||||
.x = look_from.x - horizontal.x / 2.f - vertical.x / 2.f - w.x,
|
||||
.y = look_from.y - horizontal.y / 2.f - vertical.y / 2.f - w.y,
|
||||
.z = look_from.z - horizontal.z / 2.f - vertical.z / 2.f - w.z,
|
||||
};
|
||||
|
||||
return (df_pinhole_camera_data){
|
||||
.viewport_size = {.x = viewport_width, .y = viewport_height},
|
||||
.lower_left = { .x = lower_left_x, .y = lower_left_y, .z = lower_left_z },
|
||||
.origin = look_from,
|
||||
.horizontal = horizontal,
|
||||
.vertical = vertical,
|
||||
.lower_left = lower_left,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -96,11 +90,14 @@ DF_API df_ray df_pinhole_camera(float u, float v, unsigned int sample_idx, void
|
|||
DF_UNUSED(sample_idx);
|
||||
df_pinhole_camera_data *data = camera_data;
|
||||
|
||||
df_v3 origin = {0.f, 0.f, 0.f};
|
||||
df_v3 origin = data->origin;
|
||||
df_v3 horizontal = data->horizontal;
|
||||
df_v3 vertical = data->vertical;
|
||||
|
||||
df_v3 target = {
|
||||
data->lower_left.x + u * data->viewport_size.x,
|
||||
data->lower_left.y + v * data->viewport_size.y,
|
||||
data->lower_left.z
|
||||
data->lower_left.x + u * horizontal.x + v * vertical.x - origin.x,
|
||||
data->lower_left.y + u * horizontal.y + v * vertical.y - origin.y,
|
||||
data->lower_left.z + u * horizontal.z + v * vertical.z - origin.z,
|
||||
};
|
||||
|
||||
return (df_ray){
|
||||
|
@ -116,40 +113,38 @@ static df_v2 random_point_on_disk(unsigned int i)
|
|||
|
||||
while (1) {
|
||||
df_v2 p = {.x = (float)pcg32_boundedrand(1024) / 1023.f, .y = (float)pcg32_boundedrand(1024) / 1023.f};
|
||||
if (v2_len(p) <= 1.f)
|
||||
if (df_len_v2(p) <= 1.f)
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(int image_width,
|
||||
int image_height,
|
||||
float aperture,
|
||||
float focal_distance)
|
||||
DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(
|
||||
df_v3 look_from, df_v3 look_at, df_v3 up, float vfov, float aspect, float aperture, float focal_distance)
|
||||
{
|
||||
float aspect_ratio = (float)image_width / (float)image_height;
|
||||
float viewport_height = 2.f;
|
||||
float viewport_width = aspect_ratio * viewport_height;
|
||||
float theta = DF_DEGREES_TO_RADIANS(vfov);
|
||||
float h = tanf(theta * .5f);
|
||||
float viewport_height = 2.f * h;
|
||||
float viewport_width = aspect * viewport_height;
|
||||
|
||||
/* Simple perspective projection.
|
||||
* The lens is placed at (0, 0, 0)
|
||||
*/
|
||||
float lower_left_x = -viewport_width / 2.f;
|
||||
float lower_left_y = -viewport_height / 2.f;
|
||||
float lower_left_z = -focal_distance;
|
||||
df_v3 view_vec = df_sub_v3(look_from, look_at);
|
||||
df_v3 w = df_normalize_v3(view_vec);
|
||||
df_v3 u = df_normalize_v3(df_cross(up, w));
|
||||
df_v3 v = df_cross(w, u);
|
||||
|
||||
float lens_radius = aperture / 2.f;
|
||||
df_v3 horizontal = df_mul_v3(viewport_width, u);
|
||||
df_v3 vertical = df_mul_v3(viewport_height, v);
|
||||
df_v3 lower_left = {
|
||||
.x = look_from.x - horizontal.x / 2.f - vertical.x / 2.f - focal_distance * w.x,
|
||||
.y = look_from.y - horizontal.y / 2.f - vertical.y / 2.f - focal_distance * w.y,
|
||||
.z = look_from.z - horizontal.z / 2.f - vertical.z / 2.f - focal_distance * w.z,
|
||||
};
|
||||
|
||||
return (df_thin_lense_camera_data){
|
||||
.lens_radius = lens_radius,
|
||||
.lower_left = {
|
||||
.x = lower_left_x,
|
||||
.y = lower_left_y,
|
||||
.z = lower_left_z,
|
||||
},
|
||||
.viewport_size = {
|
||||
.x = viewport_width,
|
||||
.y = viewport_height
|
||||
}
|
||||
.origin = look_from,
|
||||
.horizontal = horizontal,
|
||||
.vertical = vertical,
|
||||
.lower_left = lower_left,
|
||||
.lens_radius = aperture / 2.f,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -162,12 +157,20 @@ DF_API df_ray df_thin_lense_camera(float u, float v, unsigned int sample_idx, vo
|
|||
lensp.y *= data->lens_radius;
|
||||
|
||||
df_v3 offset = {u * lensp.x, v * lensp.y, .z = 0.f};
|
||||
df_v3 origin = df_add_v3(data->origin, offset);
|
||||
df_v3 horizontal = data->horizontal;
|
||||
df_v3 vertical = data->vertical;
|
||||
|
||||
df_v3 origin = offset;
|
||||
df_v3 target = {data->lower_left.x + u * data->viewport_size.x + offset.x,
|
||||
data->lower_left.y + v * data->viewport_size.y + offset.y,
|
||||
data->lower_left.z + offset.z};
|
||||
return (df_ray){.origin = origin, .dir = target};
|
||||
df_v3 target = {
|
||||
data->lower_left.x + u * horizontal.x + v * vertical.x - origin.x,
|
||||
data->lower_left.y + u * horizontal.y + v * vertical.y - origin.y,
|
||||
data->lower_left.z + u * horizontal.z + v * vertical.z - origin.z,
|
||||
};
|
||||
|
||||
return (df_ray){
|
||||
.origin = origin,
|
||||
.dir = target,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
@ -305,17 +308,17 @@ DF_API int df_trace_rays(df_trace_rays_settings settings,
|
|||
return 0;
|
||||
void *camera_data = settings.camera_data;
|
||||
|
||||
uint8_t *pixels = malloc(image_width * image_height * 3);
|
||||
if (!pixels)
|
||||
float *fpixels = malloc(sizeof(float) * image_width * image_height * 3);
|
||||
if (!fpixels)
|
||||
return 0;
|
||||
memset(pixels, 0, image_width * image_height * 3);
|
||||
memset(fpixels, 0, sizeof(float) * image_width * image_height * 3);
|
||||
|
||||
df_ray_packet packet;
|
||||
packet.samples_per_pixel = samples_per_pixel;
|
||||
packet.ray_count = image_width * image_height * samples_per_pixel;
|
||||
void *packet_mem = malloc(packet.ray_count * (2 * sizeof(df_v3) + sizeof(df_v2i)));
|
||||
if (!packet_mem) {
|
||||
free(pixels);
|
||||
free(fpixels);
|
||||
return 0;
|
||||
}
|
||||
packet.ray_origins = (df_v3 *)packet_mem;
|
||||
|
@ -329,7 +332,6 @@ DF_API int df_trace_rays(df_trace_rays_settings settings,
|
|||
unsigned int ray_idx = 0;
|
||||
for (int y = 0; y < image_height; ++y) {
|
||||
/* TODO(Kevin): SIMD */
|
||||
uint8_t *row = pixels + y * image_width * 3;
|
||||
for (int x = 0; x < image_width; ++x) {
|
||||
float u = (float)x / (float)(image_width - 1);
|
||||
float v = (float)y / (float)(image_height - 1);
|
||||
|
@ -418,11 +420,12 @@ DF_API int df_trace_rays(df_trace_rays_settings settings,
|
|||
}
|
||||
}
|
||||
|
||||
float fsamples = (float)samples_per_pixel;
|
||||
/* Trace the rays */
|
||||
for (unsigned int i = 0; i < packet.ray_count; ++i) {
|
||||
df_v2i pixelp = packet.ray_pixels[i];
|
||||
|
||||
uint8_t *row = pixels + pixelp.y * image_width * 3;
|
||||
float *row = fpixels + pixelp.y * image_width * 3;
|
||||
|
||||
df_hit plane_hit = plane_test(packet.ray_origins[i], packet.ray_deltas[i], planes, plane_count);
|
||||
|
||||
|
@ -438,13 +441,30 @@ DF_API int df_trace_rays(df_trace_rays_settings settings,
|
|||
stbi_uc *pixel = _image_table.images[plane_hit.image].pixels +
|
||||
4 * (pixely * _image_table.images[plane_hit.image].w + pixelx);
|
||||
|
||||
row[pixelp.x * 3 + 0] += pixel[0] / samples_per_pixel;
|
||||
row[pixelp.x * 3 + 1] += pixel[1] / samples_per_pixel;
|
||||
row[pixelp.x * 3 + 2] += pixel[2] / samples_per_pixel;
|
||||
row[pixelp.x * 3 + 0] += (float)pixel[0];
|
||||
row[pixelp.x * 3 + 1] += (float)pixel[1];
|
||||
row[pixelp.x * 3 + 2] += (float)pixel[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Map down to 8bit rgb */
|
||||
uint8_t *pixels = malloc(image_width * image_height * 3);
|
||||
if (!pixels) {
|
||||
free(packet_mem);
|
||||
free(fpixels);
|
||||
return 0;
|
||||
}
|
||||
for (unsigned int i = 0; i < image_width * image_height; ++i) {
|
||||
float *fp = &fpixels[i * 3];
|
||||
uint8_t *p = &pixels[i * 3];
|
||||
|
||||
p[0] = (uint8_t)(fp[0] / fsamples);
|
||||
p[1] = (uint8_t)(fp[1] / fsamples);
|
||||
p[2] = (uint8_t)(fp[2] / fsamples);
|
||||
}
|
||||
|
||||
free(fpixels);
|
||||
free(packet_mem);
|
||||
*result = pixels;
|
||||
return 1;
|
||||
|
|
|
@ -13,7 +13,9 @@ endif
|
|||
lib = library('df',
|
||||
'lib/raytracer.c',
|
||||
'lib/utils.c',
|
||||
'lib/df_math.c',
|
||||
'include/defocus/defocus.h',
|
||||
'include/defocus/df_math.h',
|
||||
'3p/stb_image.h',
|
||||
'3p/pcg/pcg_basic.c',
|
||||
'3p/pcg/pcg_basic.h',
|
||||
|
|
Loading…
Reference in New Issue
Block a user