3. js Как получить 2 текстуры на одном объекте, причем вторая будет прозрачной согласно полутоновому png? - PullRequest
1 голос
/ 25 мая 2020

Мне нужен объект с текстурой, цвет которой я могу изменить, и еще один поверх первого для цветных деталей.

Вот несколько изображений, чтобы описать это:

R

Результат, который мне нужен: Фиг1 и 2.

Фиг3 - текстура фона.

Фиг4 - альфа текстура деталей.

Я знаю, как это сделать с световой волной, например, это называется текстурными слоями. Но я не могу разобраться в трех js.

Спасибо.

1 Ответ

1 голос
/ 25 мая 2020

Вы можете использовать THREE.ShaderMaterial() для смешивания этих текстур, используя канал .r для значения смешивания текстуры с шаблоном:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 100);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

var c1 = document.createElement("canvas");
c1.width = 128;
c1.height = 128;
var ctx1 = c1.getContext("2d");
ctx1.fillStyle = "gray";
ctx1.fillRect(0, 0, 128, 128);
var tex1 = new THREE.CanvasTexture(c1); // texture of a solid color

var c2 = document.createElement("canvas");
c2.width = 128;
c2.height = 128;
var ctx2 = c2.getContext("2d");
ctx2.fillStyle = "black";
ctx2.fillRect(0, 0, 128, 128);
ctx2.strokeStyle = "white";
ctx2.moveTo(50, -20);
ctx2.lineTo(100, 148);
ctx2.lineWidth = 20;
ctx2.stroke();
var tex2 = new THREE.CanvasTexture(c2); // texture with a pattern

var planeGeom = new THREE.PlaneBufferGeometry(10, 10);
var planeMat = new THREE.ShaderMaterial({
  uniforms: {
    tex1: {
      value: tex1
    },
    tex2: {
      value: tex2
    },
    color: {
      value: new THREE.Color() //color of the pattern
    }
  },
  vertexShader: `
    varying vec2 vUv;
    void main() {
      vUv = uv;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
    }
  `,
  fragmentShader: `
    uniform sampler2D tex1;
    uniform sampler2D tex2;
    uniform vec3 color;
    varying vec2 vUv;
    void main() {
      
      vec3 c1 = texture2D(tex1, vUv).rgb;
      float m = texture2D(tex2, vUv).r;
      
      vec3 col = mix(c1, color, m);
      
      gl_FragColor = vec4(col, 1);
    }
  `
});

var plane = new THREE.Mesh(planeGeom, planeMat);
scene.add(plane);

var clock = new THREE.Clock();

renderer.setAnimationLoop(() => {
  let t = (clock.getElapsedTime() * 0.125) % 1;
  planeMat.uniforms.color.value.setHSL(t, 1, 0.5);
  renderer.render(scene, camera);
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
...