dump state

This commit is contained in:
Kevin Trogant 2023-07-12 22:57:49 +02:00
parent fca2c54ab3
commit fc39ee66df
6 changed files with 149 additions and 82 deletions

View File

@ -1,6 +1,7 @@
/* Main command line executable. */ /* Main command line executable. */
#include <defocus/defocus.h> #include <defocus/defocus.h>
#include <defocus/df_math.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION #define STB_IMAGE_WRITE_IMPLEMENTATION
#include <stb_image_write.h> #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); df_image_handle input_image = df_load_image("../test_image.png", &image_width, &image_height);
float aspect = (float)image_width / (float)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; 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){ df_trace_rays((df_trace_rays_settings){
.image_width = image_width, .image_width = image_width,
.image_height = image_height, .image_height = image_height,
.samples_per_pixel = 64, .samples_per_pixel = 64,
.camera = df_thin_lense_camera, .camera = df_pinhole_camera,
.camera_data = &camera_data, .camera_data = &camera_data,
}, },
spheres, 0, spheres, 0,

View File

@ -26,6 +26,9 @@
#define DF_PIF32 3.1415926f #define DF_PIF32 3.1415926f
#define DF_PI_OVER_4F32 (DF_PIF32 / 4.f) #define DF_PI_OVER_4F32 (DF_PIF32 / 4.f)
#define DF_PI_OVER_2F32 (DF_PIF32 / 2.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_ARRAY_COUNT(A) (sizeof((A)) / sizeof((A)[0]))
#define DF_UNUSED(x) ((void)sizeof((x))) #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 */ /* 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 typedef struct
{ {
df_v3 origin; df_v3 origin;
@ -70,25 +79,31 @@ typedef df_ray (*df_camera_fn)(float u, float v, unsigned int sample_idx, void *
typedef struct typedef struct
{ {
df_v2 viewport_size; df_v3 horizontal;
df_v3 vertical;
df_v3 lower_left; df_v3 lower_left;
df_v3 origin;
} df_pinhole_camera_data; } 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); DF_API df_ray df_pinhole_camera(float u, float v, unsigned int sample_idx, void *camera_data);
typedef struct typedef struct
{ {
df_v2 viewport_size; df_v3 horizontal;
df_v3 vertical;
df_v3 lower_left; df_v3 lower_left;
df_v3 origin;
float lens_radius; float lens_radius;
} df_thin_lense_camera_data; } df_thin_lense_camera_data;
DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(int image_width, DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(df_v3 look_from, df_v3 look_at, df_v3 up,
int image_height, float vfov, float aspect, float aperture, float focal_distance);
float aperture,
float focal_distance);
DF_API df_ray df_thin_lense_camera(float u, float v, unsigned int sample_idx, void *camera_data); 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 image_height;
int samples_per_pixel; int samples_per_pixel;
df_v3 look_from;
df_v3 look_at;
df_camera_fn camera; df_camera_fn camera;
void *camera_data; void *camera_data;
} df_trace_rays_settings; } df_trace_rays_settings;

BIN
include/defocus/df_math.h Normal file

Binary file not shown.

BIN
lib/df_math.c Normal file

Binary file not shown.

View File

@ -1,4 +1,5 @@
#include <defocus/defocus.h> #include <defocus/defocus.h>
#include <defocus/df_math.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
@ -9,23 +10,6 @@
#include "pcg/pcg_basic.h" #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 * * 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 theta = DF_DEGREES_TO_RADIANS(vfov);
float viewport_height = 2.f; float h = tanf(theta * .5f);
float viewport_width = aspect_ratio * viewport_height; float viewport_height = 2.f * h;
float viewport_width = aspect * viewport_height;
/* Simple perspective projection. df_v3 view_vec = df_sub_v3(look_from, look_at);
* The lens is placed at (0, 0, 0) df_v3 w = df_normalize_v3(view_vec);
*/ df_v3 u = df_normalize_v3(df_cross(up, w));
float lower_left_x = -viewport_width / 2.f; df_v3 v = df_cross(w, u);
float lower_left_y = -viewport_height / 2.f;
float lower_left_z = -focal_length; 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){ return (df_pinhole_camera_data){
.viewport_size = {.x = viewport_width, .y = viewport_height}, .origin = look_from,
.lower_left = { .x = lower_left_x, .y = lower_left_y, .z = lower_left_z }, .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_UNUSED(sample_idx);
df_pinhole_camera_data *data = camera_data; 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 = { df_v3 target = {
data->lower_left.x + u * data->viewport_size.x, data->lower_left.x + u * horizontal.x + v * vertical.x - origin.x,
data->lower_left.y + v * data->viewport_size.y, data->lower_left.y + u * horizontal.y + v * vertical.y - origin.y,
data->lower_left.z data->lower_left.z + u * horizontal.z + v * vertical.z - origin.z,
}; };
return (df_ray){ return (df_ray){
@ -116,40 +113,38 @@ static df_v2 random_point_on_disk(unsigned int i)
while (1) { while (1) {
df_v2 p = {.x = (float)pcg32_boundedrand(1024) / 1023.f, .y = (float)pcg32_boundedrand(1024) / 1023.f}; 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; return p;
} }
} }
DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(int image_width, DF_API df_thin_lense_camera_data df_create_thin_lense_camera_data(
int image_height, df_v3 look_from, df_v3 look_at, df_v3 up, float vfov, float aspect, float aperture, float focal_distance)
float aperture,
float focal_distance)
{ {
float aspect_ratio = (float)image_width / (float)image_height; float theta = DF_DEGREES_TO_RADIANS(vfov);
float viewport_height = 2.f; float h = tanf(theta * .5f);
float viewport_width = aspect_ratio * viewport_height; float viewport_height = 2.f * h;
float viewport_width = aspect * viewport_height;
/* Simple perspective projection. df_v3 view_vec = df_sub_v3(look_from, look_at);
* The lens is placed at (0, 0, 0) df_v3 w = df_normalize_v3(view_vec);
*/ df_v3 u = df_normalize_v3(df_cross(up, w));
float lower_left_x = -viewport_width / 2.f; df_v3 v = df_cross(w, u);
float lower_left_y = -viewport_height / 2.f;
float lower_left_z = -focal_distance;
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){ return (df_thin_lense_camera_data){
.lens_radius = lens_radius, .origin = look_from,
.lower_left = { .horizontal = horizontal,
.x = lower_left_x, .vertical = vertical,
.y = lower_left_y, .lower_left = lower_left,
.z = lower_left_z, .lens_radius = aperture / 2.f,
},
.viewport_size = {
.x = viewport_width,
.y = viewport_height
}
}; };
} }
@ -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; lensp.y *= data->lens_radius;
df_v3 offset = {u * lensp.x, v * lensp.y, .z = 0.f}; 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 = {
df_v3 target = {data->lower_left.x + u * data->viewport_size.x + offset.x, data->lower_left.x + u * horizontal.x + v * vertical.x - origin.x,
data->lower_left.y + v * data->viewport_size.y + offset.y, data->lower_left.y + u * horizontal.y + v * vertical.y - origin.y,
data->lower_left.z + offset.z}; data->lower_left.z + u * horizontal.z + v * vertical.z - origin.z,
return (df_ray){.origin = origin, .dir = target}; };
return (df_ray){
.origin = origin,
.dir = target,
};
} }
@ -305,17 +308,17 @@ DF_API int df_trace_rays(df_trace_rays_settings settings,
return 0; return 0;
void *camera_data = settings.camera_data; void *camera_data = settings.camera_data;
uint8_t *pixels = malloc(image_width * image_height * 3); float *fpixels = malloc(sizeof(float) * image_width * image_height * 3);
if (!pixels) if (!fpixels)
return 0; return 0;
memset(pixels, 0, image_width * image_height * 3); memset(fpixels, 0, sizeof(float) * image_width * image_height * 3);
df_ray_packet packet; df_ray_packet packet;
packet.samples_per_pixel = samples_per_pixel; packet.samples_per_pixel = samples_per_pixel;
packet.ray_count = image_width * image_height * 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))); void *packet_mem = malloc(packet.ray_count * (2 * sizeof(df_v3) + sizeof(df_v2i)));
if (!packet_mem) { if (!packet_mem) {
free(pixels); free(fpixels);
return 0; return 0;
} }
packet.ray_origins = (df_v3 *)packet_mem; 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; unsigned int ray_idx = 0;
for (int y = 0; y < image_height; ++y) { for (int y = 0; y < image_height; ++y) {
/* TODO(Kevin): SIMD */ /* TODO(Kevin): SIMD */
uint8_t *row = pixels + y * image_width * 3;
for (int x = 0; x < image_width; ++x) { for (int x = 0; x < image_width; ++x) {
float u = (float)x / (float)(image_width - 1); float u = (float)x / (float)(image_width - 1);
float v = (float)y / (float)(image_height - 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 */ /* Trace the rays */
for (unsigned int i = 0; i < packet.ray_count; ++i) { for (unsigned int i = 0; i < packet.ray_count; ++i) {
df_v2i pixelp = packet.ray_pixels[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); 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 + stbi_uc *pixel = _image_table.images[plane_hit.image].pixels +
4 * (pixely * _image_table.images[plane_hit.image].w + pixelx); 4 * (pixely * _image_table.images[plane_hit.image].w + pixelx);
row[pixelp.x * 3 + 0] += pixel[0] / samples_per_pixel; row[pixelp.x * 3 + 0] += (float)pixel[0];
row[pixelp.x * 3 + 1] += pixel[1] / samples_per_pixel; row[pixelp.x * 3 + 1] += (float)pixel[1];
row[pixelp.x * 3 + 2] += pixel[2] / samples_per_pixel; 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); free(packet_mem);
*result = pixels; *result = pixels;
return 1; return 1;

View File

@ -13,7 +13,9 @@ endif
lib = library('df', lib = library('df',
'lib/raytracer.c', 'lib/raytracer.c',
'lib/utils.c', 'lib/utils.c',
'lib/df_math.c',
'include/defocus/defocus.h', 'include/defocus/defocus.h',
'include/defocus/df_math.h',
'3p/stb_image.h', '3p/stb_image.h',
'3p/pcg/pcg_basic.c', '3p/pcg/pcg_basic.c',
'3p/pcg/pcg_basic.h', '3p/pcg/pcg_basic.h',