Files
HelloVulkan/shaders/env/ibl_brdf_lut.comp
T
atdunbg f73e52926f Reorganize directory layout: editor panels/, grouped shaders, drop stale header
- App/editor: move 7 panels into panels/ (Editor core stays at root)
- shaders/: group into pbr/ post/ debug/ env/ (runtime load paths updated)
- Delete outdated duplicate Engine/src/Renderer/VulkanAssetUploader.h
2026-10-07 09:52:17 +08:00

55 lines
1.9 KiB
Plaintext
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.
#version 450
// IBL ④:BRDF 积分 LUT(2D,纯数学,与环境内容无关)。
// (NdotV, roughness) → (F 缩放 A, F 偏置 B):specular = prefiltered·(F·A + B)。
// 与环境切换无关,但随生成链一起跑(GPU 亚毫秒级),省去跨环境缓存。
#include "ibl_common.glsl"
layout(local_size_x = 8, local_size_y = 8) in;
layout(set = 0, binding = 0, rg16f) uniform restrict writeonly image2D outLut;
const uint SAMPLES = 128;
void main()
{
ivec2 gid = ivec2(gl_GlobalInvocationID);
if (gid.x >= imageSize(outLut).x || gid.y >= imageSize(outLut).y) return;
vec2 uv = (vec2(gid) + 0.5) / vec2(imageSize(outLut));
float nDotV = uv.x;
float roughness = uv.y;
// V 在以 N 为 +Z 的切线空间里(积分只依赖这两角度)
vec3 V = vec3(sqrt(1.0 - nDotV * nDotV), 0.0, nDotV);
vec3 Nz = vec3(0.0, 0.0, 1.0);
float a = 0.0, b = 0.0;
float k = roughness * roughness * 0.5; // IBL 版 Smith k
for (uint i = 0u; i < SAMPLES; ++i) {
vec3 H = iblImportanceSampleGGX(iblHammersley(i, SAMPLES), Nz, roughness);
vec3 L = normalize(2.0 * dot(V, H) * H - V);
float lDotN = L.z;
float nDotL = max(lDotN, 0.0);
float nDotH = max(H.z, 0.0);
float vDotH = max(dot(V, H), 0.0);
if (nDotL <= 0.0) continue;
float g = (nDotV / (nDotV * (1.0 - k) + k)) *
(nDotL / (nDotL * (1.0 - k) + k));
// 高 roughness 时部分样本 H.z 恰为 0(g 也为 0),0/0 = NaN
// 会累进 LUT——分母钳 epsilon(与 CPU 版一致)
float gVis = g * vDotH / max(nDotH * nDotV, 1e-6);
float fc = 1.0 - vDotH;
float f = fc * fc * fc * fc * fc; // (1-vDotH)⁵
a += (1.0 - f) * gVis;
b += f * gVis;
}
imageStore(outLut, gid, vec4(a / float(SAMPLES), b / float(SAMPLES), 0.0, 1.0));
}