带有独立 alphamap 的 threejs texturemap UV
threejs texturemap UV with independent alphamap
我有一个大纹理 - 一张照片 - 和一个应该显示主纹理区域的简单小网格。这些网格应该有一个 alphaMap,例如一个圆。
在网格 material 的纹理 (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,
});
有没有办法只更改 material 贴图的 UV 贴图,而让其他贴图(alphaMap 和 normalMap)保持独立...或者有其他方法吗?
解决此问题的最简单方法是单独保留几何体 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
结合使用。
一个可能的选择是将第二组 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 ) );
并修改 material 着色器以将那组坐标用于您的颜色贴图纹理:
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 集时都需要不同的几何体。这可能会对性能产生影响,具体取决于您的应用程序。
我有一个大纹理 - 一张照片 - 和一个应该显示主纹理区域的简单小网格。这些网格应该有一个 alphaMap,例如一个圆。
在网格 material 的纹理 (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,
});
有没有办法只更改 material 贴图的 UV 贴图,而让其他贴图(alphaMap 和 normalMap)保持独立...或者有其他方法吗?
解决此问题的最简单方法是单独保留几何体 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
结合使用。
一个可能的选择是将第二组 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 ) );
并修改 material 着色器以将那组坐标用于您的颜色贴图纹理:
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 集时都需要不同的几何体。这可能会对性能产生影响,具体取决于您的应用程序。