web-dev-qa-db-fra.com

Plusieurs textures transparentes sur la même face maillée dans Three.js

Est-il possible de superposer plusieurs textures les unes sur les autres sur la même face dans Three.js pour que le mélange alpha se fasse en accélération GPU dans webGL?

Les textures sont (ou devraient être) appliquées à la même face afin que la texture du bas (texture 1) soit sans canal alpha et que les textures ci-dessus soient canalisées alpha d'une manière similaire à la texture 2 dans l'exemple d'image ci-dessous.

Ce mélange peut être réalisé en utilisant HTML5 Canvas comme pré-étape, mais comme les bitmaps de texture peuvent être énormes, je préfère ignorer les opérations de mélange de Canvas.

J'ai testé en créant une copie du maillage et en appliquant une texture par maillage et en rendant un autre maillage transparent et en le déplaçant un peu, ce qui a réussi presque bien, mais il y a du scintillement et parce que les objets ne peuvent pas être exactement dans la même position, il y en a place entre textures ce qui n'est pas le bon effet. Ils devraient avoir l'air d'avoir été mélangés, par exemple. Photoshop (comme l'image ci-dessous).

enter image description here

29
Timo Kähkönen

Utilisez ShaderMaterial et définissez les deux textures comme uniformes, puis mélangez-les dans le shader.

J'ai fait cet exemple: http://abstract-algorithm.com/three_sh/ et cela devrait vraiment suffire.

Donc, vous créez 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

});

Et créez un maillage avec ce matériau:

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

Vous pouvez mettre le vertex shader le plus simple:

varying vec2 vUv;

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

Et un shader de fragments qui fera le mélange:

#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);
}

Si vous avez besoin de mélanger encore plus de textures, vous utilisez la même équation pour mélanger plusieurs fois seulement.

Voici donc le résultat:

enter image description here

58