【问题标题】:three.js How to have 2 textures on one object, the second being transparent according to a grayscale png?three.js 如何在一个对象上有 2 个纹理,第二个根据灰度 png 是透明的?
【发布时间】:2020-09-12 00:10:21
【问题描述】:

我需要一个具有可以更改其颜色的纹理的对象,并在第一个对象之上再创建一个对象以获取彩色细节。

这里有一些图片来描述这一点:

我需要的结果:图 1 和图 2。

图3是背景的纹理。

图4是细节的alpha纹理。

我知道如何使用光波来做到这一点,例如,它被称为纹理层。但是我在threejs中无法弄清楚。

谢谢。

【问题讨论】:

    标签: three.js textures


    【解决方案1】:

    您可以使用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>

    【讨论】:

    • 感谢您的回答。但我有一个问题作为回报:有没有更简单的方法在同一个对象上拥有 2 个纹理?因为我不熟悉着色器。
    • 不幸的是,没有这样的开箱即用功能,允许以您想要的方式使用两个纹理(使用灰度纹理的值进行混合)。
    猜你喜欢
    • 2013-04-23
    • 2015-09-11
    • 2019-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-03
    相关资源
    最近更新 更多