542 lines
16 KiB
GLSL
542 lines
16 KiB
GLSL
#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;
|
||
}
|
||
}
|
||
}
|