Gamebryo—Shader System

来源:互联网 发布:数据追溯 编辑:程序博客网 时间:2024/04/29 02:44
Shader System

一、 介绍

GB的NiShader系统控制了物体如何被渲染的,包括它们的顶点和像素

着色。NiShader被NiMaterial创建,NiMaterial会分析物体的状态从而决定、创建合适的NiShader对象。材质和着色组成了pipline,它们时基于数据驱动的(data-driven)。

一个shader在GB中代表了一个完整物体的渲染特效。它和DX中的terminology有点差异。当渲染一个物体时,一个GB shader包含了渲染物体时所需的所有pass和render state。

顶点和像素着色器在GB中被作为着色程序来使用。一个render pass只包含一个顶点着色器和一个像素着色器。一个GB shader或者一个复杂的渲染特效,会使用许多pass。

为了和GB中的工具交互,shaders被打包成一个shader library集。这些库支持动态链接库和静态链接库。

Binary shader实例代表了一个完整的GB着色系统中的数据驱动接口。该类提供了一个简单而高效的方法去和应用程序中的shader technology交互。

1. 例子

CubeMap: This sample uses a shader to demonstrate a bump map effect. The shader can be swapped out for the default Gamebryo rendering pipeline.

Picking: This sample demonstrates how to use a shader to perform a screen-space picking operation.

ShaderSample: This sample demonstrates the use of a number of different formats for getting shaders into Gamebryo. These formats include the use of NSF shaders that use shader programs written in HLSL, assembly, and Cg, as well as FX shaders written in HLSL, and programmatic shaders loaded from a shader library.

ShadowMap: This sample demonstrates the use of a shader to create a shadow map effect.

MetalWars: Virtually every object is rendered with shaders, and the sample illustrates advanced shader techniques, such as full-screen post-processing effects and the use of multiple render targets.

Lenguins On Ice: This sample uses the Gamebryo fur shader, a transperency shader for ice, shadow shaders, and whole-screen shader effects such as motion blur and heat shimmer.

2. 构建自己的shader子类

引擎用户可以从NiD3DShaderInterface接口中派生出符合自己需要的shader。NiD3DShaderInterface是一个和D3D 渲染器交互的。

根据你使用的渲染器,在继承shader类时可以有多个层次上的选择。对于D3D renderer,最低级别的继承是从NiD3DShaderInterface。该类要求实现所有被渲染器导出的功能函数,

NiD3DDefaultShader

NiDX9FragmentShader

3. 把自定义shader子类和shaderlibrary进行结合

为了和美术工具交互,提供一个简单的方法不用改变程序来更新shader集。GB提供了NiShader接口。Shader library代表了一系列程序运行时可用的shader.若想要使用该library,应用程序只要使用shader factory来注册级即可.

从美术工具导出library后,美术在场景中把它们和相关模型包进行绑定.一旦合适的library被注册到游戏中,系统会在游戏加载时自动挂载shader.

4. 使用ShaderFactory注册用户的ShaderLibrary。

为了使用“数据流”的形式访问库里的shader,应用程序必须使用shader factory注册该流系统。该过程可以通过调用函数NiShaderFactory::LoadAndRegisterShaderLibrary来完成。静态创建也需要为每一个将要加载的shaer library包含顶级头。在动态创建时包含该头文件也是安全的。

此时最后一件要做的事就是为NiD3DShaderProgramFactory设置目录环境。该过程可以通过NiD3DShaderProgramFactory::SetProgramDirectory函数来完成,以及设置shader program文件所在的目录。

5. 向工具中导入ShaderLibrary

让工具识别你的shader library将会为GB开发者提供极大的方便。

首先它可以把将要添加到物体上的shader以流的形式当作场景中的一部分。为程序注册合适的shader library,当程序运行时它会自动挂载到相应物体上.另一方面,一旦开发者写完了shader effect后,他们不需要去手动把这些shader绑定到相应物体上。

其次,可以导出“tweakable”属性,它使得美术可以使特效变得更加完美。该功能使通过着色系统向几何体提添加NiExtraData标志。可以把把相关属性设置给相应的物体,这些属性会被映射到shader的常量中。这些属性值会被作为物体的一部分导出,并且这些值可以被美术调整,达到可见即所得。这些属性可以被制作成一个动画循环,从而创作出动态的动态效果。

