Three.js中同一网格面上的多个透明纹理
Posted
技术标签:
【中文标题】Three.js中同一网格面上的多个透明纹理【英文标题】:Multiple transparent textures on the same mesh face in Three.js 【发布时间】:2013-04-23 15:28:18 【问题描述】:是否可以在 Three.js 中的同一张面上放置多个纹理,以便在 webGL 中通过 GPU 加速完成 alpha 混合?
纹理被(或应该)应用到同一个面上,这样底部纹理(纹理 1)就没有 Alpha 通道,并且上面的纹理以类似于下图示例中的纹理 2 的方式进行 Alpha 通道。
这种混合可以使用 html5 Canvas 作为前置步骤来实现,但由于纹理位图可能很大,我更喜欢跳过 Canvas 混合操作。
我通过创建网格副本并为每个网格应用一个纹理并让其他网格透明并稍微移动它来进行测试,这几乎成功了,但是有一些闪烁,因为对象不能完全位于相同的位置,纹理之间有一些空间,这不是正确的效果。它们应该看起来像是混合在一起的。 Photoshop(如下图)。
【问题讨论】:
你可以试试答案here中的方法 谢谢。似乎是个好办法。并且可能还可以处理在彼此之上渲染多个纹理。但目前尚未测试。 【参考方案1】:使用 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);
如果您需要混合更多纹理,您可以使用相同的公式进行多次混合。
结果如下:
【讨论】:
感谢您的回答。我需要等待 17 小时才能获得赏金。 这种方法不适合我们必须在特定位置放置多个纹理的情况。 @Tarun 是的,UV 映射可以解决这个问题。好吧,任何类型的 UV 坐标操作。 不错!但是,如果我想制作金属/闪亮/发光/等任何材料怎么办?我如何控制 RGBA 颜色以外的其他材质属性? 您总是以某种方式插入/混合属性。但重要的是如何以及何时混合它们。例如,您不能只是将两个闪亮系数相加,您可能想要计算光照,然后以某种方式组合着色结果而不是属性本身。还要考虑法线贴图,然后不能只是插值,而是需要将它们一层一层地组合起来。取决于属性类型和物理逻辑上的做法。以上是关于Three.js中同一网格面上的多个透明纹理的主要内容,如果未能解决你的问题,请参考以下文章