Shader 优化 | OpenGL 绘制网格效果

简介: Shader 讲解

作者:星陨
来源:音视频开发进阶

前几天发布了这样一篇文章:
KodeLife | Shader 实时编辑预览的强大工具使用实践

除了介绍 KodeLife 的使用之外,还附带了一个 Shader 绘制网格效果的代码。

把这篇文章发到技术群里,随机就有大佬指出不足之处,提示说代码还可以进一步优化,并且提供了源码学习。

可见加入一个高质量的技术群是多么重要,哪怕平时不说话,围观大佬们聊天都能学到很多。

现在加入还来得及,尚有余位,详情点击如下链接:

移动端技术交流喊你入群啦~~~

Shader 讲解

在我的 Shader 代码中是这样绘制网格的:

vec2 fragcoord = vec2(gl_FragCoord.xy / u_resolution);
    vec3 bgColor = vec3(1.0,1.0,1.0);
    vec3 pixelColor = bgColor;
    vec3 gridColor = vec3(0.5,0.5,0.5);

    const float width = 0.1;
    const float minWidth = 0.003;
    for(float i = 0.0; i < 1.0; i+=width){
    if (mod(fragcoord.x,width) < minWidth || mod(fragcoord.y,width) < minWidth){
            pixelColor = gridColor;
        }
    }
    gl_FragColor = vec4(pixelColor,1.0);

首先,讲解几个概念:

gl_FragCoord 代表当前像素相对于屏幕的坐标,屏幕左下角为原点。

u_resolution 是当前图像的分辨率。

用 gl_FragCoord 除以 u_resolution 得到的结果 fragcoord 就是归一化的屏幕坐标。

由于已经归一化了那么 fragcoord 的值就在 [0,1] 的闭区间内。

同时用 gridColor 作为网格的颜色,bgColor 作为背景色,也是默认的颜色,pixelColor 作为最后输出的颜色。

那么,代码的重点就在于 for 循环里面了。

由于 fragcoord 归一化有了确定的值域范围,所以可以在 for 循环中将它十等分。

另外,因为片段着色器每个像素都会执行一遍,每次 fragcoord 值都是变化的,但不管怎么变化,它的范围都会落在 for 循环的十等份里面。

比如其中某一份的范围是 [0.2,0.3) 的左闭右开区间,当前像素就落在这个范围内。

那么 mod 取模函数就会判断当前值距离左区间阈值是否在 minWidth 范围内,其中 minWidth 相当于是指定网格线的宽度。

如果在范围内,那么显示的颜色就是网格色,否则就是默认的背景色。

以上的讲解对于坐标的 x 和 y 值是一样的道理。原理通过判断该像素点的坐标是否位于临界范围内来选择性着色。

显示这种绘制方式是有它的弊端,因为每一个像素执行片段着色器的时候,都要进行一次 for 循环判断它处于哪个区域内。

这样就有了太多不必要的计算流程,尤其是 for 循环的每次遍历。

接下来就是微信群中大佬给出的 Shader 代码:

vec2 st = vec2(gl_FragCoord.xy / u_resolution);
st.x *= u_resolution.x / u_resolution.y;

vec3 color = vec3(.0);

st *= 10.;

vec2 i_st = floor(st);
vec2 f_st = fract(st);

color += step(.98,f_st.x) + step(.98,f_st.y);

gl_FragColor = vec4(color,1.0);

可以一眼看出这里面没有 for 循环的操作了。

还是先讲解几个级别操作:

floor 函数就是向下取整的操作

fract 函数是 x - floor(x) 的操作,也就是取小数部分的意思。

通过对 st 进行 floor 和 fract 操作可以分出它的整数和小数部分。

step 函数类似于 if 判断,当第二个参数大于等于第一个参数,则返回 1 ,否则返回 0 。

整个 Shader 代码第一行还是相同的,都是归一化操作。

然后在第二行

st.x *= u_resolution.x / u_resolution.y

实际上是做了一个比例切换的操作。将 st 的 x ,y 值按照图像分辨率的宽高比做了调整,其中以 y 为基准 1 。

这样一来,st 的 y 值还是在 [0,1] 范围内,而 x 值可能大于也可能小于这个范围了,这都取决于图像分辨率了。

接下来将 st 乘了 10 ,这下 st 的值域范围就在 [0,10] 了 ,这样的操作是为了接下来的 floor 函数,因为它是取整,如果都在 [0,1] 范围内,取的整数永远都是 0 了。

前面转换操作是为了接下来的重点函数 step 。