作为一个例子,通过制作光晕来产生角色通的魔法效果。Shader作者可以写一个shader去渲染一个光晕,并且把该光晕的颜色作为一个外观属性导出,并且把该属性作为初始颜色绑定到物体上。同样光晕的大小也作为一个属性被导出。当美术把该shader指定该一个物体,该颜色和大小属性将被添加到modelingtool中的材质编辑器中的shader参数中。美术创建投掷光晕的角色动画,随着大小值的变化光晕会膨胀;颜色会从一个很淡的白色逐渐变成一个红色火花,此时魔法达到顶端。在魔法消失过程中,可时大小值变小到零,颜色最后蜕变成黑色。当角色被导出时,该shader名字、动画参数和角色一次被导出。当游戏进行时,随着角色的动画播放,shader会自动使用动画参数,从而会自动产生特效,而不用去写代码处理。

最后,该系统允许美术和策划预览效果。

为了使用tool-chain组织你的shader library,你必须遵循如下规则:

(1) 你必须实现DLL-builds,tool-chain只有和DLL build一起才能操作shader library,同时当shader library改变时,允许使用工具去操作而不用重新编译。

(2) 你必须实现LoadShaderLibrary函数,该函数原型位于NiD3DShaderLibraryInterface.h中。该函数负责创建library实例以及返回它的调用者。

(3) 从NiShaderLibrary继承的子类,必须实现NiShaderLibrary::GetShaderLibraryDesc函数。该函数告诉美术工具library中有关shader的信息。

(4) DLL的导出格式必须正确。对于DX9-based builds,当shipping版本时为‘.sl9’为后缀名;Release为‘.nl9’;Debug为‘dl9’。

(5) Library的结果必须被放置到合适的路径中,默认是路径为:

%EMERGENT_PATH%\SDK\Win32\DLL\ShaderLibs\VC#

...where "VC#" is "VC80"for libraries built under Visual Studio 2005 and "VC90"for libraries built under Visual Studio 2008.

An example of a programmatic shader library that has been exposed to the tool chain is theShaderLibrary library in theShaderSample sample

6. 为几何体绑定shaders

在GB中Shader不是直接挂载到NiRenderObject上,相反NiMaterial对象负责把相应的shader指定到相应的几何体上。当物体不需要使用shader时,可以使用NiSingleShaderMaterial去对物体设置一个独立的shader。

有三种方法使用NiSingleShaderMaterial给一个NiRnederObject绑定shader。

第一种,使用shader library和tool-chain去绑定一个shader。该方法通过材质编辑器中的“Gamebryo Shader”。当场景被导出时,拥有shader的几何体,将随一个NiSingleShaderMaterial(保存了shader的名字)以及所有shader所需要的属性被stream out。当应用程序被加载时,shader factory会注册shader library,在绘制时正确的shader会通过NiSingleShaderMaterial返回。

第二种,通过NiRenderObject的SetShader方法。当几何体没有shader时,该方将会创建一个NiSingleShaderMaterial实例。有两种SetShader方法。使用shader名字作为参数,此时包含该shader的shader library必须被注册。使用shader指针作为参数,此时必须确保该shader以及被创建。

第三种,可以创建一个NiSingleShaderMaterial实例,然后通过NiRenderObject的ApplyMaterial或ApplyAndActiveMaterial来绑定该material shader到相应的几何体上。

7. 使用NSB/NSF格式

GB的shader系统提供了一组库,从而支持和DX的Effect相似文本shader。该系统把含了三个库:NiBinararyShaderLib、NSBShaderLib、NSFParser。

NiBinaryShaderLib提供了一个NiD3DShader-类的实现和相关支持类。这些支持类实现了数据驱动shader系统、序列化、描述类、以及跨平台相关(使用NDL shader binary(NSB)文件格式文件)。

NSBShaderLib提供了一个NiD3DShaderLibrary的实现,它将返回一个NSB文件所在的目录。每个发现的文件都会被添加到一个shader变量链表上里,该链表将被导出以供应用程序和工具使用。

NSFParserLib提供了解析DSF格式文件的解析功能。和DX中的effect文件相似。该解析库会在指定的目录里搜索。每个搜索到的文件将会被加载、解析、最后组成NSB文件(把文本文件)。这些NSB文件可以被NSBShaderLib访问。工具将首先注册NSBShaderLib。

二、 Shader系统的架构

1. 简介

2. NiShader

3. NiShaderLibrary

4. NiShaderFactory

5. NiShaderParser

