WebGL半透明物体的绘制
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) | 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场景中绘制多个圆锥圆柱
前几天解决了原生WebGL开发中的一个问题,就是在一个场景中绘制多个几何网格特征不同的模型,比如本文所做的绘制多个圆锥和圆柱在同一个场景中,今天抽空把解决的办法记录下来,同时也附上代码.首先声明,圆柱 ...
- 一篇文章理清WebGL绘制流程
转自:https://www.jianshu.com/p/e3d8a244f3d9 目录 初始化WebGL环境 顶点着色器(Vertex Shader)与片元着色器(Fragment Shader) ...
- WebGL简易教程(三):绘制一个三角形(缓冲区对象)
目录 1. 概述 2. 示例:绘制三角形 1) HelloTriangle.html 2) HelloTriangle.js 3) 缓冲区对象 (1) 创建缓冲区对象(gl.createBuffer( ...
- canvas高效绘制10万图形,你必须知道的高效绘制技巧
最近的一个客户项目中,简化的需求是绘制按照行列绘制很多个圆圈.需求看起来不难,上手就可以做,写两个for循环. 原始绘制方法 首先定义了很多Circle对象,在遍历循环中调用该对象的draw方法.代码 ...
- WebGL树形结构的模型渲染流程
今天和大家分享的是webgl渲染树形结构的流程.用过threejs,babylonjs的同学都知道,一个大模型都是由n个子模型拼装而成的,那么如何依次渲染子模型,以及渲染每个子模型在原生webgl中的 ...
- WebGL之物体选择
原文地址: WebGL之物体选择 使用WebGL将图形绘制到画布后,如何与外部进行交互?这其中最关键的就是如何实现物体的选择.比如鼠标点击后判断是否选中了某个图形或图形的某个部分. 本节实现的效果: ...
- WEBGL学习【八】模型视图投影矩阵
<!--探讨WEBGL中不同图形的绘制方法:[待测试2017.11.6]--> <!DOCTYPE HTML> <html lang="en"> ...
- WEBGL学习【七】画布绘图
主要是对WEBGL的绘图部分进行了进一步加强的认识和理解 <!DOCTYPE HTML> <html lang="en"> <head> < ...
- WebGL简易教程(一):第一个简单示例
目录 1. 概述 2. 示例:绘制一个点 1) HelloPoint1.html 2) HelloPoint1.js (1) 准备工作 (2) 着色器 (3) 顶点着色器 (4) 片元着色器 (5) ...
随机推荐
- 【CSP模拟赛】God knows (李超线段树)
题面 CODE 稍微分析一下,发现把(i,pi)(i,p_i)(i,pi)看做二维数点,就是求极长上升子序列的权值最小值. 直接李超线段树 #include <bits/stdc++.h> ...
- Maximum Subarray II
Given an array of integers, find two non-overlapping subarrays which have the largest sum. The numbe ...
- LeetCode 269. Alien Dictionary
原题链接在这里:https://leetcode.com/problems/alien-dictionary/ 题目: There is a new alien language which uses ...
- P1928 外星密码
题目描述 有了防护伞,并不能完全避免 2012 的灾难.地球防卫小队决定去求助外星种族的帮 助.经过很长时间的努力,小队终于收到了外星生命的回信.但是外星人发过来的却是一 串密码.只有解开密码,才能知 ...
- tsar安装和使用
Tsar简介 Tsar是淘宝自己开发的一个采集工具,主要用来收集服务器的系统信息(如cpu,io,mem,tcp等),以及应用数据(如squid haproxy nginx等). 收集到的数据存储在磁 ...
- CSPS分数取mod赛92-93
我好菜啊..... 92只会打暴力,93暴力都不会了 模拟92, T1:直接ex_gcd加分类讨论即可 T2:考场只会打暴搜,正解为排序后线段树解决,排序的关键字为a+b,因为如果ai<bj&a ...
- 第90节:Java中的Linux基础
第90节:Java中的Linux基础 linux是装载虚拟机上面的: JDK依赖包: yum install glibc.i686 MYSQL依赖包: yum -y install libaio.so ...
- [Shell]CVE-2019-0708漏洞复现及修复补丁
0x01 漏洞原理 Windows系列服务器于2019年5月15号,被爆出高危漏洞,该漏洞影响范围较广,windows2003.windows2008.windows2008 R2.windows 7 ...
- ICEM-叶轮泵腔(2D转3D)
原视频下载地址:https://yunpan.cn/cqUfdgMPzyr5y 访问密码 bb4f
- 2018-2019-2 网络对抗技术 20165202 Exp7 网络欺诈防范
博客目录 一.实践目标 二.实践内容 简单应用SET工具建立冒名网站 (1分) ettercap DNS spoof (1分) 结合应用两种技术,用DNS spoof引导特定访问到冒名网站.(1.5分 ...