Three.js中同一网格面上的多个透明纹理

时间:2013-04-29 20:23:35

标签: javascript three.js webgl textures alphablending

是否有可能在Three.js中的同一面上将多个纹理叠加在一起,以便在webGL中加速alpha加速?

将纹理(或应该)应用于同一个面,以便底部纹理(纹理1)没有alpha通道,并且上面的纹理在下面的图像示例中以纹理2的方式进行alpha通道。

这种混合可以使用HTML5 Canvas作为前置步骤来实现,但由于纹理位图可能很大,我更喜欢跳过Canvas混合操作。

我通过创建网格的副本并对每个网格应用一个纹理进行测试,并使其他网格透明并移动了一点,这几乎成功,但有一些闪烁,因为对象不能完全在同一位置,纹理之间有一些空间,这不是正确的效果。他们看起来应该像是混合在一起。 Photoshop(如下图所示)。

enter image description here

1 个答案:

答案 0 :(得分:58)

使用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