Update project roadmap and improve rendering logic
Changed the pixel rendering function to include anti-aliasing using Sobol sampling in Renderer.c. Changed the path tracing function to adjust light shading context and Russian roulette logic in PathTracing.c. Changed the normal calculation logic to use a ternary operator in RayIntersection.c. Changed the Sobol sample calculation for consistency in Debug.c. Removed some items from the project roadmap in README.md. Modified the sample count from 64 to 16 in main.c, affecting rendering quality and performance.
This commit is contained in:
@@ -56,6 +56,8 @@ If you have powershell installed, you can run the build.ps1 script in project ro
|
|||||||
|
|
||||||
## 🚧 Roadmap
|
## 🚧 Roadmap
|
||||||
|
|
||||||
|
- [ ] AOV support (e.g. normals, albedo, depth)
|
||||||
|
- [ ] Support for more complex materials (e.g. glass)
|
||||||
- [ ] Standardize light unit
|
- [ ] Standardize light unit
|
||||||
- [ ] General speed improvements
|
- [ ] General speed improvements
|
||||||
- [ ] Add GPU backend with CUDA
|
- [ ] Add GPU backend with CUDA
|
||||||
|
|||||||
15
header/Algorithm/ATrous.h
Normal file
15
header/Algorithm/ATrous.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef ATROUS_H
|
||||||
|
#define ATROUS_H
|
||||||
|
|
||||||
|
// TODO: Since a trous requires albedo and normal buffer, we may need to implement aov first.
|
||||||
|
|
||||||
|
const float kernel[5][5] =
|
||||||
|
{
|
||||||
|
{1.0f/256, 4.0f/256, 6.0f/256, 4.0f/256, 1.0f/256},
|
||||||
|
{4.0f/256,16.0f/256,24.0f/256,16.0f/256, 4.0f/256},
|
||||||
|
{6.0f/256,24.0f/256,36.0f/256,24.0f/256, 6.0f/256},
|
||||||
|
{4.0f/256,16.0f/256,24.0f/256,16.0f/256, 4.0f/256},
|
||||||
|
{1.0f/256, 4.0f/256, 6.0f/256, 4.0f/256, 1.0f/256}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ATROUS_H
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 1.9 MiB After Width: | Height: | Size: 7.1 MiB |
@@ -38,7 +38,8 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
|||||||
vec3s emission = hit_material->emission;
|
vec3s emission = hit_material->emission;
|
||||||
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(glms_vec3_mul(throughput, emission), 0.0f));
|
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(glms_vec3_mul(throughput, emission), 0.0f));
|
||||||
|
|
||||||
light_shading_context_t light_context = {
|
light_shading_context_t light_context =
|
||||||
|
{
|
||||||
.hit_point = closest_hit.point,
|
.hit_point = closest_hit.point,
|
||||||
.normal = closest_hit.normal,
|
.normal = closest_hit.normal,
|
||||||
.tangent = closest_hit.tangent,
|
.tangent = closest_hit.tangent,
|
||||||
@@ -64,7 +65,8 @@ 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));
|
accumulated_color = glms_vec4_add(accumulated_color, glms_vec4(sky_light, 0.0f));
|
||||||
|
|
||||||
// Bounce and prepare for the next iteration
|
// Bounce and prepare for the next iteration
|
||||||
shading_context_t shading_context = {
|
shading_context_t shading_context =
|
||||||
|
{
|
||||||
.position = closest_hit.point,
|
.position = closest_hit.point,
|
||||||
.normal = closest_hit.normal,
|
.normal = closest_hit.normal,
|
||||||
.tangent = closest_hit.tangent,
|
.tangent = closest_hit.tangent,
|
||||||
@@ -91,7 +93,6 @@ vec4s path_trace(const scene_t* scene, ray_t ray, uint32_t sample_index, uint16_
|
|||||||
{
|
{
|
||||||
float q = fminf(glms_vec3_max(throughput), 0.95f);
|
float q = fminf(glms_vec3_max(throughput), 0.95f);
|
||||||
float rr_sample = sobol_sample(sample_index, sobol_get_dimension(depth, PRNG_TERMINATE));
|
float rr_sample = sobol_sample(sample_index, sobol_get_dimension(depth, PRNG_TERMINATE));
|
||||||
// float rr_sample = random_float();
|
|
||||||
if (rr_sample > q)
|
if (rr_sample > q)
|
||||||
{
|
{
|
||||||
break; // Terminate the path
|
break; // Terminate the path
|
||||||
|
|||||||
@@ -213,17 +213,12 @@ hit_result_t ray_intersect_triangle(const ray_t* ray, const triangle_t* triangle
|
|||||||
vec3s normal = glms_vec3_scale(triangle->vertices[0].normal, w);
|
vec3s normal = glms_vec3_scale(triangle->vertices[0].normal, w);
|
||||||
normal = glms_vec3_add(normal, glms_vec3_scale(triangle->vertices[1].normal, u));
|
normal = glms_vec3_add(normal, glms_vec3_scale(triangle->vertices[1].normal, u));
|
||||||
normal = glms_vec3_add(normal, glms_vec3_scale(triangle->vertices[2].normal, v));
|
normal = glms_vec3_add(normal, glms_vec3_scale(triangle->vertices[2].normal, v));
|
||||||
if (glms_vec3_dot(normal, direction) > 0.0f)
|
normal = glms_vec3_dot(normal, direction) < 0.0f ? normal : glms_vec3_negate(normal);
|
||||||
{
|
|
||||||
normal = glms_vec3_negate(normal);
|
|
||||||
}
|
|
||||||
|
|
||||||
result.normal = glms_vec3_normalize(normal);
|
result.normal = glms_vec3_normalize(normal);
|
||||||
|
|
||||||
vec3s tangent = glms_vec3_scale(triangle->vertices[0].tangent, w);
|
vec3s tangent = glms_vec3_scale(triangle->vertices[0].tangent, w);
|
||||||
tangent = glms_vec3_add(tangent, glms_vec3_scale(triangle->vertices[1].tangent, u));
|
tangent = glms_vec3_add(tangent, glms_vec3_scale(triangle->vertices[1].tangent, u));
|
||||||
tangent = glms_vec3_add(tangent, glms_vec3_scale(triangle->vertices[2].tangent, v));
|
tangent = glms_vec3_add(tangent, glms_vec3_scale(triangle->vertices[2].tangent, v));
|
||||||
|
|
||||||
result.tangent = glms_vec3_normalize(tangent);
|
result.tangent = glms_vec3_normalize(tangent);
|
||||||
|
|
||||||
result.uv.x = w * triangle->vertices[0].uv.x
|
result.uv.x = w * triangle->vertices[0].uv.x
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ vec4s render_debug(scene_t* scene, ray_t ray, uint16_t sample_index, int flag)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
case DEBUG_SOBOL:
|
case DEBUG_SOBOL:
|
||||||
uint16_t i = sample_index ^ (sample_index >> 1);
|
float sobol_sample_value = sobol_sample(sample_index, 1); // Assuming dimension 0 for simplicity
|
||||||
float sobol_sample_value = sobol_sample(i, 1); // Assuming dimension 0 for simplicity
|
|
||||||
return (vec4s){sobol_sample_value, sobol_sample_value, sobol_sample_value, 1.0f};
|
return (vec4s){sobol_sample_value, sobol_sample_value, sobol_sample_value, 1.0f};
|
||||||
|
|
||||||
case DEBUG_UV:
|
case DEBUG_UV:
|
||||||
|
|||||||
@@ -43,17 +43,24 @@ static inline uint16_t get_sample_count(uint16_t sample_count, int flag)
|
|||||||
static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s coord, uint32_t x, uint32_t y, debug_flag_t flag, vec4s* pixel_color)
|
static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s coord, uint32_t x, uint32_t y, debug_flag_t flag, vec4s* pixel_color)
|
||||||
{
|
{
|
||||||
vec4s accumulated_color = glms_vec4_zero();
|
vec4s accumulated_color = glms_vec4_zero();
|
||||||
uint32_t pixel_id = y * config->width + x;
|
|
||||||
|
|
||||||
|
uint32_t pixel_id = y * config->width + x;
|
||||||
uint16_t sample_count = get_sample_count(config->sample_count, flag);
|
uint16_t sample_count = get_sample_count(config->sample_count, flag);
|
||||||
float inv_sample = 1.0f / (float)sample_count;
|
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_right = quat_get_right(scene->camera.rotation);
|
||||||
vec3s camera_up = quat_get_up(scene->camera.rotation);
|
vec3s camera_up = quat_get_up(scene->camera.rotation);
|
||||||
|
|
||||||
for (uint16_t k = 0; k < sample_count; k++)
|
for (uint16_t k = 0; k < sample_count; k++)
|
||||||
{
|
{
|
||||||
|
// TODO: Hash it
|
||||||
|
uint32_t sobol_idx = pixel_id * config->sample_count + (k + 1);
|
||||||
|
|
||||||
|
// Apply AA
|
||||||
|
float du = sobol_sample(sobol_idx, PRNG_FILTER_U);
|
||||||
|
float dv = sobol_sample(sobol_idx, PRNG_FILTER_V);
|
||||||
|
vec2s position_ndc = compute_ndc((float)x + du, (float)y + dv, config->width, config->height);
|
||||||
|
|
||||||
float screen_x = position_ndc.x * 2.0f - 1.0f;
|
float screen_x = position_ndc.x * 2.0f - 1.0f;
|
||||||
float screen_y = position_ndc.y * 2.0f - 1.0f;
|
float screen_y = position_ndc.y * 2.0f - 1.0f;
|
||||||
float sensor_offset_x = screen_x * scene->camera.size_x * 0.5f;
|
float sensor_offset_x = screen_x * scene->camera.size_x * 0.5f;
|
||||||
@@ -65,19 +72,7 @@ static void render_pixel(const rendering_config_t* config, scene_t* scene, vec3s
|
|||||||
|
|
||||||
ray_t ray = ray_create(scene->camera.position, 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();
|
vec4s out_color = flag == 0 ? path_trace(scene, ray, sobol_idx, config->max_depth) : render_debug(scene, ray, sobol_idx, flag);
|
||||||
|
|
||||||
if (flag != 0)
|
|
||||||
{
|
|
||||||
out_color = render_debug(scene, ray, k, flag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// TODO: Hash it
|
|
||||||
uint32_t sobol_idx = pixel_id * config->sample_count + (k + 1);
|
|
||||||
out_color = path_trace(scene, ray, sobol_idx, config->max_depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
accumulated_color = glms_vec4_add(accumulated_color, out_color);
|
accumulated_color = glms_vec4_add(accumulated_color, out_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ int WINAPI wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance,
|
|||||||
rendering_config_t config = {
|
rendering_config_t config = {
|
||||||
.width = 1920 / 2,
|
.width = 1920 / 2,
|
||||||
.height = 1080 / 2,
|
.height = 1080 / 2,
|
||||||
.sample_count = 64 * 1,
|
.sample_count = 16 * 1,
|
||||||
.max_depth = 4,
|
.max_depth = 4,
|
||||||
.bucket_size = 64,
|
.bucket_size = 64,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user