Files
Prism/Editor/assets/shaders/SceneComposite.glsl
2026-04-06 19:06:04 +08:00

164 lines
4.2 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.

#type vertex
#version 430
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoord;
out vec2 v_TexCoord;
void main()
{
vec4 position = vec4(a_Position.xy, 0.0, 1.0);
v_TexCoord = a_TexCoord;
gl_Position = position;
}
#type fragment
#version 430
layout(location = 0) out vec4 o_Color;
layout(location = 1) out vec4 o_BloomTexture;
in vec2 v_TexCoord;
uniform sampler2DMS u_Texture;
uniform sampler2DMS u_DepthTexture;
uniform sampler2D u_BloomTexture;
uniform mat4 u_InvProjection;
uniform mat4 u_InvView;
// Fog
uniform float u_FogEnabled;
uniform vec3 u_FogColor;
uniform float u_FogDensity; // 雾密度,典型值 0.01~0.05
uniform float u_FogHeight; // 雾的起始高度(世界 Y 坐标),低于此高度雾最浓
uniform float u_FogHeightFalloff; // 高度衰减系数,值越大高度影响越剧烈(典型 0.5~2.0
uniform bool u_EnableAutoExposure;
uniform float u_ManualExposure;
layout(std430, binding = 2) buffer Exposure
{
float u_Exposure;
};
uniform int u_TextureSamples;
uniform bool u_EnableBloom;
uniform float u_BloomThreshold;
const float uFar = 1.0;
vec4 SampleTexture(sampler2D tex, vec2 texCoord)
{
return texture(tex, texCoord);
}
vec4 MultiSampleTexture(sampler2DMS tex, vec2 tc)
{
ivec2 texSize = textureSize(tex);
ivec2 texCoord = ivec2(tc * texSize);
vec4 result = vec4(0.0);
for (int i = 0; i < u_TextureSamples; i++)
result += texelFetch(tex, texCoord, i);
result /= float(u_TextureSamples);
return result;
}
float MultiSampleDepth(sampler2DMS tex, vec2 tc)
{
ivec2 texSize = textureSize(tex);
ivec2 texCoord = ivec2(tc * texSize);
float result = 0.0;
for (int i = 0; i < u_TextureSamples; i++)
result += texelFetch(tex, texCoord, i).r;
result /= float(u_TextureSamples);
return result;
}
void main()
{
const float gamma = 2.2;
const float pureWhite = 1.0;
// Tonemapping
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
vec3 color = msColor.rgb;
if (u_EnableBloom)
{
vec3 bloomColor = texture(u_BloomTexture, v_TexCoord).rgb;
color += bloomColor;
}
float exposure = 1.0f;
if(u_EnableAutoExposure)
exposure = u_Exposure;
else
exposure = u_ManualExposure;
color *= exposure;
// Reinhard tonemapping operator.
// see: "Photographic Tone Reproduction for Digital Images", eq. 4
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722));
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance);
// Scale color by ratio of average luminances.
vec3 mappedColor = (mappedLuminance / luminance) * color;
if (u_FogEnabled > 0.5)
{
// 1. 获取深度并重建视空间坐标
float depth = MultiSampleDepth(u_DepthTexture, v_TexCoord);
vec4 clipPos = vec4(v_TexCoord * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 viewPos4 = u_InvProjection * clipPos;
viewPos4 /= viewPos4.w;
vec3 viewPos = viewPos4.xyz; // 视空间坐标相机为原点Z 轴向内)
// 2. 距离雾因子(指数雾)
float distance = length(viewPos);
float distanceFactor = 1.0 - exp(-distance * u_FogDensity);
// 可选:指数平方雾(更平滑)
// float distanceFactor = 1.0 - exp(-pow(distance * u_FogDensity, 2.0));
// 3. 高度雾因子(基于世界 Y
// 将视空间坐标转换到世界空间
vec4 worldPos4 = u_InvView* vec4(viewPos, 1.0);
vec3 worldPos = worldPos4.xyz / worldPos4.w;
float worldY = worldPos.y;
float heightFactor = 0.0;
if (worldY < u_FogHeight)
{
// 低于起始高度:雾最浓,因子为 1
heightFactor = 1.0;
}
else
{
// 高于起始高度:指数衰减,高度越高雾越淡
float deltaY = worldY - u_FogHeight;
heightFactor = exp(-deltaY * u_FogHeightFalloff);
}
// 可选:使用 clamp 限制范围
heightFactor = clamp(heightFactor, 0.0, 1.0);
// 4. 综合雾因子(可相乘,也可取最大值,通常相乘)
float fogFactor = distanceFactor * heightFactor;
// 5. 混合雾颜色(雾颜色直接使用 u_FogColor已在 LDR 空间)
mappedColor = mix(mappedColor, u_FogColor, fogFactor);
}
// Gamma correction.
o_Color = vec4(pow(mappedColor, vec3(1.0 / gamma)), 1.0);
// Show over-exposed areas
// if (o_Color.r > 1.0 || o_Color.g > 1.0 || o_Color.b > 1.0)
// o_Color.rgb *= vec3(1.0, 0.25, 0.25);
}