2017-01-25 5 views
0

Я пытаюсь понять, как использовать две разные текстуры на передней и задней части окна. Всякий раз, когда я масштабирую свою коробку (ExtrudeGeometry), UV-карты, похоже, не обновляются. Поэтому я определяю свои собственные UV-карты для передней и задней части коробки.Three.js Несколько UV-карт на одном объекте

Чтобы определить переднюю UV карту я использую:

geometry.faceVertexUvs[0] 

, который работает соответствующим образом.
Для задней УФ карты я использую:

geometry.faceVertexUvs[1]; 

Однако я не могу открыть «второй» слой УФ-карту.

Так что мой вопрос:

  1. Можно ли обновить UV карты в соответствии с масштабом объекта?
  2. Возможно ли получить доступ к «второй» УФ-карте слоя внутри материала?

Я создал пример здесь: jsfiddle.

Я создал три разных коробки с тремя различными шкалами. Слева направо: 0.01 x 2.97 x 2.1, 0.01 x 1 x 1 и 0.01 x 0.297 x 0.21. В самом левом окне текстуры покрывают только небольшую часть коробки. Среднее поле имеет правильное текстурирование. В правом поле есть обновленная uv-карта (иначе будет отображаться только небольшая часть текстуры).
(Я должен использовать малый шкаф на коробке!)

Я надеюсь, что кто-то может мне помочь!

Three.js 84

ответ

1

Вы можете определить attribute vec2 uv2 в вашем вершинном шейдере, а затем получить доступ к нему, как обычно.

precision highp int; 
precision highp float; 

uniform mat4 modelViewMatrix; 
uniform mat4 projectionMatrix; 

attribute vec2 uv; 
attribute vec2 uv2; 
attribute vec3 normal; 
attribute vec3 position; 

void main() { 
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 
} 
+1

Благодарим за быстрый ответ! Я еще не пришел, чтобы реализовать его. Как только я это сделаю, я приму ответ и предоставил свою реализацию. – Yannickd

+0

@Yannickd Это решение работает для вас? Я также сталкиваюсь с этой проблемой, но я стараюсь держаться подальше от шейдерного кода насколько могу. – danyim

0

В ответ на @danyim.

В конце концов я также избегал использования шейдерных кодов. Я решил полностью uv-развернуть мой объект и нарисовать собственную текстуру с помощью WebGL (поскольку мне нужна была простая текстура переднего и заднего фона). В приведенной ниже функции я рисую объект с переменным количеством подразделений и разворачиваю их.

С помощью функции drawTexture (далее ниже) я предоставляю «O» и «X» в качестве текстур для своей передней и задней части объекта.

Надеюсь, это поможет вам (и возможно другим) выйти. Если у вас есть дополнительные вопросы, не стесняйтесь спрашивать.

drawObject() { 
    //Draw a shape with the measures of a object. 
    var length = 0.01, width = 0.297; 
    var shape = new THREE.Shape(); 
    shape.moveTo(0, 0); 
    shape.lineTo(0, width); 
    shape.lineTo(length, width); 
    shape.lineTo(length, 0); 
    shape.lineTo(0, 0); 

    var canvasTexture = drawTexture('x', 'o'); 
    var textures = [ 
     new THREE.MeshPhongMaterial({ color: 0xf9f9f9, side: THREE.BackSide, overdraw: 0.5 }),//GENERAL 0 
     new THREE.MeshPhongMaterial({ map: canvasTexture, side: THREE.BackSide, overdraw: 0.5 }), //FRONT 1 
     new THREE.MeshPhongMaterial({ map: canvasTexture, side: THREE.BackSide, overdraw: 0.5 }), //BACK 2 
     new THREE.MeshPhongMaterial({ color: 0x00ff00, side: THREE.BackSide, overdraw: 0.5 }) 
    ]; 

    var material = new THREE.MultiMaterial(textures); 

    subDivs = parseInt(objectLength/40); //Amount of subdivision (more provides a smoother result) 
    subDivs = 5; 
    var extrudeSettings = { 
     amount: 0.21, 
     steps: this.subDivs, 
     bevelEnabled: false 
    }; 
    //Create a UVMap(u,v). 
    var uvMap = []; 
    for (let i = 0; i <= (subDivs) * 2; i++) { 
     var u = i/(subDivs * 2); 
     uvMap.push(new THREE.Vector2(u, 0)); 
     uvMap.push(new THREE.Vector2(u, 1)); 
    } 

    //Create the object. 
    var geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); 
    var tempI = (uvMap.length - 2)/2; 
    //Map the vertices to the UVMap (only mapping top and bottom of the object (for 'x' and 'o' texture)) 
    for (let i = 0; i < geometry.faceVertexUvs[0].length; i++) { 
     if (i >= 4 && i < 4 + (subDivs * 2)) { 
      if (isOdd(i)) { 
       geometry.faceVertexUvs[0][i] = [uvMap[i - 4], uvMap[i - 2], uvMap[i - 3]]; 
      } else { 
       geometry.faceVertexUvs[0][i] = [uvMap[i - 4], uvMap[i - 3], uvMap[i - 2]]; 
      } 
     } 
     else if (i >= 4 + (subDivs * 4) && i < 4 + (subDivs * 4) + (subDivs * 2)) { 
      if (isOdd(i)) { 
       geometry.faceVertexUvs[0][i] = [uvMap[tempI], uvMap[tempI + 2], uvMap[tempI + 1]]; 
      } else { 
       geometry.faceVertexUvs[0][i] = [uvMap[tempI], uvMap[tempI + 1], uvMap[tempI + 2]]; 
      } 
      tempI++; 
     } 
    } 

    //Assigning different materialIndices to different faces 
    for (var i = 4; i <= 13; i++) { //Front 
     geometry.faces[i].materialIndex = 1; 
    } 

    for (var i = 4 + (subDivs * 4); i < 4 + (subDivs * 4) + (subDivs * 2); i++) { //Back 
     geometry.faces[i].materialIndex = 2; 
    } 

    for (var i = 0; i <= 1; i++) { 
     geometry.faces[i].materialIndex = 3; 
    } 
    var plane = new THREE.Mesh(geometry, material); 
    return plane; 

function drawTexture (msg1, msg2) { 
    var canvas = document.createElement('canvas'); //Create a canvas element. 
    var size = 128; 
    canvas.width = size; 
    canvas.height = size; 

    var ctx = canvas.getContext('2d'); 
    //Draw a white background 
    ctx.beginPath(); 
    ctx.rect(0, 0, size, size); 
    ctx.fillStyle = 'white'; 
    ctx.fill(); 

    //Draw the message (e.g. 'x' or 'o') 
    ctx.fillStyle = 'black'; 
    ctx.font = '64px Arial'; 

    //Determien the size of the letters. 
    var metrics1 = ctx.measureText(msg1); 
    var textWidth1 = metrics1.width; 
    var textHeight = parseInt(ctx.font); 

    var metrics2 = ctx.measureText(msg2); 
    var textWidth2 = metrics2.width; 

    ctx.fillText(msg1, size/4 - textWidth1/2, size/2 + (textHeight/4)); 
    ctx.fillText(msg2, (3 * size/4) - textWidth2/2, size/2 + (textHeight/4)); 

    //Store the canvas in a THREE.js texture. 
    var texture = new THREE.Texture(canvas); 
    texture.needsUpdate = true; 
    return texture; //Return Three.Texture