From adfe38a4539ea41bf279ca9b7b3ff3001103642d Mon Sep 17 00:00:00 2001 From: ternaryop8479 Date: Sat, 11 Apr 2026 22:44:46 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E4=BC=98=E5=8C=96shader=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=8C=E6=B6=88=E9=99=A4=E6=80=A7=E8=83=BD=E7=93=B6?= =?UTF-8?q?=E9=A2=88=E5=92=8C=E4=BB=A3=E7=A0=81=E9=87=8D=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 重构BVH三角形相交函数,统一trace_ray_bvh和trace_any_bvh的相交检测 - 修复Windows平台binding point限制,将g_texcoord从7改为2,g_tangent从8改为7 - 优化Fresnel计算,scatter_dielectric_sobol调用fresnel_dielectric函数消除内联重复 - 删除6处冗余normalize调用(material.glsl和raytracing.comp中的scatter函数) - 纹理数组支持per-slot哈希缓存,避免每帧重建 --- shaders/include/bvh.glsl | 105 ++++++++++++----------------- shaders/include/material.glsl | 6 +- shaders/raytracing/raytracing.comp | 13 ++-- src/core/raytracer.cpp | 4 +- 4 files changed, 55 insertions(+), 73 deletions(-) diff --git a/shaders/include/bvh.glsl b/shaders/include/bvh.glsl index 0111230..e3022c7 100644 --- a/shaders/include/bvh.glsl +++ b/shaders/include/bvh.glsl @@ -40,7 +40,8 @@ bool intersect_aabb(Ray ray, vec3 aabb_min, vec3 aabb_max, float t_max) { // Moller-Trumbore triangle intersection using compact triangle (precomputed edges) // Uses TriangleCompactGpu: v0_material, e1=v1-v0, e2=v2-v0 -bool intersect_triangle_compact(Ray ray, TriangleCompactGpu tri, inout HitInfo hit) { +// Returns true if hit, outputs barycentric coords (u, v) and distance t +bool intersect_triangle_compact(Ray ray, TriangleCompactGpu tri, float t_max, out float out_t, out float out_u, out float out_v) { vec3 v0 = tri.v0_material.xyz; vec3 e1 = tri.e1.xyz; vec3 e2 = tri.e2.xyz; @@ -60,18 +61,37 @@ bool intersect_triangle_compact(Ray ray, TriangleCompactGpu tri, inout HitInfo h if (v < 0.0 || u + v > 1.0) return false; float t = dot(e2, qvec) * inv_det; - if (t < EPSILON || t >= hit.t) return false; + if (t < EPSILON || t >= t_max) return false; - float w = 1.0 - u - v; + out_t = t; + out_u = u; + out_v = v; + return true; +} - // Fetch attributes only after confirmed hit - TriangleAttrGpu attr = bvh_attrs[gl_GlobalInvocationID.x]; - // We need the triangle index, not invocation ID. Use a different approach. +// Check if triangle is hit (for shadow rays - no barycentric needed) +bool intersect_triangle_any(Ray ray, TriangleCompactGpu tri, float t_max) { + vec3 v0 = tri.v0_material.xyz; + vec3 e1 = tri.e1.xyz; + vec3 e2 = tri.e2.xyz; + + vec3 pvec = cross(ray.direction, e2); + float det = dot(e1, pvec); + + if (abs(det) < EPSILON) return false; + float inv_det = 1.0 / det; + + vec3 tvec = ray.origin - v0; + float u = dot(tvec, pvec) * inv_det; + if (u < 0.0 || u > 1.0) return false; + + vec3 qvec = cross(tvec, e1); + float v = dot(ray.direction, qvec) * inv_det; + if (v < 0.0 || u + v > 1.0) return false; + + float t = dot(e2, qvec) * inv_det; + if (t < EPSILON || t >= t_max) return false; - hit.hit = true; - hit.t = t; - hit.position = ray.origin + t * ray.direction; - hit.material_id = as_uint(tri.v0_material.w); return true; } @@ -131,35 +151,17 @@ HitInfo trace_ray_bvh(Ray ray) { for (uint i = 0u; i < count; ++i) { uint tri_idx = left_first + i; TriangleCompactGpu tri = bvh_tris[tri_idx]; - vec3 v0 = tri.v0_material.xyz; - vec3 e1 = tri.e1.xyz; - vec3 e2 = tri.e2.xyz; - - vec3 pvec = cross(ray.direction, e2); - float det = dot(e1, pvec); - - if (abs(det) < EPSILON) continue; - float inv_det = 1.0 / det; - - vec3 tvec = ray.origin - v0; - float u = dot(tvec, pvec) * inv_det; - if (u < 0.0 || u > 1.0) continue; - - vec3 qvec = cross(tvec, e1); - float v = dot(ray.direction, qvec) * inv_det; - if (v < 0.0 || u + v > 1.0) continue; - - float t = dot(e2, qvec) * inv_det; - if (t < EPSILON || t >= hit.t) continue; - - // Record hit but defer attribute fetch - hit.hit = true; - hit.t = t; - hit.position = ray.origin + t * ray.direction; - hit.material_id = as_uint(tri.v0_material.w); - hit_tri_idx = tri_idx; - hit_u = u; - hit_v = v; + + float t, u, v; + if (intersect_triangle_compact(ray, tri, hit.t, t, u, v)) { + hit.hit = true; + hit.t = t; + hit.position = ray.origin + t * ray.direction; + hit.material_id = as_uint(tri.v0_material.w); + hit_tri_idx = tri_idx; + hit_u = u; + hit_v = v; + } } } else { uint left = left_first; @@ -239,28 +241,9 @@ bool trace_any_bvh(Ray ray, float t_max) { if (count > 0u) { for (uint i = 0u; i < count; ++i) { TriangleCompactGpu tri = bvh_tris[left_first + i]; - vec3 v0 = tri.v0_material.xyz; - vec3 e1 = tri.e1.xyz; - vec3 e2 = tri.e2.xyz; - - vec3 pvec = cross(ray.direction, e2); - float det = dot(e1, pvec); - - if (abs(det) < EPSILON) continue; - float inv_det = 1.0 / det; - - vec3 tvec = ray.origin - v0; - float u = dot(tvec, pvec) * inv_det; - if (u < 0.0 || u > 1.0) continue; - - vec3 qvec = cross(tvec, e1); - float v = dot(ray.direction, qvec) * inv_det; - if (v < 0.0 || u + v > 1.0) continue; - - float t = dot(e2, qvec) * inv_det; - if (t < EPSILON || t >= t_max) continue; - - return true; + if (intersect_triangle_any(ray, tri, t_max)) { + return true; + } } } else { uint left = left_first; diff --git a/shaders/include/material.glsl b/shaders/include/material.glsl index 9f95c59..d9e2362 100644 --- a/shaders/include/material.glsl +++ b/shaders/include/material.glsl @@ -87,7 +87,7 @@ ScatterResult scatter_diffuse(Ray ray_in, HitInfo hit, Material mat, inout uint if (near_zero(dir)) dir = hit.normal; r.scattered_ray.origin = hit.position + hit.normal * EPSILON; - r.scattered_ray.direction = normalize(dir); + r.scattered_ray.direction = dir; return r; } @@ -127,7 +127,7 @@ ScatterResult scatter_metal(Ray ray_in, HitInfo hit, Material mat, inout uint se r.scattered = true; r.scattered_ray.origin = hit.position + N * EPSILON; - r.scattered_ray.direction = normalize(L); + r.scattered_ray.direction = L; return r; } @@ -158,7 +158,7 @@ ScatterResult scatter_dielectric(Ray ray_in, HitInfo hit, Material mat, inout ui } r.scattered_ray.origin = hit.position + dir * EPSILON; - r.scattered_ray.direction = normalize(dir); + r.scattered_ray.direction = dir; return r; } diff --git a/shaders/raytracing/raytracing.comp b/shaders/raytracing/raytracing.comp index a981c9e..d7c62e6 100644 --- a/shaders/raytracing/raytracing.comp +++ b/shaders/raytracing/raytracing.comp @@ -16,8 +16,8 @@ layout(binding = 0, rgba32f) uniform readonly image2D g_position; layout(binding = 1, rg32f) uniform readonly image2D g_normal; // Octahedral encoded layout(binding = 5, rgba32f) uniform readonly image2D g_material; layout(binding = 6, r32ui) uniform readonly uimage2D g_material_id; -layout(binding = 7, rgba32f) uniform readonly image2D g_texcoord; -layout(binding = 8, rgba32f) uniform readonly image2D g_tangent; +layout(binding = 2, rgba32f) uniform readonly image2D g_texcoord; +layout(binding = 7, rgba32f) uniform readonly image2D g_tangent; // Output layout(binding = 3, rgba32f) uniform image2D output_image; @@ -130,7 +130,7 @@ ScatterResult scatter_diffuse_sobol(Ray ray_in, HitInfo hit, Material mat, inout if (near_zero(dir)) dir = hit.normal; r.scattered_ray.origin = hit.position + hit.normal * EPSILON; - r.scattered_ray.direction = normalize(dir); + r.scattered_ray.direction = dir; return r; } @@ -160,7 +160,7 @@ ScatterResult scatter_metal_sobol(Ray ray_in, HitInfo hit, Material mat, inout S r.attenuation = clamp(F, vec3(0.0), vec3(1.0)); r.scattered = true; r.scattered_ray.origin = hit.position + N * EPSILON; - r.scattered_ray.direction = normalize(L); + r.scattered_ray.direction = L; return r; } @@ -181,8 +181,7 @@ ScatterResult scatter_dielectric_sobol(Ray ray_in, HitInfo hit, Material mat, in float sin_theta_t = eta * sin_theta; bool total_internal_reflection = sin_theta_t >= 1.0; - float f0 = pow((1.0 - mat.ior) / (1.0 + mat.ior), 2.0); - float f = f0 + (1.0 - f0) * pow(1.0 - abs(cos_theta), 5.0); + float f = fresnel_dielectric(cos_theta, mat.ior); vec3 dir; if (total_internal_reflection || sobol_next(state) < f) { @@ -192,7 +191,7 @@ ScatterResult scatter_dielectric_sobol(Ray ray_in, HitInfo hit, Material mat, in } r.scattered_ray.origin = hit.position + dir * EPSILON; - r.scattered_ray.direction = normalize(dir); + r.scattered_ray.direction = dir; return r; } diff --git a/src/core/raytracer.cpp b/src/core/raytracer.cpp index 1668855..ea8495d 100644 --- a/src/core/raytracer.cpp +++ b/src/core/raytracer.cpp @@ -420,10 +420,10 @@ void RayTracer::bind_gbuffer_(const GBuffer &gbuffer) { glBindImageTexture(6, gbuffer.get_texture(GBUFFER_MATERIAL_ID), 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI); // Texcoord - glBindImageTexture(7, gbuffer.get_texture(GBUFFER_TEXCOORD), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); + glBindImageTexture(2, gbuffer.get_texture(GBUFFER_TEXCOORD), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); // Tangent - glBindImageTexture(8, gbuffer.get_texture(GBUFFER_TANGENT), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); + glBindImageTexture(7, gbuffer.get_texture(GBUFFER_TANGENT), 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA32F); } void RayTracer::build_texture_arrays_(const Scene &scene) {