три js текстура карты UV с независимой альфа-картой - PullRequest
1 голос
/ 29 января 2020

У меня есть большая текстура - фото - и небольшие простые сетки, которые должны отображать области основной текстуры. Эти сетки должны иметь альфа-карту, например, круг.

В текстуре материала me sh (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) вид независимый ... Или есть какой-то другой подход?

Ответы [ 2 ]

3 голосов
/ 29 января 2020

Один из возможных вариантов - добавить второй набор 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;

}

Недостаток этого метода в том, что вам нужна другая геометрия каждый раз, когда вы хотите использовать другой набор uvs. Это может повлиять на производительность в зависимости от вашего приложения.

Пример JSFiddle

3 голосов
/ 29 января 2020

Самый простой способ сделать это - оставить геометрию uvs в покое, а вместо этого использовать некоторые встроенные свойства преобразования текстур на вашей фототекстуре. Это .offset, .repeat, .rotation. и .center. Вы можете прочитать описание в документации . Например, если вы хотите увеличить текстуру фотографии до 200%, вы можете использовать

imageTexture.repeat.set(0.5, 0.5);

, если хотите переместить ее:

imageTexture.offset.set(0.0, 0.7);

Это повлияет только на imageTexture и оставит вашу текстуру alphaMap в покое.

.rotation и .center работают совместно, если вы хотите изменить начало вращения.

...