Подтвердить что ты не робот

Несколько прозрачных текстур на одной и той же поверхности сетки в Three.js

Возможно ли разместить несколько текстур друг над другом на одной грани в Three.js, чтобы альфа-смешение выполнялось с помощью GPU, ускоренного в webGL?

Текстуры применяются (или должны быть) к одной и той же стороне, чтобы нижняя текстура (текстура 1) не имела альфа-канала, а приведенные выше текстуры альфа-канала были подобны текстуре 2 в примере ниже.

Это смешение может быть достигнуто с использованием HTML5 Canvas в качестве предварительного шага, но поскольку текстурные растровые изображения могут быть огромными, я предпочитаю пропускать операции смешивания холста.

Я протестировал, создав копию сетки и применив одну текстуру в ячейку, и сделал другую сетку прозрачной и немного переместил ее, что получилось почти хорошо, но есть некоторые мерцания и потому, что объекты не могут быть точно в том же положении, есть некоторая комната между текстурами, которая не является правильным эффектом. Они должны казаться, что они были смешаны, например. Photoshop (как показано ниже).

enter image description here

4b9b3361

Ответ 1

Используйте ShaderMaterial и установите обе текстуры как униформы, а затем смешайте их в шейдере.

Я сделал этот пример: http://abstract-algorithm.com/three_sh/, и этого действительно должно быть достаточно.

Итак, вы создаете ShaderMaterial:

var vertShader = document.getElementById('vertex_shh').innerHTML;
var fragShader = document.getElementById('fragment_shh').innerHTML;

var attributes = {}; // custom attributes

var uniforms = {    // custom uniforms (your textures)

  tOne: { type: "t", value: THREE.ImageUtils.loadTexture( "cover.png" ) },
  tSec: { type: "t", value: THREE.ImageUtils.loadTexture( "grass.jpg" ) }

};

var material_shh = new THREE.ShaderMaterial({

  uniforms: uniforms,
  attributes: attributes,
  vertexShader: vertShader,
  fragmentShader: fragShader

});

И создайте сетку с этим материалом:

var me = new THREE.Mesh( new THREE.CubeGeometry(80,80,80), material_shh );

Вы можете задать простейший вершинный шейдер:

varying vec2 vUv;

void main()
{
    vUv = uv;
    vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
    gl_Position = projectionMatrix * mvPosition;
}

И фрагментарный шейдер, который на самом деле будет выполнять смешение:

#ifdef GL_ES
precision highp float;
#endif

uniform sampler2D tOne;
uniform sampler2D tSec;

varying vec2 vUv;

void main(void)
{
    vec3 c;
    vec4 Ca = texture2D(tOne, vUv);
    vec4 Cb = texture2D(tSec, vUv);
    c = Ca.rgb * Ca.a + Cb.rgb * Cb.a * (1.0 - Ca.a);  // blending equation
    gl_FragColor= vec4(c, 1.0);
}

Если вам нужно смешать еще больше текстур, вы используете одно и то же уравнение для смешивания всего несколько раз.

Итак, вот результат:

enter image description here