Ping pong blur WebGL

Started by
6 comments, last by Deliverance 8 years, 11 months ago

Hi guys,

I'm trying to blur a depth texture acquired for variance shadow mapping using webgl and I only get the result of the firs blur tap inside a texture, the other stays the same as the original. I'm new to JavaScript and I'm wondering what am I missing. The complete method is the following. There are no errors from OpenGL.

I'm enabling and disabling everything inside the for loop just to be sure there are no conflicts with resources owned by multiple objects.


function blurShadowTexture() {

        checkError();
        
        shaderBlur.bind();
      
        shaderBlur.enablePosition();
        shaderBlur.enableUV();
        shaderBlur.disableNormal();
        
        checkError();
        
        GL.bindFramebuffer(GL.FRAMEBUFFER, rttFramebufferSoft);
        GL.viewport(0.0, 0.0, SHADOW_MAP_WIDTH_SOFT, SHADOW_MAP_WIDTH_SOFT);
        GL.clear(0,0,0,0);
        
        var TRIANGLE_VERTEX = bufferScreenSpaceVertex;
        var TRIANGLE_TEXCOORD = bufferScreenSpaceTexcoords;
        
        GL.bindBuffer(GL.ARRAY_BUFFER, TRIANGLE_VERTEX);
        shaderBlur.setPositionAttrib();
        
        GL.bindBuffer(GL.ARRAY_BUFFER, TRIANGLE_TEXCOORD);
        shaderBlur.setUVAttrib();
        
        GL.activeTexture(GL.TEXTURE0);
        
        checkError();
        
        var i = 0;
        for (i=0; i<10; i++) {
            
            shaderBlur.bind();
            checkError();
            GL.bindFramebuffer(GL.FRAMEBUFFER, rttFramebufferSoft);
            GL.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, rttFloatTexture2, 0);
           
            GL.bindTexture(GL.TEXTURE_2D, rttFloatTexture);
            shaderBlur.setTexTexture(0);
            
            GL.drawArrays(GL.TRIANGLES, 0, 6);

            var t = rttFloatTexture2;
            rttFloatTexture2 = rttFloatTexture;
            rttFloatTexture = t;
  
            GL.bindTexture(GL.TEXTURE_2D, null);
            GL.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, null, 0);
            GL.bindFramebuffer(GL.FRAMEBUFFER, null);
            GL.useProgram(null);
        }
        
        checkError();
        
        shaderBlur.disableUV();
        shaderBlur.disablePosition();
   
        GL.bindFramebuffer(GL.FRAMEBUFFER, null);
    }

Advertisement

Hi, try calling checkError (if it's calling glGetError internally) after every single GL call. On first sight I can't see anything wrong (didn't try myself).

Nothing comes up. The result of the blur is written in the second texture but the first texture ( rttFloatTexture ) remains unchanged during the loop, so the rttFloatTexture2 contains only 1 tap of blur so to speak.

I'm no JavaScript expert either but I think the "scoped" t variable in the loop isn't scoped in JavaScript at all but lives in the scope of the function.

Could someone with JS knowledge affirm that the swap is fine?

Try a swap like this [rttFloatTexture2, rttFloatTexture] = [rttFloatTexture, rttFloatTexture2];

Also try an indexed array of textures and only swap the integer index to be extra sure that your problem isn't there (that it might copy the texture instance instead of the reference, etc).

But I feel I'm totally off here and the problem is something completely else smile.png

Maybe also try binding your vertex buffers, setting the viewport, etc, every time in the loop to rule out that it gets unbound or something...

Thanks pcmaster. I was looking into that and I've also implemented the code using an array of textures and only switching indices, still it doesn't work.

The curious thing is that this code was written using classes and replaced this (working) code that did the exact thing. I'm gonna have to write a minimal complete example of doing a blur and start over if I don't find the error sometimes soon today.


    function blurShadowTexture() {

        GL.useProgram(SHADER_PROGRAM_BLUR);
        
        GL.bindFramebuffer(GL.FRAMEBUFFER, rttFramebufferSoft);

        GL.viewport(0.0, 0.0, SHADOW_MAP_WIDTH_SOFT, SHADOW_MAP_WIDTH_SOFT);
        
        for (i=0; i<16; i++) {
 
            GL.framebufferTexture2D(GL.FRAMEBUFFER, GL.COLOR_ATTACHMENT0, GL.TEXTURE_2D, rttFloatTexture2, 0);

            GL.activeTexture(GL.TEXTURE0);
            GL.bindTexture(GL.TEXTURE_2D, rttFloatTexture);
            GL.uniform1i(GL.getUniformLocation(SHADER_PROGRAM_BLUR, "tex"), 0);
        
            var TRIANGLE_VERTEX = bufferScreenSpaceVertex;
            var TRIANGLE_TEXCOORD = bufferScreenSpaceTexcoords;
            
            GL.bindBuffer(GL.ARRAY_BUFFER, TRIANGLE_VERTEX);
            GL.vertexAttribPointer(_position_pt, 3, GL.FLOAT, false, 0, 0) ;
            
            GL.bindBuffer(GL.ARRAY_BUFFER, TRIANGLE_TEXCOORD);
            GL.vertexAttribPointer(_texcoord_pt, 2, GL.FLOAT, false, 0, 0) ;
            
            GL.drawArrays(GL.TRIANGLES, 0, 6);

            GL.bindTexture(GL.TEXTURE_2D, null);

            var rtt = rttFloatTexture;
            rttFloatTexture = rttFloatTexture2;
            rttFloatTexture2 = rtt;
        }
        
        GL.viewport(0.0, 0.0, CANVAS.width, CANVAS.height);
        
        GL.clearColor(0.5, 0.5, 0.5, 0.0);
        
        GL.bindFramebuffer(GL.FRAMEBUFFER, null);
    } 

I've found the error. I was rendering with a depth function of GL_LESS, instead of GL_LEQUAL.

I was also not clearing the depth buffer and this caused the second draw of the blurring algorithm to fail because of the depth test.

Switching to GL_LEQUAL solved the problem.

Or you could disable depth testing altogether ( glDisable( GL_DEPTH_TEST ) ). You don't need it for a blur pass.

"I AM ZE EMPRAH OPENGL 3.3 THE CORE, I DEMAND FROM THEE ZE SHADERZ AND MATRIXEZ"

My journals: dustArtemis ECS framework and Making a Terrain Generator

Yep :D

This topic is closed to new replies.

Advertisement