Shader 优化 | OpenGL 绘制网格效果-阿里云开发者社区

开发者社区> 视频云小助手> 正文

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 相当于是指定网格线的宽度。

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

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

显示这种绘制方式是有它的弊端,因为每一个像素执行片段着色器的时候,都要进行一次 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 进行 floorfract 操作可以分出它的整数和小数部分。

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

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

然后在第二行

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

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

这样一来,sty 值还是在 [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 其实也是将 xy 轴做了等分,比如 y 的值域是 [0,1] ,乘以 10 之后,就是十等分,x 的值域如果是 [0,1.7] ,乘以 10 之后,就是十七等分。

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

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

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

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

总结对比

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

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

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

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

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

OpenGL 系列文章

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

阿里云社区.png

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
7287 0
《OpenACC并行程序设计:性能优化实践指南》一 3.11 小结
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.11节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
909 0
网站订单少?学会五步,线上销售效果翻倍!
营销型网站对消费类企业十分重要。建设营销型网站,就是要明确网站的营销职能,以营销为核心目标来进行网站建设运营,目标是获得销售线索或直接获得订单。营销型网站应该具有以下五大特征:1、体验好;2、有流量;3、能成交;4、集数据;5、好维护。
4406 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
8987 0
《OpenACC并行程序设计:性能优化实践指南》一 3.12 参考文献
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.12节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
592 0
《OpenACC并行程序设计:性能优化实践指南》一 3.10 使用Score-P和Vampir记录OpenACC运行时事件
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第3章,第3.10节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1242 0
《OpenACC并行程序设计:性能优化实践指南》一 1.1 简单的数据并行循环
本节书摘来自华章出版社《OpenACC并行程序设计:性能优化实践指南》一 书中的第1章,第1.1节,作者:[美] 罗布·法伯(Rob Farber),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2744 0
OpenCV 实现哈哈镜效果
代码,有参考别人的代码 // haha_mirror.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include #include "cv.
1444 0
227
文章
0
问答
来源圈子
更多
+ 订阅
文章排行榜
最热
最新
相关电子书
更多
《Nacos架构&原理》
立即下载
《看见新力量:二》电子书
立即下载
云上自动化运维(CloudOps)白皮书
立即下载