前言

在写HTML这类自带样式设置的渲染语言时,可能写出一个圆角矩形仅仅就是一个样式设置就搞定了;但是有没有想过,直接在webGL中用原生的着色器算法写出一个类似CSS圆角样式的效果怎么做?

四角等价圆角效果的实现

所谓的四角等价圆角效果就是指:暂时考虑四个角的圆角效果一致,且圆角在水平和竖直方向的半径是一致的,换言之就是四个角共用一个参数;因为像CSS圆角效果目前是可以分别控制四个角以及圆角水平及竖直方向的半径的。

绘制算法简单的来说就是:

找到矩形区域的像素;

抠掉圆角区域外的像素;

圆角边缘区域抗锯齿处理(光滑过渡);

矩形区域

无论外层抽象数据的矩形区域如何确认,用何种距离单位;输入到顶点着色器内时,都需要将顶点坐标转为NDC坐标(标准化设备坐标),这之间的转换无非就是一个二维坐标系之间的映射;

得到了矩形区域的顶点坐标,输入到片元着色器内就可以得到插值后的片元坐标(可以看做是像素坐标),然后进一步根据片元坐标来判断相应片元是否处于圆角区域之外了;

抠掉圆角区域外的像素

有了插值化的顶点NDC坐标和圆角半径参数就可以对圆角外的区域进行计算了,考虑到实际上是以像素作为单位,因此可以构建一个以矩形左上角为原点,单位为像素的本地化坐标系,这样便于进行计算;

分别计算四个角对应的圆中心位置在矩形本地坐标系中的位置;

判断片元是否位于四个角的区域内;

若片元位于四个角的区域内,判断是否位于中心圆的区域之外,位于区域外即可舍去(抠掉);

上述做法听起来很不错,但是这种像素级别的图形光栅化都会有一个问题,那就是曲线边缘会出现锯齿:

抗锯齿处理

通用的抗锯齿做法就是在边缘附近做一个光滑过渡,而非粗暴的直接在边缘处进行直接切割;

以边缘处(阈值,此处为圆角半径长度)为中心,将±1像素长度的范围内的值进行插值;

插值函数可以直接用GLSL自带的smoothstep方法即可;

上述方法得到的效果如下:

可以看到圆角边缘处光滑多了;

着色器代码

下面是针对上述算法实现的一个片元着色器,仅供参考;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43precision highp float; // 高精度

uniform vec2 u_Screen; // 屏幕尺寸

uniform vec4 u_Background; // 背景色

uniform float u_Radius; // 圆角半径

uniform vec2 u_Size; // 矩形尺寸(px)

varying vec2 v_Local; // 局部坐标

uniform bool u_LinearGradient; // 是否为线性渐变填充

uniform vec4 u_FromColor;

uniform vec4 u_ToColor;

vec2 topLeft = vec2(1.0) + u_Radius;

vec2 topRight = vec2(u_Size.x - u_Radius, 1.0 + u_Radius);

vec2 bottomLeft = vec2(1.0 + u_Radius, u_Size.y - u_Radius);

vec2 bottomRight = u_Size - u_Radius;

#pragma glslify: linearGradient = require(./shader-function/linearGradient.glsl)

/** 判断是否为圆角外区域 */

float isCorner() {

float d = 0.0; // 距离所属圆角中心的距离

if (v_Local.x < u_Radius + 1.0 && v_Local.y < u_Radius + 1.0) { // 左上

d = distance(v_Local, topLeft);

}

if (v_Local.x > u_Size.x - u_Radius && v_Local.y < u_Radius + 1.0) { // 右上

d = distance(v_Local, topRight);

}

if (v_Local.x < u_Radius + 1.0 && v_Local.y > u_Size.y - u_Radius) { // 左下

d = distance(v_Local, bottomLeft);

}

if (v_Local.x > u_Size.x - u_Radius && v_Local.y > u_Size.y - u_Radius) { // 右下

d = distance(v_Local, bottomRight);

}

return 1.0 - smoothstep(u_Radius - 1.0, u_Radius + 1.0, d); // ±1像素的过渡光滑处理

}

void main() {

float corner = isCorner();

vec4 bgColor = u_LinearGradient ? linearGradient(u_FromColor, u_ToColor, u_Size, v_Local) : u_Background;

if (corner == 0.0) {

discard; // 废弃像素渲染比透明色更好

} else {

gl_FragColor = corner * bgColor;

}

}

相关文档

