Поверните карту текстуры только на одной грани куба - PullRequest
1 голос
/ 10 февраля 2020

У меня к вам вопрос:

есть ли способ повернуть карту текстуры на 90 ° только на одну грань куба (BoxGeometry)?

Я имею в виду, Я могу сделать это путем клонирования материала, чтобы получить 6 идентичных массивов материалов, назначить каждому клону клонированную текстуру, применить его к кубу и затем повернуть только неправильную uvmapped клонированную текстуру. Мне интересно, есть ли лучший способ сделать это, потому что я должен делать это много раз.

Заранее спасибо!

1 Ответ

2 голосов
/ 11 февраля 2020

Как вариант, вы можете сделать это следующим образом (один измененный материал + 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>
...