前言

Unity Vision VR/AR Summit来到中国了(http://www.bagevent.com/event/197605?bag_track=http://www.bagevent.com/event/197605   ),最近也关注了一下Unity的VR开发。


大概是6月份看到新闻:Steam发布了The Lab所使用的渲染器的所有源代码。我一直挺好奇的, 对于Unity3D这样不开源的引擎,如果搞一个渲染器呢?今天有时间读一下代码,一探究竟。

相关链接
- 官方帖子:http://steamcommunity.com/games/250820/announcements/detail/604985915045842668
- GitHub下载:https://github.com/ValveSoftware/the_lab_renderer
- Unity Asset Store下载:https://www.assetstore.unity3d.com/en/#!/content/63141

特性&实现

从GitHub下载了The Lab Renderer之后,粗略的浏览一遍,内容不多,主要是几个组件的C#代码和一些Shader。接下来就看看它的主要特性是怎么实现的。

Single-Pass Forward Rendering

The Lab Renderer使用Forward Rendering的原因主要是为了MSAA(MultiSampling Anti-Aliasing)和效率。然而Unity默认的Forward Rendering使用了Multi-Pass来渲染所有灯光(每个物体的每个动态灯要多一个Pass来渲染它的光照),The Lab Renderer提供了一个单Pass渲染多个灯光的解决方案。


为了实现Single-Pass Forward Rendering,首先要在Player Settings做一些设置,如上图所示。所谓的“Single-Pass”主要靠Shader来实现了。大体思路就是在“vr_lightng.cginc”这个shader文件中定义了一系列灯光参数的数组:

#define MAX_LIGHTS 18
...
float4 g_vLightColor[ MAX_LIGHTS ];
float4 g_vLightPosition_flInvRadius[ MAX_LIGHTS ];
float4 g_vLightDirection[ MAX_LIGHTS ];

然后使用一个for循环,一次性计算所有灯光的光照:

LightingTerms_t ComputeLighting( float3 vPositionWs ...)
{[ loop ] for ( int i = 0; i < g_nNumLights; i++ ){}
}

接下来就是在C#层来处理灯光信息了。

  • 首先,需要为每个Unity中的灯光对象添加“ValveRealtimeLight.cs ”脚本,class ValveRealtimeLight管理一个静态变量“List< ValveRealtimeLight > s_allLights”用来簿记所有的灯光数据。
  • 然后,需要在Main Camera对象上添加“ValveCamera.cs”脚本。在class ValveCamera.UpdateLightConstants()成员函数中,会计算所有的灯光相关的参数,并设置到Shader的常量中。

    以上就是The Lab Renderer的Single-Pass Forward Rendering这个特性的实现思路。

Shadows

The Lab Renderer还接管了阴影的渲染。需要在Unity的Quality->Shadows settings 中选择“Disable Shadows”来关闭Unity默认的阴影。


如上图所示,The Lab Renderer使用Shadow Mapping的算法来生成实时阴影。这个算法粗略的过程是这样的:

  1. 从灯光的角度渲染一个深度缓冲。这个深度缓冲的几何意义,可以粗略的理解为每个像素点到灯光最近的距离;这个深度缓冲又被成为Shadow Buffer或者Shadow Map。
  2. 在渲染Back Buffer的时候,对于每个需要着色的点,将其“投影”(Projection)到上述的Shadow Map空间,然后进行比较,来判断这个点是不是离灯光最近—-也就是有没有被其他物体遮挡,即在阴影之中。
  3. 生成Shadow Buffer的渲染,对于Spot Light非常直观啦;对于方向光,The Lab采用了近似的方法:将方向光替换成一个“非常远”的点光源;对于点光源,The Lab使用6个假的Spot Light来替代。0_0|||

上述算法的流程控制,在ValveCamera.cs脚本中实现。首先它需要一个从灯光角度渲染的Camera、一个RenderTexture用做Shadow Map,还需要一个Shader来进行Shadow Map渲染(Resources/vr_cast_shadows.shader)。

[ExecuteInEditMode]
[RequireComponent( typeof( Camera ) )]
public class ValveCamera : MonoBehaviour
{...[NonSerialized] private Camera m_shadowCamera = null;[NonSerialized] public RenderTexture m_shadowDepthTexture = null;[NonSerialized] public Shader m_shaderCastShadows = null;...
}

在ValueCamera.OnPreCull()脚本回调函数中会调用ValueCamera.ValveShadowBufferRender()来渲染Shadow Buffer。如上图的Shadow所示,The Lab把所有灯光渲染到了一个整体的Shadow Buffer之中,把每个灯光Shadow Buffer对应的区域,存储到Shader参数“g_vShadowMinMaxUv”之中。这样在前面讲的Single-Pass Forward Rendering过程中,就可以在一个Pass实现所有灯光的光影计算了。

至于vr_cast_shadows.shader的内容,就很简单了,它核心就是一个Vertex Shader,用来计算Projection之后的Position坐标就好,UV啊什么之类的都可以省略掉了。

在灯光渲染的Shader中(vr_lighting.cginc)通过ComputeShadow_PCF_3x3_Gaussian()函数来计算阴影。所谓的PCF就是Percentage Closer Filter,为的是产生阴影的边缘柔滑效果。在这个函数中,它才算有了高斯过滤来对目标点周围的3x3范围进行计算。

Adaptive Quality

对于VR来说,帧速率是非常重要的,所以Valve的大牛就添加了这个特性:动态调节渲染质量,达到稳定的搞效率,这是他在GDC 2016上的一个演讲:https://www.youtube.com/watch?v=eIlb688pUu4
这部分主要涉及到何时去调节质量,调节哪些地方(哪些是不能随便调的),具体的逻辑都在ValveCamera.UpdateAdaptiveQuality()这个函数里了。

Steam VR - The Lab Renderer学习笔记相关推荐

  1. ICC使用----ICC 1 Lab Guide学习笔记

    文章目录 Preface ICC 1 Lab Guide Note: 1.Data Setup & Basic Flow(P27) Learning Objectives Create a M ...

  2. Jupyter Lab的学习笔记

    1 执行终端命令--"!"命令 在Jupyter-Lab中执行终端命令可以使用!命令,因为Jupyter-Lab中无法单独开启终端:

  3. unity3D-游戏/AR/VR在线就业班 C#入门访问修饰符学习笔记

    unity3D-游戏/AR/VR在线就业班 C#入门访问修饰符学习笔记 点击观看视频学习:http://edu.csdn.NET/lecturer/107 访问修饰符 public --公共的,在哪里 ...

  4. VR视频拍摄手法学习笔记

    [本人专业与项目涉及一点VR,这里整理学习时的笔记与经验,若有兴趣相投的童鞋可以一起交流互相学习~~] VR视频\全景视频(叙述手法与后期流程较传统视频更复杂): 1)实拍类(第一人称沉浸.VR广告试 ...

  5. xv6学习笔记——Lab: Xv6 and Unix utilities

    文章目录 前言 一.进程与内存 1.1 fork() 1.2 wait() 1.3 exit() 1.4 exec() 前言 最近在学习MIT经典的操作系统课程--xv6操作系统,之前在本科生期间同样 ...

  6. R语言可视化学习笔记之相关矩阵可视化包ggcorrplot

    本文转载自"R语言中文社区",己获授权. 作者简介Introduction taoyan:伪码农,R语言爱好者,爱开源. 个人博客: https://ytlogos.github. ...

  7. 大数据与智能算法(二-应用级技术)-SMU在线学习笔记

    [课程来源]感谢B站Up主leonding1018的分享,老师的课程内容非常精彩. 本文是观看网络视频课程后的笔记,如涉及版权问题,请及时留言或私信与我联系. 上一篇讲述了一些基本算法,详见<大 ...

  8. Unity学习笔记2 简易2D横版RPG游戏制作(二)

    十二.敌人受攻击时的闪烁和Player的生命值的修正 上一篇中,我们利用Controller2D中的IEnumerator TakenDamage接口,使得我们的Player受到攻击时会进行闪烁,我们 ...

  9. Programming Computer Vision with Python (学习笔记一)

    转载自:http://segmentfault.com/a/1190000003941588 介绍 <Programming Computer Vision with Python>是一本 ...

最新文章

  1. ms-sql是mysql吗_mssql和mysql有哪些区别?
  2. 做最轻量级的数据库中间层,赶紧学起来
  3. Java 5种字符串拼接方式性能比较。
  4. linux oracle无法解析指定的连接标识符_ORA-12154: TNS: 无法解析指定的连接标识符解决...
  5. 计算机休眠怎么唤醒,电脑休眠后,就无法唤醒了?怎么办?快速教你解决这个问题...
  6. 【华为大咖分享】4.反脆弱,高效能组织的能力构建(后附PPT下载地址)
  7. offer上不写具体薪资合理吗_拿着OFFER当白菜?职场菜鸟不带这么玩的
  8. intellij idea 忽略文件不提交
  9. td和div超出部分隐藏的区别和用法
  10. linux如何导出mysql数据,linux下mysql数据的导出和导入
  11. 韦东山freeRTOS系列教程之【第六章】信号量(semaphore)
  12. xml文件怎么转换成wps_word文档怎样转换成xml 怎么将XML文档转成WORD文档
  13. Django笔记09:一招解决使用regroup模板标签出现的重复分组问题
  14. 超说网络NO.4 | 深入了解应用层原理(中科大 郑烇)
  15. 产品| 产品经理学习路径及职业规划
  16. 中国医科大学2021年9月《护理研究》作业考核试题
  17. ArcMap出图小技巧:主图设计、图例、比例尺、指北针、标题
  18. 【测试算法】深入浅出Pairwise 算法
  19. Apache Kudo: 1.0版和未来 [session]
  20. 5分钟学会Linux上传文件和下载文件命令

热门文章

  1. CSDN博客怎么编辑表格
  2. RabbitMQ消息可靠性投递及分布式事务最终一致性实现
  3. 脚本之查询Shared Pool空闲率
  4. TIA博途(西门子PLC)V15/V16上传程序的方法总结
  5. 免费企业签名免费应用分发悠万签名分发
  6. 基于bash通过cdo批处理数据
  7. python实现自动登录QQ邮箱
  8. 移动互联应用开发者的乐园
  9. win10无法安装若要在此计算机,WIN10无法安装以下功能 .net framework 3.5解决办法
  10. 开放式激光雷达 API 旨在加速软件定义的激光雷达采用