6. NiGPUProgram

7. NiShaderConstantMap

8. NiShaderConstantMapEntry

9. Description Class

10. Shader System Class Interaction Diagram

把一个shader添加到一个几何体上需要进过如下步骤:

(1)应用程序或材质系统使用静态NiShaderFactory去请求把一个特定名字的shader添加到指定几何体上。如果几何体从material里获取到shader,材质系统将会自动添加shader到几何体。要不然,应用程序将会应用程序将使用NiShaderFactory从使用上一个shader作为该。

(2)如果shader不在已加载的array里,NiD3DShaderFactory将会查询每个已注册的NiD3DShaderLibrary,如果某个NiD3DShaderLibrary含有该shader,则把它返回给Factory,Factory将会把该shader映射到加载的shader array中。

三、 和渲染器的交互

NiShader的所有子类是通过其父类处理的。在D3D平台上,该指针可以被看作是NiD3DShaderInterface。

Per-mesh Rendering code:NiDX9Renderer:: Do_RenderMesh

Per-pass Rendering code

四、 错误处理

五、 NSPF、NSB着色

六、 使用shader driven assets设计应用程序

1. 简介

GB的shader系统支持art pipeline结构。

2. 构造一个光照模型

3. 解析NSF shander

4. 运行时加载Binary shader

5. Shader中的宏

6. 使用事件控制器

7. 加载

七、 FX着色

当NiD3DXEffectShaderLib被连接到应用程序时,无论时静态方式还是动态的,应用程序都会把FX文件看作是一个NSB文件,并且创建shader library来代表该文件,同时包含所有该文件中的techniques。应用程序会从library中获取一个shader,该library将创建一个NiD3DXEffectShader,该NiD3DXEffectShader封装了给定一个technique去绘制一个物体的所有东西。通过D3D的annotations和semantics,techique中的parameters可以被连接到一个GB data,犹如NSF/NSB。

GB可以加载一个文本格式和二进制格式的FX shader(被fxc.exe编译过的)。编译过的fx shader会使用一个扩展名为“.FXO”从而区分未编译的。

1. 编译一个NiD3DXEffectShaderLib

为了加载D3D effect,NiD3DXEffceShadeLib会直接使用DirectX9的接口。所以必须要有相应的DX SDK。

2. 连接和使用NiD3DXEffectShaderLib

和其它shader library相似,NiD3DXEffectLShaderLib既能动态也能静态地连接到应用程序上。在程序运行时,应用程序调用NiD3DShaderFactory::LoadAndRegisterShaderLibrary去创建一个NiD3DXEffectShaderLibrary对象,并且使用它去加载D3D Effect文件中的所有shader。如果此时,渲染器已经存在则会使用渲染器去加载D3D Effct文件,要不然一个空DX9设备将被创建,从而完成加载D3D Effct文件的工作,但此时的结果未必正确。所以在使用shader之前必须保证有个正确的渲染器。

3. 整合D3D 特效文件

为了使用好D3D Effct文件,必须对应用程序和shader之间进行数据映射,如变换、常量、纹理等。传统的做法是基于使用Microsoft’s EffctEdit,要求D3D Effct文件去作为参数包含semantics和annotations,从而应用程序可以修改和访问。

一些绑定是通过semantics或annotations去完成的。

全局属性

全局变量用来影响场景中的所有物体,这些属性包含光照、雾化这些被存储在全局shader constant map中。这些变量可以被应用程序通过NiD3DShaderFactory::UpdateGloabalShaderConstant重新设置。在D3D Effct文件中可以使用semantic(语法)或annotation(标记)进行说明。如:

属性

属性是被应用到特定物体上的一组数据,如材质颜色。这些属性通过NiExData绑定到特定物体上。这些属性在D3D Effct文件中被标记为ATTRIBUTE,如:

预定义常量

代表了一些共同的值如、world matrix、projection matrix.....。

纹理

通过标记来把一个纹理连接成一个参数。两种连接方式:对纹理用途进行命名;通过表明GB NiTexturingPropty中那个map使用。纹理支持以下标记:

纹理既可以通过纹理数据来构建,也可以通过贴图文件。此时NiD3DXShaderEffectLib将在当前工程目录下寻找文件。

Techniques

Implementations

4. Semantic Adapter Tables in D3D Effect Files

5. Object Annotations and Semantics for D3D Effect Files

八、 CGFX着色

九、 Shader程序

原创粉丝点击