164 lines
4.2 KiB
GLSL
164 lines
4.2 KiB
GLSL
#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);
|
||
}
|