WebGL Depth blur 深度模糊

251 阅读1分钟

Vox Renderer Demo (artvily.com)

最后的GLSL

precision mediump float;
attribute vec3 a_vs;
attribute vec2 a_uvs;
uniform mat4 u_objMat;
varying vec2 v_texUV;
void main() {
    gl_Position = u_objMat * vec4(a_vs, 1.0);
    v_texUV = vec2(a_uvs.x, 1.0 - a_uvs.y);
}
precision mediump float;
uniform sampler2D u_sampler0;
uniform sampler2D u_sampler1;
uniform sampler2D u_sampler2;
uniform vec4 u_color;
varying vec2 v_texUV;
//layout(location = 0) out vec4 gl_FragColor;

void main() {
    vec4 blurColor4 = texture2D(u_sampler0, v_texUV);
    vec4 depthColor4 = texture2D(u_sampler1, v_texUV);
    vec4 baseColor4 = texture2D(u_sampler2, v_texUV);
    float k = (depthColor4.w - 1000.0) / 1000.0;
    if(k > 1.0 || depthColor4.r < 0.5) k = 1.0; //把1000作为分界线
    if(k < 0.0) k = 0.0;
    //1000以上用模糊的,1000以下用basecolor
    gl_FragColor = vec4(baseColor4.xyz * (1.0 - k) + k * blurColor4.xyz, 1.0) * u_color; 
}
  • u_sampler0 image.png
  • u_sampler1 image.png
  • u_sampler2 image.png

深度图的GLSL

image.png

precision mediump float;
attribute vec3 a_vs;
uniform mat4 u_objMat;
uniform mat4 u_viewMat;
uniform mat4 u_projMat;
varying vec4 v_color;
void main() {
    vec4 viewPv = u_viewMat * u_objMat * vec4(a_vs, 1.0);
    gl_Position = u_projMat * viewPv;
    v_color = vec4(abs(viewPv.xyz), length(viewPv.xyz));
}
precision mediump float;
varying vec4 v_color;
//layout(location = 0) out vec4 gl_FragColor;

void main() {
    gl_FragColor = vec4(vec3(1.0), v_color.w);
}
  • 这里的深度是真实的长度,储存在w中,不太需要考虑精度的问题

blur图的计算

image.png

image.png

precision mediump float;
attribute vec3 a_vs;
attribute vec2 a_uvs;
varying vec2 v_uvs;
void main() {
    gl_Position = vec4(a_vs, 1.0);
    v_uvs = vec2(a_uvs.x, 1.0 - a_uvs.y); //上下翻转
}
precision mediump float;
uniform vec4 u_color;
uniform vec4 u_texSize;
uniform sampler2D u_sampler0;
varying vec2 v_uvs;
//out vec4 gl_FragColor;

void main() {
    vec2 tex_offset = u_color.a / u_texSize.xy;
    float dy = tex_offset.y;
    tex_offset.x = 0.0;
    vec3 result = texture2D(u_sampler0, v_uvs).rgb * 0.227027;
    result += texture2D(u_sampler0, v_uvs + tex_offset).rgb * 0.1945946;
    result += texture2D(u_sampler0, v_uvs - tex_offset).rgb * 0.1945946;
    tex_offset.y = dy * 2.0;
    result += texture2D(u_sampler0, v_uvs + tex_offset).rgb * 0.1216216;
    result += texture2D(u_sampler0, v_uvs - tex_offset).rgb * 0.1216216;
    tex_offset.y = dy * 3.0;
    result += texture2D(u_sampler0, v_uvs + tex_offset).rgb * 0.054054;
    result += texture2D(u_sampler0, v_uvs - tex_offset).rgb * 0.054054;
    tex_offset.y = dy * 4.0;
    result += texture2D(u_sampler0, v_uvs + tex_offset).rgb * 0.016216;
    result += texture2D(u_sampler0, v_uvs - tex_offset).rgb * 0.016216;
    gl_FragColor = vec4(result * u_color.rgb, 1.0);
}
  • u_color大部分时候都是(1,1,1,2)
  • 只通过y轴方向模糊