Desenhando elementos da UI diretamente na área WebGL com Three.js
-
11-12-2019 - |
Pergunta
No Three.js, é possível desenhar diretamente na área WebGL (para um display heads-up ou elementos de UI, por exemplo) da mesma forma que você faria com um elemento de tela HTML5 normal?
Se sim, como você pode obter o contexto e quais comandos de desenho estão disponíveis?
Caso contrário, existe outra maneira de fazer isso, por meio de outros comandos de desenho específicos do Three.js ou do WebGL que cooperariam com o Three.js?
Meu plano de backup é usar divs HTML como sobreposições, mas acho que deveria haver uma solução melhor.
Obrigado!
Solução
Você não pode desenhar diretamente para a tela da WebGL da mesma maneira que você tem com tela regular. No entanto, existem outros métodos, e.
- desenhar para uma tela 2D oculta como de costume e transferir isso para webgl, usando-o como uma textura para um quad
- imagens de desenho usando quadras mapeadas texturas (por exemplo, quadros de sua caixa de saúde)
- traçar caminhos (e formas) colocando seus vértices para um VBO e desenhe que com o tipo de polígono apropriado
- desenhar texto usando uma fonte de bitmap (basicamente quads texturizados) ou geometria real (três.js tem exemplos e ajudantes para isso)
Usando estes geralmente significa configurar uma câmera ortográfica.
No entanto, tudo isso é um pouco de trabalho e e. Texto de desenho com geometria real pode ser caro. Se você puder fazer com o HTML Divs com o estilo CSS, você deve usá-los como é muito rápido para configurar. Além disso, desenhando sobre a tela do webgl, talvez usando a transparência, deve ser uma dica forte para o navegador para a GPU acelerar seu desenho div Se ele ainda não acelere tudo.
Lembre-se também que você pode conseguir muito com o CSS3, e. Cantos arredondados, transparência alfa, até mesmo transformações de perspectiva 3D, conforme demonstrado pela ligação de Anton no comentário da pergunta.
Outras dicas
Eu tive exatamente o mesmo problema.Eu estava tentando criar um HUD (Head-up display) sem DOM e acabei criando esta solução:
- Criei uma cena separada com câmera ortográfica.
- Criei um elemento canvas e usei primitivos de desenho 2D para renderizar meus gráficos.
- Então criei um plano que se ajustasse a toda a tela e usei o elemento canvas 2D como textura.
- Eu renderizei aquela cena secundária em cima da cena original
É assim que o código do HUD se parece:
// 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 );
E foi isso que adicionei ao meu loop de renderização:
// Render HUD on top of the scene.
renderer.render(sceneHUD, cameraHUD);
Você pode brincar com o código-fonte completo aqui:http://codepen.io/jaamo/pen/MaOGZV
E leia mais sobre a implementação no meu blog:http://www.evermade.fi/pure-três-js-hud/