Ogre – 材质脚本(三) (转)

我的评论:这篇转载大体内容不错,但有些错误地方,如:对矩阵的行主列主的说明有问题,其他都不错,矩阵的行主列主仅针对输入数据的顺序,和与向量左乘右乘没关系

转载自: http://www.zyh1690.org/ogre-material-script-3/


Ogre – 材质脚本(三)

 CADCG  Kevin Zhang   3年前 (2014-04-21)   453次浏览   已收录  0个评论  扫描二维码 

目录:

Cg程序

DirectX9 HLSL

OpenGL GLSL

统一高级程序

Cg程序

为了定义Cg程序,你需要在开始时装载Plugin_CgProgramManager,方式可以通过plugins.cfg(默认装载)也可以通过自己的插件装载代码。它们非常容易定义:

Cg程序与汇编程序有少许不同,在开始部分,我们声明片断程序的类型为’cg’而不是’asm’,即指明这段程序使用的是Cg高级程序。’source‘参数是一样的,只不过这次引用的是Cg源文件,而不是汇编文件。

接下来就是开始有变化的地方了。首先,我们要定义一个’entry_point‘,这是Cg程序中的一个函数名,也是第一个被调用的片断程序部分。与汇编程序从头到尾运行不同,Cg程序可以包含多个函数,所以你要指定从哪里开始。

接下来,不是固定的’syntax‘参数,而是你要指定一个或多个’profiles‘;即Cg如何将程序编译为低级的汇编程序。它们有与上面提到的汇编语法代码一样的名字;唯一的不同就是你可以列出不止一种汇编语言,因此你可以将程序编译成多种低级汇编程序,所以你写的一个高级程序既可以运行在D3D下也可以运行在GL下。建议你在编译程序时只写入最简单的profile以便获得最大的兼容性。此外,顺序也很关键。如果显卡支持多种语法,那么会使用列在第一个的那一种。

最后,还有一个可选项叫做’compile_arguments‘,你可以像在cgc命令行编译器上面一样指定你想要使用的参数。

DirectX9 HLSL

DirectX9 HLSL有一个与Cg非常近似的语法,但是被绑定在DirectX API上唯一超过Cg的优势就是它只需要DirectX渲染系统插件,不需要其他插件。声明一个DirectX9 HLSL程序非常类似于Cg。举例如下:

如你所见,除了用一个汇编格式列表代替了’profiles‘,几乎主要的语法都是见过的。你有一个’target‘参数,用以指定一个针对性的汇编语法——显然必须是DirectX汇编形式语法代码。

重要注释——矩阵的顺序:有一件事需要牢记,HLSL允许你使用2种不同方式处理矩阵和向量相乘——mul(v,m)或者mul(m,v)。二者之间唯一的区别就是矩阵被有效地变换。在OGRE中传递矩阵你应该使用mul(m,v)——因为这与渲染器从像RenderMonkey一样的工具中生成的结果保持一致,并且也和Cg一致,但是与使用mul(v,m)Dx9 SDKFX合成器不一致——在使用那些渲染器时,你不得不转换mul()的参数

注意,如果你在渲染器中使用了float3x4 / matrix3x4类型,且绑定了OGRE自动定义(例如骨骼矩阵),那么你在程序定义时或许需要使用column_major_matrices = false选项(下面讨论)。这是因为OGRE会将float3x4视为行主的节省一定的空间(3个float4的空间而不是4个float4的空间只占用了前3个),并且也告诉OGRE像这样传递所有矩阵,这样可以使你对于所有计算一致地使用mul(m,v)。OGRE也将告诉渲染器按行主形式编译你不必设置/Zpr编译选项或者#pragma pack(行主)选项,因为OGRE为你做了这些)。注意OGRE不支持以float4x3形式传递骨骼,但是没关系,你根本也不需要这样传递。

高级选项

preprocessor_defines <defines>

