初始化内容

This commit is contained in:
2026-09-16 14:07:40 +08:00
parent 6934b390bf
commit 4f643c1e7c
18350 changed files with 6088489 additions and 305 deletions
+541
View File
@@ -0,0 +1,541 @@
#version 450
#extension GL_GOOGLE_cpp_style_line_directive : enable
#extension GL_GOOGLE_include_directive : enable
#include "include/light.glsl"
const float M_PI = 3.141592653589793;
const float c_MinRoughness = 0.04;
#define ONLY_SH false
layout (constant_id = 0) const int SHADOW_MAP_CASCADE_COUNT = 4;
layout (constant_id = 1) const int enablePCF = 1;
layout (set = 0, binding = 0) uniform UniformBufferObject
{
mat4 proj;
mat4 view;
vec3 camPos;
float pad;
} ubo;
layout(set = 0, binding = 1) uniform UniformBufferMaterial
{
vec4 baseColorFactor; // 基础颜色系数
vec4 emissiveFactor; // 自发光系数
// -1.无贴图 0.使用UV0 1.使用UV1
int baseColorTextureSet;
int physicalDescriptorTextureSet;
int normalTextureSet;
int occlusionTextureSet;
int emissiveTextureSet;
float metallicFactor; // 金属度
float roughnessFactor; // 粗糙度
float alphaMask; // 透明度裁剪
float alphaMaskCutoff; // 丢弃阈值
float emissiveStrength; // 自发光强度
vec2 pad;
} material;
layout(set = 0, binding = 2) uniform UniformBufferPass
{
float exposure; // 曝光度
float gamma; // gamma校正
float prefilteredCubeMipLevels; // 预过滤的立方体贴图级数
float scaleIBLAmbient; // ibl环境光系数
vec4 sh[9]; // 球谐漫反射
vec4 cascadeSplits; // 级联分割
float debugViewInputs;
Light light[NUM_LIGHT];
} pass;
layout (set = 0, binding = 3) uniform UniformBufferCascade
{
mat4 viewProj[SHADOW_MAP_CASCADE_COUNT];
} cascade;
// 依赖pass
#include "include/tonemap.glsl"
// 预过滤镜面环境贴图(ibl
layout (set = 0, binding = 4) uniform samplerCube prefilteredMap;
// BRDF 积分查找表
layout (set = 0, binding = 5) uniform sampler2D samplerBRDFLUT;
// 阴影贴图
layout (set = 0, binding = 6) uniform sampler2DArray shadowMap;
layout(set = 1, binding = 0) uniform sampler2D diffuseMap; // 漫反射
layout(set = 1, binding = 1) uniform sampler2D physicalMap; // 物理
layout(set = 1, binding = 2) uniform sampler2D normalMap; // 法线
layout(set = 1, binding = 3) uniform sampler2D aoMap; // 环境光遮蔽
layout(set = 1, binding = 4) uniform sampler2D emissiveMap; // 自发光
layout (location = 0) in vec3 inPosition;
layout (location = 1) in vec3 inNormal;
layout (location = 2) in vec2 inUV0;
layout (location = 3) in vec2 inUV1;
layout (location = 4) in vec4 inColor;
layout (location = 5) in vec3 inViewPos;
layout(location = 0) out vec4 outColor;
// 计算中间值
struct PbrInfo
{
float NdotL; // 法线 · 光照方向 夹角余弦
float NdotV; // 法线 · 视角方向 夹角余弦
float NdotH; // 法线 · 半角向量 夹角余弦
float LdotH; // 光照方向 · 半角向量 夹角余弦
float VdotH; // 视角方向 · 半角向量 夹角余弦
float perceptualRoughness; // 感知粗糙度(美术编辑的原始值)
float metalness; // 金属度
vec3 reflectance0; // 0度入射角 反射率(垂直入射)
vec3 reflectance90; // 90度入射角 反射率(掠射入射)
float alphaRoughness; // 物理粗糙度(perceptualRoughness²,用于光照计算)
vec3 diffuseColor; // 漫反射颜色
vec3 specularColor; // 高光反射颜色
};
// 从顶点或贴图获取法线(世界坐标系)
vec3 getNormal()
{
vec3 tangentNormal = texture(normalMap, material.normalTextureSet == 0 ? inUV0 : inUV1).xyz * 2.0 - 1.0;
// dFdx的返回值表示当前片元在屏幕空间x方向上的局部偏导数
// 即当屏幕坐标x增加1个像素时,输入变量的变化率。
// 它通常在GPU的2x2像素块内计算,通过相邻像素的值差来获得。
vec3 q1 = dFdx(inPosition);
vec3 q2 = dFdy(inPosition);
vec2 st1 = dFdx(inUV0);
vec2 st2 = dFdy(inUV0);
// N 向上(模型表面法线)
// T 向右(切线 纹理 U 方向)
// B 向前(副切线 纹理 V 方向)
vec3 N = normalize(inNormal);
vec3 T = normalize(q1 * st2.t - q2 * st1.t);
vec3 B = normalize(cross(N, T));
mat3 TBN = mat3(T, B, N);
return normalize(TBN * tangentNormal);
}
vec4 SRGBtoLINEAR(vec4 srgbIn)
{
//#define MANUAL_SRGB 1
#ifdef MANUAL_SRGB
#ifdef SRGB_FAST_APPROXIMATION
vec3 linOut = pow(srgbIn.xyz,vec3(2.2));
#else //SRGB_FAST_APPROXIMATION
vec3 bLess = step(vec3(0.04045),srgbIn.xyz);
vec3 linOut = mix( srgbIn.xyz/vec3(12.92), pow((srgbIn.xyz+vec3(0.055))/vec3(1.055),vec3(2.4)), bLess );
#endif //SRGB_FAST_APPROXIMATION
return vec4(linOut,srgbIn.w);;
#else //MANUAL_SRGB
return srgbIn;
#endif //MANUAL_SRGB
}
// F 菲涅尔函数
vec3 specularReflection(PbrInfo pbrInputs)
{
// reflectance0:垂直入射反射率
// reflectance90:掠射入射反射率
// VdotH:视线与半角向量夹角
// 公式效果:角度越偏,反射越强
return pbrInputs.reflectance0 + (pbrInputs.reflectance90 - pbrInputs.reflectance0) * pow(clamp(1.0 - pbrInputs.VdotH, 0.0, 1.0), 5.0);
}
// G 几何遮蔽函数
float geometricOcclusion(PbrInfo pbrInputs)
{
// 粗糙表面会自己遮挡自己 → 让高光更真实、不刺眼
// 越粗糙 → G 值越小 → 高光越暗
float NdotL = pbrInputs.NdotL;
float NdotV = pbrInputs.NdotV;
float r = pbrInputs.alphaRoughness;
// 计算光方向的遮蔽
// 计算视线方向的遮蔽
// 相乘得到总遮蔽
float attenuationL = 2.0 * NdotL / (NdotL + sqrt(r * r + (1.0 - r * r) * (NdotL * NdotL)));
float attenuationV = 2.0 * NdotV / (NdotV + sqrt(r * r + (1.0 - r * r) * (NdotV * NdotV)));
return attenuationL * attenuationV;
}
// D 微表面分布函数
float microfacetDistribution(PbrInfo pbrInputs)
{
// 控制高光的形状与大小
// 光滑 → D 值高 → 小而亮的高光
// 粗糙 → D 值低 → 大而散的高光
float roughnessSq = pbrInputs.alphaRoughness * pbrInputs.alphaRoughness;
float f = (pbrInputs.NdotH * roughnessSq - pbrInputs.NdotH) * pbrInputs.NdotH + 1.0;
return roughnessSq / (M_PI * f * f);
}
// 漫反射率,能量守恒所以除以PI
vec3 diffuse(PbrInfo pbrInputs)
{
// 漫反射率 = 漫反射颜色 / π
return pbrInputs.diffuseColor / M_PI;
}
#include "include/tocubemap.glsl"
// 球谐函数
vec3 irradianceFromSH(vec3 i_normal)
{
vec3 normal = tocubemap(i_normal);
vec3 result =
pass.sh[0].xyz +
pass.sh[1].xyz * normal.y +
pass.sh[2].xyz * normal.z +
pass.sh[3].xyz * normal.x +
pass.sh[4].xyz * normal.y * normal.x +
pass.sh[5].xyz * normal.y * normal.z +
pass.sh[6].xyz * (1.0 - 3.0*normal.z*normal.z) +
pass.sh[7].xyz * normal.z * normal.x +
pass.sh[8].xyz * (normal.x*normal.x - normal.y*normal.y);
return result * 0.282095;
}
// 计算IBL环境光照
vec3 getIBLContribution(PbrInfo pbrInputs, vec3 n, vec3 reflection)
{
vec3 cubeVec = tocubemap(reflection);
float lod = (pbrInputs.perceptualRoughness * pass.prefilteredCubeMipLevels);
// 从 BRDF LUT 获取缩放和偏移
vec3 brdf = (texture(samplerBRDFLUT, vec2(pbrInputs.NdotV, 1.0 - pbrInputs.perceptualRoughness))).rgb;
// 球谐函数 计算漫反射环境光
vec3 diffuseLight = irradianceFromSH(n);
// 镜面反射:采样预过滤贴图
vec3 specularLight = tonemap(textureLod(prefilteredMap, cubeVec, lod)).rgb;
// 漫反射 + 镜面反射 计算
vec3 diffuse = diffuseLight * pbrInputs.diffuseColor;
vec3 specular = specularLight * (pbrInputs.specularColor * brdf.x + brdf.y);
// 环境光强度缩放
diffuse *= pass.scaleIBLAmbient;
if(ONLY_SH)
return diffuse;
specular *= pass.scaleIBLAmbient;
return diffuse + specular;
}
#define ambient 0.3
float textureProj(vec4 shadowCoord, vec2 offset, uint cascadeIndex)
{
float shadow = 1.0;
float bias = 0.005;
if ( shadowCoord.z > 0 && shadowCoord.z < 1.0 )
{
float dist = texture(shadowMap, vec3(shadowCoord.st + offset, cascadeIndex)).r;
// 从光看 dist
// 同一个点,但是主相机看 shadowCoord.z
// 如果光看到的更小,则说明被遮挡
if (shadowCoord.w > 0 && dist < shadowCoord.z - bias)
{
shadow = ambient;
}
}
return shadow;
}
// 百分比渐进过滤
float filterPCF(vec4 sc, uint cascadeIndex)
{
ivec2 texDim = textureSize(shadowMap, 0).xy;
float scale = 0.75;
float dx = scale * 1.0 / float(texDim.x);
float dy = scale * 1.0 / float(texDim.y);
float shadowFactor = 0.0;
int count = 0;
int range = 1;
for (int x = -range; x <= range; x++)
{
for (int y = -range; y <= range; y++)
{
shadowFactor += textureProj(sc, vec2(dx*x, dy*y), cascadeIndex);
count++;
}
}
return shadowFactor / count;
}
const mat4 biasMat = mat4(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.5, 0.5, 0.0, 1.0
);
void main()
{
float perceptualRoughness;
float metallic;
vec3 diffuseColor;
vec4 baseColor;
// 基础反射值
vec3 f0 = vec3(0.04);
// 透明度裁剪
if (material.alphaMask == 1.0f)
{
if (material.baseColorTextureSet > -1)
{
baseColor = SRGBtoLINEAR(texture(diffuseMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1)) * material.baseColorFactor;
}
else
{
baseColor = material.baseColorFactor;
}
if (baseColor.a < material.alphaMaskCutoff)
{
discard;
}
}
// 粗糙度(基础值)
perceptualRoughness = material.roughnessFactor;
// 金属度(基础值)
metallic = material.metallicFactor;
// 采样 粗糙度和金属度
if (material.physicalDescriptorTextureSet > -1)
{
// R 通道 = 环境光遮蔽 AO (Occlusion)
// G 通道 = 粗糙度 (Roughness)
// B 通道 = 金属度 (Metallic)
vec4 mrSample = texture(physicalMap, material.physicalDescriptorTextureSet == 0 ? inUV0 : inUV1);
perceptualRoughness = mrSample.g * perceptualRoughness;
metallic = mrSample.b * metallic;
}
else
{
perceptualRoughness = clamp(perceptualRoughness, c_MinRoughness, 1.0);
metallic = clamp(metallic, 0.0, 1.0);
}
// 采样 基础颜色
if (material.baseColorTextureSet > -1)
{
baseColor = SRGBtoLINEAR(texture(diffuseMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1)) * material.baseColorFactor;
}
else
{
baseColor = material.baseColorFactor;
}
baseColor *= inColor;
diffuseColor = baseColor.rgb * (vec3(1.0) - f0);
diffuseColor *= 1.0 - metallic;
// 粗糙度的平方(人眼对粗糙的感受不是线性的)
float alphaRoughness = perceptualRoughness * perceptualRoughness;
//--------------------------------------------------------------------------
// 高光颜色
// 它决定了:
// 物体反光有多亮
// 反光是什么颜色
// 金属 / 非金属的反光区别
vec3 specularColor = mix(f0, baseColor.rgb, metallic);
// 计算反射率基准值
float reflectance = max(max(specularColor.r, specularColor.g), specularColor.b);
// 计算90°掠射时的反射强度(菲涅尔上限)
float reflectance90 = clamp(reflectance * 25.0, 0.0, 1.0);
// 定义菲涅尔的两个关键参数:垂直入射(R0) / 掠射入射(R90)
vec3 specularEnvironmentR0 = specularColor.rgb;
vec3 specularEnvironmentR90 = vec3(1.0) * reflectance90;
//--------------------------------------------------------------------------
// 1. 获取最终表面法线(纹理法线 / 模型法线)
vec3 n = (material.normalTextureSet > -1) ? getNormal() : normalize(inNormal);
// 2. 计算PBR核心方向向量
vec3 v = normalize(ubo.camPos - inPosition); // 点 -> 相机
vec3 l = normalize(-pass.light[0].direction); // 点 -> 光源(平行光需要取反)
vec3 h = normalize(l+v); // 半角向量:光线+视角的中间方向
// 相机 -> 点 转换为 点 -> 光
vec3 reflection = normalize(reflect(-v, n)); // 环境反射向量(用于环境贴图采样)
// 3. 计算PBR必需的点积(全部钳位避免除零/负数)
float NdotL = clamp(dot(n, l), 0.001, 1.0); // 法线·光线
float NdotV = clamp(abs(dot(n, v)), 0.001, 1.0); // 法线·视角(取绝对值)
float NdotH = clamp(dot(n, h), 0.0, 1.0); // 法线·半角向量
float LdotH = clamp(dot(l, h), 0.0, 1.0); // 光线·半角向量
float VdotH = clamp(dot(v, h), 0.0, 1.0); // 视角·半角向量
PbrInfo pbrInputs = PbrInfo(
NdotL,
NdotV,
NdotH,
LdotH,
VdotH,
perceptualRoughness,
metallic,
specularEnvironmentR0,
specularEnvironmentR90,
alphaRoughness,
diffuseColor,
specularColor
);
// 计算参数
vec3 F = specularReflection(pbrInputs);
float G = geometricOcclusion(pbrInputs);
float D = microfacetDistribution(pbrInputs);
const vec3 u_LightColor = pass.light[0].strength;
// 计算光照结果
// 漫反射
vec3 diffuseContrib = (1.0 - F) * diffuse(pbrInputs);
// 高光部分
vec3 specContrib = F * G * D / (4.0 * NdotL * NdotV);
// 最终光照 = 漫反射 + 高光,受法线与灯光夹角影响
vec3 color = NdotL * u_LightColor * (diffuseContrib + specContrib);
if(ONLY_SH)
color = diffuseContrib;
//----------------------------------阴影计算
// 返回所在级联
uint cascadeIndex = 0;
for(uint i = 0; i < SHADOW_MAP_CASCADE_COUNT - 1; ++i)
{
if(inViewPos.z < pass.cascadeSplits[i])
{
cascadeIndex = i + 1;
}
}
// 所在贴图位置
vec4 shadowCoord = (biasMat * cascade.viewProj[cascadeIndex]) * vec4(inPosition, 1.0);
// xy 纹理坐标
// z 点到光源的距离
shadowCoord.xyz /= shadowCoord.w;
float shadow = 0;
if (enablePCF == 1)
{
shadow = filterPCF(shadowCoord, cascadeIndex);
}
else
{
shadow = textureProj(shadowCoord, vec2(0.0), cascadeIndex);
}
// 只影响直射光
if(!ONLY_SH)
color *= shadow;
// 计算ibl光照
color += getIBLContribution(pbrInputs, n, reflection);
const float u_OcclusionStrength = 1.0f;
// 采样 环境光遮蔽
if (material.occlusionTextureSet > -1)
{
float ao = texture(aoMap, (material.occlusionTextureSet == 0 ? inUV0 : inUV1)).r;
color = mix(color, color * ao, u_OcclusionStrength);
}
// 采样 自发光
vec3 emissive = material.emissiveFactor.rgb * material.emissiveStrength;
if (material.emissiveTextureSet > -1)
{
emissive *= SRGBtoLINEAR(texture(emissiveMap, material.emissiveTextureSet == 0 ? inUV0 : inUV1)).rgb;
};
if(!ONLY_SH)
color += emissive;
outColor = vec4(color, baseColor.a);
// --------------------------------调试绘图-------------------------------
if (pass.debugViewInputs > 0.0)
{
int index = int(pass.debugViewInputs);
switch (index)
{
case 1:
outColor.rgba = material.baseColorTextureSet > -1 ? texture(diffuseMap, material.baseColorTextureSet == 0 ? inUV0 : inUV1) : vec4(1.0f);
break;
case 2:
outColor.rgb = (material.normalTextureSet > -1) ? texture(normalMap, material.normalTextureSet == 0 ? inUV0 : inUV1).rgb : inNormal;
break;
case 3:
outColor.rgb = (material.occlusionTextureSet > -1) ? texture(aoMap, material.occlusionTextureSet == 0 ? inUV0 : inUV1).rrr : vec3(0.0f);
break;
case 4:
outColor.rgb = (material.emissiveTextureSet > -1) ? texture(emissiveMap, material.emissiveTextureSet == 0 ? inUV0 : inUV1).rgb : vec3(0.0f);
break;
case 5: // 金属度
outColor.rgb = texture(physicalMap, inUV0).bbb;
break;
case 6: // 粗糙度
outColor.rgb = texture(physicalMap, inUV0).ggg;
break;
// PBR 光照方程 调试可视化
case 10:
outColor.rgb = diffuseContrib; // 漫反射
break;
case 11:
outColor.rgb = F; // 菲涅尔
break;
case 12:
outColor.rgb = vec3(G); // 几何遮蔽
break;
case 13:
outColor.rgb = vec3(D); // 微表面分布
break;
case 14:
outColor.rgb = specContrib; // 高光
break;
case 15:// 点 -> 光
outColor.rgb = reflection; // 反射向量
break;
// 级联阴影
case 20:
{
switch(cascadeIndex)
{
case 0 :
outColor.rgb *= vec3(1.0f, 0.25f, 0.25f);
break;
case 1 :
outColor.rgb *= vec3(0.25f, 1.0f, 0.25f);
break;
case 2 :
outColor.rgb *= vec3(0.25f, 0.25f, 1.0f);
break;
case 3 :
outColor.rgb *= vec3(1.0f, 1.0f, 0.25f);
break;
}
}
break;
case 21:
outColor.rgb = shadowCoord.xxx; // 采样坐标
break;
case 22:
outColor.rgb = shadowCoord.zzz; //当前点 到光源的距离(深度)
break;
case 23:
// 把屏幕UV直接当阴影贴图UV,全屏展示阴影贴图
vec2 uv = gl_FragCoord.xy / vec2(1280.0, 720.0); // 换成你屏幕分辨率
float depth = texture(shadowMap, vec3(uv, cascadeIndex)).r;
// 直接把阴影贴图的深度值画出来
outColor = vec4(vec3(depth), 1.0);
break;
}
}
}