Unity3D中提供了很多API用于向shader传值,这篇文章对比测试了两类不同的使用方法的性能。

正文

Unity3D中,通过C#代码向shader传值有两种方式。 
一种是面向具体的material,另一种是面向所有的material。 
以上两种方式分别对应下面两类API:

  • Material.SetXXX();
  • Shader.SetGlobalXXX();

例如,现在的需求是,需要每帧向shader传递一个offset、一个scale、和一个alpha。

普通的做法是:

在shader中添加:

    float _Offset;
float _Scale;
float _Alpha;

在C#中通过以下方式进行传值:

    Shader.SetGlobalFloat("_Offset", offset);
Shader.SetGlobalFloat("_Scale", scale);
Shader.SetGlobalFloat("_Alpha", alpha);

以上写法可以正常工作,但是更好的方法是下面这种:

Shader中:

    float4 _Parameter;

C#中:

    Vector4 parameter = new Vector4(offset, scale, alpha, 0);
Shader.SetGlobalVector("_Parameter", parameter );

第二种方法在GPU寄存器的使用方面会优于第一种方法,因为不论是SetFloat还是SetVector,都会占用一个寄存器。CPU和GPU通信次数越少性能开销也就越少。 
用下面的方法做一下测试,可以发现两种方式在CPU方面开销变化很明显,在我的电脑上,万次循环一帧大约可以节省2ms左右。

void Update()
{
for (int i = 0; i < 10000; i++)
{
if (_switcher)
{
Shader.SetGlobalVector("_Parameter", new Vector4(1, 0, 0, 1));
}
else
{
Shader.SetGlobalFloat("_R", 0);
Shader.SetGlobalFloat("_G", 1);
Shader.SetGlobalFloat("_B", 1);
Shader.SetGlobalFloat("_A", 1);
}
}
}

最后

其实这个技巧也不仅仅局限于Unity3d,在dx和gl中也应该是这样,思想是通用的,如果谁能分享一些不是非常难的结合代码的GPU和CPU通信的学习资料大普通将be very appreciate。

[Unity3D]降低向Shader中传值的开销的更多相关文章

  1. 【Unity Shaders】Shader中的光照

    写在前面 自己写过Vertex & Fragment Shader的童鞋,大概都会对Unity的光照痛恨不已.当然,我相信这是因为我们写得少...不过这也是由于官方文档对这方面介绍很少的缘故, ...

  2. Unity关闭shader中的光照模型以及如何自定义光照模型

    // Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject' // Upgrade NOTE: replaced '_Wor ...

  3. unity, multi pass shader中的surface pass

    今天尝试写一个multi pass shader,但其中有一个Pass是surface pass,总是莫名奇妙地报错.后来看到下面帖子: http://forum.unity3d.com/thread ...

  4. java中传值及引伸深度克隆的思考(说白了Java只能传递对象指针)

    java中传值及引伸深度克隆的思考 大家都知道java中没有指针.难道java真的没有指针吗?句柄是什么?变量地址在哪里?没有地址的话简直不可想象! java中内存的分配方式有两种,一种是在堆中分配, ...

  5. 关于获取URL中传值的解决方法

    在我们页面的URL中包含着很多信息,包括域名,协议等等这里就不一一介绍了),对于我们开发者而言,使用比较多的就是页面之间的传值.为什么要页面传值呢?很简单,当你在浏览一个商品页面的时候你要看到一个商品 ...

  6. 【Unity Shaders】Diffuse Shading——在Surface Shader中使用properties

    本系列主要参考<Unity Shaders and Effects Cookbook>一书(感谢原书作者),同时会加上一点个人理解或拓展. 这里是本书所有的插图.这里是本书所需的代码和资源 ...

  7. OpenGL下多个sampler在shader中的使用

    在OpenGL中,sampler2D/Cube等做为uniform可以在fragment shader中使用.结合glActiveTexture和glUniform1i,实现texture与sampl ...

  8. 关于获取URL中传值的解决方法--升级版

    这次页面之间的传值是升级版本,为什么是升级版本呢,因为这次页面的传值不一样了.大家可以看一下我原来的文章<关于获取URL中传值的解决方法> 其实上次就已经比较清楚的介绍了页面之间的传值,但 ...

  9. unity, shader中获得当前像素深度

    frag shader中直接访问i.pos.z就是深度,不必除以i.pos.w,因为系统已经自动进行过了透视除法且已将i.pos.w置为0.

随机推荐

  1. STM32F103C8开发板原理图和管脚图

  2. 让linux每天定时备份MySQL数据库并删除五天前的备份文件

    MYSQL定期备份是一项重要的工作,但人工操作太繁琐,也难避免有所疏漏,使用下面的方法即可让系统定期备份数据.利用系统crontab来定时执行备份文件,按日期对备份结果进行保存,达到备份的目的. 1. ...

  3. python 阿狸的进阶之路(6)

    常用模块 json # 序列化 #将内存的数据存到硬盘中,中间的格式,可以被多种语言识别,跨平台交互数据 #json 可以将字典之类的数据类型存到字典中 import json dic = {&quo ...

  4. Android虚拟机与Java虚拟机 两种虚拟机的比较

    在Android的体系框架中有一部分叫做Android Runtime,即Android运行时环境,这个环境包括了两个部分,一个是Android的核心类库,还有一个就是Dalvik虚拟机了. Andr ...

  5. RocketMQ服务搭建_1

    rocketmq是阿里研发,并贡献给Apache的一款分布式消息中间件. RcoketMQ 是一款低延迟.高可靠.可伸缩.易于使用的消息中间件. ACE环境:(Adapted communicatio ...

  6. 1037B--Reach Median(中位数)

    median 中位数 odd 奇数 even 奇数 You are given an array aa of nn integers and an integer ss. It is guarante ...

  7. Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务(转载6)

    Redis进阶实践之六Redis Desktop Manager连接Windows和Linux系统上的Redis服务 一.引言 今天本来没有打算写这篇文章,但是,今天测试Redis的时候发现了两个问题 ...

  8. 13.Java国际化.md

    一.国际化开发概述 软件的国际化:软件开发时,要使它能同时应对世界不同地区和国家的访问,并针对不同地区和国家的访问,提供相应的.符合来访者阅读习惯的页面或数据. 国际化(internationaliz ...

  9. eval 用法

    计算 eval('1+1') # 2 在字典中提取键 的值 eval('a',{'a':1}) # 1 计算 Boolean 值 eval( 'True',{'a':1}) # True eval(' ...

  10. 16.2 profile 显示或者隐藏页面 修改密码

    我们auth在clent端有更加强大的功能 显示或者隐藏component 或者 我们可以阻止或者允许某个用户访问url