这个选项允许你定义可以在HLSL渲染代码内部使用的符号用以改变行为(通过使用#ifdef或者#if语句)。定义用’;‘或者’,‘隔开,并且可选择’=‘操作符指定定义值,没有’=’的那些隐含地被定义为1。

column_major_matrices <true|false>

这个选项的默认值为’true’,因此OGRE传递的矩阵自动绑定为适合mul(m,v)使用的形式。设置这个选项为false,起到2个作用:它自动转换成4×4矩阵并且在渲染编译中设置好/Zpr(行主)选项。这意味着你仍然可以使用mul(m,v),但是矩阵的排布已经替换成了行主的。这只在你需要使用骨骼矩阵(float3x4)时有用,因为它为包含的每一个骨骼都节省了一个float4常量的空间。

OpenGL GLSL

OpenGL GLSL有着与HLSL相似的语法,但是与OpenGL API绑定比Cg好在只需要OpenGL渲染系统插件,不需其他额外的插件。声明也与Cg类似,但更简单。举例如下:

在GLSL中,不需要定义进入点(entry point),因为它总是从’main()’开始,而且也没有目标定义(target definition),因为GLSL源都编译到本地图形处理单元中了,不用再进行中间编译

GLSL支持使用模块化的渲染。这就意味着你可以写GLSL外部功能,供多渲染器使用

外部GLSL功能可以附加到使用它们的程序上,使用’attach‘,然后是所有需要的外部程序名,这些程序名写在同一行上,其间用空格隔开。这在顶点程序和片断程序内都可以使用。

GLSL纹理取样器

在GLSL中,为了从材质脚本向纹理取样器传递纹理单元索引值,要使用’int’类型命名参数。如下例所示:摘自GLSL example.frag资源

在材质脚本中:

索引值0表示渲染通路的第一个渲染单元,索引值1表示第二个,以此类推。

矩阵参数

下面是按GLSL mat2,mat3,mat4格式传递矩阵的例子:

在GLSL中访问OpenGL状态

GLSL可以直接访问大多数GL状态,所以你无须通过材质脚本中的param_named_auto传递这些状态。这些状态包括光源材质状态,以及所有在OpenGL中使用的矩阵的状态,如:模型视图矩阵,世界视图投影矩阵等。

绑定顶点属性

GLSL原生支持自动绑定大多数普通的每顶点输入属性(例如:gl_Vertex,gl_Normal,gl_MultiTexCoord0等)。但是,也有一些不是自动绑定的。必须在渲染中使用’attribute <type> <name>‘语法声明,然后OGRE才将顶点数据绑定到它上面。

OGRE支持如下的自动绑定属性

tangent

如果你在你的GLSL顶点程序的开头部分声明了一个如’attribute vec3 tangent;‘一样的属性,OGRE会自动地将VES_TANGENT类型的顶点元素绑定到这个属性上。注意为了最大限度地兼容渲染器版本,默认情况下,切线被放在一个多余的纹理坐标内,而不是一个切线元素内,但是你可以使用OgreXmlConverter / OgreMeshUpgrader或者通过你的导出器控制这一切。

binormal

如果你在你的GLSL顶点程序的开头部分声明了一个如’attribute vec3 binormal;‘一样的属性,OGRE会VES_BINORMAL类型的顶点元素绑定到这个属性上。注意没有OGRE工具生成双法线,因为它们可以通过顶点程序中的法线和切线被轻易地计算出来。

blendIndices

如果你在你的GLSL顶点程序的开头部分声明了一个如’attribute vec4 blendIndices;‘一样的属性,OGRE会自动地将VES_BLEND_INDICES类型的顶点元素绑定到这个属性上。

blendWeights

如果你在你的GLSL顶点程序的开头部分声明了一个如’attribute vec4 blendWeights;’一样的属性,OGRE会自动地将VES_BLEND_WEIGHTS类型的顶点元素绑定到这个属性上。

预处理器定义

GLSL支持你在代码中使用预处理器——一些靠实现定义,但是你也可以定义你自己的,即对于同一技术的几种不同变体使用使用相同的源代码。为了使用这个特性,在你的GLSL代码中包含进预处理器条件,诸如#ifdef SYMBOL,#if SYMBOL==2之类的等等。然后,在你的程序定义中,使用’preprocessor_defines‘选项,后跟一个字符串。定义用’;‘或者’,‘隔开,其中还可以选择使用’=‘操作符指定定义值。没有’=’的那些被隐含地定义为1。例如:

这种方法你可以使用相同的源代码又可以包括少许变化,每一个都定义为不同的OGRE程序名,但是基于相同的源代码。

统一高级程序

如前文所述,同时编写HLSLGLSL程序以便针对各自的平台经常是十分有用的,但是如果通过多纹理技术做这个工作,当仅是编程语言不同时,可能会引起材质定义臃肿的问题。好在,还有另一种选择。你可以在一个“统一的”程序定义中“包含”多个程序,那样就能依赖于渲染系统和硬件支持自动地选择一个“代理”程序。

这对顶点片断程序都有效,并且你想列出多少个代理程序你就可以列出多少个——第一个被当前渲染系统和硬件支持的程序将会被用于真正的程序中。这近乎于一个微技术系统,但是是为了一个单独的程序而且带有特定的目的。你只能把这用在程序带有全部相同的输入、特定的纹理及其他渲染通路/取样状态这些地方。程序之间唯一的不同之处是语言(或者用HLSL的话来说可能就是目标——你可以在单独一个统一程序中包含带有不同目标的多个HLSL程序,或者任意数量的其他高级语言程序),这可能成为一个非常重要的特性。例如,没有这项特性,你就必须如下所示定义一个同时支持HLSL和GLSL的可编程材质:

这只是一个小例子。你向HLSL中添加的所有东西,不得不也复制一遍到GLSL中。因此,替代这种做法,你可以使用统一程序定义,如下所示:

在运行时中使用到myVertexProgram或者myFragmentProgram时,OGRE基于当前硬件/渲染系统的支持自动挑选一个对应代理的真实程序。如果没有代理可被支持,那么引用统一程序的整个技术被标记为不支持,然后像平常一样检查材质中的下一个技术,看看是否支持当前的渲染系统和硬件。随着你的材质变得越来越大,你就会发现你需要特别的支持HLSL和GLSL(或者需要为了其他什么原因编写多个版本的接口兼容的程序),而统一程序确实可以帮助减少重复。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值