Fixed cdf and added Standard Lit

This commit is contained in:
2025-12-29 22:01:44 +09:00
parent e1693764f7
commit adee5acd10
24 changed files with 830 additions and 570 deletions

View File

@@ -1,6 +1,6 @@
#include "ALgorithm/BSDF.h"
#include "cglm/util.h"
#include "cglm/struct/mat3.h"
#include "cglm/util.h"
float power_heuristic(float pdf_a, float pdf_b)
{
@@ -39,23 +39,39 @@ vec3s normal_unpack(vec3s normal)
vec3s normal_ts_to_ws(vec3s normal, vec3s geo_normal, vec3s tangent)
{
// 1. Sanitize inputs
tangent = glms_vec3_normalize(tangent);
vec3s bitangent = glms_vec3_cross(geo_normal, tangent);
float w = (glms_vec3_dot(glms_vec3_cross(geo_normal, tangent), bitangent) < 0.0f) ? -1.0f : +1.0f;
geo_normal = glms_vec3_normalize(geo_normal);
// 2. Gram-Schmidt with safety check
float proj = glms_vec3_dot(geo_normal, tangent);
vec3s t_prime = glms_vec3_normalize(glms_vec3_sub(tangent, glms_vec3_scale(geo_normal, proj)));
vec3s b_prime = glms_vec3_scale(glms_vec3_cross(geo_normal, t_prime), w);
vec3s t_prime_unorm = glms_vec3_sub(tangent, glms_vec3_scale(geo_normal, proj));
// Matrix in cglm is column-major, not row-major
mat3s tbn =
// SAFETY: If tangent is parallel to normal, t_prime is zero.
// Fallback to original tangent or arbitrary axis to avoid NaN.
if (glms_vec3_norm2(t_prime_unorm) < FLT_EPSILON)
{
t_prime.x, t_prime.y, t_prime.z,
b_prime.x, b_prime.y, b_prime.z,
geo_normal.x, geo_normal.y, geo_normal.z
};
t_prime_unorm = tangent;
// If tangent was also bad, pick an arbitrary axis
if (glms_vec3_norm2(t_prime_unorm) < FLT_EPSILON)
{
create_orthonormal_basis(geo_normal, &t_prime_unorm, &tangent); // Recycle variable
}
}
vec3s t_prime = glms_vec3_normalize(t_prime_unorm);
// 3. Calculate Bitangent
vec3s b_prime = glms_vec3_cross(geo_normal, t_prime);
// 4. Apply Tangent Handedness (w)
// NOTE: Check if tangent W component is stored/passed correctly.
// If not sure, assuming 1.0 is safer than calculating it from cross products of unnormalized vectors.
float w = (glms_vec3_dot(glms_vec3_cross(geo_normal, tangent), b_prime) < 0.0f) ? -1.0f : 1.0f;
b_prime = glms_vec3_scale(b_prime, w);
mat3s tbn = {t_prime.x, t_prime.y, t_prime.z, b_prime.x, b_prime.y, b_prime.z, geo_normal.x, geo_normal.y, geo_normal.z};
// 5. Transform and Re-normalize
return glms_vec3_normalize(glms_mat3_mulv(tbn, normal));
}
@@ -104,10 +120,10 @@ float pdf_blinn_phong_lobe(vec3s normal, vec3s wi, vec3s wo, float roughness)
return pdf_spec;
}
vec3s sample_cosine_weighted_hemisphere_z_angular(float angular, uint32_t index, uint32_t d1, uint32_t d2)
vec3s sample_cosine_weighted_hemisphere_z_angular(float angular, uint32_t index, uint16_t d1, uint16_t d2, uint32_t scramble)
{
float r1 = sobol_sample(index, d1);
float r2 = sobol_sample(index, d2);
float r1 = sobol_sample_scrambled(index, d1, scramble);
float r2 = sobol_sample_scrambled(index, d2, scramble);
float phi = 2.0f * PI * r1;
@@ -128,10 +144,10 @@ vec3s sample_cosine_weighted_hemisphere_z_angular(float angular, uint32_t index,
// Function to generate a direction with cosine weighting around (0, 0, 1)
// This is the local coordinate sample.
vec3s sample_cosine_weighted_hemisphere_z(uint32_t index, uint32_t d1, uint32_t d2)
vec3s sample_cosine_weighted_hemisphere_z(uint32_t index, uint16_t d1, uint16_t d2, uint32_t scramble)
{
float r1 = sobol_sample(index, d1);
float r2 = sobol_sample(index, d2);
float r1 = sobol_sample_scrambled(index, d1, scramble);
float r2 = sobol_sample_scrambled(index, d2, scramble);
float r = sqrtf(r1);
float phi = 2.0f * PI * r2;
@@ -155,20 +171,20 @@ void create_orthonormal_basis(vec3s direction, vec3s* u, vec3s* v)
vec3s a;
if (fabsf(direction.x) > 0.9f)
{
a = (vec3s){{0.0f, 1.0f, 0.0f}}; // Use y-axis
a = (vec3s){0.0f, 1.0f, 0.0f}; // Use y-axis
}
else
{
a = (vec3s){{1.0f, 0.0f, 0.0f}}; // Use x-axis
a = (vec3s){1.0f, 0.0f, 0.0f}; // Use x-axis
}
*u = glms_vec3_normalize(glms_vec3_cross(a, direction));
*v = glms_vec3_normalize(glms_vec3_cross(direction, *u));
}
vec3s random_cosine_direction_angular(vec3s direction, float angular, uint32_t index, uint32_t d1, uint32_t d2)
vec3s random_cosine_direction_angular(vec3s direction, float angular, uint32_t index, uint32_t d1, uint32_t d2, uint32_t scramble)
{
vec3s local_dir = sample_cosine_weighted_hemisphere_z_angular(angular, index, d1, d2);
vec3s local_dir = sample_cosine_weighted_hemisphere_z_angular(angular, index, d1, d2, scramble);
vec3s u, v;
create_orthonormal_basis(direction, &u, &v);
@@ -184,9 +200,9 @@ vec3s random_cosine_direction_angular(vec3s direction, float angular, uint32_t i
// Samples a direction from the hemisphere oriented along 'normal'
// with a cosine-weighted distribution.
vec3s random_cosine_direction(vec3s direction, uint32_t index, uint32_t d1, uint32_t d2)
vec3s random_cosine_direction(vec3s direction, uint32_t index, uint32_t d1, uint32_t d2, uint32_t scramble)
{
vec3s local_dir = sample_cosine_weighted_hemisphere_z(index, d1, d2);
vec3s local_dir = sample_cosine_weighted_hemisphere_z(index, d1, d2, scramble);
vec3s u, v;
create_orthonormal_basis(direction, &u, &v);
@@ -199,10 +215,10 @@ vec3s random_cosine_direction(vec3s direction, uint32_t index, uint32_t d1, uint
return world_dir;
}
vec3s random_uniform_cdf_direction(vec3s direction, uint32_t index, uint32_t d1, uint32_t d2)
vec3s random_uniform_cdf_direction(vec3s direction, uint32_t index, uint16_t d1, uint16_t d2, uint32_t scramble)
{
float r1 = sobol_sample(index, d1);
float r2 = sobol_sample(index, d2);
float r1 = sobol_sample_scrambled(index, d1, scramble);
float r2 = sobol_sample_scrambled(index, d2, scramble);
float phi = 2.0f * PI * r1;
float cos_theta = 1.0f - r2 * 2.0f;
@@ -223,10 +239,10 @@ vec3s random_uniform_cdf_direction(vec3s direction, uint32_t index, uint32_t d1,
return world_dir;
}
vec3s random_uniform_cdf_direction_angular(vec3s direction, uint32_t index, float angular, uint32_t d1, uint32_t d2)
vec3s random_uniform_cdf_direction_angular(vec3s direction, uint32_t index, float angular, uint16_t d1, uint16_t d2, uint32_t scramble)
{
float r1 = sobol_sample(index, d1);
float r2 = sobol_sample(index, d2);
float r1 = sobol_sample_scrambled(index, d1, scramble);
float r2 = sobol_sample_scrambled(index, d2, scramble);
float cos_alpha = cosf(angular);
float cos_theta = 1.0f - r1 * (1.0f - cos_alpha);
@@ -249,11 +265,10 @@ vec3s random_uniform_cdf_direction_angular(vec3s direction, uint32_t index, floa
return world_dir;
}
// Must use this function to weight any nee light contribution before accumulate.
vec3s weight_nee_light(vec3s bsdf, vec3s light, float pdf_bsdf, float pdf_sky)
{
light = glms_vec3_mul(bsdf, light);
float weight = power_heuristic(pdf_sky, pdf_bsdf);
return glms_vec3_scale(light, weight);
}
}