Update project files and enhance rendering system
Added: - Updated `.gitignore` to ignore the `[Bb]uild/` directory. - Additional tasks added to the roadmap in `README.md` for light unit standardization and GPU backend support. Changed: - Removed line in `settings.json` that disabled error squiggles for C/C++ code. - Modified `Triangle.h` to include `material_id` in `triangle_t` and reorganized properties. - Reordered parameters in `triangle_collection_init` for clarity. - Updated `shading_context_t` in `Material.h` and added size parameter to `material_create`. - Streamlined initialization in `scene_init` and updated `scene_free` for proper resource management. - Updated `window_create` in `Window.h` to accept a `render_job_t` parameter. - Introduced `renderer_start` in `Renderer.c` to handle rendering jobs and optimized pixel rendering logic.
This commit is contained in:
@@ -1,14 +1,10 @@
|
||||
#include "Debug.h"
|
||||
#include "Rendering/Scene.h"
|
||||
#include "Algorithm/PathTracing.h"
|
||||
|
||||
#define FLIP_Y
|
||||
|
||||
bool scene_init(uint64_t triangle_count, uint8_t material_count, uint32_t punctual_light_count, scene_t* scene)
|
||||
bool scene_init(scene_t* scene, uint64_t triangle_count, uint8_t material_count, uint32_t punctual_light_count)
|
||||
{
|
||||
scene_t temp = {0};
|
||||
|
||||
if (!triangle_collection_init(triangle_count, &temp.triangles))
|
||||
if (!triangle_collection_init(&temp.triangles, triangle_count))
|
||||
{
|
||||
goto triangle_failed;
|
||||
}
|
||||
@@ -42,14 +38,6 @@ triangle_failed:
|
||||
return false;
|
||||
}
|
||||
|
||||
void scene_free(scene_t* scene)
|
||||
{
|
||||
bvh_tree_free(&scene->bvh_tree);
|
||||
triangle_collection_free(&scene->triangles);
|
||||
material_collection_free(&scene->materials);
|
||||
light_collection_free(&scene->lights);
|
||||
}
|
||||
|
||||
bool scene_build_bvh(scene_t* scene)
|
||||
{
|
||||
if (scene == NULL || scene->triangles.count == 0)
|
||||
@@ -68,193 +56,10 @@ bool scene_build_bvh(scene_t* scene)
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void ensure_camera_aspect_ratio(camera_t* camera, rendering_config_t config)
|
||||
void scene_free(scene_t* scene)
|
||||
{
|
||||
if (fabsf((float)config.width / config.height - camera->aspect_ratio) > FLT_EPSILON)
|
||||
{
|
||||
*camera = camera_create(
|
||||
camera->position,
|
||||
camera->rotation,
|
||||
camera->focal_length,
|
||||
camera->size_x,
|
||||
(float)config.width / (float)config.height
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
static inline vec2s compute_ndc(float x, float y, uint32_t width, uint32_t height)
|
||||
{
|
||||
return (vec2s){
|
||||
.x = x / (float)width,
|
||||
#ifdef FLIP_Y
|
||||
.y = 1.0f - y / (float)height
|
||||
#else
|
||||
.y = y / (float)height
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
||||
static inline uint16_t get_sample_count(uint16_t sample_count, int flag)
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case DEBUG_BVH:
|
||||
case DEBUG_SOBOL:
|
||||
return 1;
|
||||
default:
|
||||
return sample_count;
|
||||
}
|
||||
|
||||
return sample_count;
|
||||
}
|
||||
|
||||
static void screen_render_pixel(scene_t* scene, rendering_config_t config, vec3s coord, uint32_t x, uint32_t y, int flag, vec4s* pixel_color)
|
||||
{
|
||||
vec4s accumulated_color = glms_vec4_zero();
|
||||
*pixel_color = accumulated_color;
|
||||
uint32_t pixel_id = y * config.width + x;
|
||||
|
||||
uint16_t sample_count = get_sample_count(config.sample_count, flag);
|
||||
vec2s position_ndc = compute_ndc((float)x, (float)y, config.width, config.height);
|
||||
vec3s camera_right = quat_get_right(scene->camera.rotation);
|
||||
vec3s camera_up = quat_get_up(scene->camera.rotation);
|
||||
|
||||
for (uint16_t k = 0; k < sample_count; k++)
|
||||
{
|
||||
float screen_x = position_ndc.x * 2.0f - 1.0f;
|
||||
float screen_y = position_ndc.y * 2.0f - 1.0f;
|
||||
float sensor_offset_x = screen_x * scene->camera.size_x / 2.0f;
|
||||
float sensor_offset_y = screen_y * scene->camera.size_y / 2.0f;
|
||||
|
||||
vec3s image_plane_point = coord;
|
||||
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(camera_right, sensor_offset_x));
|
||||
image_plane_point = glms_vec3_add(image_plane_point, glms_vec3_scale(camera_up, sensor_offset_y));
|
||||
|
||||
ray_t ray = {
|
||||
.origin = scene->camera.position,
|
||||
.direction = glms_vec3_normalize(glms_vec3_sub(image_plane_point, scene->camera.position))
|
||||
};
|
||||
|
||||
vec4s out_color = glms_vec4_zero();
|
||||
|
||||
if (flag != 0)
|
||||
{
|
||||
out_color = render_debug(scene, ray, k, flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Hash it
|
||||
uint32_t sobol_idx = pixel_id * config.sample_count + (k + 1);
|
||||
out_color = path_trace(scene, ray, sobol_idx, config.max_depth);
|
||||
}
|
||||
|
||||
accumulated_color = glms_vec4_add(accumulated_color, out_color);
|
||||
}
|
||||
|
||||
*pixel_color = glms_vec4_scale(accumulated_color, 1.0f / (float)sample_count);
|
||||
}
|
||||
|
||||
// TODO: This should be moved to renderer
|
||||
bool scene_render_tile(scene_t* scene, rendering_context_t* ctx, rendering_config_t config, uint32_t tile_index, int rendering_flag, render_target_t* render_target, tile_t* tile_out)
|
||||
{
|
||||
if (ctx->is_done)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!ctx->is_init)
|
||||
{
|
||||
ensure_camera_aspect_ratio(&scene->camera, config);
|
||||
ctx->tile_count_x = (config.width + config.bucket_size - 1) / config.bucket_size;
|
||||
ctx->tile_count_y = (config.height + config.bucket_size - 1) / config.bucket_size;
|
||||
ctx->coord = glms_vec3_add(scene->camera.position, glms_vec3_scale(quat_get_forward(scene->camera.rotation), scene->camera.focal_length));
|
||||
ctx->is_init = true;
|
||||
}
|
||||
|
||||
if (tile_index >= ctx->tile_count_x * ctx->tile_count_y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t tile_x_0 = tile_index % ctx->tile_count_x * config.bucket_size;
|
||||
uint32_t tile_y_0 = tile_index / ctx->tile_count_x * config.bucket_size;
|
||||
uint32_t tile_x_1 = (uint32_t)fmin(tile_x_0 + config.bucket_size, config.width);
|
||||
uint32_t tile_y_1 = (uint32_t)fmin(tile_y_0 + config.bucket_size, config.height);
|
||||
|
||||
tile_out->x = tile_x_0;
|
||||
tile_out->y = tile_y_0;
|
||||
tile_out->width = tile_x_1 - tile_x_0;
|
||||
tile_out->height = tile_y_1 - tile_y_0;
|
||||
|
||||
int64_t x, y; // OpenMP requires these to be declared outside the parallel region. Also, they need to be signed integers. To avoid overflow, we need to use int64_t
|
||||
rendering_config_t config_copy = config; // Have to copy it, otherwise OpenMP will cause it become invalid. Not sure if this is a bug or not.
|
||||
|
||||
#pragma omp parallel for schedule(dynamic, 1) default(none) \
|
||||
shared(tile_x_0, tile_x_1, tile_y_0, tile_y_1, config_copy) \
|
||||
private(x, y)
|
||||
for (y = tile_y_0; y < tile_y_1; y++)
|
||||
{
|
||||
for (x = tile_x_0; x < tile_x_1; x++)
|
||||
{
|
||||
vec4s pixel_color;
|
||||
screen_render_pixel(scene, config_copy, ctx->coord, (uint32_t)x, (uint32_t)y, rendering_flag, &pixel_color);
|
||||
render_target_set_pixel(render_target, (uint32_t)x, (uint32_t)y, pixel_color);
|
||||
}
|
||||
}
|
||||
|
||||
if (tile_index == ctx->tile_count_x * ctx->tile_count_y - 1)
|
||||
{
|
||||
ctx->is_done = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: This should be moved to renderer
|
||||
bool scene_render(scene_t* scene, rendering_config_t config, int rendering_flag, render_target_t* render_target)
|
||||
{
|
||||
ensure_camera_aspect_ratio(&scene->camera, config);
|
||||
|
||||
if (render_target->buffer != NULL)
|
||||
{
|
||||
render_target_free(render_target);
|
||||
}
|
||||
|
||||
if (render_target_init(config.width, config.height, render_target))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t tile_count_x = (config.width + config.bucket_size - 1) / config.bucket_size;
|
||||
uint32_t tile_count_y = (config.height + config.bucket_size - 1) / config.bucket_size;
|
||||
uint32_t tile_count = tile_count_x * tile_count_y;
|
||||
|
||||
float inv_sample = 1.0f / config.sample_count;
|
||||
vec3s coord = glms_vec3_add(scene->camera.position, glms_vec3_scale(quat_get_forward(scene->camera.rotation), scene->camera.focal_length));
|
||||
|
||||
int64_t x, y, tile_index; // OpenMP requires these to be declared outside the parallel region. Also, they need to be signed integers. To avoid overflow, we need to use int64_t
|
||||
rendering_config_t config_copy = config;
|
||||
|
||||
#pragma omp parallel for schedule(dynamic, 1) default(none) \
|
||||
shared(tile_count_x, tile_count_y, tile_count, config_copy, coord, inv_sample, render_target) \
|
||||
private(x, y, tile_index)
|
||||
for (tile_index = 0; tile_index < tile_count; tile_index++)
|
||||
{
|
||||
uint32_t tile_x_0 = (uint32_t)tile_index % tile_count_x * config.bucket_size;
|
||||
uint32_t tile_y_0 = (uint32_t)tile_index / tile_count_x * config.bucket_size;
|
||||
uint32_t tile_x_1 = (uint32_t)fmin(tile_x_0 + config.bucket_size, config.width);
|
||||
uint32_t tile_y_1 = (uint32_t)fmin(tile_y_0 + config.bucket_size, config.height);
|
||||
|
||||
for (y = tile_y_0; y < tile_y_1; y++)
|
||||
{
|
||||
for (x = tile_x_0; x < tile_x_1; x++)
|
||||
{
|
||||
vec4s pixel_color;
|
||||
screen_render_pixel(scene, config_copy, coord, (uint32_t)x, (uint32_t)y, rendering_flag, &pixel_color);
|
||||
render_target_set_pixel(render_target, (uint32_t)x, (uint32_t)y, pixel_color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
bvh_tree_free(&scene->bvh_tree);
|
||||
triangle_collection_free(&scene->triangles);
|
||||
material_collection_free(&scene->materials);
|
||||
light_collection_free(&scene->lights);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user