feat&fix: 优化shaders
- fix: 修复raytracing.comp random_in_unit_sphere()死循环 - fix: 合并raytracing.comp相机光线生成函数 - feat: 将denoiser.comp修改为双边滤波降噪 - chore: 格式化shader注释master
parent
687a79b526
commit
d7f5c7e5cc
Binary file not shown.
|
|
@ -7,22 +7,47 @@ layout(binding = 1, rgba32f) uniform writeonly image2D u_output;
|
|||
|
||||
uniform int u_radius; // 1 => 3x3, 2 => 5x5
|
||||
|
||||
// Gaussian weight based on distance
|
||||
float gaussian_weight(float dist, float sigma) {
|
||||
return exp(-0.5 * dist * dist / (sigma * sigma));
|
||||
}
|
||||
|
||||
// Bilateral filter: considers both spatial distance and color similarity
|
||||
void main() {
|
||||
ivec2 p = ivec2(gl_GlobalInvocationID.xy);
|
||||
ivec2 size = imageSize(u_output);
|
||||
if (p.x >= size.x || p.y >= size.y) return;
|
||||
|
||||
vec3 center_color = imageLoad(u_input, p).rgb;
|
||||
|
||||
// Sigma values for bilateral filter
|
||||
float sigma_space = float(u_radius); // spatial sigma
|
||||
float sigma_color = 0.3; // color sigma (adjust for more/less smoothing)
|
||||
|
||||
vec3 sum = vec3(0.0);
|
||||
int count = 0;
|
||||
float weight_sum = 0.0;
|
||||
|
||||
for (int dy = -u_radius; dy <= u_radius; ++dy) {
|
||||
for (int dx = -u_radius; dx <= u_radius; ++dx) {
|
||||
ivec2 q = clamp(p + ivec2(dx, dy), ivec2(0), size - ivec2(1));
|
||||
sum += imageLoad(u_input, q).rgb;
|
||||
count += 1;
|
||||
vec3 sample_color = imageLoad(u_input, q).rgb;
|
||||
|
||||
// Spatial weight (Gaussian based on distance)
|
||||
float spatial_dist = length(vec2(float(dx), float(dy)));
|
||||
float spatial_weight = gaussian_weight(spatial_dist, sigma_space);
|
||||
|
||||
// Color weight (Gaussian based on color difference)
|
||||
float color_dist = length(sample_color - center_color);
|
||||
float color_weight = gaussian_weight(color_dist, sigma_color);
|
||||
|
||||
// Combined bilateral weight
|
||||
float weight = spatial_weight * color_weight;
|
||||
|
||||
sum += sample_color * weight;
|
||||
weight_sum += weight;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 out_color = sum / float(count);
|
||||
vec3 out_color = sum / max(weight_sum, 1e-6);
|
||||
imageStore(u_output, p, vec4(out_color, 1.0));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,21 +139,21 @@ vec4 sample_texture_array(int slot, int index, vec2 uv) {
|
|||
// Utility
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Check if vector is near zero
|
||||
*/
|
||||
bool near_zero(vec3 v) {
|
||||
return (abs(v.x) < EPSILON) && (abs(v.y) < EPSILON) && (abs(v.z) < EPSILON);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Reflect vector around normal
|
||||
*/
|
||||
vec3 reflect_vector(vec3 v, vec3 n) {
|
||||
return v - 2.0 * dot(v, n) * n;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Refract vector through surface
|
||||
*/
|
||||
vec3 refract_vector(vec3 uv, vec3 n, float etai_over_etat) {
|
||||
|
|
@ -186,10 +186,11 @@ vec3 random_vec3(inout uint seed) {
|
|||
}
|
||||
|
||||
vec3 random_in_unit_sphere(inout uint seed) {
|
||||
while (true) {
|
||||
vec3 p = 2.0 * random_vec3(seed) - vec3(1.0);
|
||||
if (dot(p, p) < 1.0) return p;
|
||||
}
|
||||
// Use cosine-weighted hemisphere sampling to avoid infinite loop
|
||||
float z = 1.0 - 2.0 * random_float(seed);
|
||||
float r = sqrt(max(0.0, 1.0 - z * z));
|
||||
float phi = 2.0 * PI * random_float(seed);
|
||||
return vec3(r * cos(phi), r * sin(phi), z);
|
||||
}
|
||||
|
||||
vec3 random_unit_vector(inout uint seed) {
|
||||
|
|
@ -200,12 +201,11 @@ vec3 random_unit_vector(inout uint seed) {
|
|||
// Camera ray
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* @brief Generate primary ray in world space
|
||||
/*
|
||||
* @brief Generate primary ray in world space (center pixel, no jitter)
|
||||
*/
|
||||
Ray generate_camera_ray(ivec2 pixel_coords, ivec2 image_size, inout uint seed) {
|
||||
vec2 jitter = vec2(random_float(seed), random_float(seed));
|
||||
vec2 uv = (vec2(pixel_coords) + jitter) / vec2(image_size);
|
||||
Ray generate_camera_ray(ivec2 pixel_coords, ivec2 image_size) {
|
||||
vec2 uv = (vec2(pixel_coords) + vec2(0.5)) / vec2(image_size);
|
||||
vec2 ndc = uv * 2.0 - 1.0;
|
||||
|
||||
vec4 p_near = u_inv_view_projection * vec4(ndc, 0.0, 1.0);
|
||||
|
|
@ -223,7 +223,7 @@ Ray generate_camera_ray(ivec2 pixel_coords, ivec2 image_size, inout uint seed) {
|
|||
// Intersection
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Ray-AABB intersection
|
||||
*/
|
||||
bool intersect_aabb(Ray ray, vec3 aabb_min, vec3 aabb_max, float t_max) {
|
||||
|
|
@ -240,7 +240,7 @@ bool intersect_aabb(Ray ray, vec3 aabb_min, vec3 aabb_max, float t_max) {
|
|||
return (tmax2 >= max(tmin, 0.0)) && (tmin <= t_max);
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Moller-Trumbore triangle intersection
|
||||
*/
|
||||
bool intersect_triangle(Ray ray, TriangleGpu tri, inout HitInfo hit) {
|
||||
|
|
@ -295,7 +295,7 @@ bool intersect_triangle(Ray ray, TriangleGpu tri, inout HitInfo hit) {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief BVH traversal (closest hit)
|
||||
*/
|
||||
HitInfo trace_ray_bvh(Ray ray) {
|
||||
|
|
@ -339,7 +339,7 @@ HitInfo trace_ray_bvh(Ray ray) {
|
|||
return hit;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Any-hit BVH for shadow ray
|
||||
*/
|
||||
bool trace_any_bvh(Ray ray, float t_max) {
|
||||
|
|
@ -385,7 +385,7 @@ bool trace_any_bvh(Ray ray, float t_max) {
|
|||
// Primary-ray fast path via G-Buffer
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Read primary hit from G-Buffer if current pixel has geometry
|
||||
* @note Uses g_position.w as "valid" marker (your gbuffer writes 1.0 on hits, clear is 0).
|
||||
*/
|
||||
|
|
@ -648,26 +648,11 @@ vec3 environment_color(vec3 dir) {
|
|||
return vec3(0.1, 0.1, 0.15);
|
||||
}
|
||||
|
||||
Ray generate_camera_ray_center(ivec2 pixel_coords, ivec2 image_size) {
|
||||
vec2 uv = (vec2(pixel_coords) + vec2(0.5)) / vec2(image_size);
|
||||
vec2 ndc = uv * 2.0 - 1.0;
|
||||
|
||||
vec4 p_near = u_inv_view_projection * vec4(ndc, 0.0, 1.0);
|
||||
vec4 p_far = u_inv_view_projection * vec4(ndc, 1.0, 1.0);
|
||||
vec3 near_ws = p_near.xyz / p_near.w;
|
||||
vec3 far_ws = p_far.xyz / p_far.w;
|
||||
|
||||
Ray r;
|
||||
r.origin = near_ws;
|
||||
r.direction = normalize(far_ws - near_ws);
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
/*
|
||||
* @brief Trace path with primary-ray G-Buffer acceleration
|
||||
*/
|
||||
vec3 trace_path_primary_gbuffer(ivec2 pixel_coords, ivec2 image_size, inout uint seed) {
|
||||
Ray ray = generate_camera_ray_center(pixel_coords, image_size);
|
||||
Ray ray = generate_camera_ray(pixel_coords, image_size);
|
||||
|
||||
vec3 radiance = vec3(0.0);
|
||||
vec3 throughput = vec3(1.0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue