Files
HelloVulkan/shaders/ibl_common.glsl
T
atdunbg 1d690067bd feat: IBL 预积分 GPU compute 化 + 环境资产入 Assets 层(动态切换)
CPU 逐像素卷积(venice 4k 阻塞 7.36s)→ 4 个 compute shader 一次性
提交:equirect→cube / irradiance / prefilter×5mip / BRDF LUT。
Cubemap 瘦身为纯资源持有类,生成职责移交 IblGenerator;
环境经 AssetManager 缓存(EnvRef),Renderer::SetEnvironment
动态换绑(RenderPass::OnEnvironmentChanged 广播)。
调试视图 +4:EnvCube / Irradiance / Prefilter / BRDF LUT。

性能前后对比(RTX 5060 Laptop,venice_dawn_1_4k.hdr):
- 改造前 CPU:7.36 s(主线程阻塞)
- 改造后 GPU:HDR decode 127-134ms + 资源 22-35ms + compute 17-19ms
  ≈ 165-190ms(约 40×);Neutral 兜底 ~6ms
- 运行中动态切换环境同量级(ms 级 GPU,decode 占大头)

冒烟:两构建目录 0 警告;运行期 0 validation(含两次环境切换 +
调试视图 9-12 轮播自动化验证)。
2026-09-24 13:23:59 +08:00

61 lines
2.3 KiB
GLSL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ibl_common:IBL compute 预积分共享数学(与原 CPU 实现逐式对齐)。
//
// 被 4 个 .comp 包含(glslc 相对 include)。改造自 Cubemap.cpp 的
// CPU 积分路径——公式一致保证视觉无回归,可直接对比验证。
#ifndef IBL_COMMON_GLSL
#define IBL_COMMON_GLSL
const float IBL_PI = 3.14159265358979;
// ---- GL/Vulkan cube 面方向表(与 GL spec 立方体选择表互逆)----
// (u,v)∈[0,1](u 向右 v 向下)→ s,t∈[-1,1] → 单位方向
vec3 iblFaceDir(uint face, float u, float v)
{
float s = u * 2.0 - 1.0;
float t = v * 2.0 - 1.0;
vec3 dir;
if (face == 0u) dir = vec3( 1.0, -t, -s); // +X(面片顶行 = +Y)
else if (face == 1u) dir = vec3(-1.0, -t, s); // -X
else if (face == 2u) dir = vec3( s, 1.0, t); // +Y
else if (face == 3u) dir = vec3( s,-1.0, -t); // -Y
else if (face == 4u) dir = vec3( s, -t, 1.0); // +Z
else dir = vec3(-s, -t,-1.0); // -Z
return normalize(dir); // equirect 查表要求单位方向
}
// 单位方向 → 等距柱状 uv。行 0 = 天顶(+Y):v = acos(y)/π,
// 与 stbi 行序一致;u 经度环绕交给采样器 S = eRepeat 处理接缝
vec2 iblDirToEquirectUv(vec3 dir)
{
float u = atan(dir.z, dir.x) / (2.0 * IBL_PI) + 0.5;
float v = acos(clamp(dir.y, -1.0, 1.0)) / IBL_PI;
return vec2(u, v);
}
// van der Corput 基底反转。硬件位反转指令替代 CPU 手写交换链;
// 整数值转浮点(不是位型重解读),序列与 CPU 版一致
vec2 iblHammersley(uint i, uint n)
{
return vec2(float(i) / float(n),
float(bitfieldReverse(i)) * 2.3283064365386963e-10);
}
// GGX NDF 按概率密度取半程向量 H(切线空间 → 世界)
vec3 iblImportanceSampleGGX(vec2 xi, vec3 N, float roughness)
{
float a = roughness * roughness;
float phi = 2.0 * IBL_PI * xi.x;
float cosTheta = sqrt((1.0 - xi.y) / (1.0 + (a * a - 1.0) * xi.y));
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
vec3 H = vec3(sinTheta * cos(phi), sinTheta * sin(phi), cosTheta);
vec3 up = abs(N.z) > 0.999 ? vec3(1.0, 0.0, 0.0) : vec3(0.0, 1.0, 0.0);
vec3 T = normalize(cross(up, N));
vec3 B = cross(N, T);
return normalize(T * H.x + B * H.y + N * H.z);
}
#endif // IBL_COMMON_GLSL