#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; in vec2 v_TexCoord; uniform sampler2D u_Texture; uniform bool u_Horizontal; // 未使用,可保留或移除 uniform bool u_FirstPass; // 是否进行阈值处理 uniform float u_Threshold; // 亮度阈值 uniform int u_Quality; uniform float u_Directions; // 模糊方向数 uniform float u_Size; // 模糊半径 void main() { float Pi = 6.28318530718; // 2*PI vec2 Radius = u_Size / textureSize(u_Texture, 0); // 中心像素采样 vec3 centerColor = texture(u_Texture, v_TexCoord).rgb; float centerLum = dot(centerColor, vec3(0.2126, 0.7152, 0.0722)); // 如果启用第一次处理且中心像素亮度低于阈值,则直接输出黑色(不进行模糊) if (u_FirstPass && centerLum <= u_Threshold) { o_Color = vec4(0.0, 0.0, 0.0, 1.0); return; } vec3 result = centerColor; // 先累加中心像素 float totalSamples = 1.0; // 有效采样计数(中心像素已计入) // 周围像素采样 for (float d = 0.0; d < Pi; d += Pi / u_Directions) { for (float i = 1.0 / u_Quality; i <= 1.0; i += 1.0 / u_Quality) { vec2 offset = vec2(cos(d), sin(d)) * Radius * i; vec3 sampleColor = texture(u_Texture, v_TexCoord + offset).rgb; if (u_FirstPass) { float lum = dot(sampleColor, vec3(0.2126, 0.7152, 0.0722)); if (lum <= u_Threshold) { // 低于阈值则贡献黑色,但采样点仍计入分母?这里选择不计入有效采样数 // 若希望保持模糊能量,可以 continue 跳过累加,但需调整分母 // 为简单起见,此处设为黑色并计入计数(分母不变),也可选择跳过 sampleColor = vec3(0.0); // 如果希望忽略该采样点,可以 continue 并减少 totalSamples // 但为了效果平滑,这里保留为黑色并计入计数 } } result += sampleColor; totalSamples += 1.0; } } // 归一化:除以总采样数(包括中心像素) // 若之前选择忽略低于阈值的采样点(continue),则需相应调整 totalSamples result /= totalSamples; o_Color = vec4(result, 1.0); }