正当防卫2 渲染技术

简介: 引用:http://blog.csdn.net/ccanan/article/details/7935183   http://www.humus.name/Articles/Persson_CreatingVastGameWorlds.

引用:http://blog.csdn.net/ccanan/article/details/7935183

 

http://www.humus.name/Articles/Persson_CreatingVastGameWorlds.pptx

http://www.humus.name/Articles/Persson_GraphicsGemsForGames.pptx

humus在siggraph12上做的关于just cause 2的渲染技术的分享,这里并不像voxel cone tracing里面会讲一个大的,一脉相承的道理,主要是各种游戏开发过程中很实用的一些做法,非常不错。

游戏的一些特点:

 

  • 大:32kmx32km
  • 动态:动态的天气,日夜变化,各种气候
 
远处的点光源

使用sprite emissive来做,可以大量使用,非常高效
 
浮点数计算
浮点数的精度问题的确让人比较头痛,绝大多数是对的,%0.9有一定不太能忍的误差,%0.1的会出现明显错误。
比如这个代码:

uint32fixed_zs=(uint32(16777215.0f * depth + 0.5f) << 8) | stencil;

如果depth是1,返回的最终结果不是我们预想的0xffffffff,而是0,因为浮点数的精度问题,在16777215.0f这个数量级上,加0.5f会变成16777216.0f,而不是16777215.5f。

这里humus列了一个浮点数精度的一个表:


所以很自然也就引出了float的积累误差的问题,基本道理就是所有的计算,尽可能减少中间步骤,具体到实际的example,包括:

 

  • 不要localPos乘以worldMatrix,然后乘以viewProjMatrix,最好能直接乘以MVP matrix
  • 尽量不要去invert matrix,如果不得不如此的话,去构建inverse matrix
    • 比如基于translation,scale, rotation的矩阵的inverse,完全可以使用-translation, 1/scale, -rotation来重新构建
depth buffer的精度
just cause2使用了reverse depth buffer,也就是near是1,far是0,
在console上,使用的是24float的depth buffer,那么绝对值越小,float精度越高,这个很明显的会在远处的depth精度上受益。
在pc上,使用的24bit定点数的depth buffer,定点数其实也会从reverse depth buffre中受益,因为浮点数的积累误差发生在vertex shader计算中,如果使用reverse的,那么精度也会更好。
当然24bit depth定点数的buffer本身的精度表示能力在reverse还是正常的都是一样的。
 
