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:
2025-04-29 01:43:52 +09:00
parent 4db14ffdb0
commit 3de6b83d32
53 changed files with 8939 additions and 162671 deletions

View File

@@ -1,7 +1,9 @@
#include "Material/Material.h"
#include <string.h>
bool material_collection_init(size_t size, material_collection_t* materials)
bool material_collection_init(uint8_t size, material_collection_t* materials)
{
if (size > 254)
{
@@ -41,21 +43,12 @@ void material_collection_free(material_collection_t* materials)
{
if (materials->buffer != NULL)
{
for (uint8_t i = 0; i < materials->count; i++)
{
void* data = materials->buffer[i].data;
if (data != NULL)
{
free(data);
}
}
free(materials->buffer);
materials->buffer = NULL;
}
}
material_entity_t material_create(sample_bsdf_f sample, sample_bsdf_pdf_f sample_pdf, evaluate_bsdf_f evaluate, void* data, size_t size_of_data, material_collection_t* collection)
material_entity_t material_create(const void* properties, size_t properties_size, compute_surface_data_f surface_data, sample_bsdf_f sample, sample_bsdf_pdf_f sample_pdf, evaluate_bsdf_f evaluate, material_collection_t* collection)
{
material_t material = {0};
@@ -64,16 +57,11 @@ material_entity_t material_create(sample_bsdf_f sample, sample_bsdf_pdf_f sample
material_collection_resize(collection, collection->size * 2);
}
memcpy(material.properties, properties, properties_size);
material.compute_surface_data = surface_data;
material.sample_bsdf = sample;
material.sample_bsdf_pdf = sample_pdf;
material.evaluate_bsdf = evaluate;
material.data = malloc(size_of_data);
if (material.data == NULL)
{
return (material_entity_t){.id = 255};
}
memcpy(material.data, data, size_of_data);
material_entity_t entity = {.id = collection->count};
@@ -83,23 +71,36 @@ material_entity_t material_create(sample_bsdf_f sample, sample_bsdf_pdf_f sample
return entity;
}
vec3s sample_material_bsdf(const material_t* material, vec3s normal, vec3s wo, uint32_t sample_index, uint32_t bounce, float* pdf_out)
vec3s sample_material_bsdf(const material_t* material, vec3s normal, vec3s wo, vec2s uv, uint32_t sample_index, uint32_t bounce, float* pdf_out)
{
vec3s wi = glms_vec3_zero();
if (material->sample_bsdf != NULL)
if (material->compute_surface_data != NULL && material->sample_bsdf != NULL)
{
wi = material->sample_bsdf(material->data, normal, wo, sample_index, bounce, pdf_out);
shading_context_t context =
{
.normal = normal,
.wo = wo,
.uv = uv,
};
wi = material->sample_bsdf(&context, material->properties, material->compute_surface_data, sample_index, bounce, pdf_out);
}
return wi;
}
float sample_material_bsdf_pdf(const material_t* material, vec3s normal, vec3s wo, vec3s wi)
float sample_material_bsdf_pdf(const material_t* material, vec3s normal, vec3s wo, vec3s wi, vec2s uv)
{
float pdf = 0.0f;
if (material->sample_bsdf_pdf != NULL)
if (material->compute_surface_data != NULL && material->sample_bsdf_pdf != NULL)
{
pdf = material->sample_bsdf_pdf(material->data, normal, wo, wi);
shading_context_t context =
{
.normal = normal,
.wo = wo,
.wi = wi,
.uv = uv,
};
pdf = material->sample_bsdf_pdf(&context, material->properties, material->compute_surface_data);
}
return pdf;
@@ -108,9 +109,9 @@ float sample_material_bsdf_pdf(const material_t* material, vec3s normal, vec3s w
vec3s evaluate_material_bsdf(const material_t* material, const shading_context_t* context)
{
vec3s bsdf_color = glms_vec3_zero();
if (material->evaluate_bsdf != NULL)
if (material->compute_surface_data != NULL && material->evaluate_bsdf != NULL)
{
bsdf_color = material->evaluate_bsdf(context, material->data);
bsdf_color = material->evaluate_bsdf(context, material->properties, material->compute_surface_data);
}
return bsdf_color;

View File

@@ -6,14 +6,39 @@
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, vec3s normal, vec3s wo, uint32_t sample_index, uint32_t bounce, float* pdf_out)
void simple_lit_data_default(const shading_context_t* context, const void* properties, void* data_out)
{
simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
const simple_lit_properties_t* prop = (simple_lit_properties_t*)properties;
simple_lit_data_t* data = (simple_lit_data_t*)data_out;
data->albedo = prop->albedo;
if (prop->albedo_texture != NULL && prop->albedo_texture->data != NULL)
{
data->albedo = glms_vec3_mul(data->albedo, glms_vec3(texture_sample(prop->albedo_texture, context->uv.x, context->uv.y)));
}
data->roughness = prop->roughness;
if (prop->roughness_texture != NULL && prop->roughness_texture->data != NULL)
{
data->roughness = data->roughness * texture_sample(prop->roughness_texture, context->uv.x, context->uv.y).x;
}
data->metallic = prop->metallic;
if (prop->metallic_texture != NULL && prop->metallic_texture->data != NULL)
{
data->metallic = data->metallic * texture_sample(prop->metallic_texture, context->uv.x, context->uv.y).x;
}
}
// Simple lit, but keep it unbiased as much as possible
vec3s sample_bsdf_simple_lit(const shading_context_t* context, const void* properties, const compute_surface_data_f compute_surface_data, uint32_t sample_index, uint32_t bounce, float* pdf_out)
{
simple_lit_data_t shading_data;
compute_surface_data(context, properties, &shading_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);
float cos_theta_0 = fmaxf(glms_vec3_dot(normal, wo), 0.0f);
float cos_theta_0 = fmaxf(glms_vec3_dot(context->normal, context->wo), 0.0f);
vec3s f = fresnel_schlick_vec3(f0, cos_theta_0);
float lum_f = (f.x + f.y + f.z) / 3.0f;
@@ -38,7 +63,7 @@ vec3s sample_bsdf_simple_lit(const void* data, vec3s normal, vec3s wo, uint32_t
if (lob_sample < prob_diffuse) // Diffuse Lobe
{
wi = random_cosine_direction(normal, sample_index, d1, d2);
wi = random_cosine_direction(context->normal, sample_index, d1, d2);
}
else // Specular Lobe
{
@@ -61,11 +86,11 @@ vec3s sample_bsdf_simple_lit(const void* data, vec3s normal, vec3s wo, uint32_t
vec3s tangent_u; // World-space tangent (U)
vec3s bitangent_v; // World-space bitangent (V)
create_orthonormal_basis(normal, &tangent_u, &bitangent_v);
create_orthonormal_basis(context->normal, &tangent_u, &bitangent_v);
vec3s scaled_u = glms_vec3_scale(tangent_u, h_ts.x);
vec3s scaled_v = glms_vec3_scale(bitangent_v, h_ts.y);
vec3s scaled_n = glms_vec3_scale(normal, h_ts.z);
vec3s scaled_n = glms_vec3_scale(context->normal, h_ts.z);
// Transform h from tangent space to world space
vec3s h_ws;
@@ -74,37 +99,37 @@ vec3s sample_bsdf_simple_lit(const void* data, vec3s normal, vec3s wo, uint32_t
h_ws = glms_vec3_normalize(h_ws);
// wi is simple now, just reflect wo around normal
wi = glms_vec3_reflect(glms_vec3_negate(wo), h_ws);
wi = glms_vec3_reflect(glms_vec3_negate(context->wo), h_ws);
}
// Final check to ensure wi is in the correct hemisphere
if (glms_vec3_dot(wi, normal) < 0.0f)
if (glms_vec3_dot(wi, context->normal) < 0.0f)
{
*pdf_out = 0.0f;
return glms_vec3_zero();
}
float pdf_diffuse = pdf_cosine_weighted_hemisphere(normal, wi);
float pdf_specular = pdf_blinn_phong_lobe(normal, wi, wo, shading_data.roughness);
float pdf_diffuse = pdf_cosine_weighted_hemisphere(context->normal, wi);
float pdf_specular = pdf_blinn_phong_lobe(context->normal, wi, context->wo, shading_data.roughness);
*pdf_out = prob_diffuse * pdf_diffuse + prob_specular * pdf_specular;
return wi;
}
//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, vec3s normal, vec3s wo, vec3s wi)
float sample_bsdf_pdf_simple_lit(const shading_context_t* context, const void* properties, const compute_surface_data_f compute_surface_data)
{
// 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
if (glms_vec3_dot(context->normal, context->wi) <= 0.0f) // Use <= to be safe
{
return 0.0f;
}
simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
simple_lit_data_t shading_data;
compute_surface_data(context, properties, &shading_data);
// Again, we need bsdf data;
vec3s f0 = glms_vec3_lerp(DIELECTRIC_REFLECTIVE, shading_data.albedo, shading_data.metallic);
float cos_theta_o = fmaxf(glms_vec3_dot(normal, wo), 0.0f); // Use 'o' for outgoing (wo)
float cos_theta_o = fmaxf(glms_vec3_dot(context->normal, context->wo), 0.0f); // Use 'o' for outgoing (wo)
float F = glms_vec3_max(fresnel_schlick_vec3(f0, cos_theta_o));
float prob_specular = glm_lerp(F, 1.0f, shading_data.metallic);
@@ -118,25 +143,25 @@ float sample_bsdf_pdf_simple_lit(const void* data, vec3s normal, vec3s wo, vec3s
prob_diffuse /= total_prob;
prob_specular /= total_prob;
float pdf_diff = pdf_cosine_weighted_hemisphere(normal, wi);
float pdf_diff = pdf_cosine_weighted_hemisphere(context->normal, context->wi);
float diffuse_pdf_component = prob_diffuse * pdf_diff;
float pdf_spec = pdf_blinn_phong_lobe(normal, wo, wi, shading_data.roughness);
float pdf_spec = pdf_blinn_phong_lobe(context->normal, context->wo, context->wi, shading_data.roughness);
float specular_pdf_component = prob_specular * pdf_spec;
return diffuse_pdf_component + specular_pdf_component;
}
vec3s evaluate_bsdf_simple_lit(const shading_context_t* context, const void* data)
vec3s evaluate_bsdf_simple_lit(const shading_context_t* context, const void* properties, const compute_surface_data_f compute_surface_data)
{
simple_lit_data_t shading_data = *(const simple_lit_data_t*)data;
shading_context_t shading_context = *context;
simple_lit_data_t shading_data;
compute_surface_data(context, properties, &shading_data);
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));
float n_dot_v = fmaxf(FLT_EPSILON, glms_vec3_dot(shading_context.normal, shading_context.wo));
float n_dot_h = glms_vec3_dot(shading_context.normal, h);
float v_dot_h = glms_vec3_dot(shading_context.wo, h);
vec3s h = glms_vec3_normalize(glms_vec3_add(context->wi, context->wo));
float n_dot_l = fmaxf(FLT_EPSILON, glms_vec3_dot(context->normal, context->wi));
float n_dot_v = fmaxf(FLT_EPSILON, glms_vec3_dot(context->normal, context->wo));
float n_dot_h = glms_vec3_dot(context->normal, h);
float v_dot_h = glms_vec3_dot(context->wo, h);
vec3s f0 = glms_vec3_lerp(DIELECTRIC_REFLECTIVE, shading_data.albedo, shading_data.metallic);