对着色器代码与纹理图优化的一些体会

        在以前的项目中写了这么多着色器,以及最近看一些书籍,对着色器的优化有了一些自己的体会,在这里总结一下。

        一.尽量将复杂的计算放在顶点着色器中计算:

        顶点着色器在渲染过程中对物体的每个顶点执行一次,片元着色器则对每一片元执行一次,也就是对顶点构成的面进行插值(也就是求出渐变的值),所以在绘制一个物体时顶点着色器绘制2千次,片元着色器可能就会执行几万次,这样极大地提高了执行效率,但是视觉效果上肯定没有没有对每个片元进行操作来得好。

        二.在使用函数时的优化:

        这里主要指的是三方面的优化

        1:重复计算的部分提前计算好并扒出来放着,从而简化等式提高执行效率,比如说:p = sqrt(2*(X+1))可以改写成1.414*sqrt(X+1)等。

                                                        

        2:尽量使用着色器内建函数,例如在比较大小时不需要自己写判断,直接使用使用max(a,b),在需要计算点乘时使用dot(a,b);这些函数大部分都是硬件实现的,开发时可以直接利用,能够降低代码的复杂度,优化计算速度。 这些函数在我另一篇文章里有转载:http://blog.youkuaiyun.com/srk19960903/article/details/74034721

                                                         

       3:编写着色代码的过程中,有时候需要进行一些简单的计算,对于这些重复性较低的操作,而且计算的内容较为简单,开发过程中不应该将这种计算封装成函数,直接用代码计算即可。这样能大大减少GPU函数调用与返回的消耗。

        三.关于discard:

        discard(丢弃片元)该方法的目的是当满足某条件时将片元丢弃。该操作很耗费资源,其目的大部分也就是让该片元不再显示,所以当不需要该片元时直接将其alpha值设为0或是不做任何处理就可以实现该目标。

        四.着色器中尽量使用顺序结构替代分支结构

        着色器是在GPU中执行,GPU与CPU在硬件结构上有很大的差异,其执行分支语句的效率非常低。故在GPU中需要执行分支语句时往往需要想办法用内建的函数计算出因子,再结合数学表达式来替代分支操作,下面给出一个实际操作的例子:

       1.直观的易于编写的用分支语句完成的代码

       vec4projColor=texture(sTexture,vec2(s,t));

       if(a>0.9999){

                fragColor=colorA;

       }elseif(a<0.0001){

                fragColor=colorB;

       }else{

                fragColor=mix(colorB,colorA,smoothstep(0.0,1.0,projColor.r));

       }

     2.适合提高GPU执行效率的使用内建函数替代分支操作的代码

     vec4 projColor=texture(sTexture,vec2(s,t));

     floata=step(0.9999,projColor.r);

     floatb=step(0.0001,projColor.r);

     floatc=1.0-sign(a);

     fragColor=a*colorA+(1.0-b)*colorB+b*c*mix(colorB,colorA,smoothstep(0.0,1.0,projColor.r));

        通过这个案例就可以体现出着色器优化的一个具体方法,不使用if语句转而灵活的使用内建函数来使分支结构变为顺序结构,具体的方法是将条件分支中的“是”和“否”转换成“1”和“0“”这两个数字。通过内建函数step(a,b),当b<a是值为0否则为1,这样就把分支没有执行到的地方转换成0的值顺序执行下去了。

        五.纹理图的优化

        1.纹理图尽量使用2的n次方大小:这样可以提高转换效率,在一些情况下,不使用2的n次方大小的纹理图可能会出现显示不正确的情况,大部分情况下虽然能够显示正确,但是是因为系统对其自动进行了转换,影响了执行效率。

        2.将许多小的纹理拼成一个大的纹理:这样驱动程序在加载纹理的时候,仅仅需要加载一次就可以了。例如,开发人体模型,可以将一个人的头发,脸,眼睛等组合为一个纹理。

        3.在大场景贴图:对其进行纹理采样时要尽量使用mipmap,虽然这样相对而言会占用一些内存。但是,这样会提高纹理采样的效率,同时一般会得到更好的画面效果。

        4.纹理采样:进行纹理采样时若最近点采样就能满足视觉效果的要求,就不要使用线性采样。由于线性采样算法比最近点采样算法复杂很多,其执行效率要比最近点采样低不少。(线性采样需要将对每一个点进行插值计算)

        以上就是我自己开发经验和阅读一些书籍得到的关于着色器与纹理图优化的知识,如有不对或是不准确的地方还望大家指正,共同进步。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值