JS, WebGL: 如何多次在视频帧上应用模糊滤镜

huangapple go评论65阅读模式
英文:

JS, WebGL: how to apply a blur filter on a video frame multiple times

问题

我想在视频帧上使用WebGL着色器应用模糊滤镜,并将结果呈现在HTML画布上。模糊滤镜应该被多次应用。第一次应用的结果应该成为下一次的源。

我不太熟悉WebGL,但我创建了一个只应用一次模糊滤镜的简单示例。我尝试多次运行“blur”函数并使用“mix”来合并结果,但它不起作用。
演示在这里。 它有两个滑块,用于应用模糊滤镜。第二个应该模糊前一次应用的结果。

uniform sampler2D texture0;
uniform sampler2D texture1;
uniform float texWidth;
uniform float texHeight;

uniform float u_sigma;
uniform float u_sigma2;

float CalcGauss( float x, float sigma )
{
  return exp(-0.5*(x*x)/(sigma*sigma));
}

vec4 blur(vec2 texCoord, sampler2D texture, float sigma) {
    vec2 texC = texCoord;
    vec4 texCol = texture2D( texture, texC );

    vec4 gaussCol = vec4( texCol.rgb, 1.0 );
    vec2 steph     = vec2(1.0, 0.0) / texWidth;
    for ( int i = 1; i <= 32; ++ i )
    {
        float weight = CalcGauss( float(i) / 32.0, sigma * 0.5 );
        if ( weight < 1.0/255.0 )
            break;
        texCol    = texture2D( texture, texC + steph * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
        texCol    = texture2D( texture, texC - steph * float(i) );
        gaussCol += vec4( texCol.rgb * weight, weight );
    }
    
    gaussCol.rgb = clamp( gaussCol.rgb / gaussCol.w, 0.0, 1.0 );
    return vec4( gaussCol.rgb, 1.0 );
}

void main(void) {
    vec2 texCoord = vec2(gl_FragCoord.x/texWidth, 1.0 - (gl_FragCoord.y/texHeight));
    vec4 blur0 = blur(texCoord, texture0, u_sigma);
    vec4 blur1 = blur(texCoord, texture1, u_sigma2);
    gl_FragColor = mix(blur0, blur1, blur0.a);
}```

<details>
<summary>英文:</summary>

I want to apply a blur filter on a video frame using WebGL shader and render result on HTML canvas. The blur filter should be applied multiple times. The result of the first application should be the source for the next and so on.

I&#39;m not familiar with WebGL well, but I created a simple example that applies a blur filter only one time. I tried to run the &quot;blur&quot; function multiple times and used &quot;mix&quot; to merge results, but it doesn&#39;t work.
[Demo is here.](https://jsfiddle.net/liubomyrB/L3sqdvp1/4/) It has two sliders that apply a blur filter. The second one should blur the result of the previous application.

precision mediump float;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform float texWidth;
uniform float texHeight;

uniform float u_sigma;
uniform float u_sigma2;

float CalcGauss( float x, float sigma )
{
return exp(-0.5*(xx)/(sigmasigma));
}

vec4 blur(vec2 texCoord, sampler2D texture, float sigma) {
vec2 texC = texCoord;
vec4 texCol = texture2D( texture, texC );

vec4 gaussCol = vec4( texCol.rgb, 1.0 );
vec2 steph     = vec2(1.0, 0.0) / texWidth;
for ( int i = 1; i &lt;= 32; ++ i )
{
    float weight = CalcGauss( float(i) / 32.0, sigma * 0.5 );
    if ( weight &lt; 1.0/255.0 )
        break;
    texCol    = texture2D( texture, texC + steph * float(i) );
    gaussCol += vec4( texCol.rgb * weight, weight );
    texCol    = texture2D( texture, texC - steph * float(i) );
    gaussCol += vec4( texCol.rgb * weight, weight );
}

gaussCol.rgb = clamp( gaussCol.rgb / gaussCol.w, 0.0, 1.0 );
return vec4( gaussCol.rgb, 1.0 );

}

void main(void) {
vec2 texCoord = vec2(gl_FragCoord.x/texWidth, 1.0 - (gl_FragCoord.y/texHeight));
vec4 blur0 = blur(texCoord, texture0, u_sigma);
vec4 blur1 = blur(texCoord, texture1, u_sigma2);
gl_FragColor = mix(blur0, blur1, blur0.a);
}



</details>


# 答案1
**得分**: 1

要对图像进行第二次模糊处理,需要通过额外的渲染通道进行操作,例如使用额外的纹理和帧缓冲。

我已经在你的示例中进行了两次渲染尝试 -

```javascript
if (lastWidth != metadata.width) {
    prepareOffscreenFrameBuffer(fb, texfb, metadata.width, metadata.height);
    lastWidth = metadata.width;
}

// 第一次渲染通道
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.viewport(0, 0, metadata.width, metadata.height);
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, videoEl);
gl.uniform1i(texLoc, 0);
gl.uniform1f(texWidthLoc, metadata.width);
gl.uniform1f(texHeightLoc, metadata.height);
gl.uniform1f(sigmaLoc, parseFloat(sigmaInput.value));
gl.uniform1f(sigmaLoc2, parseFloat(sigmaInput2.value));
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

// 第二次渲染通道
gl.viewport(0, 0, metadata.width, metadata.height);
gl.bindTexture(gl.TEXTURE_2D, texfb);
gl.uniform1i(texLoc, 0);
gl.uniform1f(texWidthLoc, metadata.width);
gl.uniform1f(texHeightLoc, metadata.height);
gl.uniform1f(sigmaLoc, parseFloat(sigmaInput2.value));
gl.uniform1f(sigmaLoc2, parseFloat(sigmaInput.value));
gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
videoEl.requestVideoFrameCallback(processFrame);

修改后的示例

英文:

for applying blur for the second time, you have to run it withing additional pass, by using, for example, additional texture and framebuffer.

I've played around with your fiddle to run with 2 passes -

        if (lastWidth != metadata.width) {
        	prepareOffscreenFrameBuffer(fb, texfb, metadata.width, metadata.height);
          lastWidth = metadata.width;
        }
        	
        // first pass
        gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
        gl.viewport(0, 0, metadata.width, metadata.height);
        gl.bindTexture(gl.TEXTURE_2D, tex);
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, videoEl);
        gl.uniform1i(texLoc, 0);
        gl.uniform1f(texWidthLoc, metadata.width);
        gl.uniform1f(texHeightLoc, metadata.height);
        gl.uniform1f(sigmaLoc, parseFloat(sigmaInput.value));
        gl.uniform1f(sigmaLoc2, parseFloat(sigmaInput2.value));
        gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
        
        // second pass
        gl.viewport(0, 0, metadata.width, metadata.height);
        gl.bindTexture(gl.TEXTURE_2D, texfb);
        gl.uniform1i(texLoc, 0);
        gl.uniform1f(texWidthLoc, metadata.width);
        gl.uniform1f(texHeightLoc, metadata.height);
        gl.uniform1f(sigmaLoc, parseFloat(sigmaInput2.value));
        gl.uniform1f(sigmaLoc2, parseFloat(sigmaInput.value));
        gl.drawArrays(gl.TRIANGLE_FAN, 0, 4);
        videoEl.requestVideoFrameCallback(processFrame);

modified fiddle

huangapple
  • 本文由 发表于 2023年2月27日 05:18:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/75575063.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定