Changed function signatures to remove const qualifiers

Changed several function signatures across multiple files to remove the `const` qualifier from parameters of type `vec3s` for improved flexibility.
Changed `material_collection_create` to `material_collection_init` for better initialization handling.
Changed `scene_create` to `scene_init` to return a boolean indicating success or failure.
Changed `render_target_create` to `render_target_init` for consistent initialization practices.
Changed `window_create` to remove `const` from its parameters for consistency.
Changed `evaluate_bsdf_directional` and `evaluate_bsdf_const_sky` to remove `const` from their parameters.
Changed `sample_bsdf_simple_lit` and `sample_bsdf_pdf_simple_lit` to remove `const` from the `normal` parameter.
Changed `scene_render` to take a pointer to `render_target_t` instead of returning it directly.
Updated `main.c` to reflect new initialization functions for better memory management.
This commit is contained in:
2025-04-18 10:51:46 +09:00
parent bfc94f0008
commit 1162575545
27 changed files with 231 additions and 166 deletions

View File

@@ -6,7 +6,7 @@
// TODO: Implement a faster methods like BVH, KD-Tree or uniform grid acceleration
// TODO: Split the diffuse and specular into different Monte Carlo, so we can decide the sample count for each one
vec3s path_trace(const scene_t* scene, const ray_t ray, const uint32_t sample_index, const int max_depth)
vec3s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, int max_depth)
{
const triangle_collection_t* triangles = &scene->triangles;
const material_collection_t* materials = &scene->materials;

View File

@@ -1,6 +1,6 @@
#include "algorithm/RayIntersection.h"
hit_result_t ray_intersect(const triangle_t triangle, const ray_t ray)
hit_result_t ray_intersect( triangle_t triangle, ray_t ray)
{
hit_result_t result = {0};
@@ -80,7 +80,7 @@ hit_result_t ray_intersect(const triangle_t triangle, const ray_t ray)
return result;
}
hit_result_t ray_intersect_closest(const triangle_collection_t* triangles, const ray_t ray)
hit_result_t ray_intersect_closest(const triangle_collection_t* triangles, ray_t ray)
{
hit_result_t closest_hit = {0};
closest_hit.distance = FLT_MAX;
@@ -98,7 +98,7 @@ hit_result_t ray_intersect_closest(const triangle_collection_t* triangles, const
return closest_hit;
}
hit_result_t ray_intersect_any(const triangle_collection_t* triangles, const ray_t ray)
hit_result_t ray_intersect_any(const triangle_collection_t* triangles, ray_t ray)
{
for (uint64_t i = 0; i < triangles->count; i++)
{

View File

@@ -8,8 +8,7 @@ mesh_entity_t mesh_load(const char* filename, uint8_t material_id, triangle_coll
{
mesh_entity_t entity = {0};
const C_STRUCT aiScene* scene = NULL;
scene = aiImportFile(filename,aiProcessPreset_TargetRealtime_MaxQuality);
const C_STRUCT aiScene* scene = aiImportFile(filename,aiProcessPreset_TargetRealtime_MaxQuality);
if (scene == NULL)
{
// fprintf(stderr, "Error loading mesh: %s\n", aiGetErrorString());
@@ -18,7 +17,7 @@ mesh_entity_t mesh_load(const char* filename, uint8_t material_id, triangle_coll
for (uint32_t i = 0; i < scene->mNumMeshes; i++)
{
const struct aiMesh* mesh = scene->mMeshes[i];
struct aiMesh* mesh = scene->mMeshes[i];
//TODO: Handle all mesh types, not just triangles
if (mesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE)
@@ -29,7 +28,7 @@ mesh_entity_t mesh_load(const char* filename, uint8_t material_id, triangle_coll
for (uint32_t j = 0; j < mesh->mNumFaces; j++)
{
const struct aiFace* face = &mesh->mFaces[j];
struct aiFace* face = &mesh->mFaces[j];
if (face->mNumIndices != 3)
{
// fprintf(stderr, "Face %llu in mesh %llu does not have 3 indices\n", j, i);

View File

@@ -1,41 +1,5 @@
#include "Geometry/Triangle.h"
triangle_collection_t triangle_collection_create(size_t size)
{
if (size > UINT64_MAX)
{
size = UINT64_MAX;
}
triangle_collection_t collection = {0};
collection.buffer = (triangle_t*)malloc(size * sizeof(triangle_t));
collection.size = (uint64_t)size;
return collection;
}
void triangle_collection_resize(triangle_collection_t* collection, size_t size)
{
if (size > UINT64_MAX)
{
size = UINT64_MAX;
}
triangle_t* temp = realloc(collection->buffer, size * sizeof(triangle_t));
if (temp != NULL)
{
collection->buffer = temp;
collection->size = (uint64_t)size;
}
}
void triangle_collection_free(triangle_collection_t* collection)
{
if (collection->buffer != NULL)
{
free(collection->buffer);
collection->buffer = NULL;
}
}
void triangle_create_with_normals(vec3s point1, vec3s point2, vec3s point3,
vec3s normal1, vec3s normal2, vec3s normal3,
uint8_t material_id, triangle_collection_t* collection)

View File

@@ -2,7 +2,7 @@
#include "Algorithm/RayIntersection.h"
#include "Algorithm/Sobol.h"
vec3s evaluate_bsdf_directional(const directional_light_t light, const light_shading_context_t* context, sobol_state_t* sobol_state)
vec3s evaluate_bsdf_directional( directional_light_t light, const light_shading_context_t* context, sobol_state_t* sobol_state)
{
float angular_radius = glm_rad(light.angular_diameter / 2.0f);
vec3s wi = random_cosine_direction_angular(light.direction, angular_radius, sobol_state);

View File

@@ -5,7 +5,7 @@
vec3s evaluate_bsdf_const_sky(const void* data, const light_shading_context_t* context, sobol_state_t* sobol_state)
{
const constant_sky_data_t sky_data = *(const constant_sky_data_t*)data;
constant_sky_data_t sky_data = *(const constant_sky_data_t*)data;
if (context == NULL)
{

View File

@@ -2,13 +2,13 @@
#include "Algorithm/BSDF.h"
#include <float.h>
static const float DIELECTRIC_REFLECTIVE_F0 = 0.04f; // Standard dielectric reflectivity coef at incident angle (= 4%)
static const vec3s DIELECTRIC_REFLECTIVE = {0.04f, 0.04f, 0.04f}; // Standard dielectric reflectivity coef at incident angle (= 4%)
static float DIELECTRIC_REFLECTIVE_F0 = 0.04f; // Standard dielectric reflectivity coef at incident angle (= 4%)
static vec3s DIELECTRIC_REFLECTIVE = {0.04f, 0.04f, 0.04f}; // Standard dielectric reflectivity coef at incident angle (= 4%)
// Simple lit, but keep it unbiased as much as possible
vec3s sample_bsdf_simple_lit(const void* data, const vec3s normal, const vec3s wo, sobol_state_t* sobol_state, float* pdf_out)
vec3s sample_bsdf_simple_lit(const void* data, vec3s normal, vec3s wo, sobol_state_t* sobol_state, float* pdf_out)
{
const simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
//TODO: having a bsdf data struct to avoid recomputing the same thing in both sample and evaluate
vec3s f0 = glms_vec3_lerp(DIELECTRIC_REFLECTIVE, shading_data.albedo, shading_data.metallic);
@@ -83,7 +83,7 @@ vec3s sample_bsdf_simple_lit(const void* data, const vec3s normal, const vec3s w
}
//TODO: Most of the calculation here is same as in sample_bsdf_simple_lit, we can optimize this by using a bsdf data struct to avoid recomputing the same thing in both sample and evaluate
float sample_bsdf_pdf_simple_lit(const void* data, const vec3s normal, const vec3s wo, const vec3s wi)
float sample_bsdf_pdf_simple_lit(const void* data, vec3s normal, vec3s wo, vec3s wi)
{
// If wi is below the horizon relative to the normal, PDF must be 0
if (glms_vec3_dot(normal, wi) <= 0.0f) // Use <= to be safe
@@ -91,7 +91,7 @@ float sample_bsdf_pdf_simple_lit(const void* data, const vec3s normal, const vec
return 0.0f;
}
const simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
// Again, we need bsdf data;
vec3s f0 = glms_vec3_lerp(DIELECTRIC_REFLECTIVE, shading_data.albedo, shading_data.metallic);
@@ -120,8 +120,8 @@ float sample_bsdf_pdf_simple_lit(const void* data, const vec3s normal, const vec
vec3s evaluate_bsdf_simple_lit(const shading_context_t* context, const void* data)
{
const simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
const shading_context_t shading_context = *context;
simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
shading_context_t shading_context = *context;
vec3s h = glms_vec3_normalize(glms_vec3_add(shading_context.wi, shading_context.wo));
float n_dot_l = fmaxf(FLT_EPSILON, glms_vec3_dot(shading_context.normal, shading_context.wi));

View File

@@ -3,27 +3,33 @@
#include <string.h>
#include <math.h>
render_target_t render_target_create(uint32_t width, uint32_t height)
bool render_target_init(uint32_t width, uint32_t height, render_target_t* render_target)
{
render_target_t target;
target.width = width;
target.height = height;
*render_target = (render_target_t){0};
render_target->width = width;
render_target->height = height;
size_t size_of_pixel = sizeof(vec4s);
size_t buffer_size = (size_t)width * height * size_of_pixel;
target.buffer = (vec4s*)malloc(buffer_size);
vec4s* buffer = (vec4s*)malloc(buffer_size);
if (buffer == NULL)
{
return false;
}
memset(target.buffer, 0, buffer_size);
memset(buffer, 0, buffer_size);
for (size_t i = 0; i < buffer_size / size_of_pixel; i++)
{
target.buffer[i].w = 1.0;
buffer[i].w = 1.0;
}
return target;
render_target->buffer = buffer;
return true;
}
vec4s render_target_get_pixel(render_target_t* render_target, uint32_t x, uint32_t y)
vec4s render_target_get_pixel(const render_target_t* render_target, uint32_t x, uint32_t y)
{
if (x < render_target->width && y < render_target->height)
{
@@ -47,6 +53,10 @@ unsigned char* render_target_to_char(render_target_t* render_target)
{
size_t buffer_size = (size_t)render_target->width * render_target->height * 4; // 4 bytes for RGBA
unsigned char* char_buffer = (unsigned char*)malloc(buffer_size);
if (char_buffer == NULL)
{
return NULL;
}
for (uint32_t y = 0; y < render_target->height; y++)
{

View File

@@ -3,26 +3,7 @@
#include "Rendering/Scene.h"
#include "Algorithm/PathTracing.h"
scene_t scene_create(const uint64_t triangle_count, const uint8_t material_count, const uint32_t punctual_light_count)
{
scene_t scene = {0};
scene.triangles = triangle_collection_create(triangle_count);
scene.materials = material_collection_create(material_count);
scene.lights = light_collection_create(punctual_light_count, 16); // NOTE: We just fixed the max directional light count to 16.
scene.camera = camera_create(
(vec3s){0.0f, 0.0f, 5.0f},
(vec3s){0.0f, 0.0f, -1.0f},
(vec3s){0.0f, 1.0f, 0.0f},
0.025f,
0.036f,
16.0f / 9.0f
);
return scene;
}
static inline void ensure_camera_aspect_ratio(camera_t* camera, const rendering_config_t config)
static inline void ensure_camera_aspect_ratio(camera_t* camera, rendering_config_t config)
{
if (fabsf((float)config.width / config.height - camera->aspect_ratio) > FLT_EPSILON)
{
@@ -49,7 +30,7 @@ static inline vec2s compute_ndc(float x, float y, uint32_t width, uint32_t heigh
};
}
static void screne_render_pixel(scene_t* scene, const rendering_config_t config, const vec3s coord, const uint32_t x, const uint32_t y, vec4s* pixel_color)
static void screne_render_pixel(scene_t* scene, rendering_config_t config, vec3s coord, uint32_t x, uint32_t y, vec4s* pixel_color)
{
vec4s accumulated_color = glms_vec4_zero();
*pixel_color = accumulated_color;
@@ -84,8 +65,8 @@ static void screne_render_pixel(scene_t* scene, const rendering_config_t config,
*pixel_color = glms_vec4_scale(accumulated_color, 1.0f / (float)config.sample_count);
}
bool scene_render_tile(scene_t* scene, rendering_context_t* ctx, render_target_t* render_target,
const rendering_config_t config, const uint32_t tile_index, tile_t* tile_out)
bool scene_render_tile(scene_t* scene, rendering_context_t* ctx, render_target_t* render_target,
rendering_config_t config, uint32_t tile_index, tile_t* tile_out)
{
if (ctx->is_done)
{
@@ -140,12 +121,19 @@ bool scene_render_tile(scene_t* scene, rendering_context_t* ctx, render_target_t
return true;
}
render_target_t scene_render(scene_t* scene, const rendering_config_t config)
bool scene_render(scene_t* scene, rendering_config_t config, render_target_t* render_target)
{
ensure_camera_aspect_ratio(&scene->camera, config);
// The actual float buffer inside the render target is on the heap, copy return shoudl be fine.
render_target_t render_target = render_target_create(config.width, config.height);
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;
@@ -173,17 +161,10 @@ render_target_t scene_render(scene_t* scene, const rendering_config_t config)
{
vec4s pixel_color;
screne_render_pixel(scene, config_copy, coord, (uint32_t)x, (uint32_t)y, &pixel_color);
render_target_set_pixel(&render_target, (uint32_t)x, (uint32_t)y, pixel_color);
render_target_set_pixel(render_target, (uint32_t)x, (uint32_t)y, pixel_color);
}
}
}
return render_target;
}
void scene_free(scene_t* scene)
{
triangle_collection_free(&scene->triangles);
material_collection_free(&scene->materials);
light_collection_free(&scene->lights);
return true;
}

View File

@@ -14,8 +14,7 @@ static LRESULT CALLBACK wndow_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
bitmap_info.bmiHeader.biBitCount = 32; // 32 bits per pixel (RGBA)
bitmap_info.bmiHeader.biCompression = BI_RGB;
bitmap = CreateDIBSection(hdc, &bitmap_info, DIB_RGB_COLORS,
(void**)&pixel_buffer, NULL, 0);
bitmap = CreateDIBSection(hdc, &bitmap_info, DIB_RGB_COLORS, (void**)&pixel_buffer, NULL, 0);
hdc_mem = CreateCompatibleDC(hdc);
SelectObject(hdc_mem, bitmap);
@@ -49,7 +48,7 @@ static LRESULT CALLBACK wndow_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lp
}
}
int window_create(const char* title, HINSTANCE hInst, const int width, const int height)
int window_create(const char* title, HINSTANCE hInst, int width, int height)
{
RECT rect = {0, 0, width, height};
AdjustWindowRect(&rect, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX, FALSE);
@@ -71,9 +70,8 @@ int window_create(const char* title, HINSTANCE hInst, const int width, const int
int pos_x = (screen_width - window_width) / 2;
int pos_y = (screen_height - window_height) / 2;
hwnd = CreateWindowEx(0, title, title, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE,
pos_x, pos_y, window_width, window_height,
NULL, NULL, wc.hInstance, NULL);
hwnd = CreateWindowEx(0, title, title, WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, pos_x, pos_y,
window_width, window_height, NULL, NULL, wc.hInstance, NULL);
if (!hwnd)
{
@@ -85,7 +83,7 @@ int window_create(const char* title, HINSTANCE hInst, const int width, const int
return 0;
}
void window_update_pixels(const vec4s color, const int pixel_x, const int pixel_y)
void window_update_pixels(vec4s color, int pixel_x, int pixel_y)
{
int pixel_index = (pixel_y * window_width + pixel_x) * 4;
@@ -96,7 +94,7 @@ void window_update_pixels(const vec4s color, const int pixel_x, const int pixel_
pixel_buffer[pixel_index + 3] = COLOR_CLAMP(color.w * 255.0f);
}
void window_refresh_region(const int pixel_x, const int pixel_y, const int region_width, const int region_height)
void window_refresh_region(int pixel_x, int pixel_y, int region_width, int region_height)
{
HDC hdc = GetDC(hwnd);
BitBlt(hdc, pixel_x, pixel_y, region_width, region_height, hdc_mem, pixel_x, pixel_y, SRCCOPY);

View File

@@ -9,7 +9,7 @@
#include "Geometry/GeometryUtilities.h"
#include "Window.h"
static void save_img(render_target_t* source, const uint32_t width, const uint32_t height, const char* filename)
static void save_img(render_target_t* source, uint32_t width, uint32_t height, const char* filename)
{
FILE* file_stream;
fopen_s(&file_stream, filename, "wb");
@@ -48,7 +48,11 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
omp_set_num_threads(16);
sobol_init();
scene_t scene = scene_create(64, 8, 4);
scene_t scene;
if (!scene_init(64, 8, 4, &scene))
{
return -1;
}
scene.camera.position = (vec3s){0.0f, 0.0f, 5.0f};
@@ -142,7 +146,8 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
#pragma endregion
render_target_t img = render_target_create(config.width, config.height);
render_target_t img;
render_target_init(config.width, config.height, &img);
// render_target_t img = scene_render(&scene, config);
// save_img(&img, config.width, config.height, "output.png");