• 首页
  • 技术
  • 旅行
  • 车模
  • 关于

JZ's Blog

{技术, 绘画, 旅行, 摄影, 多肉}
  • 首页
  • 技术
  • 旅行
  • 车模
  • 关于
首页  /  开发 • 技术  /  WebGL 绘制技巧之:如何绘制有洞的多边形。
31 十月 2018

WebGL 绘制技巧之:如何绘制有洞的多边形。

作者:jz1108
开发, 技术 WebGL 2 条留言

在绘制面的时候可能会遇到需要绘制带有“洞”的多边形,比如下面这种情况:

传统前端绘制方法

在传统的前端绘制技术中(如 SVG、Canvas 2D),可以通过设置填充方式(fill-rule)来方便的实现“洞”的效果,这种填充方式称作“evenodd”,翻译过来叫做“奇偶填充”。

下图展示了奇偶填充和普通填充在填充效果上的区别:


图片来源:http://www.enfocus.com/manuals/ReferenceGuide/PP/13/zhCN/zh-cn/common/ppr/concept/c_aa1141812.html

所谓奇偶填充就是从多边形的外层开始算,奇数边内部填充,偶数边内部不填充。

WebGL 实现

在 WebGL 中绘制面需要借助一个三角形分解的库来实现,这个库会根据面的坐标串生成坐标索引,WebGL 才能根据索引绘制出一个面来。如果三角形分解库支持传入“洞”坐标,那么可以直接利用这样的接口实现。比如常见的earcut的前端js库(https://github.com/mapbox/earcut)就能支持单独传入“洞”参数。

earcut(vertices[, holes, dimensions = 2])

问题

虽然这样做可以实现洞的效果,但前提是开发者需要知道给定的一系列闭合坐标串中哪些是外轮廓,哪些是“洞”。这无疑会增加判断成本,且牺牲了通用性。有没有可能像 SVG 或者 Canvas 2d 那样自动根据轮廓的相交关系实现奇偶填充呢?答案是可以,需要用到模板检测(Stencil Test)。

在前面的文章中,我介绍过模板测试的基本概念和使用方法。这里我们要利用 stencilOp 方法将模板缓冲区的内容做取反处理:

stencilOp(gl.INVERT, gl.INVERT, gl.INVERT)

如果只有一个面,或者多个面互不相交,那么所有区域就会做一次取反操作,这时我们定下这个值,模板检测时只有等于这个值的时候才允许绘制。这样所有面都可以绘制出来。如果其中一个区域位于另一个区域内部,则这个区域会有两次取反操作,那么这个区域就不会被绘制出来。从而实现“洞”的效果。

核心代码如下:

// 模板绘制
gl.stencilFunc(gl.ALWAYS, 0, 0xff);
// 取反操作
gl.stencilFunc(gl.INVERT, gl.INVERT, gl.INVERT);
gl.stencilMask(0xff);
gl.colorMask(false, false, false, false);
drawAreas();
// 绘制真正的面
// 0 取反一次是 0xff,那么只有等于 0xff 的情况才通过测试
gl.stencilFunc(gl.EQUAL, 0xff, 0xff);
gl.stencilMask(0);
gl.colorMask(true, true, true, true);
drawAreas();

 Previous Article 我在英格兰——车专辑
Next Article   欢迎来看我的个人画展——观看的印象

相关文章

  • iOS 13 Safari 的一些变化

    2019年11月13日
  • WebGL 文章汇总

    2019年9月12日
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能

    2019年3月24日

2 条留言

  1. LLhc Reply to LLhc
    2021年9月24日 at 上午11:02

    如果存在多个洞的话,使用模版裁剪好,还是用耳切计算三角形?

    • jz1108 Reply to jz1108
      2021年10月14日 at 下午12:38

      使用哪种方案和洞的个数无关。只和文中提到的是否知道在给定的一系列坐标串中,哪些是外轮廓,哪些是洞。

留言

取消回复

近期文章

  • 记录一次解决 no buffer is bound to enabled attribute 报错的过程
  • TypeScript 中的装饰器
  • iOS 13 Safari 的一些变化
  • WebGL 文章汇总
  • 高性能 WebGL —— 使用 ImageBitmap 提升纹理性能

近期评论

  • lew发表在《WebGL绘制详解之五:Stencil Buffer》
  • jz1108发表在《WebGL基础绘制之一:绘制一个点》
  • jz1108发表在《WebGL 文章汇总》
  • xtx发表在《WebGL 文章汇总》
  • thy发表在《WebGL基础绘制之一:绘制一个点》

文章归档

  • 2021年三月
  • 2019年十一月
  • 2019年九月
  • 2019年三月
  • 2018年十二月
  • 2018年十一月
  • 2018年十月
  • 2017年十一月
  • 2017年十月
  • 2017年九月
  • 2017年五月
  • 2017年四月
  • 2017年三月
  • 2017年二月
  • 2017年一月
  • 2016年十一月
  • 2016年十月
  • 2016年四月
  • 2016年三月
  • 2016年二月
  • 2016年一月
  • 2015年十二月
  • 2015年十一月
  • 2015年十月
  • 2015年九月
  • 2015年八月
  • 2015年七月
  • 2015年六月
  • 2015年三月
  • 2014年十二月
  • 2014年十一月
  • 2014年十月
  • 2014年八月
  • 2014年七月
  • 2014年六月
  • 2014年五月
  • 2014年四月
  • 2014年三月
  • 2014年二月
  • 2014年一月
  • 2013年十二月
  • 2013年十一月
  • 2013年十月
  • 2013年九月
  • 2013年八月
  • 2013年七月
  • 2013年六月
  • 2013年五月
  • 2013年四月
  • 2013年三月
  • 2013年二月
  • 2013年一月
  • 2012年十二月
  • 2012年十月
  • 2012年九月
  • 2012年七月
  • 2012年六月
  • 2012年五月
  • 2012年一月
  • 2011年十一月
  • 2011年十月
  • 2011年九月
  • 2011年八月
  • 2011年七月
  • 2011年六月
  • 2011年五月
  • 2011年四月
  • 2011年二月
  • 2011年一月
  • 2010年十二月
  • 2010年十月
  • 2010年九月
  • 2010年六月
  • 2010年五月
  • 2010年四月
  • 2010年三月
  • 2010年二月
  • 2010年一月
  • 2009年十二月
  • 2009年十一月
  • 2009年九月
  • 2009年八月
  • 2009年六月
  • 2009年三月
  • 2009年二月
  • 2009年一月

分类目录

  • 地图API
  • 多肉
  • 开发
  • 技术
  • 摄影
  • 旅行
  • 未分类
  • 汽车
  • 绘画
  • 美食
  • 车模
  • 随笔

功能

  • 登录
  • 文章RSS
  • 评论RSS
  • WordPress.org
© Copyright 2015. Theme by BloomPixel.