简体   繁体   English

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

[英]Multiple transparent textures on the same mesh face in Three.js

Is it possible to lay multiple textures on top of each other on the same face in Three.js so that the alpha blending is done GPU accelerated in webGL? 是否有可能在Three.js中的同一面上将多个纹理叠加在一起,以便在webGL中加速alpha加速?

The textures are (or should be) applied to the same face so that the bottom texture (texture 1) is without alpha channel and the above textures are alpha channeled in a way like texture 2 in the below image example. 纹理(或应该)应用于同一面,使得底部纹理(纹理1)没有alpha通道,并且上面的纹理以类似下面图像示例中的纹理2的方式被引导。

This blending can be achieved using HTML5 Canvas as pre-step, but because texture bitmaps can be huge, I prefer to skip Canvas blending operations. 这种混合可以使用HTML5 Canvas作为前置步骤来实现,但由于纹理位图可能很大,我更喜欢跳过Canvas混合操作。

I tested by creating a copy of the mesh and applying one texture per mesh and made other mesh transparent and moved it a little, which succeeded nearly well, but there is some flickering and because objects cannot be exactly in the same position, there is some room between textures which is not the right effect. 我通过创建网格的副本并对每个网格应用一个纹理进行测试,并使其他网格透明并移动了一点,几乎成功,但有一些闪烁,因为对象不能完全在同一位置,有一些纹理之间的空间不是正确的效果。 They should seem like they were blended in eg. 他们看起来应该像是混合在一起。 Photoshop (as is the below image). Photoshop(如下图所示)。

在此输入图像描述

Use ShaderMaterial and set both textures as uniforms, and then blend them within shader. 使用ShaderMaterial并将两个纹理设置为制服,然后在着色器中混合它们。

I made this example: http://abstract-algorithm.com/three_sh/ and that really should be enough. 我做了这个例子: http//abstract-algorithm.com/three_sh/ ,这真的应该足够了。

So, you make ShaderMaterial: 所以,你制作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

});

And create mesh with that material: 并使用该材质创建网格:

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

You can put simplest vertex shader: 你可以把最简单的顶点着色器:

varying vec2 vUv;

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

And fragment shader that will actually do the blending: 并且片段着色器将实际进行混合:

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

If you need to blend even more textures, you use same equation for blending just multiple times. 如果您需要混合更多纹理,则可以使用相同的方程式进行多次混合。

So here's the result: 所以这是结果:

在此输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM