`
yanlijun250
  • 浏览: 783418 次
文章分类
社区版块
存档分类
最新评论

2月22日更新《DirectX11的Shader Reflect的几个问题》

 
阅读更多

又看了看U3的实现方式,写了些新的东西:原文见:
http://blog.csdn.net/noslopforever/article/details/7269353


节选:


2.2.1-----2012-2月22日更新----关于U3

又看了看U3 CBuffer这块儿的组织,不是怪异,而是牛逼。

U3因为它整个渲染引擎是具有一整套完整的体系的,而且借助于其优秀的Vertex Factory / Material Template设计,所以可以做到一开始就把所有的Constant全部合理安排的地步,因此它把自己所可能用到的所有CB按照频率和其它因素设置成了8个Buffer。

例如,其Vertex Factory相关的Buffer,在整个Static Mesh的各个SubMesh渲染完之前,是不会Update的,因为没有Update的必要,里面记录的World Matrix信息在这中间是不会改动的。

这样合理的划分即便是相比于使用Effect Pool,也要合理很多,而很多人使用Effect连Effect Pool都不用,性能上的浪费可想而知!因为Effect的实现,是每个Effect自己为自己下属的所有Shader保存一个Cbuffer Cache的,每切换一次Effect,哪怕Shader本身没有变化,CBuffer都会强制重新提交。而且更重要的是,Shader间的CBuffer不共享,明明两个Shader的某个CBuffer的信息完全一样,但只是因为Shader不一样,这个Shader的World Matrix变化还需要在另一个Shader里面设置一次,使得CBuffer重新提交的数量级迅速增加。而U3的组织流程就不存在这个问题。

当然了,整个游戏每次只需要渲染不到100个批次,你用Effect和自己管理Shader代价当然差不了多少了。

但是10000个呢?材质爆炸后呢?单不同Shader的这些Cache Buffer的浪费就是一个恐怖的数量。须知Unreal3就算在材质良好设计大量使用Material Instance的情况下,Shader Pool仍能保持在K这个数量级,还是没开DX11的,K个Shader的Cached Buffer,如果每个Shader独立存储的话,再加上需要临时记录在内存里的Shadow Buffer,是什么概念呢?可想而知。

但是,为什么U3可以这么做呢?是因为它不是一个通用化图形引擎,而是一个体系化的游戏引擎。

通用化图形引擎你不知道别人会怎么使用你的引擎,有些人做《Magicka》那样的小品级游戏(没有任何别的意思,我很喜欢这种小品级游戏),你迫使他花精力去管理各种Buffer组织什么的,人家才不跟你玩那个呢,XNA比你这套方便多了。

但还有些人,整个场景里1000个物体,1000种不同的材质,每个材质都一个独立Shader,这种游戏你如果只支持Effect式的方案就麻烦了,浪费+切换,在这方面可能就会落后一些。

所以,根据实际情况来选择吧。


2.2.2——2012-2-22——关于KlayGE的CBuffer(?)

“印象里,Klay并没有把CB按照RB里的Binding Point重排位置,而是按照CBuffers的获取时传入的Index(就是foreach CBuffers那会儿)直接建立了CB表,这两者是否真正一致?”

手头暂时没有Klay,之前看过,也不敢确认自己到底是不是记得准确。Klay是个优秀的引擎,事实上去年自己用过一段时间,很好用,写的也很不错。这里本文并无意于去讨论Klay,本文还是主要想讨论CB的使用和组织问题,如果这里小生记错了,还望龚大海涵。

这个问题的答案是——不一致如果在使用CBuffer时,强制通过register(b13)把CBuffer设到靠后的位置,就会很快发现这种不一致。

所以,组织CBuffer时,千万记得按照Resource Binding里的Binding Point信息重排CBuffer的位置,否则在后面Set Constant Buffer时,传入的Index就有可能是错的

例如我建立了1个CBuffer,在register b13,但是按照Desc.ConstantBuffers获取出来的数量是1个,所以如果按照ConstantBuffers来阻止的话,这个CB的索引是0,而不是13,提交时如果也按照这个索引提交,就会把本身应提交到13的CB提交给0。




2.3.1——2012-2-22——再论U3的组织

上面说到的问题,感觉U3的那个思路也是很不错的,但是就像之前所说的,那是一种体系化游戏引擎的思路,对于做通用化图形引擎来说并没有太多的参考价值。因为实际的使用者很可能并不能像U3那样去把整个应用程序的CBuffer安排出来,而且这样做对于使用者本身的要求就太高了,会把很多创意高手、图形新手给拒之门外。

另外就是也可以考虑一下Effect Pool的那个思路,把一些可能会共享的参数通过一个Pool,来使得若干个从此Pool产生的Shader可以共享。但是Effect Pool本身事实上是通过对Effect脚本语法分析得出来的,如果要做这个,而不想在D3D的基础上引出太多概念,要怎么做确实还是一个新的问题。

引擎要做成什么样,只有做引擎的人最了解,没有一成不变的方案,只有最适合自己的方案。No Silver Bullets,任何时候都别忘记这一点,既然没有银弹,与其花时间去追寻“一揽子解决方案”,不妨更多时候考虑考虑“他想要什么”。


2.4 关于Samplers、Textures的组织

这玩意基本上比前面的CBuffer要简单,因为它不存在着一个CBuffer里好几个Sampler,Texture每个要去算Offset的问题。
所以只需要围绕着各自Resource Binding的BindingPoint、BindingCount建表即可,也是需要注意Binding Point的问题,Texture和Sampler也是可能会通过register给强制设到后面的。
此外,Sampler、Textures还需要注意的一点在于他们是可以“Array化”的。
是的:
Texture2D GMRTs[4];
可以这样。
有什么不同吗?
两点:
第一,他们的Array信息记录在BindingCount里,上面的情况,BindingCount就不再是正常情况下的1了,而是4。这个是废话,因为前面已经强调过这个问题了。
最需注意的在于第二点,你通过Name获得到的这个变量的变量名不是GMRTs,而是GMRTs[4]!所以如果按照经验,直接把这个Name放到变量表里,后面您可就找不到这个变量咯。
解决方案不麻烦:放到变量表前,先看看有木有“[x]”,有的话干掉,然后再放到变量表即可。
还需注意的是,Texture和Sampler跟CB一样,也是可以在不同的Shader间通用的喔~~所以,优化CBuffer的思路也可以跟这些放到一起来做的~


分享到:
评论

相关推荐

    Reflect.shader

    伪镜面+透明,原理:将cubemap和透明混合实现。可用参数:OA贴图,cubemap,反射强度,透明度

    Simple LWRP Reflective Shaders(个人高价官网购买).rar

    为了充分利用Simple LWRP Reflective Shaders,开发者还需要理解Unity的 Shader Graph,这是一个可视化工具,允许用户通过节点方式创建自定义着色器。通过Shader Graph,即使是对编程不熟悉的设计者也能轻松调整或...

    unity中shader入门

    #### 二、Shader的创建与应用 1. **创建Shader**:通过Assets > Create > Shader,在项目资源面板创建一个新的Shader文件。可以在该文件中编写自定义的Shader代码。 2. **关联Shader与材质**:创建材质(Assets >...

    Shader-graph.zip

    在"Shader-Gragh实现水体效果"这个主题中,我们将探讨如何利用Shader Graph来制作逼真的水面效果。 1. **Shader Graph基础知识** Shader Graph通过图形化界面,将各种节点(Nodes)连接起来,形成一个完整的Shader...

    reflect doc

    在编程领域,`reflect` 是一个非常重要的概念,特别是在诸如 Go、Python 和 Java 等高级语言中。这个概念允许程序在运行时检查自身结构,包括类型、字段和方法,从而实现动态类型检查和元编程。`reflect` 包在 Go ...

    .NET反编译工具 Reflect

    Reflect就是这样的一款工具,它能够将二进制的.NET程序集还原成可读的源代码,帮助开发者深入理解程序的工作原理。 首先,让我们详细了解一下.NET框架。.NET是微软推出的一种开发平台,它提供了一整套用于构建各种...

    android 字体倒影Reflect

    在Android开发中,实现独特的视觉效果是提升用户体验的重要手段之一,"android 字体倒影Reflect"就是一个这样的案例。倒影效果通常用于增加UI的美观度,使得文本在视觉上更吸引人。本教程将深入探讨如何在Android...

    C++ reflect 反射

    本文将深入探讨C++的反射(reflect)特性,并通过一个简单的示例来展示如何实现类对象的方法调用。 反射的核心在于创建一种映射,将编译时的信息(如类型信息)转换为运行时的数据结构,这样就可以在运行时访问这些...

    kotlin-reflect.jar

    kotlin-reflect.jar

    前端项目-reflect-metadata.zip

    Reflect Metadata API解决了这个问题,它允许我们在类、属性、方法等上添加自定义的数据,这些数据可以在运行时被查询和使用。 首先,我们需要理解元数据(Metadata)。元数据是在程序中附加的数据,它提供了关于...

    kotlin-reflect-1.3.70.jar

    Could not download kotlin-reflect.jar 这个问题 是墙的原因 没有下载下来kotlin-reflect.jar的jar包资源。 把下载的kotlin-reflect-1.3.70.jar,放在版本文件的子目录中,重新启动电脑就可以。网上都有对应的操作...

    Orm_Reflect_DB

    在项目中引入"Orm_Reflect_DB",你需要注意的是,反射虽然强大,但也可能导致性能问题,因为它涉及到运行时的类信息查找和动态代码执行。因此,对于性能敏感的场景,可能需要权衡是否使用反射或者如何优化反射的使用...

    Unity Shader Forge 中文版基础+实例手册

    ### Unity Shader Forge 中文版基础+实例手册 #### 概述 《Unity Shader Forge 中文版基础+实例手册》是一本全面介绍Shader Forge这一强大工具的教程书籍。它不仅覆盖了Shader Forge的基础知识,还提供了丰富的实践...

    JBL Reflect Mini NC用户快速说明书.pdf

    * 为了延长电池寿命,请至少每三个月完全充电一次。 结论 JBL Reflect Mini NC 是一款功能强大且高质量的蓝牙耳机,提供了先进的降噪技术和高质量的音频性能。通过本手册,您可以快速地了解 JBL Reflect Mini NC ...

    JBL Reflect Flow用户配置手册.pdf

    JBL Reflect Flow 用户配置手册 本文将围绕 JBL Reflect Flow 耳机的用户配置手册进行详细的知识点总结,涵盖耳机的设计理念、功能特点、技术规格等方面。 一、设计理念 JBL Reflect Flow 耳机的设计理念是为了...

    Vc Reflect1.0(ae插件)

    VC Reflect 是一款After Effects的倒影快速制作插件,VC Reflect 插件简单实用,只需添加插件,就能简单的实现倒影效果,以免去你复制图层,添加效果,然后再预合成什么等一系列麻烦操作。

    Macrium Reflect 磁盘映像备份工具 免费版

    Macrium Reflect Reflect 是一款让你可以在你的磁盘上创建你的硬盘或者分区的一个精确且可靠的映像的简单易用的软件包。使用该映像你可以在部分或者整个系统丢失的情况下恢复你的整 个磁盘,分区或者个别文件和...

    scrcpy投屏 AssertionError: java.lang.reflect.InvocationTargetExcep

    解决这个问题的方法可能有以下几点: 1. **检查版本兼容性**:确保你的Scrcpy版本与你的Android设备以及电脑操作系统兼容。描述中提到安装特定版本(scrcpy-win64-v1.25)可以解决问题,这可能是因为新版本或旧版本...

    reflect-2.0.0.zip

    标题中的"reflect-2.0.0.zip"可能是指一个包含反射库的版本2.0.0的压缩文件。在编程中,反射是Java、Python、C#等面向对象语言的一种高级特性,允许运行时检查类、接口、字段和方法的信息,甚至能够动态调用方法和...

    reflectmetadata的轻量级3KES模块实现

    `reflect-metadata`库在此基础上扩展了几个新的方法,如`Reflect.metadata`、`Reflect.getMetadata`、`Reflect.hasMetadata`等。 `Reflect.metadata`方法用于定义元数据键和值。它接受两个参数:元数据键(通常是...

Global site tag (gtag.js) - Google Analytics