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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16287547/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 04:04:57  来源:igfitidea点击:

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

javascriptthree.jswebgltexturesalphablending

提问by Timo K?hk?nen

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 中通过 GPU 加速来完成 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 的方式进行 alpha 通道。

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(如下图所示)。

enter image description here

在此处输入图片说明

回答by Abstract Algorithm

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:

结果如下:

enter image description here

在此处输入图片说明