WebGL 中当透明和半透明物体共存时,相关设置不正确的话,物体表面会出现破碎杂乱的断面,非常影响效果,我们接着就来解决这个问题。
完成的展示Demo请看: 半透明物体和透明物体共存
α 混合
让物体实现半透明效果需要用到颜色的α分量。该功能被称为a混合(Alpha blending) 或 混合 blending,WebGL已经内置该功能,但需要开启,如果只设置了颜色的第四个分量 α 是看不到透明效果的,这第四分量α其实和 CSS 样式的 rgba / hsla 颜色模式 中的 α 是一样的,或者类似 opacity 属性。必须要执行下面两个步骤才能看到透明效果:
开启混合功能:gl.enable(gl.BLEND)。 指定混合函数:gl.blendFunc(gl.SRC_Alpha,gl.ONE_MINUS_SRC_Alpha)。 gl.blendFunc(src_factor,dst_factor)a混合函数,指定如如何混合两者的颜色,权重因子的类型多种多样,参数:
src_factor: 指定源颜色在混合颜色的权重因子,如下表所示 dst_factor: 指定目标颜色在混合后颜色的权重因子,如下表所示// 混合颜色计算公式: <混合后的颜色> = <源颜色> * src_factor + <目标颜色> * dst_factor// 一般半透明效果常用如下形式gl.blendFunc(gl.SRC_Alpha,gl.ONE_MINUS_SRC_Alpha)权重因子列表
(Rs,Gs,Bs,As) 表示源颜色各分量, (Rd,Gd,Bd,Ad) 表示目标颜色的各分量
常量 | R分量的系数 | G分量的系数 | B分量的系数 |
---|---|---|---|
gl.ZERO | 0.0 | 0.0 | 0.0 |
gl.ONE | 1.0 | 1.0 | 1.0 |
gl.SRC_color | Rs | Gs | Bs |
gl.ONE_MINUS_SRC_color | 1-Rs | 1-Gs | 1-Bs |
gl.DST_color | Rd | Gd | Bd |
gl.ONE_MINUS_DST_color | 1-Rd | 1-Gd | 1-Bd |
gl.SRC_Alpha | As | As | As |
gl.ONE_MINUS_SRC_Alpha | 1-As | 1-As | 1-As |
gl.DST_Alpha | Ad | Ad | Ad |
gl.ONE_MINUS_DST_Alpha | 1-Ad | 1-Ad | 1-Ad |
gl.SRC_Alpha_SATUREATE | min(As,Ad) | min(As,Ad) |
实现 a 混合最简单的方式是屏蔽掉隐藏面消除功能,即去掉 gl.enable(gl.DEPTH_TEST),但关闭隐藏面消除功能是一个粗暴的解决方案,并不能满足实际需求。其实可通过某些机制,同时实现隐藏面消除和半透明效果,步骤如下:
//1.开启隐藏面消除功能:gl.enable(gl.DEPTH_TEST)。//2.绘制所有不透明的物体(a == 1.0)//3.锁定深度缓冲区的写入 *** 作,使之只读 (深度缓冲区用于隐藏面消除):gl.depthMask(false);//4.绘制所有半透明的物体 a < 1.0,注意将物体按深度排序,a 最小最先绘制//5.释放深度缓冲区,使之可读可写: gl.depthMask(true)gl.depthMask(mask)
锁定或释放深度缓冲区的写入 *** 作
mask: 锁定深度缓冲区的写入 *** 作 false,释放 true
实现效果我们写个Demo来实际演示效果,比如我要绘制8个物体,其中前面4个是非透明的物体,即 α 分量值则为1,剩余物体的 α 分量分别从 0.1至0.4不等。
for (var i = 0; i < 8; i++) { let color = randomcolor(); color[3] = i > 3 ? (i - 3)/10 :1;// 透明物体 α 分量小于1,非透明物体则等于1 polygons.push({ x: random(-9,9),y: random(0,6),z: random(-5,5),color: color });}
如果是绘制的物体队列是无序的,则必须手动排序。但我这里建立图形时已经排好序,前4个为不透明物体,剩余是透明物体,所以可直接按顺序绘制,针对是否为透明物体,分别设置缓冲区写入和隐藏面删除功能。
if(i < 4){ // 非透明物体 gl.depthMask(true); gl.disable(gl.BLEND);} else { //透明物体 gl.depthMask(false); gl.enable(gl.BLEND); gl.blendFunc( gl.SRC_Alpha,gl.ONE_MINUS_SRC_Alpha );}drawBufferInfo(gl,vao);
最终完成效果请看:半透明物体和透明物体共存
总结以上是内存溢出为你收集整理的WebGL半透明物体的绘制全部内容,希望文章能够帮你解决WebGL半透明物体的绘制所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)