WebGL 高斯模糊

1,406 阅读2分钟

three.js examples (threejs.org)

(6条消息) webgl智慧楼宇发光效果算法系列之高斯模糊_netcy的专栏-CSDN博客_webgl 光晕

WebGL学习之HDR与Bloom - Jeff.Zhong - 博客园 (cnblogs.com)

image.png - 高斯模糊的数值,好像很常见

  • 先施加垂直方向的高斯模糊算法;
  • 在垂直模糊的基础上进行水平方向的高斯模糊算法。
    • 分两步(左右N+N)高斯模糊算法和一步(NxN)进行两个方向的高斯模糊算法的结果基本是一致的,但是却可以提高算法的效率。

乒乓帧缓存

  • 声明
//2乒乓帧缓存(都只包含1颜色附件)
const hFbo = createFramebuffer(gl,{informat:gl.RGBA16F, type:gl.FLOAT});
const vFbo = createFramebuffer(gl,{informat:gl.RGBA16F, type:gl.FLOAT});
  • bindFramebufferInfo
  • drawBuffer
/**
 * 乒乓帧缓存
 */
gl.useProgram(pProgram.program);
for(let i=0; i < 6; i++){
    bindFramebufferInfo(gl, i%2 ? hFbo:vFbo);
    setBuffersAndAttributes(gl, pProgram, pVao);
    setUniforms(pProgram,{
        horizontal: i%2? true:false,
        image: i == 0 ? fbo.textures[1]: i%2 ? vFbo.textures[0]: hFbo.textures[0], //第1次两个乒乓帧缓存都为空,因此第一次要将灯光纹理传入
    });
    drawBufferInfo(gl, pVao);
}

THREEJS高斯模糊

image.png image.png

varying vec2 vUv;
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
#define SIGMA 3
#define KERNEL_RADIUS 3 //循环次数
varying vec2 vUv;
uniform sampler2D colorTexture;
uniform vec2 texSize; //这个是贴图的大小 往往是屏幕空间
uniform vec2 direction;//1, 0 , 是个是水平 0,1是垂直  都是遍历3次
float gaussianPdf(in float x, in float sigma) { //高斯模糊
    return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;
}
void main() {
    vec2 invSize = 1.0 / texSize;  
    float fSigma = float(SIGMA);
    float weightSum = gaussianPdf(0.0, fSigma); //0.0 
    vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum; //这个是0.0最初的那个
    for( int i = 1; i < KERNEL_RADIUS; i ++ ) { //只有一个方向的
        float x = float(i);
        float w = gaussianPdf(x, fSigma); //高斯比例
        vec2 uvOffset = direction * invSize * x; //vec2 偏移方向
        vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb; //
        vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb; //
        diffuseSum += (sample1 + sample2) * w; //相加
        weightSum += 2.0 * w; //weightSum也要相加
    }
    gl_FragColor = vec4(diffuseSum/weightSum, 1.0);
}

其他网站高斯模糊

#version 300 es
precision highp float;
uniform sampler2D image;
uniform bool horizontal;
in vec2 texcoord;
out vec4 FragColor;
const float weight[5] = float[](0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162); //加起来是一 至于为什么是这些数字 不清楚

void main() {
    vec2 tex_offset = vec2(1.0 / float(textureSize(image, 0)));//每个像素的尺寸
    vec3 result = texture(image, texcoord).rgb * weight[0];
    if (horizontal) {
        for (int i = 0; i < 5; ++i) {
            result += texture(image, texcoord + vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i];
            result += texture(image, texcoord - vec2(tex_offset.x * float(i), 0.0)).rgb * weight[i];
        }
    } else {
        for (int i = 0; i < 5; ++i) {
            result += texture(image, texcoord + vec2(0.0, tex_offset.y * float(i))).rgb * weight[i];
            result += texture(image, texcoord - vec2(0.0, tex_offset.y * float(i))).rgb * weight[i];
        }
    }
    FragColor = vec4 (result, 1.0);
}