使用Three.js将UI元素直接绘制到WebGL区域

时间:2012-10-01 04:20:37

标签: user-interface webgl three.js hud

在Three.js中,是否可以使用常规HTML5画布元素直接绘制到WebGL区域(例如,平视显示或UI元素)?

如果是这样,您如何获得上下文以及可用的绘图命令?

如果没有,是否还有另一种方法可以通过其他Three.js或特定于WebGL的绘图命令与Three.js合作完成此任务?

我的备份计划是使用HTML div作为叠加层,但我认为应该有更好的解决方案。

谢谢!

2 个答案:

答案 0 :(得分:11)

您无法像使用常规画布一样直接绘制到WebGL画布。但是,还有其他方法,例如

  • 像往常一样绘制到隐藏的2D画布,并将其作为四边形纹理传输到WebGL
  • 使用纹理映射四边形(例如,健康框的框架)绘制图像
  • 通过将顶点放入VBO并使用适当的多边形类型绘制路径(和形状)来绘制路径(和形状)
  • 使用位图字体(基本上是纹理四边形)或真实几何图形来绘制文本(three.js有示例和帮助程序)

使用这些通常意味着设置正交相机。

然而,所有这些都是相当多的工作,例如用真实几何图形绘制文本可能很昂贵。如果您可以使用CSS样式处理HTML div,则应该使用它们,因为它可以非常快速地进行设置。此外,绘制WebGL画布(可能使用透明度)应该是浏览器向GPU加速其div绘图的强烈提示,如果它还没有加速所有内容。

还记得你可以用CSS3实现很多,例如圆角,alpha透明度,甚至是3D透视变换,如问题评论中Anton的链接所示。

答案 1 :(得分:7)

我有完全相同的问题。我试图创建一个没有DOM的HUD(平视显示器),最后我创建了这个解决方案:

  1. 我用正交相机创建了一个单独的场景。
  2. 我创建了一个canvas元素,并使用2D绘图基元来渲染我的图形。
  3. 然后我创建了一个适合整个屏幕的平面,并使用2D画布元素作为纹理。
  4. 我在原始场景的顶部渲染了次要场景
  5. 那是HUD代码的样子:

    // We will use 2D canvas element to render our HUD.  
    var hudCanvas = document.createElement('canvas');
    
    // Again, set dimensions to fit the screen.
    hudCanvas.width = width;
    hudCanvas.height = height;
    
    // Get 2D context and draw something supercool.
    var hudBitmap = hudCanvas.getContext('2d');
    hudBitmap.font = "Normal 40px Arial";
    hudBitmap.textAlign = 'center';
    hudBitmap.fillStyle = "rgba(245,245,245,0.75)";
    hudBitmap.fillText('Initializing...', width / 2, height / 2);
    
    // Create the camera and set the viewport to match the screen dimensions.
    var cameraHUD = new THREE.OrthographicCamera(-width/2, width/2, height/2, -height/2, 0, 30 );
    
    // Create also a custom scene for HUD.
    sceneHUD = new THREE.Scene();
    
    // Create texture from rendered graphics.
    var hudTexture = new THREE.Texture(hudCanvas) 
    hudTexture.needsUpdate = true;
    
    // Create HUD material.
    var material = new THREE.MeshBasicMaterial( {map: hudTexture} );
    material.transparent = true;
    
    // Create plane to render the HUD. This plane fill the whole screen.
    var planeGeometry = new THREE.PlaneGeometry( width, height );
    var plane = new THREE.Mesh( planeGeometry, material );
    sceneHUD.add( plane );
    

    这就是我添加到渲染循环中的内容:

    // Render HUD on top of the scene.
    renderer.render(sceneHUD, cameraHUD);
    

    您可以在此处使用完整的源代码: http://codepen.io/jaamo/pen/MaOGZV

    在我的博客上阅读有关实施的更多信息: http://www.evermade.fi/pure-three-js-hud/