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 轮播自动化验证)。
49 lines
1.6 KiB
Plaintext
49 lines
1.6 KiB
Plaintext
#version 450
|
||
|
||
// IBL ②:环境 cube → 漫反射辐照度 cube(半球 Lambert 卷积)。
|
||
// E = ∫ L·cosθ·sinθ dθ dφ,切线基 up×N 构造。64×32 = 2048 采样/像素
|
||
// (与 CPU 版同级精度),32² 低频输出上 GPU 耗时可忽略。
|
||
|
||
#include "ibl_common.glsl"
|
||
|
||
layout(local_size_x = 8, local_size_y = 8) in;
|
||
|
||
layout(set = 0, binding = 0) uniform samplerCube env;
|
||
layout(set = 0, binding = 1, rgba16f) uniform restrict writeonly image2DArray outCube;
|
||
|
||
const int PHI_STEPS = 64;
|
||
const int THETA_STEPS = 32;
|
||
|
||
void main()
|
||
{
|
||
ivec3 gid = ivec3(gl_GlobalInvocationID);
|
||
ivec2 size = imageSize(outCube).xy;
|
||
if (gid.x >= size.x || gid.y >= size.y) return;
|
||
|
||
vec2 uv = (vec2(gid.xy) + 0.5) / vec2(size);
|
||
vec3 N = iblFaceDir(uint(gid.z), uv.x, uv.y);
|
||
|
||
vec3 up = abs(N.y) > 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0);
|
||
vec3 T = normalize(cross(up, N));
|
||
vec3 B = cross(N, T);
|
||
|
||
float dPhi = 2.0 * IBL_PI / float(PHI_STEPS);
|
||
float dTheta = 0.5 * IBL_PI / float(THETA_STEPS);
|
||
|
||
vec3 irradiance = vec3(0.0);
|
||
for (int p = 0; p < PHI_STEPS; ++p) {
|
||
float phi = (float(p) + 0.5) * dPhi;
|
||
for (int t = 0; t < THETA_STEPS; ++t) {
|
||
float theta = (float(t) + 0.5) * dTheta;
|
||
float sinT = sin(theta);
|
||
float cosT = cos(theta);
|
||
vec3 sampleDir = T * (sinT * cos(phi)) +
|
||
B * (sinT * sin(phi)) +
|
||
N * cosT;
|
||
irradiance += texture(env, sampleDir).rgb * (cosT * sinT);
|
||
}
|
||
}
|
||
|
||
imageStore(outCube, gid, vec4(irradiance * (dPhi * dTheta), 1.0));
|
||
}
|