Add texture handling and refactor material functions
Added a new function `blinn_phong_specular_exponent_to_roughness` in `BSDF.h` to convert a specular exponent to roughness. Added a `textures` member to the `shading_context_t` structure in `Material.h` for passing texture information during shading. Added a new member `textures` in the `light_shading_context_t` structure in `Light.h` to hold texture information. Added inline functions in `Texture.h` for handling texture entities, including `invalid_texture_entity`, `is_texture_entity_valid`, and `get_texture`. Changed the texture-related members in `simple_lit_properties_t` in `SimpleLit.h` from pointers to `texture_entity_t` to better manage texture entities. Changed the `sample_material_bsdf` and `sample_material_bsdf_pdf` functions in `Material.h` to accept a `shading_context_t` instead of individual parameters. Changed the `mesh_load` function in `Mesh.c` to use the new roughness calculation and texture entity handling. Changed the `path_trace` function in `PathTracing.c` to use the new structure and functions for handling materials and textures. Refactored the `sample_material_bsdf` and `sample_material_bsdf_pdf` functions in `Material.c` to utilize the new `shading_context_t` structure. Updated the `material_collection_init` function in `Material.h` to reflect changes in the material sampling functions. Updated the `evaluate_bsdf_directional` and `evaluate_bsdf_const_sky` functions to use the new shading context structure. Adjusted the `simple_lit_data_default` function in `SimpleLit.c` to work with the new texture handling approach. Added texture entity handling in `Texture.c` for managing invalid texture entities.
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
float power_heuristic(float pdf_a, float pdf_b);
|
||||
float roughness_to_blinn_phong_specular_exponent(float roughness);
|
||||
float blinn_phong_specular_exponent_to_roughness(float specular_exponent);
|
||||
vec3s fresnel_schlick_vec3(vec3s f0, float cos_theta);
|
||||
|
||||
// BSDF sampling functions
|
||||
|
||||
@@ -24,6 +24,7 @@ typedef struct
|
||||
|
||||
const bvh_tree_t* bvh_tree;
|
||||
const material_t* material;
|
||||
const texture_collection_t* textures;
|
||||
} light_shading_context_t;
|
||||
|
||||
#ifdef __STDC_ALIGN__
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "Algorithm/Sobol.h"
|
||||
#include "Common.h"
|
||||
#include "Rendering/Texture.h"
|
||||
|
||||
#define PROPERTY_SIZE 64
|
||||
#define INVALID_MATERIAL_ID 255
|
||||
@@ -14,6 +15,8 @@ typedef struct
|
||||
vec3s wi;
|
||||
vec3s wo;
|
||||
vec2s uv;
|
||||
|
||||
const texture_collection_t* textures;
|
||||
} shading_context_t;
|
||||
|
||||
typedef void (*compute_surface_data_f)(const shading_context_t* context, const void* properties, void* surface_data_out);
|
||||
@@ -53,8 +56,8 @@ void material_collection_free(material_collection_t* materials);
|
||||
|
||||
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);
|
||||
|
||||
vec3s sample_material_bsdf(const material_t* material, vec3s normal, vec3s wo, vec2s uv, uint32_t sample_index, uint32_t bounce, float* pdf_out);
|
||||
float sample_material_bsdf_pdf(const material_t* material, vec3s normal, vec3s wo, vec3s wi, vec2s uv);
|
||||
vec3s sample_material_bsdf(const material_t* material, const shading_context_t* context, uint32_t sample_index, uint32_t bounce, float* pdf_out);
|
||||
float sample_material_bsdf_pdf(const material_t* material, const shading_context_t* context);
|
||||
vec3s evaluate_material_bsdf(const material_t* material, const shading_context_t* context);
|
||||
|
||||
#endif // MATERIAL_H
|
||||
|
||||
@@ -18,9 +18,9 @@ typedef struct
|
||||
float roughness;
|
||||
float metallic;
|
||||
|
||||
const texture_t* albedo_texture;
|
||||
const texture_t* roughness_texture;
|
||||
const texture_t* metallic_texture;
|
||||
texture_entity_t albedo_texture;
|
||||
texture_entity_t roughness_texture;
|
||||
texture_entity_t metallic_texture;
|
||||
} simple_lit_properties_t;
|
||||
|
||||
void simple_lit_data_default(const shading_context_t* context, const void* properties, void* data_out);
|
||||
|
||||
@@ -50,4 +50,24 @@ texture_entity_t texture_load(const char* filename, bool srgb, texture_collectio
|
||||
vec4s texture_sample(const texture_t* texture, float u, float v);
|
||||
void texture_free(texture_t* texture);
|
||||
|
||||
inline texture_entity_t invalid_texture_entity()
|
||||
{
|
||||
return (texture_entity_t){.id = INVALID_TEXTURE_ID};
|
||||
}
|
||||
|
||||
inline bool is_texture_entity_valid(texture_entity_t entity)
|
||||
{
|
||||
return entity.id != INVALID_TEXTURE_ID;
|
||||
}
|
||||
|
||||
inline texture_t* get_texture(const texture_collection_t* textures, texture_entity_t entity)
|
||||
{
|
||||
if (entity.id >= textures->count || !is_texture_entity_valid(entity))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &textures->buffer[entity.id];
|
||||
}
|
||||
|
||||
#endif // TEXTURE_H
|
||||
|
||||
@@ -12,6 +12,11 @@ float roughness_to_blinn_phong_specular_exponent(float roughness)
|
||||
return glm_clamp(2.0f * 1.0f / (fmaxf(roughness * roughness, FLT_EPSILON)) - 2.0f, FLT_EPSILON, 1.0f / FLT_EPSILON);
|
||||
}
|
||||
|
||||
float blinn_phong_specular_exponent_to_roughness(float specular_exponent)
|
||||
{
|
||||
return sqrtf(2.0f / (specular_exponent + 2.0f));
|
||||
}
|
||||
|
||||
vec3s fresnel_schlick_vec3(vec3s f0, float cos_theta)
|
||||
{
|
||||
float x = 1.0f - cos_theta;
|
||||
|
||||
@@ -7,11 +7,6 @@
|
||||
// TODO: Split the diffuse and specular into different Monte Carlo, so we can decide the sample count for each one
|
||||
vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_t max_depth)
|
||||
{
|
||||
const triangle_collection_t* triangles = &scene->triangles;
|
||||
const bvh_tree_t* bvh_tree = &scene->bvh_tree;
|
||||
const material_collection_t* materials = &scene->materials;
|
||||
const light_collection_t* lights = &scene->lights;
|
||||
|
||||
vec4s accumulated_color = (vec4s){0.0f, 0.0f, 0.0f, 1.0f};
|
||||
vec3s throughput = glms_vec3_one();
|
||||
|
||||
@@ -39,7 +34,7 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
||||
}
|
||||
|
||||
// Add the emission of the hit material to the accumulated color
|
||||
material_t* hit_material = &materials->buffer[triangles->buffer[closest_hit.triangle_id].material_id];
|
||||
const material_t* hit_material = &scene->materials.buffer[scene->triangles.buffer[closest_hit.triangle_id].material_id];
|
||||
vec3s emission = hit_material->emission;
|
||||
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(glms_vec3_mul(throughput, emission), 0.0f));
|
||||
|
||||
@@ -51,15 +46,16 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
||||
|
||||
.bounce_depth = depth,
|
||||
|
||||
.bvh_tree = bvh_tree,
|
||||
.material = hit_material
|
||||
.bvh_tree = &scene->bvh_tree,
|
||||
.material = hit_material,
|
||||
.textures = &scene->textures,
|
||||
};
|
||||
|
||||
// Running the light loop.
|
||||
// TODO: Implementing other light types.
|
||||
for (uint32_t i = 0; i < lights->directional_light_count; i++)
|
||||
for (uint32_t i = 0; i < scene->lights.directional_light_count; i++)
|
||||
{
|
||||
vec3s l = evaluate_bsdf_directional(lights->directional_lights[i], &light_context, throughput, sample_index);
|
||||
vec3s l = evaluate_bsdf_directional(scene->lights.directional_lights[i], &light_context, throughput, sample_index);
|
||||
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(l, 0.0f));
|
||||
}
|
||||
|
||||
@@ -67,26 +63,28 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
||||
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(sky_light, 0.0f));
|
||||
|
||||
// Bounce and prepare for the next iteration
|
||||
vec3s wo = glms_vec3_negate(active_ray.direction); // We need to negate the direction of the incoming ray
|
||||
vec3s wi = sample_material_bsdf(hit_material, closest_hit.normal, wo, closest_hit.uv, sample_index, depth, &pdf_bsdf);
|
||||
shading_context_t shading_context = {
|
||||
.normal = closest_hit.normal,
|
||||
.position = closest_hit.point,
|
||||
.wo = glms_vec3_negate(active_ray.direction),
|
||||
.uv = closest_hit.uv,
|
||||
|
||||
.textures = &scene->textures,
|
||||
};
|
||||
|
||||
vec3s wi = sample_material_bsdf(hit_material, &shading_context, sample_index, depth, &pdf_bsdf);
|
||||
shading_context.wi = wi;
|
||||
if (pdf_bsdf <= 0.0f)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
shading_context_t shading_context = {
|
||||
.normal = closest_hit.normal,
|
||||
.position = closest_hit.point,
|
||||
.wi = wi,
|
||||
.wo = wo,
|
||||
.uv = closest_hit.uv,
|
||||
};
|
||||
vec3s bsdf = evaluate_material_bsdf(hit_material, &shading_context);
|
||||
float cos_theta = fmaxf(0.0f, glms_vec3_dot(wi, closest_hit.normal));
|
||||
|
||||
throughput = glms_vec3_mul(throughput, glms_vec3_scale(bsdf, cos_theta / pdf_bsdf));
|
||||
|
||||
// We do Russian roulette to decide whether to continue tracing or terminate the path
|
||||
// We do Russian roulette to decide whether to continue tracing or terminate the path
|
||||
if (depth > 1)
|
||||
{
|
||||
float q = fminf(glms_vec3_max(throughput), 0.95f);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "Geometry/Mesh.h"
|
||||
#include "ALgorithm/BSDF.h"
|
||||
#include "Common/String.h"
|
||||
#include "Material/SimpleLit.h"
|
||||
#include "assimp/cimport.h"
|
||||
@@ -26,10 +27,11 @@ mesh_entity_t mesh_load(const char* filename, scene_t* scene)
|
||||
struct aiColor4D base_color;
|
||||
aiGetMaterialColor(src, AI_MATKEY_COLOR_DIFFUSE, &base_color);
|
||||
|
||||
float smoothness = 0.5f;
|
||||
aiGetMaterialFloat(src, AI_MATKEY_SHININESS, &smoothness);
|
||||
float roughness = 0.5f;
|
||||
aiGetMaterialFloat(src, AI_MATKEY_SHININESS, &roughness);
|
||||
roughness = blinn_phong_specular_exponent_to_roughness(roughness);
|
||||
|
||||
texture_t* albedo_texture = NULL;
|
||||
texture_entity_t albedo_entity = invalid_texture_entity();
|
||||
if (aiGetMaterialTextureCount(src, aiTextureType_DIFFUSE) > 0)
|
||||
{
|
||||
struct aiString path;
|
||||
@@ -47,7 +49,7 @@ mesh_entity_t mesh_load(const char* filename, scene_t* scene)
|
||||
texture_entity_t entity = texture_load(path.data, true, &scene->textures);
|
||||
if (entity.id != INVALID_TEXTURE_ID)
|
||||
{
|
||||
albedo_texture = &scene->textures.buffer[entity.id];
|
||||
albedo_entity = entity;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -55,13 +57,14 @@ mesh_entity_t mesh_load(const char* filename, scene_t* scene)
|
||||
simple_lit_properties_t prop =
|
||||
{
|
||||
.albedo = {base_color.r, base_color.g, base_color.b},
|
||||
.roughness = 1.0f - smoothness,
|
||||
.roughness = roughness,
|
||||
.metallic = 0.0f,
|
||||
|
||||
.albedo_texture = albedo_texture,
|
||||
.albedo_texture = albedo_entity,
|
||||
};
|
||||
|
||||
material_create_simple_lit_default(&prop, &scene->materials);
|
||||
entity.material_count++;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mesh_scene->mNumMeshes; i++)
|
||||
|
||||
@@ -33,6 +33,8 @@ vec3s evaluate_bsdf_directional(directional_light_t light, const light_shading_c
|
||||
.wi = wi,
|
||||
.wo = glms_vec3_negate(context->wo),
|
||||
.uv = context->uv,
|
||||
|
||||
.textures = context->textures,
|
||||
};
|
||||
vec3s bsdf = evaluate_material_bsdf(context->material, &shading_context);
|
||||
|
||||
|
||||
@@ -34,13 +34,15 @@ vec3s evaluate_bsdf_const_sky(const void* data, const light_shading_context_t* c
|
||||
.wi = wi,
|
||||
.wo = glms_vec3_negate(context->wo),
|
||||
.uv = context->uv,
|
||||
|
||||
.textures = context->textures,
|
||||
};
|
||||
|
||||
vec3s bsdf = evaluate_material_bsdf(context->material, &shading_context);
|
||||
bsdf = glms_vec3_mul(bsdf, sky_color);
|
||||
float cos_theta = fmaxf(glms_vec3_dot(wi, context->normal), 0.0f);
|
||||
|
||||
float pdf_bsdf = sample_material_bsdf_pdf(context->material, shading_context.normal, shading_context.wo, shading_context.wi, context->uv);
|
||||
float pdf_bsdf = sample_material_bsdf_pdf(context->material, &shading_context);
|
||||
float weight = power_heuristic(pdf, pdf_bsdf);
|
||||
|
||||
vec3s env_contrib = glms_vec3_scale(glms_vec3_mul(throughput, bsdf), cos_theta / pdf);
|
||||
|
||||
@@ -71,36 +71,23 @@ material_entity_t material_create(const void* properties, size_t properties_size
|
||||
return entity;
|
||||
}
|
||||
|
||||
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 sample_material_bsdf(const material_t* material, const shading_context_t* context, uint32_t sample_index, uint32_t bounce, float* pdf_out)
|
||||
{
|
||||
vec3s wi = glms_vec3_zero();
|
||||
if (material->compute_surface_data != NULL && material->sample_bsdf != NULL)
|
||||
{
|
||||
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);
|
||||
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, vec2s uv)
|
||||
float sample_material_bsdf_pdf(const material_t* material, const shading_context_t* context)
|
||||
{
|
||||
float pdf = 0.0f;
|
||||
if (material->compute_surface_data != NULL && material->sample_bsdf_pdf != NULL)
|
||||
{
|
||||
shading_context_t context =
|
||||
{
|
||||
.normal = normal,
|
||||
.wo = wo,
|
||||
.wi = wi,
|
||||
.uv = uv,
|
||||
};
|
||||
pdf = material->sample_bsdf_pdf(&context, material->properties, material->compute_surface_data);
|
||||
pdf = material->sample_bsdf_pdf(context, material->properties, material->compute_surface_data);
|
||||
}
|
||||
|
||||
return pdf;
|
||||
|
||||
@@ -12,21 +12,27 @@ void simple_lit_data_default(const shading_context_t* context, const void* prope
|
||||
|
||||
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)
|
||||
|
||||
const texture_t* albedo_texture = get_texture(context->textures, prop->albedo_texture);
|
||||
if (albedo_texture != NULL && 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->albedo = glms_vec3_mul(data->albedo, glms_vec3(texture_sample(albedo_texture, context->uv.x, context->uv.y)));
|
||||
}
|
||||
|
||||
data->roughness = prop->roughness;
|
||||
if (prop->roughness_texture != NULL && prop->roughness_texture->data != NULL)
|
||||
|
||||
const texture_t* roughness_texture = get_texture(context->textures, prop->roughness_texture);
|
||||
if (roughness_texture != NULL && roughness_texture->data != NULL)
|
||||
{
|
||||
data->roughness = data->roughness * texture_sample(prop->roughness_texture, context->uv.x, context->uv.y).x;
|
||||
data->roughness = data->roughness * texture_sample(roughness_texture, context->uv.x, context->uv.y).x;
|
||||
}
|
||||
|
||||
data->metallic = prop->metallic;
|
||||
if (prop->metallic_texture != NULL && prop->metallic_texture->data != NULL)
|
||||
|
||||
const texture_t* metallic_texture = get_texture(context->textures, prop->metallic_texture);
|
||||
if (metallic_texture != NULL && metallic_texture->data != NULL)
|
||||
{
|
||||
data->metallic = data->metallic * texture_sample(prop->metallic_texture, context->uv.x, context->uv.y).x;
|
||||
data->metallic = data->metallic * texture_sample(metallic_texture, context->uv.x, context->uv.y).x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,11 +5,6 @@
|
||||
|
||||
#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};
|
||||
|
||||
Reference in New Issue
Block a user