32

是否可以在 Three.js 的同一张面上放置多个纹理,以便在 webGL 中通过 GPU 加速完成 alpha 混合?

纹理被(或应该)应用到同一个面上,这样底部纹理(纹理 1)就没有 alpha 通道,并且上面的纹理以类似于下图示例中的纹理 2 的方式进行 alpha 通道。

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

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

在此处输入图像描述

4

1 回答 1

69

使用 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);
}

如果您需要混合更多纹理,您可以使用相同的公式进行多次混合。

结果如下:

在此处输入图像描述

于 2013-06-03T12:52:23.133 回答