shadows
  • 使用3级的cascaded shadow map
  • 3个light view depth,pack到一个buffer上,这样一个sample就可以搞定
  • 使用snapping防止像素抖动,(http://blog.csdn.net/ccanan/article/details/7391961,这里也记录过cryengine也有同样的做法)
  • 在cascade之间使用了dither来过渡自然
  • 在不同的cascade中,设置object投射到屏幕空间的像素数量的阀值,小于这个阀值的就skip,这样远处的cascade可以提出大量的物件,进而提升效率
  • 大量的tweak,在直升机上的时候的shadow的参数和地上跑的时候完全不同,这一点是程序和美术一起猛调
现存的优化
  • 3张luminance的texture,会pack到一个dxt1的texture里面
  • vertex format压缩
vertex shader里的压缩
这部分亮了,首先是定点压缩,读这个paper之前知道的最好的压缩是:http://blog.csdn.net/ccanan/article/details/7172940,8byte搞定tbn矩阵。
just cause2使用的是4byte(狠!)
存角度:
  1.   

 

  1. <span style="font-family:Microsoft YaHei;">float4 angles=In.Tangents*PI2-PI;  
  2. float4 sc0,sc1;  
  3. sincos(angles.x,sc0.x, sc0.y);  
  4. sincos(angles.y, sc0.z, sc0.w);  
  5. sincos(angles.z, sc1.x, sc1.y);  
  6. sincos(angles.w, sc1.z, sc1.w);  
  7. float3 tangent   = float3(sc0.y * abs(sc0.z), sc0.x * abs(sc0.z), sc0.w);  
  8. float3 bitangent= float3(sc1.y * abs(sc1.z), sc1.x * abs(sc1.z), sc1.w);  
  9. float3 normal    = cross(tangent, bitangent);  
  10. normal =(angles.w>0.0f)?normal:-normal;</span>  
just cause2里面也用了一些quaternion的压缩方式:这个crytek也用了:解压方式略有不同

 

 

  1. <span style="font-family:Microsoft YaHei;">void UnpackQuat(float4 q, out float3 t, out float3 b, out float3 n)  
  2. {  
  3.   t = float3(1,0,0) + float3(-2,2,2)*q.y*q.yxw + float3(-2,-2,2)*q.z*q.zwx;  
  4.   b = float3(0,1,0) + float3(2,-2,2)*q.z*q.wzy + float3(2,-2,-2)*q.x*q.yxw;  
  5.   n = float3(0,0,1) + float3(2,2,-2)*q.x*q.zwx + float3(-2,2,-2)*q.y*q.wzy;  
  6. }  
  7.   
  8. float4 quat = In.TangentSpace * 2.0f - 1.0f;  
  9. UnpackQuat(rotated_quat, tangent, bitangent, normal);  
  10. </span>  
然后一般都是tbn的空间转换,是先解压成3个float3,然后和矩阵做运算,just cause2使用的是quaternion和矩阵做运算,然后解压,可以节省8个指令。

 

 

particle trimming

10年来,几项关键指标的变化,可以看出bandwidth和rop是变化最小的。

particle一直是消耗ROP的大户,使用接近贴图的非矩形来做particle的geometry,降低覆盖的pixel shader计算。


最右边的使用8个顶点来trim的情况,已经可以可以把面积减少到原来的%59.

有专门的工具来自动的进行trim。

 

 

draw call

节省drawcall这件事情在2003年有一个文章<batch!batch!batch!>很大声的讲了,但是到了2012年,已经不是这么回事了。

在pc上,driver model已经非常快了,尤其是在win7和dx11搭配的时候,drawcall的汇编指令是5条,而且里面没有call,是一个jmp,会立即返回。

在dx9上,还是有点小费,不过已经和我们早先听说的严重程度大不相同了,所以是否instancing的确要认真考虑,而且instancing在gpu里面会消耗更多的性能,在cull的时候会造成很大麻烦,时过境迁也。

 

culling

使用的brute force的cull,其中使用了simd指令。

just cause 2认为,基于hierarchy的场景管理虽然理论剔除会更高效,但是其中的执行过程非常的不cache友好,而且大量的branch会把节省的性能都吐回去。

而且hierarchy的维护和实现都麻烦和复杂很多。

最后just cause2选择的是bruce force box cull。

话说这个在之前项目里也发生过,一个哥们想测试四叉树到底比暴力做(还没用simd呢)快多少,结果是暴力更快,当然里面四叉树由于疏于维护,性能也不好。

cull的时候也用到了一些occluder,是美术摆进去的一些box,在大山里面,在大的建筑里面。。。

 

其他:

动态降resolution,会从720p逐渐降resolution,最低640p,群众表示比较ok。

shader performance script,这个会在相关的changelist上面,把shader的消耗(register num, instruction num。。。)和之前的版本做比较。

了解gpu的指令集,可以让shader写的更快更好。

要掂量掂量下自己的水平,不要做不成熟的优化和“高瞻远瞩”,很多预先的为以后的事情做出的设计会带来问题。

细线AA:对于很细的东西,会有比较严重的Alias情况,这里使用一个避免subpixel的方法来达到一个很不错的AA的算法:

在vertex shader里面把线所处的位置clamp到一个pixel的中心:


code:

 

  1. // Compute view-space w  
  2. float w = dot(ViewProj[3], float4(In.Position.xyz, 1.0f));  
  3.   
  4. // Compute what radius a pixel wide wire would have  
  5. float pixel_radius = w * PixelScale;  
  6.   
  7. // Clamp radius to pixel size. Fade with reduction in radius vs original.  
  8. float radius = max(actual_radius, pixel_radius);  
  9. float fade = actual_radius / radius;  
  10.   
  11. // Compute final position  
  12. float3 position = In.Position + radius * normalize(In.Normal);  
相关文章
|
3月前
|
安全 Java 数据库
SpringSecurity认证授权及项目集成
本文介绍了基于Spring Security的权限管理框架,涵盖认证、授权与鉴权核心概念,通过快速入门示例演示集成流程,并结合数据库实现用户认证。进一步扩展实现正常登录,JWT登录及鉴权管理器,实现灵活的安全控制,适用于前后端分离项目中的权限设计与实践。
355 4
|
存储 设计模式 开发框架
总结开发中基于DevExpress的Winform界面效果
总结开发中基于DevExpress的Winform界面效果
|
10月前
|
自然语言处理 算法 API
SelfCite:  通过自监督奖励提升LLM对上下文内容的引用质量
SelfCite 是一种新颖的自监督方法,旨在提升大型语言模型(LLM)对上下文内容的引用质量。传统方法容易产生与上下文不符的“幻觉”,降低生成内容的可信度。SelfCite 通过上下文消融技术和自监督奖励机制,评估并优化引用的质量,确保生成的引用既必要又充分。实验结果显示,SelfCite 在引用召回率、精确率和F1分数上显著优于基线模型,同时保持了答案的正确性,展示了其在实际应用中的潜力。
193 0
SelfCite:  通过自监督奖励提升LLM对上下文内容的引用质量
鸿蒙开发:切换至基于rcp的网络请求
本文的内容主要是把之前基于http封装的库,修改为当前的Remote Communication Kit(远场通信服务),无非就是通信的方式变了,其他都大差不差。
419 4
鸿蒙开发:切换至基于rcp的网络请求
|
人工智能 自然语言处理 Swift
探索面向开放型问题的推理模型Marco-o1,阿里国际AI团队最新开源!
阿里国际AI团队发布的新模型Marco-o1,不仅擅长解决具有标准答案的学科问题(如代码、数学等),更强调开放式问题的解决方案。该模型采用超长CoT数据微调、MCTS扩展解空间等技术,提升了模型在翻译任务及复杂问题解决上的表现。研究团队还开源了部分数据和模型,供社区使用和进一步研究。
探索面向开放型问题的推理模型Marco-o1,阿里国际AI团队最新开源!
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
文章介绍了如何配置HAProxy以支持HTTPS协议和实现服务器的动态上下线。
753 8
HAProxy的高级配置选项-配置haproxy支持https协议及服务器动态上下线
|
网络协议 网络性能优化
第十二问:TCP慢起动详细解释
TCP的慢启动是其拥塞控制的一部分,旨在防止网络拥塞。在连接建立初期,TCP逐步增加发送的数据量,通过接收方的ACK确认来调整拥塞窗口(cwnd)。初始阶段cwnd较小,每收到一个ACK,cwnd增加1个MSS,发送速率大致翻倍。当cwnd达到慢启动阈值(ssthresh)时,进入拥塞避免阶段,cwnd改为线性增长。若发生数据丢失或网络拥塞,TCP会减小cwnd,重新进入慢启动。慢启动通过动态调整发送速率,确保网络不被瞬时大流量压垮。
|
存储 Linux Apache
释放磁盘空间:解决文件删除但空间未释放的困扰
在管理Linux系统的日常中,最令人头疼的时刻之一就是发现尽管已删除了巨大的文件,但是磁盘空间的占用率仍然没有任何下降。这种情况不仅让我怀疑自己的操作是否正确,同时也给操作系统的运行带来了隐患。 究竟问题出在哪,又该如何解决?本次记录,将演示释放磁盘空间:解决文件删除但空间未释放的困扰。
释放磁盘空间:解决文件删除但空间未释放的困扰
|
Web App开发 测试技术 API
playwright使用:启动浏览器与多种运行方式
本文介绍了Playwright,一个用于浏览器自动化的强大工具,支持Chrome、Firefox和WebKit。展示了如何同步和异步启动浏览器,以及使用`with`语句和`start/stop`方法。通过设置`headless=False`可显示浏览器界面。Playwright的等待机制不同于Selenium,采用`slow_mo`全局减速或`wait_for_timeout`进行等待。文章还展示了填写表单和点击元素的示例,并预告下文将讨论元素定位方法。
|
数据可视化 搜索推荐 vr&ar
增强现实(AR)技术在教育领域的应用研究
增强现实(AR)技术在教育领域的应用研究
683 0