使用canvas(Three.js)叠加在canvas(WebGL)上

3

我有两个画布。第一个应该是背景,它的内容通过原始WebGL(3D)渲染。第二个画布应该覆盖在第一个画布上,并且主要是透明的。它的内容通过three.js(3D内容)渲染。不幸的是,第二个画布没有被放在第一个画布的上方,而是旁边。

如何使用透明的three.js场景背景将第二个画布绘制在第一个画布的上方?

更新:

我采用了gaitat的建议。然而,它仍然没有起作用(请参见全屏截图。由于Oculus Rift支持而两次呈现的灰色框。)。Canvas 2仍然没有放在第一个画布的上方,它的背景也不透明。提醒一下:灰色正方形是通过称为webglcanvas的画布上的原始WebGL绘制的,而盒子是在leapcanvas上通过three.js渲染的。

代码1(画布和div的初始化[Xtend / Java]):

Browser::getDocument().getElementById("view").appendChild(webglDiv)


    val Element webGLCanvasDiv = Browser::getDocument().createDivElement()
    webGLCanvasDiv.style.setCssText("position: absolute")
    webGLCanvasDiv.style.setCssText("z-index: 8")
    webGLCanvasDiv.setId("webGLCanvasDiv")      
    Browser::getDocument().getElementById("webglDiv").appendChild(webGLCanvasDiv)       


    val webGLCanvas = Browser::getDocument().createCanvasElement()
    webGLCanvas.setWidth(viewportWidth)
    webGLCanvas.setHeight(viewportHeight)
    webGLCanvas.style.setCssText("border-bottom: solid 1px #DDDDDD")
    webGLCanvas.setId("webglcanvas")        
    Browser::getDocument().getElementById("webGLCanvasDiv").appendChild(webGLCanvas)        


    val Element webGLLeapDiv = Browser::getDocument().createDivElement()
    webGLLeapDiv.style.setCssText("position: absolute")
    webGLLeapDiv.style.setCssText("z-index: 10")     
    webGLLeapDiv.setId("webGLLeapDiv")      
    Browser::getDocument().getElementById("webglDiv").appendChild(webGLLeapDiv)


    val leapCanvas = Browser::getDocument().createCanvasElement()
    // canvas size is handled via renderer in Javascript        
    leapCanvas.setId("leapcanvas")      
    Browser::getDocument().getElementById("webGLLeapDiv").appendChild(leapCanvas)

代码2(three.js场景的渲染[Javascript])

var foreground = $doc.getElementById("leapcanvas");     

    var camera, scene, renderer;
    var geometry, material, mesh;

    init();
    animate();

    function init() {

        camera = new $wnd.THREE.PerspectiveCamera(75, 500 / 500, 1, 10000);
        camera.position.z = 500;

        scene = new $wnd.THREE.Scene();

        geometry = new $wnd.THREE.BoxGeometry(200, 200, 200);
        material = new $wnd.THREE.MeshNormalMaterial();         

        mesh = new $wnd.THREE.Mesh(geometry, material);
        scene.add(mesh);

        renderer = new $wnd.THREE.WebGLRenderer({
            canvas : foreground,
            alpha : true
        });


        renderer.setSize(viewportWidth / 2, viewportHeight);
        renderer.setClearColor(0x000000, 0); 

    }

    function animate() {

        requestAnimationFrame(animate);

        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.02;

        renderer.render(scene, camera);

    }

我认为 foreground.style.top = 0 就解决了问题。明天得再检查一下。 - Sincostan
foreground.style.top = 0, foreground.style.left = 0和foreground.style.position = 'absolute'也是必要的。 - Sincostan
1个回答

5

Assuming you have in your .html

<div id="container">
    <div id="webglContainer"></div>
    <div id="threeContainer"></div>
</div>

在你的 .css 文件中需要:

/* make the canvases, children of the this container */
#container {
    position: relative;
}

#webglContainer {
    position: absolute;
    pointer-events: none;   /* this element will not catch any events */
    z-index: 8;    /* position this canvas at bottom of the other one */
}

#threeContainer {
    position: absolute;
    z-index: 10;      /* position this canvas on top of the other one */
}

我在我的应用程序中使用GWT。画布是通过Java动态创建的(编译为Ajax)。目前,两个画布共享同一个div。全屏模式在该div上调用。我今晚会尝试您的解决方案。 - Sincostan
基于Mr. Doob的示例,我创建了一个简短的JSFiddle示例来展示一个可行的解决方案,感谢这个答案。现在我将尝试在我的GWT应用程序中实现相同的功能。未来的读者:我故意使用了两个渲染器,因为我使用了原始的WebGL渲染器。请参见此帖子以了解如何使用一个渲染器。 - Sincostan
更新了我的帖子。也许你可以在此基础上添加一些内容? - Sincostan
做了那件事但忘记复制了,抱歉。父容器是webglDiv。 - Sincostan
谢谢,你的解决方案帮了我很多。 - Sincostan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接