Can you use raw WebGL Textures with three.js

≡放荡痞女 提交于 2019-12-24 04:20:58

问题


I have a fairly complicated architecture where I am doing most of my stuff in Three.JS but I also have a special renderer that renders directly to a raw WebGL texture. Is it possible to use this WebGL texture in a three.js "Texture"? It looks like the Three.JS texture class is just a container for an image or video or canvas, and somewhere deep in the guts of three.js it will upload that to a real webgl texture. How can I just have Three.js render my WebGL texture onto a mesh?


回答1:


@Brendan's answer no longer works.

No idea when it changed and too lazy to go look it up but as of r102

const texture = new THREE.Texture();
renderer.setTexture2D(texture, 0);  // force three.js to init the texture
const texProps = renderer.properties.get(texture);
texProps.__webglTexture = glTex;

as of r103 setTexture2D no longer exists. You can use this instead

  const forceTextureInitialization = function() {
    const material = new THREE.MeshBasicMaterial();
    const geometry = new THREE.PlaneBufferGeometry();
    const scene = new THREE.Scene();
    scene.add(new THREE.Mesh(geometry, material));
    const camera = new THREE.Camera();

    return function forceTextureInitialization(texture) {
      material.map = texture;
      renderer.render(scene, camera);
    };
  }();

  const texture = new THREE.Texture();
  forceTextureInitialization(texture);  // force three.js to init the texture
  const texProps = renderer.properties.get(texture);
  texProps.__webglTexture = glTex;

'use strict';

/* global THREE */

function main() {
  const canvas = document.querySelector('#c');
  const renderer = new THREE.WebGLRenderer({
    canvas: canvas
  });
  
  const fov = 75;
  const aspect = 2; // the canvas default
  const near = 0.1;
  const far = 5;
  const camera = new THREE.PerspectiveCamera(fov, aspect, near, far);
  camera.position.z = 2;

  const scene = new THREE.Scene();

  const boxWidth = 1;
  const boxHeight = 1;
  const boxDepth = 1;
  const geometry = new THREE.BoxGeometry(boxWidth, boxHeight, boxDepth);
  
  const forceTextureInitialization = function() {
    const material = new THREE.MeshBasicMaterial();
    const geometry = new THREE.PlaneBufferGeometry();
    const scene = new THREE.Scene();
    scene.add(new THREE.Mesh(geometry, material));
    const camera = new THREE.Camera();

    return function forceTextureInitialization(texture) {
      material.map = texture;
      renderer.render(scene, camera);
    };
  }();

  const cubes = []; // just an array we can use to rotate the cubes

  {
    const gl = renderer.getContext();
    const glTex = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, glTex);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2, 2, 0,
        gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([
          255, 0, 0, 255,
          0, 255, 0, 255,
          0, 0, 255, 255,
          255, 255, 0, 255,
        ]));
    gl.generateMipmap(gl.TEXTURE_2D);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  
    const texture = new THREE.Texture();
    forceTextureInitialization(texture);
    const texProps = renderer.properties.get(texture);
    texProps.__webglTexture = glTex;
    
    const material = new THREE.MeshBasicMaterial({
      map: texture,
    });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);
    cubes.push(cube); // add to our list of cubes to rotate
  }

  function render(time) {
    time *= 0.001;

    cubes.forEach((cube, ndx) => {
      const speed = .2 + ndx * .1;
      const rot = time * speed;
      cube.rotation.x = rot;
      cube.rotation.y = rot;
    });

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();
<canvas id="c"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/103/three.min.js"></script>

Note: There is no such thing as "unsupported behavior" in three.js. Three.js makes no guarantee that anything you are doing today will work tomorrow. Three.js breaks whatever it wants to whenever it wants to




回答2:


This is completely unsupported behaviour, but you could imitate the WebGLRenderer and set the __webglTexture property on a Texture directly. e.g.

var texure = new THREE.Texture();
var rawTexture = gl.createTexture();
texture.__webglTexture = rawTexture;
texture.__webglInit = true;
// ... use texture as a normal three.js texture ...

Again, this is completely unsupported and undefined behaviour and likely to break in future versions of three.js, but will likely work for the time being if you're after speed.

I'd instead suggest looking into WebGLRenderTarget if you can, or submitting a feature request to enable the feature correctly.



来源:https://stackoverflow.com/questions/29325906/can-you-use-raw-webgl-textures-with-three-js

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!