Browse Source

bug fixes

Aron Kovacs 4 years ago
parent
commit
49aaa48e6e

+ 39 - 29
src/mol-canvas3d/passes/draw.ts

@@ -62,6 +62,8 @@ export class DrawPass {
     private depthTextureVolumes: Texture
     private depthMerge: DepthMergeRenderable
 
+    private readonly dummyDepthTexture: Texture
+
     constructor(private webgl: WebGLContext, width: number, height: number) {
         const { extensions, resources } = webgl;
 
@@ -83,6 +85,9 @@ export class DrawPass {
             this.depthTextureVolumes.define(width, height);
         }
         this.depthMerge = getDepthMergeRenderable(webgl, this.depthTexturePrimitives, this.depthTextureVolumes, this.packedDepth);
+
+        this.dummyDepthTexture = resources.texture('image-depth', 'depth', 'ushort', 'nearest');
+        this.dummyDepthTexture.define(2, 2);
     }
 
     setSize(width: number, height: number) {
@@ -118,6 +123,8 @@ export class DrawPass {
         const { x, y, width, height } = camera.viewport;
         renderer.setViewport(x, y, width, height);
 
+        // console.log('toDrawingBuffer', toDrawingBuffer);
+
         let renderTarget;
         if (toDrawingBuffer) {
             renderTarget = null;
@@ -131,46 +138,48 @@ export class DrawPass {
         // do a depth pass if not rendering to drawing buffer and
         // extensions.depthTexture is unsupported (i.e. depthTarget is set)
         if (!toDrawingBuffer && this.depthTargetPrimitives) {
+            console.log('packed depth opaque primitives');
             renderer.render(this.depthTargetPrimitives, scene.primitives, camera, 'depth', true, transparentBackground, 1, null, false);
         }
 
-        this.depthTexturePrimitives.attachFramebuffer(renderTarget!.framebuffer, 'depth');
-        renderer.setViewport(0, 0, this.colorTarget.getWidth(), this.colorTarget.getHeight());
-        renderer.render(renderTarget, scene.primitives, camera, 'color', true, transparentBackground, 1, null, false);
-
-        if (helper.debug.isEnabled) {
-            helper.debug.syncVisibility();
-            renderer.render(renderTarget, helper.debug.scene, camera, 'color', false, transparentBackground, 1, null, false);
-        }
-        if (helper.handle.isEnabled) {
-            renderer.render(renderTarget, helper.handle.scene, camera, 'color', false, transparentBackground, 1, null, false);
-        }
-        if (helper.camera.isEnabled) {
-            helper.camera.update(camera);
-            renderer.render(renderTarget, helper.camera.scene, helper.camera.camera, 'color', false, transparentBackground, 1, null, false);
-        }
+        // render opaque color
+        // this.depthTexturePrimitives.attachFramebuffer(renderTarget!.framebuffer, 'depth');
+        renderer.render(renderTarget, scene.primitives, camera, 'color', true, transparentBackground, 1, this.dummyDepthTexture, false);
+
+        // if (helper.debug.isEnabled) {
+        //     helper.debug.syncVisibility();
+        //     renderer.render(renderTarget, helper.debug.scene, camera, 'color', false, transparentBackground, 1, null, false);
+        // }
+        // if (helper.handle.isEnabled) {
+        //     renderer.render(renderTarget, helper.handle.scene, camera, 'color', false, transparentBackground, 1, null, false);
+        // }
+        // if (helper.camera.isEnabled) {
+        //     helper.camera.update(camera);
+        //     renderer.render(renderTarget, helper.camera.scene, helper.camera.camera, 'color', false, transparentBackground, 1, null, false);
+        // }
 
         if (!toDrawingBuffer && this.depthTargetPrimitivesTransparent) {
+            console.log('packed depth transparent primitives');
             renderer.render(this.depthTargetPrimitivesTransparent, scene.primitives, camera, 'depth', true, transparentBackground, 1, null, false);
         }
 
+        // render transparent color
         if (renderTarget !== null) {
-            // this.depthTexturePrimitivesTransparent.attachFramebuffer(renderTarget.framebuffer, 'depth');
-            renderer.setViewport(0, 0, this.colorTarget.getWidth(), this.colorTarget.getHeight());
+            this.depthTexturePrimitivesTransparent.attachFramebuffer(renderTarget.framebuffer, 'depth');
             renderer.render(renderTarget, scene.primitives, camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
         }
 
-        if (helper.debug.isEnabled) {
-            helper.debug.syncVisibility();
-            renderer.render(renderTarget, helper.debug.scene, camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
-        }
-        if (helper.handle.isEnabled) {
-            renderer.render(renderTarget, helper.handle.scene, camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
-        }
-        if (helper.camera.isEnabled) {
-            helper.camera.update(camera);
-            renderer.render(renderTarget, helper.camera.scene, helper.camera.camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
-        }
+        // if (helper.debug.isEnabled) {
+        //     helper.debug.syncVisibility();
+        //     renderer.render(renderTarget, helper.debug.scene, camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
+        // }
+        // if (helper.handle.isEnabled) {
+        //     renderer.render(renderTarget, helper.handle.scene, camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
+        // }
+        // if (helper.camera.isEnabled) {
+        //     helper.camera.update(camera);
+        //     renderer.render(renderTarget, helper.camera.scene, helper.camera.camera, 'color', false, transparentBackground, 1, this.depthTexturePrimitives, true);
+        // }
 
         // do direct-volume rendering
         if (!toDrawingBuffer) {
@@ -185,6 +194,7 @@ export class DrawPass {
 
             // do volume depth pass if extensions.depthTexture is unsupported (i.e. depthTarget is set)
             if (this.depthTargetVolumes) {
+                console.log('packed depth volumes');
                 renderer.render(this.depthTargetVolumes, scene.volumes, camera, 'depth', true, transparentBackground, 1, this.depthTexturePrimitives, false);
             }
         }
@@ -203,7 +213,7 @@ export class DrawPass {
             this.webgl.gl.scissor(x, y, width, height);
             this.webgl.gl.clear(this.webgl.gl.COLOR_BUFFER_BIT);
             this.depthMerge.render();
-            this.colorTarget.bind();
+            renderTarget!.bind();
         }
     }
 

+ 47 - 28
src/mol-gl/renderer.ts

@@ -177,32 +177,34 @@ namespace Renderer {
 
         const sharedTexturesList: Textures = [];
 
-        let enableWboit = textureFloat !== null && colorBufferFloat !== null && depthTexture !== null;
+        const enableWboit = textureFloat !== null && colorBufferFloat !== null && depthTexture !== null;
 
-        let wboitATexture = enableWboit ? resources.texture('image-float32', 'rgba', 'float', 'nearest') : null;
+        const wboitATexture = enableWboit ? resources.texture('image-float32', 'rgba', 'float', 'nearest') : null;
         wboitATexture?.define(viewport.width, viewport.height);
-        let wboitBTexture = enableWboit ? resources.texture('image-float32', 'rgba', 'float', 'nearest') : null;
+        const wboitBTexture = enableWboit ? resources.texture('image-float32', 'rgba', 'float', 'nearest') : null;
         wboitBTexture?.define(viewport.width, viewport.height);
 
-        let evaluateWboitRenderable = enableWboit ? getEvaluateWboitRenderable(ctx, wboitATexture!, wboitBTexture!) : null;
+        const evaluateWboitRenderable = enableWboit ? getEvaluateWboitRenderable(ctx, wboitATexture!, wboitBTexture!) : null;
 
-        let wboitFramebuffers = [resources.framebuffer()];
-        if (drawBuffers) {
-            wboitFramebuffers.push(resources.framebuffer());
+        const wboitFramebuffers = [resources.framebuffer()];
+        if (enableWboit) {
+            if (drawBuffers) {
+                wboitFramebuffers.push(resources.framebuffer());
 
-            wboitFramebuffers[0].bind();
-            drawBuffers?.drawBuffers([
-                drawBuffers.COLOR_ATTACHMENT0,
-                drawBuffers.COLOR_ATTACHMENT1,
-            ]);
+                wboitFramebuffers[0].bind();
+                drawBuffers.drawBuffers([
+                    drawBuffers.COLOR_ATTACHMENT0,
+                    drawBuffers.COLOR_ATTACHMENT1,
+                ]);
 
-            wboitATexture?.attachFramebuffer(wboitFramebuffers[0], 'color0');
-            wboitBTexture?.attachFramebuffer(wboitFramebuffers[0], 'color1');
-        } else {
-            wboitFramebuffers.push(resources.framebuffer(), resources.framebuffer());
+                wboitATexture!.attachFramebuffer(wboitFramebuffers[0], 'color0');
+                wboitBTexture!.attachFramebuffer(wboitFramebuffers[0], 'color1');
+            } else {
+                wboitFramebuffers.push(resources.framebuffer(), resources.framebuffer());
 
-            wboitATexture?.attachFramebuffer(wboitFramebuffers[0], 'color0');
-            wboitBTexture?.attachFramebuffer(wboitFramebuffers[1], 'color0');
+                wboitATexture!.attachFramebuffer(wboitFramebuffers[0], 'color0');
+                wboitBTexture!.attachFramebuffer(wboitFramebuffers[1], 'color0');
+            }
         }
 
         const view = Mat4();
@@ -322,6 +324,14 @@ namespace Renderer {
                     state.enable(gl.DEPTH_TEST);
                     state.depthMask(r.state.writeDepth);
                 }
+
+                // TODO: wboit needs the following state (but that is not acceptable for
+                // the volume rendering to work in all cases)
+                state.frontFace(gl.CCW);
+
+                // this is probably not needed
+                // state.enable(gl.DEPTH_TEST);
+                // state.depthMask(r.state.writeDepth);
             } else {
                 state.enable(gl.DEPTH_TEST);
                 if (r.values.dDoubleSided) {
@@ -360,6 +370,7 @@ namespace Renderer {
             if (depthTexture) {
                 localSharedTexturesList = [...localSharedTexturesList, ['tDepth', depthTexture]];
             }
+            // console.log('depthTexture', depthTexture);
 
             ValueCell.update(globalUniforms.uModel, group.view);
             ValueCell.update(globalUniforms.uView, camera.view);
@@ -399,17 +410,17 @@ namespace Renderer {
 
             const { renderables } = group;
 
-            state.enable(gl.SCISSOR_TEST);
-            state.disable(gl.BLEND);
-            state.colorMask(true, true, true, true);
-            state.enable(gl.DEPTH_TEST);
-
             if (renderTarget) {
                 renderTarget.bind();
             } else {
                 gl.bindFramebuffer(gl.FRAMEBUFFER, null);
             }
 
+            state.enable(gl.SCISSOR_TEST);
+            state.disable(gl.BLEND);
+            state.colorMask(true, true, true, true);
+            state.enable(gl.DEPTH_TEST);
+
             const { x, y, width, height } = viewport;
             gl.viewport(x, y, width, height);
             gl.scissor(x, y, width, height);
@@ -476,6 +487,7 @@ namespace Renderer {
                                 renderObject(r, variant, localSharedTexturesList);
                             }
                         }
+
                         if (renderTarget) {
                             renderTarget.bind();
                         } else {
@@ -486,8 +498,13 @@ namespace Renderer {
                         state.enable(gl.BLEND);
                         state.disable(gl.DEPTH_TEST);
 
-                        evaluateWboitRenderable?.update();
-                        evaluateWboitRenderable?.render();
+                        // unclear why needed but otherwise there is a
+                        // "Draw framebuffer is incomplete" error for the very first render call
+                        // before there are any renderables...
+                        if (renderables.length > 0) {
+                            evaluateWboitRenderable!.update();
+                            evaluateWboitRenderable!.render();
+                        }
                     }
                 } else {
                     for (let i = 0, il = renderables.length; i < il; ++i) {
@@ -603,9 +620,11 @@ namespace Renderer {
                     wboitATexture?.define(viewport.width, viewport.height);
                     wboitBTexture?.define(viewport.width, viewport.height);
 
+                    // TODO there should not be any need to re-create the framebuffers,
+                    // re-sizing the textures should do it
                     if (drawBuffers) {
                         wboitFramebuffers[0].destroy();
-                        wboitFramebuffers = [];
+                        wboitFramebuffers.length = 0;
                         wboitFramebuffers.push(resources.framebuffer());
 
                         wboitFramebuffers[0].bind();
@@ -619,7 +638,7 @@ namespace Renderer {
                     } else {
                         wboitFramebuffers[0].destroy();
                         wboitFramebuffers[1].destroy();
-                        wboitFramebuffers = [];
+                        wboitFramebuffers.length = 0;
                         wboitFramebuffers.push(resources.framebuffer(), resources.framebuffer());
 
                         wboitATexture?.attachFramebuffer(wboitFramebuffers[0], 'color0');
@@ -671,7 +690,7 @@ function getEvaluateWboitRenderable(ctx: WebGLContext, wboitATexture: Texture, w
     };
 
     const schema = { ...EvaluateWboitSchema };
-    const shaderCode = ShaderCode('ssao', quad_vert, evaluate_wboit_frag);
+    const shaderCode = ShaderCode('wboit', quad_vert, evaluate_wboit_frag);
     const renderItem = createComputeRenderItem(ctx, 'triangles', shaderCode, schema, values);
 
     return createComputeRenderable(renderItem, values);

+ 11 - 11
src/mol-gl/shader/chunks/wboit-params.glsl.ts

@@ -1,16 +1,16 @@
 export default `
 #if defined(dRenderVariant_color)
-#if !defined(dRenderMode_volume) && !defined(dRenderMode_isosurface)
-    uniform sampler2D tDepth;
-    
-    float getDepth(const in vec2 coords) {
-        #ifdef dPackedDepth
-            return unpackRGBAToDepth(texture2D(tDepth, coords));
-        #else
-            return texture2D(tDepth, coords).r;
-        #endif
-    }
-#endif
+    #if !defined(dRenderMode_volume) && !defined(dRenderMode_isosurface)
+        uniform sampler2D tDepth;
+
+        float getDepth(const in vec2 coords) {
+            #ifdef dPackedDepth
+                return unpackRGBAToDepth(texture2D(tDepth, coords));
+            #else
+                return texture2D(tDepth, coords).r;
+            #endif
+        }
+    #endif
     uniform int uRenderWboit;
     uniform vec4 uViewport;
 #endif

+ 1 - 0
src/mol-gl/shader/chunks/wboit-write.glsl.ts

@@ -4,6 +4,7 @@ if (uRenderWboit == 0) {
         discard;
     }
 } else if (uRenderWboit == 1) {
+    // TODO: volumes not rendering has something to do with the depth test
     if (gl_FragColor.a != 1.0 && absFragDepth < getDepth(gl_FragCoord.xy / uViewport.zw)) {
         float alpha = gl_FragColor.a;
         float wboitWeight = alpha * clamp(pow(1.0 - absFragDepth, 2.0), 0.01, 1.0);

+ 1 - 1
src/mol-gl/shader/direct-volume.frag.ts

@@ -431,7 +431,7 @@ void main () {
     #endif
 
     #if defined(dRenderVariant_color)
-        float absFragDepth = abs(calcDepth(vBoundingSphere.xyz));
+        float absFragDepth = abs(calcDepth((uView * vec4(vBoundingSphere.xyz, 1.0)).xyz));
         #include wboit_write
     #endif
 }

+ 6 - 2
src/mol-gl/webgl/render-item.ts

@@ -204,7 +204,11 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
                 state.currentRenderItemId = id;
             }
             if (isDebugMode) {
-                checkFramebufferStatus(ctx.gl);
+                try {
+                    checkFramebufferStatus(ctx.gl);
+                } catch (e) {
+                    throw new Error(`Framebuffer error rendering item id ${id}: '${e}'`);
+                }
             }
             if (elementsBuffer) {
                 instancedArrays.drawElementsInstanced(glDrawMode, drawCount, elementsBuffer._dataType, 0, instanceCount);
@@ -215,7 +219,7 @@ export function createRenderItem<T extends string>(ctx: WebGLContext, drawMode:
                 try {
                     checkError(ctx.gl);
                 } catch (e) {
-                    throw new Error(`Error rendering item id ${id}: '${e}'`);
+                    throw new Error(`Draw error rendering item id ${id}: '${e}'`);
                 }
             }
         },