仅在多维数据集的一个面上旋转纹理贴图

问题描述 投票:0回答:1

我有一个问题想问你:

是否有一种方法可以将立方体的一个面上的纹理贴图旋转90°(BoxGeometry)?

我的意思是,我可以通过克隆材质来实现这一点,以具有6个相同的材质阵列,为每个克隆分配一个克隆纹理,将其应用于多维数据集,然后仅旋转错误的uvmapped克隆纹理。我想知道是否有更好的方法可以做到,因为我必须多次这样做。

谢谢你!

three.js texture-mapping uv-mapping
1个回答
0
投票

作为一种选择,您可以这样做(一种改良的材料+ 6种纹理):

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, 1, 1, 1000);
camera.position.set(5, 3, 5);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
var canvas = renderer.domElement;
document.body.appendChild(canvas);

var contorls = new THREE.OrbitControls(camera, canvas);

scene.add(new THREE.GridHelper(10, 10));

var texLoader = new THREE.TextureLoader();
var texPath = "https://threejs.org/examples/textures/";

var textures = [
  texLoader.load(texPath + "colors.png"),
  texLoader.load(texPath + "hardwood2_diffuse.jpg"),
  texLoader.load(texPath + "metal.jpg"),
  texLoader.load(texPath + "sprite.png"),
  texLoader.load(texPath + "square-outline-textured.png"),
  texLoader.load(texPath + "uv_grid_opengl.jpg")
];

var uniforms = {
  textures: {
    value: [
      textures[0],
      textures[1],
      textures[2],
      textures[3],
      textures[4],
      textures[5]
    ]
  },
  time: {value: 0}
};

var boxGeom = new THREE.BoxBufferGeometry(4, 4, 4);
boxGeom.setAttribute("side", new THREE.Float32BufferAttribute([
  0, 0, 0, 0, 
  1, 1, 1, 1, 
  2, 2, 2, 2, 
  3, 3, 3, 3, 
  4, 4, 4, 4, 
  5, 5, 5, 5
], 1));

var boxMat = new THREE.MeshBasicMaterial();
boxMat.defines = {USE_UV: ""};

boxMat.onBeforeCompile = shader => {
  shader.uniforms.textures = uniforms.textures;
  shader.uniforms.time = uniforms.time;
  
  shader.vertexShader = `
    attribute float side;
    varying float vSide;
  ` + shader.vertexShader;
  shader.vertexShader = shader.vertexShader.replace(
    `#include <fog_vertex>`,
    `#include <fog_vertex>
    vSide = side;
`
  );
  
  shader.fragmentShader = `
  uniform sampler2D textures[6];
  uniform float time;
  varying float vSide;
` + shader.fragmentShader;
  
  shader.fragmentShader = shader.fragmentShader.replace(
    `#include <map_fragment>`,
    `
    #ifdef USE_UV
      vec4 texelColor = vec4(0);
      float boxSide = floor(vSide + 0.1);
      
      vec2 uvs = vUv;
      if (boxSide == 0.) { // rotate the texture on the first side (pos x)
        uvs -= 0.5;
        float a = time;
        uvs *= mat2(cos(a), -sin(a), sin(a), cos(a));
        uvs += 0.5;
      }

      if (boxSide == 0.) texelColor = texture2D( textures[0], uvs );
      else if (boxSide == 1.) texelColor = texture2D( textures[1], uvs );
      else if (boxSide == 2.) texelColor = texture2D( textures[2], uvs );
      else if (boxSide == 3.) texelColor = texture2D( textures[3], uvs );
      else if (boxSide == 4.) texelColor = texture2D( textures[4], uvs );
      else if (boxSide == 5.) texelColor = texture2D( textures[5], uvs );
      
      
      
      texelColor = mapTexelToLinear( texelColor );
      diffuseColor *= texelColor;
    #endif 
`
  );
}

var box = new THREE.Mesh(boxGeom, boxMat);
scene.add(box);

var clock = new THREE.Clock();

render();

function render() {
  uniforms.time.value = clock.getElapsedTime();
  if (resize(renderer)) {
    camera.aspect = canvas.clientWidth / canvas.clientHeight;
    camera.updateProjectionMatrix();
  }
  renderer.render(scene, camera);
  requestAnimationFrame(render);
}

function resize(renderer) {
  const canvas = renderer.domElement;
  const width = canvas.clientWidth;
  const height = canvas.clientHeight;
  const needResize = canvas.width !== width || canvas.height !== height;
  if (needResize) {
    renderer.setSize(width, height, false);
  }
  return needResize;
}
html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
}
canvas {
  width: 100%;
  height: 100%;
  display; block;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
© www.soinside.com 2019 - 2024. All rights reserved.