diff --git a/src/main.c b/src/main.c index b6b7112..8ddf20e 100644 --- a/src/main.c +++ b/src/main.c @@ -595,9 +595,8 @@ Vector3 pixel(float x, float y, float aspect_ratio) assert(!isnanv(in_ray.direction)); //Vector3 sky_color = {0.6, 0.7, 0.9}; - Vector3 sky_color = {0, 0, 0}; + //Vector3 sky_color = {0, 0, 0}; //Vector3 sky_color = {1, 1, 1}; -0; Vector3 contrib = {1, 1, 1}; Vector3 result = {0, 0, 0}; @@ -605,7 +604,7 @@ Vector3 pixel(float x, float y, float aspect_ratio) HitInfo hit = trace_ray(in_ray); if (hit.object == -1) { - //Vector3 sky_color = sample_cubemap(&skybox, normalize(in_ray.direction)); + Vector3 sky_color = sample_cubemap(&skybox, normalize(in_ray.direction)); result = combine(result, mulv(sky_color, contrib), 1, 1); break; } @@ -615,24 +614,25 @@ Vector3 pixel(float x, float y, float aspect_ratio) if (objects[j].material.emission_power == 0 || j == hit.object) continue; Vector3 dir_to_light_source = combine(origin_of(objects[j]), hit.point, 1, -1); - // Add some noise based on roughness - Vector3 rand_dir = random_direction(); - if (dotv(rand_dir, hit.normal) < 0) - rand_dir = scale(rand_dir, -1); - dir_to_light_source = normalize(combine(rand_dir, dir_to_light_source, objects[j].material.roughness, 1)); - Ray ray_to_light_source = { combine(hit.point, dir_to_light_source, 1, 0.001), dir_to_light_source }; - HitInfo hit2 = trace_ray(ray_to_light_source); - if (hit2.object == j) { - sampled_light_color = scale(objects[hit2.object].material.emission_color, objects[hit2.object].material.emission_power); - break; + int samples = 5; + float spread = 0.5; + for (int k = 0; k < samples; k++) { + // Add some noise based on roughness + Vector3 rand_dir = random_direction(); + if (dotv(rand_dir, hit.normal) < 0) + rand_dir = scale(rand_dir, -1); + Vector3 sample_dir = normalize(combine(rand_dir, dir_to_light_source, spread, 1)); + Ray sample_ray = { combine(hit.point, sample_dir, 1, 0.001), sample_dir }; + HitInfo hit2 = trace_ray(sample_ray); + if (hit2.object != -1) + sampled_light_color = combine(sampled_light_color, objects[hit2.object].material.emission_color, 1, objects[hit2.object].material.emission_power); } + sampled_light_color = scale(sampled_light_color, 1.0f / samples); + break; } Material material = objects[hit.object].material; - float perceptualRoughness = maxf(material.roughness, 0.089); - float roughness = perceptualRoughness * perceptualRoughness; - Vector3 v = scale(in_ray.direction, -1); //Vector3 l = out_dir; Vector3 n = hit.normal; @@ -643,7 +643,7 @@ Vector3 pixel(float x, float y, float aspect_ratio) //float NoL = clamp(dotv(n, l), 0, 1); Vector3 f0_dielectric = vec_from_scalar(0.16 * material.reflectance * material.reflectance); - Vector3 f0_metal = material.albedo; + Vector3 f0_metal = material.albedo; Vector3 f0 = combine(f0_dielectric, f0_metal, (1 - material.metallic), material.metallic); Vector3 F = fresnelSchlick(NoV, f0); @@ -654,24 +654,18 @@ Vector3 pixel(float x, float y, float aspect_ratio) result = combine(result, mulv(scale(material.emission_color, material.emission_power), contrib), 1, 1); Vector3 out_dir; - if (random_float() < avgv(F)) { + if (material.metallic > 0.001 || random_float() <= avgv(F)) { // Specular ray Vector3 reflect_dir = reflect(in_ray.direction, scale(hit.normal, -1)); out_dir = normalize(combine(rand_dir, reflect_dir, material.roughness, 1)); - float NoL = dotv(n, out_dir); - float specular_contrib = 1.0f / (4.0 * NoV * NoL + 0.0001); - contrib = scale(contrib, specular_contrib); } else { // Diffuse ray - Vector3 diffuse_contrib = scale(material.albedo, (1 - material.metallic)); out_dir = rand_dir; - contrib = mulv(contrib, diffuse_contrib); + contrib = mulv(contrib, scale(material.albedo, (1 - material.metallic))); } - float NoL = dotv(n, out_dir); - contrib = scale(contrib, NoL); Ray out_ray = { combine(hit.point, out_dir, 1, 0.001), out_dir }; - float light_sample_weight = 0.1; + float light_sample_weight = 0.05; if (!iszerov(sampled_light_color)) { result = combine(result, mulv(sampled_light_color, contrib), 1, light_sample_weight); contrib = scale(contrib, 1 - light_sample_weight); @@ -832,6 +826,60 @@ int main(void) { #if 0 + add_object(sphere( + (Material) { + .emission_color={1, 1, 1}, + .emission_power=1, + .metallic=0, + .reflectance=0, + .roughness=0, + .albedo=(Vector3) {0.2, 0.5, 1}, + }, + (Vector3) {0, 2, 0}, + 1) + ); + + add_object(sphere( + (Material) { + .emission_color={0}, + .emission_power=0, + .metallic=0, + .reflectance=0, + .roughness=0, + .albedo=(Vector3) {0.2, 0.5, 1}, + }, + (Vector3) {0, 0, 3}, + 1) + ); + + add_object(sphere( + (Material) { + .emission_color={0}, + .emission_power=0, + .metallic=1, + .reflectance=0, + .roughness=0, + .albedo=(Vector3) {0.5, 0.2, 1}, + }, + (Vector3) {3, 0, 0}, + 1) + ); + +#elif 0 + + add_object(sphere( + (Material) { + .emission_color={0}, + .emission_power=0, + .metallic=0, + .reflectance=1, + .roughness=0, + .albedo=(Vector3) {0.2, 0.5, 1}, + }, + (Vector3) {-3, 0, 0}, + 1) + ); + add_object(sphere( (Material) { .emission_color={0}, @@ -960,7 +1008,7 @@ int main(void) add_object(cube( (Material) { .emission_color={1, 1, 1}, - .emission_power=3, + .emission_power=1, .metallic=0, .reflectance=0, .roughness=0, @@ -976,7 +1024,7 @@ int main(void) .emission_power=0, .metallic=1, .reflectance=0, - .roughness=0, + .roughness=0.5, .albedo=(Vector3) {0, 1, 0} }, (Vector3) {box_w/2, box_w/3, box_d/2}, @@ -995,10 +1043,10 @@ int main(void) add_object(cube ((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=0, .roughness=1, .albedo=(Vector3) {0.4, 0.3, 0.9}}, (Vector3) {0, -0.1, 0}, (Vector3) {9, 0.1, 9})); add_object(cube ((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=0, .roughness=1, .albedo=(Vector3) {1, 0, 0}}, (Vector3) {5, 0, 6}, (Vector3) {1, 1, 1})); - add_object(cube ((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=0, .roughness=0, .albedo=(Vector3) {1, 0, 1}}, (Vector3) {4, 0, 5}, (Vector3) {1, 1, 1})); + add_object(cube ((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=1, .roughness=0, .albedo=(Vector3) {1, 0, 1}}, (Vector3) {4, 0, 5}, (Vector3) {1, 1, 1})); add_object(sphere((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=0, .roughness=1, .albedo=(Vector3) {1, 0.4, 0}}, (Vector3) {3, 1, 3}, 1)); - add_object(sphere((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=0, .roughness=0, .albedo=(Vector3) {0, 1, 0}}, (Vector3) {5, 1, 3}, 1)); + add_object(sphere((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=1, .roughness=0, .albedo=(Vector3) {0, 1, 0}}, (Vector3) {5, 1, 3}, 1)); add_object(sphere((Material) {.emission_color={1, 0.5, 0.5}, .emission_power=5, .metallic=0, .reflectance=0, .roughness=1, .albedo=(Vector3) {1, 0.4, 0}}, (Vector3) {3, 5, 3}, 1)); #elif 1 // add_object(cube ((Material) {.emission_color={0}, .emission_power=0, .metallic=0, .reflectance=0, .roughness=0, .albedo=(Vector3) {1, 0.3, 0.3}}, (Vector3) {0, 0, 0}, (Vector3) {10, 5, 0.1}));