Set C standard to C11 and add new assets
Changed CMakeLists.txt to set the C standard to C11. Added multiple binary image files for new visual assets. Added several new image files to enhance rendering capabilities. Changed stb_image.h to improve support for various image formats. Changed ray tracing engine to enhance ray creation and intersection. Changed triangle structure to use a vertex array for better attribute handling. Changed scene initialization to accommodate new texture management.
This commit is contained in:
@@ -14,4 +14,4 @@ camera_t camera_create(vec3s position, versors rotation, float focal_length, flo
|
||||
};
|
||||
|
||||
return camera;
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ static void ray_intersect_bvh_count(ray_t ray, bvh_tree_t bvh_tree, uint64_t nod
|
||||
const bvh_node_t* node = &bvh_tree.nodes[node_index];
|
||||
|
||||
float enter, exit;
|
||||
if (!ray_intersect_aabb(ray, node->bounds, &enter, &exit))
|
||||
if (!ray_intersect_aabb(&ray, node->bounds, &enter, &exit))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -33,11 +33,9 @@ static void ray_intersect_bvh_count(ray_t ray, bvh_tree_t bvh_tree, uint64_t nod
|
||||
|
||||
vec4s render_debug(scene_t* scene, ray_t ray, uint16_t sample_index, int flag)
|
||||
{
|
||||
vec4s result = glms_vec4_zero();
|
||||
|
||||
if (scene == NULL)
|
||||
{
|
||||
return result;
|
||||
return glms_vec4_zero();
|
||||
}
|
||||
|
||||
switch (flag & 0xFF)
|
||||
@@ -46,20 +44,23 @@ vec4s render_debug(scene_t* scene, ray_t ray, uint16_t sample_index, int flag)
|
||||
uint32_t count = 0;
|
||||
ray_intersect_bvh_count(ray, scene->bvh_tree, 0, &count);
|
||||
|
||||
vec4s result = glms_vec4_zero();
|
||||
for (uint32_t i = 0; i < count; i++)
|
||||
{
|
||||
result = glms_vec4_add(result, DEBUG_COLOR_BVH);
|
||||
}
|
||||
return result;
|
||||
|
||||
break;
|
||||
case DEBUG_SOBOL:
|
||||
uint16_t i = sample_index ^ (sample_index >> 1);
|
||||
float sobol_sample_value = sobol_sample(i, 1); // Assuming dimension 0 for simplicity
|
||||
result = glms_vec4_add(result, (vec4s){sobol_sample_value, sobol_sample_value, sobol_sample_value, 1.0f});
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (vec4s){sobol_sample_value, sobol_sample_value, sobol_sample_value, 1.0f};
|
||||
|
||||
return result;
|
||||
case DEBUG_UV:
|
||||
hit_result_t hit_result = ray_intersect_scene(&ray, scene);
|
||||
return (vec4s){fmodf(fabsf(hit_result.uv.x), 1.0f), fmodf(fabsf(hit_result.uv.y), 1.0f), 0.0f, 1.0f};
|
||||
|
||||
default:
|
||||
return glms_vec4_zero();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,8 @@ unsigned char* render_target_to_char(render_target_t* render_target)
|
||||
|
||||
void render_target_free(render_target_t* target)
|
||||
{
|
||||
if (target->buffer != NULL)
|
||||
if (target != NULL && target->buffer != NULL)
|
||||
{
|
||||
free(target->buffer);
|
||||
target->buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ static inline uint16_t get_sample_count(uint16_t sample_count, int flag)
|
||||
{
|
||||
case DEBUG_BVH:
|
||||
case DEBUG_SOBOL:
|
||||
case DEBUG_UV:
|
||||
return 1;
|
||||
default:
|
||||
return sample_count;
|
||||
@@ -45,6 +46,8 @@ static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s
|
||||
uint32_t pixel_id = y * config->width + x;
|
||||
|
||||
uint16_t sample_count = get_sample_count(config->sample_count, flag);
|
||||
float inv_sample = 1.0f / (float)sample_count;
|
||||
|
||||
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);
|
||||
@@ -60,10 +63,7 @@ static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s
|
||||
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))
|
||||
};
|
||||
ray_t ray = ray_create(scene->camera.position, glms_vec3_normalize(glms_vec3_sub(image_plane_point, scene->camera.position)));
|
||||
|
||||
vec4s out_color = glms_vec4_zero();
|
||||
|
||||
@@ -81,7 +81,7 @@ static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s
|
||||
accumulated_color = glms_vec4_add(accumulated_color, out_color);
|
||||
}
|
||||
|
||||
*pixel_color = glms_vec4_scale(accumulated_color, 1.0f / (float)sample_count);
|
||||
*pixel_color = glms_vec4_scale(accumulated_color, inv_sample);
|
||||
}
|
||||
|
||||
// TODO: Progressive rendering
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
#include "Rendering/Scene.h"
|
||||
|
||||
bool scene_init(scene_t* scene, uint64_t triangle_count, uint8_t material_count, uint32_t punctual_light_count)
|
||||
bool scene_init(scene_t* scene, uint64_t triangle_count, uint16_t texture_count, uint8_t material_count, uint32_t punctual_light_count)
|
||||
{
|
||||
scene_t temp = {0};
|
||||
|
||||
if (!triangle_collection_init(&temp.triangles, triangle_count))
|
||||
if (!triangle_collection_init(triangle_count, &temp.triangles))
|
||||
{
|
||||
goto triangle_failed;
|
||||
}
|
||||
|
||||
if (!texture_collection_init(texture_count, &temp.textures))
|
||||
{
|
||||
goto texture_failed;
|
||||
}
|
||||
|
||||
if (!material_collection_init(material_count, &temp.materials))
|
||||
{
|
||||
goto material_failed;
|
||||
@@ -33,6 +38,8 @@ bool scene_init(scene_t* scene, uint64_t triangle_count, uint8_t material_count,
|
||||
light_failed:
|
||||
material_collection_free(&temp.materials);
|
||||
material_failed:
|
||||
texture_collection_free(&temp.textures);
|
||||
texture_failed:
|
||||
triangle_collection_free(&temp.triangles);
|
||||
triangle_failed:
|
||||
return false;
|
||||
@@ -58,8 +65,14 @@ bool scene_build_bvh(scene_t* scene)
|
||||
|
||||
void scene_free(scene_t* scene)
|
||||
{
|
||||
if (scene == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bvh_tree_free(&scene->bvh_tree);
|
||||
triangle_collection_free(&scene->triangles);
|
||||
texture_collection_free(&scene->textures);
|
||||
material_collection_free(&scene->materials);
|
||||
light_collection_free(&scene->lights);
|
||||
}
|
||||
|
||||
198
source/Rendering/Texture.c
Normal file
198
source/Rendering/Texture.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#include "Rendering/Texture.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
#define GET_CHANNEL_DATA(pixel, channel, channel_count, default) (channel < channel_count ? pixel[channel] : default) / 255.0f
|
||||
|
||||
static inline texture_entity_t invalid_texture_entity()
|
||||
{
|
||||
return (texture_entity_t){.id = INVALID_TEXTURE_ID};
|
||||
}
|
||||
|
||||
bool texture_collection_init(uint16_t size, texture_collection_t* textures)
|
||||
{
|
||||
texture_collection_t temp = {0};
|
||||
temp.buffer = (texture_t*)malloc(size * sizeof(texture_t));
|
||||
if (temp.buffer == NULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
temp.size = size;
|
||||
temp.count = 0;
|
||||
*textures = temp;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void texture_collection_resize(texture_collection_t* textures, uint16_t size)
|
||||
{
|
||||
texture_t* temp = (texture_t*)realloc(textures->buffer, size * sizeof(texture_t));
|
||||
if (temp != NULL)
|
||||
{
|
||||
textures->buffer = temp;
|
||||
textures->size = size;
|
||||
}
|
||||
}
|
||||
|
||||
void texture_collection_free(texture_collection_t* textures)
|
||||
{
|
||||
if (textures == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < textures->count; i++)
|
||||
{
|
||||
texture_free(&textures->buffer[i]);
|
||||
}
|
||||
|
||||
free(textures->buffer);
|
||||
textures->buffer = NULL;
|
||||
}
|
||||
|
||||
texture_entity_t texture_load(const char* filename, bool srgb, texture_collection_t* textures)
|
||||
{
|
||||
int width, height, channels;
|
||||
uint8_t* data = stbi_load(filename, &width, &height, &channels, 0);
|
||||
if (data == NULL)
|
||||
{
|
||||
return invalid_texture_entity();
|
||||
}
|
||||
|
||||
if (srgb)
|
||||
{
|
||||
// Convert to linear space if the texture is in sRGB format
|
||||
for (int i = 0; i < width * height * channels; i++)
|
||||
{
|
||||
data[i] = (uint8_t)(powf(data[i] / 255.0f, 2.2f) * 255.0f);
|
||||
}
|
||||
}
|
||||
|
||||
texture_t texture = {0};
|
||||
texture.width = (uint32_t)width;
|
||||
texture.height = (uint32_t)height;
|
||||
texture.channel_count = (uint8_t)channels;
|
||||
texture.data = data;
|
||||
texture.wrap_mode = REPEAT;
|
||||
texture.filter_mode = LINEAR;
|
||||
|
||||
if (textures->count >= textures->size)
|
||||
{
|
||||
texture_collection_resize(textures, textures->size * 2);
|
||||
}
|
||||
|
||||
texture_entity_t entity = {.id = textures->count};
|
||||
|
||||
textures->buffer[textures->count] = texture;
|
||||
textures->count++;
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
static inline void warp_uv(wrap_mode_t mode, float* u, float* v)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case REPEAT:
|
||||
*u = fmodf(fabsf(*u), 1.0f);
|
||||
*v = fmodf(fabsf(*v), 1.0f);
|
||||
break;
|
||||
case CLAMP:
|
||||
*u = fminf(fmaxf(*u, 0.0f), 1.0f);
|
||||
*v = fminf(fmaxf(*v, 0.0f), 1.0f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static vec4s get_pixel_color(const texture_t* texture, uint32_t x, uint32_t y)
|
||||
{
|
||||
uint32_t pixel_index = y * texture->width + x;
|
||||
if (pixel_index >= texture->width * texture->height)
|
||||
{
|
||||
return (vec4s){0.0f, 0.0f, 0.0f, 1.0f};
|
||||
}
|
||||
|
||||
uint8_t* pixel = &texture->data[pixel_index * texture->channel_count];
|
||||
return (vec4s)
|
||||
{
|
||||
GET_CHANNEL_DATA(pixel, 0, texture->channel_count, 0),
|
||||
GET_CHANNEL_DATA(pixel, 1, texture->channel_count, 0),
|
||||
GET_CHANNEL_DATA(pixel, 2, texture->channel_count, 0),
|
||||
GET_CHANNEL_DATA(pixel, 3, texture->channel_count, 1)
|
||||
};
|
||||
}
|
||||
|
||||
static vec4s nearest_filter(const texture_t* texture, float u, float v)
|
||||
{
|
||||
uint32_t x = (uint32_t)floorf(u * (texture->width - 1));
|
||||
uint32_t y = (uint32_t)floorf(v * (texture->height - 1));
|
||||
|
||||
x = x < texture->width ? x : texture->width - 1;
|
||||
y = y < texture->height ? y : texture->height - 1;
|
||||
|
||||
return get_pixel_color(texture, x, y);
|
||||
}
|
||||
|
||||
static vec4s linear_filter(const texture_t* texture, float u, float v)
|
||||
{
|
||||
float x = u * (texture->width - 1);
|
||||
float y = v * (texture->height - 1);
|
||||
|
||||
uint32_t x0 = (uint32_t)floorf(x);
|
||||
uint32_t x1 = x0 + 1;
|
||||
uint32_t y0 = (uint32_t)floorf(y);
|
||||
uint32_t y1 = y0 + 1;
|
||||
|
||||
float sx = x - (float)x0;
|
||||
float sy = y - (float)y0;
|
||||
|
||||
// Clamp to edges
|
||||
x0 = x0 < texture->width ? x0 : texture->width - 1;
|
||||
x1 = x1 < texture->width ? x1 : texture->width - 1;
|
||||
y0 = y0 < texture->height ? y0 : texture->height - 1;
|
||||
y1 = y1 < texture->height ? y1 : texture->height - 1;
|
||||
|
||||
// Sample 4 texels
|
||||
vec4s c00 = get_pixel_color(texture, x0, y0);
|
||||
vec4s c10 = get_pixel_color(texture, x1, y0);
|
||||
vec4s c01 = get_pixel_color(texture, x0, y1);
|
||||
vec4s c11 = get_pixel_color(texture, x1, y1);
|
||||
|
||||
// Interpolate along x
|
||||
vec4s c0 = glms_vec4_lerp(c00, c10, sx);
|
||||
vec4s c1 = glms_vec4_lerp(c01, c11, sx);
|
||||
|
||||
// Interpolate along y
|
||||
vec4s result = glms_vec4_lerp(c0, c1, sy);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline vec4s filter_texture(const texture_t* texture, float u, float v)
|
||||
{
|
||||
switch (texture->filter_mode)
|
||||
{
|
||||
case NEAREST:
|
||||
return nearest_filter(texture, u, v);
|
||||
case LINEAR:
|
||||
return linear_filter(texture, u, v);
|
||||
default:
|
||||
return (vec4s){0.0f, 0.0f, 0.0f, 1.0f};
|
||||
}
|
||||
}
|
||||
|
||||
vec4s texture_sample(const texture_t* texture, float u, float v)
|
||||
{
|
||||
warp_uv(texture->wrap_mode, &u, &v);
|
||||
return filter_texture(texture, u, v);
|
||||
}
|
||||
|
||||
void texture_free(texture_t* texture)
|
||||
{
|
||||
if (texture != NULL && texture->data != NULL)
|
||||
{
|
||||
stbi_image_free(texture->data);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user