color += step(.98,f_st.x) + step(.98,f_st.y);

前面的 floor 其实也是将 x 和 y 轴做了等分,比如 y 的值域是 [0,1] ,乘以 10 之后,就是十等分,x 的值域如果是 [0,1.7] ,乘以 10 之后,就是十七等分。

而 fract 操作的结果范围必然是 [0,1) 的左闭右开区间。

step 函数的意图就是如果该像素点的坐标接近于等分线,那么 color 的颜色值返回的就是 1 ,显示白色,否则返回 0 ,显示黑色。

比如,st 的 x 值是 7.99 了,接近于 8 ,那么就要显示白色网格线了,对于 y 值同理。

这样一来就可以对每个像素点进行判断,根据它的坐标决定要显示什么颜色。

总结对比

在第二种绘制中,由于做了比例转换操作,所以绘制出来的网格大小都是一致的,且都是正方形。

而第一种没有比例切换操作,当宽高不同的情况下,同样进行十等分的话,画出来的网格是个长方形了。

但是,两种绘制的思路都是相同的,姑且称它为 接近法 吧,当绘制的像素接近等分线时,就显示不一样的颜色。

于是,等分线的操作思路就各有不同了。前者是利用 for 循环来制造划分,后者则是利用当前像素的 x、y 值的特点来绘制的。

当然更推崇后者的绘制方式了,也是学到了新技巧~~~

OpenGL 系列文章

「视频云技术」你最值得关注的音视频技术公众号,每周推送来自阿里云一线的实践技术文章,在这里与音视频领域一流工程师交流切磋。

阿里云社区.png

相关文章
|
XML SQL Java
Maven的三种打包方式(jar、shade、assembly)
Maven的三种打包方式(jar、shade、assembly)
6687 0
|
存储 自然语言处理 Linux
探究C/C++编码世界:从字符编码到中文处理之艺(三)
探究C/C++编码世界:从字符编码到中文处理之艺
524 2
|
数据安全/隐私保护 开发者 计算机视觉
《鸿蒙 HarmonyOS 应用开发从入门到精通(第 2 版)》学习笔记 ——HarmonyOS 环境搭建之注册华为开发者联盟帐号
要进行HarmonyOS应用开发,首先需要注册华为开发者联盟帐号并完成实名认证。注册时可选择成为个人或企业开发者,两者享有不同权益。个人开发者需准备手机号/邮箱、身份证扫描件及银行卡号等资料,通过审核后即可享受应用市场、主题、商品管理等多项服务。具体步骤包括访问华为开发者官网(https://developer.huawei.com/consumer/cn/),选择注册方式并按指引操作。实名认证需填写个人信息并签署相关协议,等待1-3个工作日的审核结果。
3295 16
|
固态存储 测试技术 iOS开发
硬盘检测工具哪个最好用?这8款值得收藏
硬盘健康状况直接影响电脑性能,选择合适的检测工具至关重要。本文推荐8款实用硬盘检测工具:Windows CHKDSK、DiskGenius免费版、Victoria、HDDScan、SeaTools、AIDA64、HD Tune Pro及Mac磁盘工具。这些工具功能全面,操作简单,涵盖S.M.A.R.T信息查看、坏道检测与修复、性能测试等,满足不同用户需求。无论是Windows还是macOS用户,均可找到适合的工具维护硬盘健康。
|
API Android开发 开发者
Android经典实战之使用ViewCompat来处理View兼容性问题
本文介绍Android中的`ViewCompat`工具类,它是AndroidX库核心部分的重要兼容性组件,确保在不同Android版本间处理视图的一致性。文章列举了设置透明度、旋转、缩放、平移等功能,并提供了背景色、动画及用户交互等实用示例。通过`ViewCompat`,开发者可轻松实现跨版本视图操作,增强应用兼容性。
736 5
|
编解码 JavaScript 编译器
[字符编码] 实战篇:QT中文乱码的解决办法
[字符编码] 实战篇:QT中文乱码的解决办法
4519 0
|
Linux 人机交互
linux系统中QT控件的操作的基本方法
linux系统中QT控件的操作的基本方法
325 0
|
前端开发
Electron入门教程4 —— 切换应用的主题
Electron入门教程4 —— 切换应用的主题
650 0
Electron入门教程4 —— 切换应用的主题
|
项目管理
CMMI之项目管理类核心框架
CMMI之项目管理类核心框架
405 0
|
监控 应用服务中间件 nginx

热门文章

最新文章