使用WebGL纹理作为Three.js纹理贴图

时间:2019-03-09 22:26:39

标签: javascript three.js webgl

我有一个带有平面的场景,该场景应使用WebGL纹理(使用gl.createTexture()创建)作为材质的贴图。基本上,此纹理的使用方式无关紧要,我只需要找到一种方法就可以以一定的一致性将其传递到ShaderMaterial。 WebGL纹理会更新每一帧。

纹理是在其他画布元素的上下文中渲染的,并且可以在这样的上下文中使用:

var imageLocation = gl.getUniformLocation(program, "u_image");
gl.uniform1i(imageLocation, 0);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, targetTexture1);

我已经尝试过this solution。但是似乎THREE.Texture()不能从原始WebGL纹理中获取数据。

1 个答案:

答案 0 :(得分:1)

如果您浏览the source,此功能将从r103开始生效。当然,不能保证它将在将来使用,但nothing in three is guaranteed to work in the future之后就可以使用。

首先创建一个Texture,然后调用forceTextureInitialization来强制Three.js初始化纹理。

  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);
    };
  }();

然后像这样用自己的语言替换Texture的WebGL纹理

const texProps = renderer.properties.get(someTexture);
texProps.__webglTexture = someGLTexture;

示例:

'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>

当然请注意,您可以抓住Texture已经在使用的纹理,然后使用WebGL对其进行操作

,而不是使用自己的纹理
相关问题