1

I’ve got a question for you:

is there a way to rotate by 90° the texture map on only one face of a cube (BoxGeometry)?

I mean, I can do it by cloning material in order to have a 6 identical material array, assigning to every clone a cloned texture, applying it to the cube and then rotate the wrong uvmapped cloned texture only. I’m wondering if there’s a better way to do it cause I’ve got to do that thing lots of times.

Thank you in advance!

1 Answers1

4

As an option, you can do it this way (one modified material + 6 textures):

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://cdn.jsdelivr.net/npm/three@0.118.1/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.118.1/examples/js/controls/OrbitControls.js"></script>
prisoner849
  • 16,894
  • 4
  • 34
  • 68
  • Wow @prisoner849 this is as amazing as complicated to me. I've got to learn shader language sooner or later. I'll go for it though, I'll try to implement your code in my script and see what happens. Thanks a lot for your answer. – tarzanello666 Feb 11 '20 at 08:06