如何用html语言制作圆角矩形,webGL中圆角矩形的绘制相关推荐

  1. 如何用易语言制作微转运国际速递运单查询工具

    前几天有个喜欢海淘的朋友就问我,能不能帮他制作运单查询软件,我问她想干嘛?她就说她经常在海外网站买东西,用的一直是微转运国际速递.所以她每次查询运单都要一次打开浏览器又一次关闭浏览器,十分繁琐.就问问 ...

  2. 如何用c语言制作飞机订票系统,C语言编程飞机订票系统如何设计?

    题目:编制一个航空客运订票系统,实现简单的机票操作 班级:计0702 姓名:学号: 完成日期:2008年12月20日 一. 实验内容: 1.问题描述: 航空客运订票的业务包括:查询航班.客票预订和办理 ...

  3. 易语言帐号密码服务器代码,如何用易语言制作一个帐号密码输入和登录功能?...

    [e].版本 2 .支持库 iext 登录 (账号, 密码) .子程序 _超级列表框1_当前表项被改变 到首记录 () 账号 = 超级列表框1.取标题 (超级列表框1.现行选中项, ) .判断开始 ( ...

  4. 如何用C语言清空特定文件夹中的所有文件

    最近笔者在做一个有关计算机视觉的项目,需要对提前的视频帧进行实验,当数据量很大且文件夹中的子文件夹和文件很多时,手工删除这些文件不现实,笔者今天写了一个程序,通过机器自动删除所有相关文件,十分快速,删 ...

  5. Windows下如何用C语言清空特定文件夹中的所有文件

    #include "iostream.h"    //由于该博客系统发布是不能显示正常,代码如需调试,只需将改成""即可 #include "stri ...

  6. c语言程序结构体排序,如何用C语言的结构体数组中的某一值排序?

    [C] 纯文本查看 复制代码#include "stdio.h" #include "string.h" struct student { char name[ ...

  7. 如何用LegendForFlashProgramming来制作SLG游戏

    ※本篇为LegendForFlashProgramming脚本引擎的使用教程第二篇. 一,关于LegendForFlashProgramming脚本引擎 http://blog.csdn.net/lu ...

  8. webgl坐标转换_WebGL笔记_绘制流程以及三维坐标变换(一)

    WebGL绘制一个模型的步骤: 1.获取模型的顶点坐标 2.图元装配(即画相应的三角形面片) 3.光栅化(生成片元,绘制每个三角片上的像素点,染色.纹理映射都在此步) 顶点坐标处理 现实中最常见的三维 ...

  9. WebGL中gl.drawArrays()与gl.drawElements()对比

    本次我们来绘制一个这样的网格(5*10),我们采用程序实现. 为什么绘制网格?!因为网格可以绘制很多不同的对象,比如球.圆环--,对于我们地理信息科学专业来说,地球就是我们关注的重点-- 通过绘制这个 ...

  10. PS圆角制作 ps圆角矩形 ps圆角边框 ps做圆角 ps圆角处理

    PS圆角制作 ps圆角矩形 ps圆角边框 ps做圆角 ps圆角处理 以上是效果 方法如下: 1:用photoshop打开原图,并取消背景锁. 2:选"工具栏"的"圆角矩形 ...

最新文章

  1. XamarinSQLite教程在Xamarin.Android项目中定位数据库文件
  2. shell脚本中$#、$0、$@等特殊变量的含义
  3. 【响应式Web前端设计】css如何设置边框的圆角样式?border-radius属性设置圆角样式(图 文)
  4. 深度学习中的batch理解(batch size 一次喂给神经网络的数据大小量)
  5. Golang gin框架:发送GET POST PUT DELETE请求
  6. c++ 一行输出八个数字_R语言笔记(三):数据输入与输出
  7. Solr管理索引库——(十三)
  8. python list倒序_python数据分析(1):内建序列函数
  9. C# 判断字符中是否包含中文
  10. IMPORT MULTIPLE JS
  11. 苹果CMSv10首涂第四套自适应视频站正版原创挖片网高级DIY模板
  12. 三种常见的ps删除通道的操作
  13. 【BottomBar】Android炫酷的底部切换
  14. 图书馆管理系统UML各种图
  15. win10支持8t 硬盘_详解win10硬盘如何直接安装
  16. 上线三年却很“鸡肋”的微信声音锁究竟做错了什么?
  17. 获得代理ippython_Python3.x:免费代理ip的批量获取并入库
  18. Vue.js 开篇---Vue的介绍及准备工作
  19. 验证Kubernetes YAML的最佳实践和策略
  20. Multi-Stage Progressive Image Restoration

热门文章

  1. 考研英语作文—谋篇布局
  2. 复频域求零输入响应_连续信号与系统的复频域分析()LCH.ppt
  3. Python基础知识——5、字典
  4. 特拉华大学计算机科学怎么样,2020年特拉华大学排名TFE Times美国最佳计算机科学硕士专业排名第84...
  5. 学习问题--js图片路径加载问题
  6. c++程序设计基础-类与对象:继承
  7. 修改hosts解决多网页加载失败/不显示/视频无法观看等问题
  8. 玩转JS|解放双手,快手一键取消多个关注教程
  9. n维立方体角、面、边的个数
  10. 交换机接口的双工模式