refactor: 优化shader代码,消除性能瓶颈和代码重复
- 重构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哈希缓存,避免每帧重建main
parent
65f2386b27
commit
adfe38a453
|
|
@ -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)
|
// Moller-Trumbore triangle intersection using compact triangle (precomputed edges)
|
||||||
// Uses TriangleCompactGpu: v0_material, e1=v1-v0, e2=v2-v0
|
// 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 v0 = tri.v0_material.xyz;
|
||||||
vec3 e1 = tri.e1.xyz;
|
vec3 e1 = tri.e1.xyz;
|
||||||
vec3 e2 = tri.e2.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;
|
if (v < 0.0 || u + v > 1.0) return false;
|
||||||
|
|
||||||
float t = dot(e2, qvec) * inv_det;
|
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
|
// Check if triangle is hit (for shadow rays - no barycentric needed)
|
||||||
TriangleAttrGpu attr = bvh_attrs[gl_GlobalInvocationID.x];
|
bool intersect_triangle_any(Ray ray, TriangleCompactGpu tri, float t_max) {
|
||||||
// We need the triangle index, not invocation ID. Use a different approach.
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -131,35 +151,17 @@ HitInfo trace_ray_bvh(Ray ray) {
|
||||||
for (uint i = 0u; i < count; ++i) {
|
for (uint i = 0u; i < count; ++i) {
|
||||||
uint tri_idx = left_first + i;
|
uint tri_idx = left_first + i;
|
||||||
TriangleCompactGpu tri = bvh_tris[tri_idx];
|
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 t, u, v;
|
||||||
float det = dot(e1, pvec);
|
if (intersect_triangle_compact(ray, tri, hit.t, t, u, v)) {
|
||||||
|
hit.hit = true;
|
||||||
if (abs(det) < EPSILON) continue;
|
hit.t = t;
|
||||||
float inv_det = 1.0 / det;
|
hit.position = ray.origin + t * ray.direction;
|
||||||
|
hit.material_id = as_uint(tri.v0_material.w);
|
||||||
vec3 tvec = ray.origin - v0;
|
hit_tri_idx = tri_idx;
|
||||||
float u = dot(tvec, pvec) * inv_det;
|
hit_u = u;
|
||||||
if (u < 0.0 || u > 1.0) continue;
|
hit_v = v;
|
||||||
|
}
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint left = left_first;
|
uint left = left_first;
|
||||||
|
|
@ -239,28 +241,9 @@ bool trace_any_bvh(Ray ray, float t_max) {
|
||||||
if (count > 0u) {
|
if (count > 0u) {
|
||||||
for (uint i = 0u; i < count; ++i) {
|
for (uint i = 0u; i < count; ++i) {
|
||||||
TriangleCompactGpu tri = bvh_tris[left_first + i];
|
TriangleCompactGpu tri = bvh_tris[left_first + i];
|
||||||
vec3 v0 = tri.v0_material.xyz;
|
if (intersect_triangle_any(ray, tri, t_max)) {
|
||||||
vec3 e1 = tri.e1.xyz;
|
return true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint left = left_first;
|
uint left = left_first;
|
||||||
|
|
|
||||||
|
|
@ -87,7 +87,7 @@ ScatterResult scatter_diffuse(Ray ray_in, HitInfo hit, Material mat, inout uint
|
||||||
if (near_zero(dir)) dir = hit.normal;
|
if (near_zero(dir)) dir = hit.normal;
|
||||||
|
|
||||||
r.scattered_ray.origin = hit.position + hit.normal * EPSILON;
|
r.scattered_ray.origin = hit.position + hit.normal * EPSILON;
|
||||||
r.scattered_ray.direction = normalize(dir);
|
r.scattered_ray.direction = dir;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ ScatterResult scatter_metal(Ray ray_in, HitInfo hit, Material mat, inout uint se
|
||||||
|
|
||||||
r.scattered = true;
|
r.scattered = true;
|
||||||
r.scattered_ray.origin = hit.position + N * EPSILON;
|
r.scattered_ray.origin = hit.position + N * EPSILON;
|
||||||
r.scattered_ray.direction = normalize(L);
|
r.scattered_ray.direction = L;
|
||||||
return r;
|
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.origin = hit.position + dir * EPSILON;
|
||||||
r.scattered_ray.direction = normalize(dir);
|
r.scattered_ray.direction = dir;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 = 1, rg32f) uniform readonly image2D g_normal; // Octahedral encoded
|
||||||
layout(binding = 5, rgba32f) uniform readonly image2D g_material;
|
layout(binding = 5, rgba32f) uniform readonly image2D g_material;
|
||||||
layout(binding = 6, r32ui) uniform readonly uimage2D g_material_id;
|
layout(binding = 6, r32ui) uniform readonly uimage2D g_material_id;
|
||||||
layout(binding = 7, rgba32f) uniform readonly image2D g_texcoord;
|
layout(binding = 2, rgba32f) uniform readonly image2D g_texcoord;
|
||||||
layout(binding = 8, rgba32f) uniform readonly image2D g_tangent;
|
layout(binding = 7, rgba32f) uniform readonly image2D g_tangent;
|
||||||
|
|
||||||
// Output
|
// Output
|
||||||
layout(binding = 3, rgba32f) uniform image2D output_image;
|
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;
|
if (near_zero(dir)) dir = hit.normal;
|
||||||
|
|
||||||
r.scattered_ray.origin = hit.position + hit.normal * EPSILON;
|
r.scattered_ray.origin = hit.position + hit.normal * EPSILON;
|
||||||
r.scattered_ray.direction = normalize(dir);
|
r.scattered_ray.direction = dir;
|
||||||
return r;
|
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.attenuation = clamp(F, vec3(0.0), vec3(1.0));
|
||||||
r.scattered = true;
|
r.scattered = true;
|
||||||
r.scattered_ray.origin = hit.position + N * EPSILON;
|
r.scattered_ray.origin = hit.position + N * EPSILON;
|
||||||
r.scattered_ray.direction = normalize(L);
|
r.scattered_ray.direction = L;
|
||||||
return r;
|
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;
|
float sin_theta_t = eta * sin_theta;
|
||||||
bool total_internal_reflection = sin_theta_t >= 1.0;
|
bool total_internal_reflection = sin_theta_t >= 1.0;
|
||||||
|
|
||||||
float f0 = pow((1.0 - mat.ior) / (1.0 + mat.ior), 2.0);
|
float f = fresnel_dielectric(cos_theta, mat.ior);
|
||||||
float f = f0 + (1.0 - f0) * pow(1.0 - abs(cos_theta), 5.0);
|
|
||||||
|
|
||||||
vec3 dir;
|
vec3 dir;
|
||||||
if (total_internal_reflection || sobol_next(state) < f) {
|
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.origin = hit.position + dir * EPSILON;
|
||||||
r.scattered_ray.direction = normalize(dir);
|
r.scattered_ray.direction = dir;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
glBindImageTexture(6, gbuffer.get_texture(GBUFFER_MATERIAL_ID), 0, GL_FALSE, 0, GL_READ_ONLY, GL_R32UI);
|
||||||
|
|
||||||
// Texcoord
|
// 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
|
// 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) {
|
void RayTracer::build_texture_arrays_(const Scene &scene) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue