【发布时间】:2020-09-12 00:10:21
【问题描述】:
我需要一个具有可以更改其颜色的纹理的对象,并在第一个对象之上再创建一个对象以获取彩色细节。
这里有一些图片来描述这一点:
我需要的结果:图 1 和图 2。
图3是背景的纹理。
图4是细节的alpha纹理。
我知道如何使用光波来做到这一点,例如,它被称为纹理层。但是我在threejs中无法弄清楚。
谢谢。
【问题讨论】:
我需要一个具有可以更改其颜色的纹理的对象,并在第一个对象之上再创建一个对象以获取彩色细节。
这里有一些图片来描述这一点:
我需要的结果:图 1 和图 2。
图3是背景的纹理。
图4是细节的alpha纹理。
我知道如何使用光波来做到这一点,例如,它被称为纹理层。但是我在threejs中无法弄清楚。
谢谢。
【问题讨论】:
您可以使用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>
【讨论】: