web-dev-qa-db-ja.com

Three.jsの同じメッシュ面にある複数の透明なテクスチャ

Three.jsの同じ面に複数のテクスチャを重ねて配置して、アルファブレンドがwebGLでGPUアクセラレーションされるようにすることはできますか?

下のテクスチャ(テクスチャ1)にアルファチャネルがなく、上記のテクスチャが下の画像の例のテクスチャ2のようにアルファチャネル化されるように、テクスチャは同じ面に適用されます(または適用する必要があります)。

このブレンディングはHTML5 Canvasをプリステップとして使用して実現できますが、テクスチャビットマップは非常に大きくなる可能性があるため、Canvasブレンディング操作をスキップすることを好みます。

メッシュのコピーを作成し、メッシュごとに1つのテクスチャを適用し、他のメッシュを透明にして少し動かしてテストしましたが、ほとんどうまくいきましたが、ちらつきがあり、オブジェクトを正確に同じ位置に配置できないため、いくつかあります。適切な効果ではないテクスチャ間の空間。彼らは、例えば、それらにブレンドされたように見えるはずです。 Photoshop(下の画像のように)。

enter image description here

29
Timo Kähkönen

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

58