如何将纹理应用于脸部的一部分?
How to apply a texture to part of a face?
我只想将纹理应用于立方体表面的指定部分 - 而不是整个表面。我想对同一张脸多次这样做。比如我想把texture1.jpg放在人脸的右上角,texture2.jpg放在右下角,texture3.jpg放在左上角,texture4.jpg在中间.
我希望能够在不为每个部分创建新网格的情况下执行此操作。
我遇到了与必须为纹理的每个部分创建一个新网格相关的性能问题,如果我可以通过某种方式将 "decals" 放置在单个网格上来做到这一点,整个过程将 运行 更顺畅。
您可以自定义组合纹理 THREE.ShaderMAterial
:
<script id="cubeFragmentShader" type="x-shader/x-fragment">
uniform vec2 aMin;
uniform vec2 aMax;
varying vec2 vUv;
uniform sampler2D texture;
uniform sampler2D texture2;
void main() {
vec2 position = vUv;
if (vUv.x<aMin.x || vUv.x>aMax.x || vUv.y<aMin.y || vUv.y>aMax.y) {
gl_FragColor = texture2D( texture2, position );
} else {
position -= aMin;
position.x /= aMax.x - aMin.x;
position.y /= aMax.y - aMin.y;
gl_FragColor = texture2D( texture, position );
}
}
</script>
我在 canvas 的不同位置绘制了多个图像,然后将 canvas 导出为 URL,我将其作为纹理 material 添加到网格:
var scene = new THREE.Scene();
var sceneWidth = window.innerWidth;
var sceneHeight = window.innerHeight;
var camera = new THREE.PerspectiveCamera(45, sceneWidth/sceneHeight, 0.1, 3000);
var controls = new THREE.OrbitControls(camera);
var raycaster = new THREE.Raycaster();
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor( 0xcccccc, 1);
renderer.setSize(sceneWidth, sceneHeight);
document.getElementById("content").appendChild(renderer.domElement);
var canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 900;
var ctx = canvas.getContext("2d");
var imgs = [];
imgs.push(loadImage('http://uobot.com/demo/1.jpg', main));
imgs.push(loadImage('http://uobot.com/demo/2.jpg', main));
imgs.push(loadImage('http://uobot.com/demo/3.jpg', main));
var imagesLoaded = 0;
function main() {
imagesLoaded ++;
if(imagesLoaded == imgs.length) {
for(var i in imgs) {
ctx.drawImage(imgs[i], 0, i*100);
}
var dataUrl = canvas.toDataURL();
var texture = THREE.ImageUtils.loadTexture(dataUrl);
texture.needsUpdate = true;
texture.minFilter = THREE.LinearFilter;
var material = new THREE.MeshPhongMaterial( {
map: texture,
specular: 0x050505,
shininess: 0
});
var object = new THREE.Mesh(new THREE.PlaneGeometry(10, 60, 1, 1), material);
scene.add(object);
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
我只想将纹理应用于立方体表面的指定部分 - 而不是整个表面。我想对同一张脸多次这样做。比如我想把texture1.jpg放在人脸的右上角,texture2.jpg放在右下角,texture3.jpg放在左上角,texture4.jpg在中间.
我希望能够在不为每个部分创建新网格的情况下执行此操作。
我遇到了与必须为纹理的每个部分创建一个新网格相关的性能问题,如果我可以通过某种方式将 "decals" 放置在单个网格上来做到这一点,整个过程将 运行 更顺畅。
您可以自定义组合纹理 THREE.ShaderMAterial
:
<script id="cubeFragmentShader" type="x-shader/x-fragment">
uniform vec2 aMin;
uniform vec2 aMax;
varying vec2 vUv;
uniform sampler2D texture;
uniform sampler2D texture2;
void main() {
vec2 position = vUv;
if (vUv.x<aMin.x || vUv.x>aMax.x || vUv.y<aMin.y || vUv.y>aMax.y) {
gl_FragColor = texture2D( texture2, position );
} else {
position -= aMin;
position.x /= aMax.x - aMin.x;
position.y /= aMax.y - aMin.y;
gl_FragColor = texture2D( texture, position );
}
}
</script>
我在 canvas 的不同位置绘制了多个图像,然后将 canvas 导出为 URL,我将其作为纹理 material 添加到网格:
var scene = new THREE.Scene();
var sceneWidth = window.innerWidth;
var sceneHeight = window.innerHeight;
var camera = new THREE.PerspectiveCamera(45, sceneWidth/sceneHeight, 0.1, 3000);
var controls = new THREE.OrbitControls(camera);
var raycaster = new THREE.Raycaster();
var renderer = new THREE.WebGLRenderer({ alpha: true });
renderer.setClearColor( 0xcccccc, 1);
renderer.setSize(sceneWidth, sceneHeight);
document.getElementById("content").appendChild(renderer.domElement);
var canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 900;
var ctx = canvas.getContext("2d");
var imgs = [];
imgs.push(loadImage('http://uobot.com/demo/1.jpg', main));
imgs.push(loadImage('http://uobot.com/demo/2.jpg', main));
imgs.push(loadImage('http://uobot.com/demo/3.jpg', main));
var imagesLoaded = 0;
function main() {
imagesLoaded ++;
if(imagesLoaded == imgs.length) {
for(var i in imgs) {
ctx.drawImage(imgs[i], 0, i*100);
}
var dataUrl = canvas.toDataURL();
var texture = THREE.ImageUtils.loadTexture(dataUrl);
texture.needsUpdate = true;
texture.minFilter = THREE.LinearFilter;
var material = new THREE.MeshPhongMaterial( {
map: texture,
specular: 0x050505,
shininess: 0
});
var object = new THREE.Mesh(new THREE.PlaneGeometry(10, 60, 1, 1), material);
scene.add(object);
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}