我有一个大的纹理-照片-和小的简单网格物体,应该显示主要纹理的区域。这些网格物体应具有alphaMap,例如圆形。
在网格材质的纹理(PlaneBufferGeometry)中,我更改了UV贴图,因此它将显示主纹理的正确区域。问题是UV贴图也应用于alphaMap,但我希望它独立。
const planeGeometry = new THREE.PlaneBufferGeometry(sz.x, sz.y);
let uvs= planeGeometry.attributes.uv;
for (let ix = 0; ix< uvs.array.length; ix++){
let x = uvs.getX(ix);
let y = uvs.getY(ix);
uvs.setXY(ix, x*.5, y*.75); // just testing
}
const planeMaterial = new THREE.MeshPhongMaterial({
map: imageTexture,
transparent: true,
alphaMap ,
normalMap,
});
是否有一种方法可以仅更改材质贴图的UV贴图,而使其他贴图(alphaMap和normalMap)保持独立...或者还有其他方法?
出于所有意图和目的,@ Marquizzo的回答是正确的。但是,我个人发现使用内置的纹理属性确实很尴尬,并且可能导致UV无法正确对齐的情况。
一个可能的选择是将第二组uv坐标添加到几何中:
// setup new attribute uvs
var uvb = new Float32Array( [
0.25, 0.75,
0.75, 0.75,
0.25, 0.25,
0.75, 0.25
] );
planeGeometry.setAttribute( 'uvB', new THREE.BufferAttribute( uvb, 2 ) );
并修改材质着色器以使用该组坐标用于颜色贴图纹理:
var planeMaterial = new THREE.MeshPhongMaterial( {
side: THREE.DoubleSide,
transparent: true,
map: colorTex,
alphaMap: alphaTex,
} );
planeMaterial.onBeforeCompile = function( shader ) {
// vertex modifications
var vertex_pars = 'attribute vec2 uvB;\nvarying vec2 vUvB;\n';
var vertex_uv = shader.vertexShader.replace(
'#include <uv_vertex>',
[
'#include <uv_vertex>',
'vUvB = uvB;'
].join( '\n' )
);
shader.vertexShader = vertex_pars + vertex_uv;
// fragment modifications
var frag_pars = 'varying vec2 vUvB;\n';
var frag_uv = shader.fragmentShader.replace(
'#include <map_fragment>',
[
'vec4 texelColor = texture2D( map, vUvB );',
'texelColor = mapTexelToLinear( texelColor );',
'diffuseColor *= texelColor;'
].join( '\n' )
);
shader.fragmentShader = frag_pars + frag_uv;
}
此方法的缺点是,每次要使用不同的uv时,您都需要不同的几何形状。这可能会影响性能,具体取决于您的应用程序。
最简单的方法是不使用几何图形uvs
,而是在照片纹理上使用一些内置的纹理变换属性。它们是.offset
,.repeat
,.rotation
。和.center
。您可以阅读说明in the docs。例如,如果要将照片纹理缩放到200%,可以使用
imageTexture.repeat.set(0.5, 0.5);
如果您要移动它:
imageTexture.offset.set(0.0, 0.7);
这只会影响imageTexture
,而不会留下您的alphaMap纹理。
[.rotation
和.center
一起使用,如果您想更改旋转原点。