OGRE顶点程序与片断程序的声明

292 篇文章 14 订阅

顶点程序与片断程序的声明

为了在你的材质中使用顶点或者片断程序(参看:3.1.9 在渲染通路中使用顶点程序和片断程序),首先你必须定义它们。一个程序定义可以被多个材质使用,唯一的前提条件是必须在引用它之前在材质的渲染通路部分中定义。

程序定义可以被嵌套在.material脚本内(在这种情况下,它必须位于任何对它的引用之前,即必须先定义后引用)或者如果你希望跨多个.material脚本使用同一个程序,你可以在一个外部的.program脚本中定义。程序定义的方式与在.program或者.material脚本中一样,唯一的区别是所有.program脚本都肯定会在.material脚本之前被处理,因此确保你的程序肯定在任何.material脚本之前被定义。正像.material脚本一样,.program脚本可以从你指定的资源路径上的任意位置读取,并且你可以在一个脚本中定义多个程序。

顶点和片断程序既可以是低级渲染语言(例如按照给定的诸如vs_1_1或者arbfp1的低级语法规格写成的汇编代码)也可以是高级渲染语言,例如DirectX9 HLSL,Open GL Shader Language,或者nVidia's Cg language(参看:高级程序部分)。高级语言给你许多优势,例如能够写出更加直观的代码,能够在一个程序中针对多种架构(例如,一段Cg程序既可用在D3D上,也可用在GL上,与此同时,低级的程序也许会需要单独的技术,各自针对不同的API)。高级程序也让你使用命名的参数替代简单的编号参数,尽管参数并不在这里定义,它们用在渲染通路里。

一个低级顶点程序示例如下:

vertex_program myVertexProgram asm
{
    source myVertexProgram.asm 
    syntax vs_1_1
}

如你所见,很简单。定义一个片断程序,与此相同,只是将vertex_program换成fragment_program。在头部给出程序的名字,后跟'asm'指示这是一个低级程序。在大括号内部,你要指定资源来自何处(从指定的资源位置查找,进行装载),还要指出要使用的语法规格。你可能会奇怪为什么要指定语法规格,头部不是已经指定了汇编器的语法了吗,其实原因在于,引擎需要在读取程序之前知道语法规格,因为在材质编译期间,我们想迅速退出使用不支持语法的程序,一开始就不装载这个程序。

当前支持的语法有:

vs_1_1
这是一种DirectX顶点渲染器汇编语法。
支持显卡有:ATI Radeon 8500,nVidia GeForce 3。
vs_2_0
另一种DirectX顶点渲染器汇编语法。
支持显卡有:ATI Radeon 9600,nVidia GeForce FX 5系列。
vs_2_x
另一种DirectX顶点渲染器汇编语法。
支持显卡有:ATI Radeon X系列,nVidia GeForce FX 6系列。
vs_3_0
另一种DirectX顶点渲染器汇编语法。
支持显卡有:nVidia GeForce FX 6系列。
arbvp1
这是OpenGL标准顶点程序汇编格式。大体上相当于DirectX vs_1_1。
vp20
这是一种nVidia特有的OpenGL顶点渲染器语法,是vs 1.1的一个超集。
vp30
另一种nVidia特有的OpenGL顶点渲染器语法。它是vs 2.0的一个超集,被nVidia GeForce FX 5系及以上系列支持。
vp40
另一种nVidia特有的OpenGL顶点渲染器语法。它是vs 3.0的一个超集,被nVidia GeForce FX 6系及以上系列支持。
ps_1_1, ps_1_2, ps_1_3
DirectX像素渲染器(例如片断程序)汇编语法。
支持显卡:ATI Radeon 8500,nVidia GeForce 3。
注解:对于ATI 8500,9000,9100,9200硬件,也可用于OpenGL。ATI 8500到9200不支持arbfp1但是确实支持OpenGL的atifs扩展,非常类似DirectX的ps_1_4。OGRE有针对atifs编译器的ps_1_x模块,当在ATI硬件上使用ps_1_x时,它会自动执行。
ps_1_4
DirectX像素渲染器(片断程序)汇编语法。
支持显卡有:ATI Radeon 8500,nVidia GeForce FX 5系列。
注解:对于ATI 8500,9000,9100,9200硬件,此项也可用于OpenGL。ATI 8500到9200不支持arbfp1但是支持OpenGL的atifs扩展,功能上非常类似于DirectX中的ps_1_4。OGRE有针对atifs编译器的ps_1_x模块,当在ATI硬件上使用ps_1_x时,它会自动执行。
ps_2_0
DirectX像素渲染器(片断程序)汇编语法。
支持显卡有:ATI Radeon 9600,nVidia GeForce FX 5系列。
ps_2_x
DirectX像素渲染器(片断程序)汇编语法。基本上是带有更多指令的ps_2_0。
支持显卡有:ATI Radeon X系列,nVidia GeForce FX 6系列。
ps_3_0
DirectX像素渲染器(片断程序)汇编语法。
支持显卡有:nVidia GeForce FX 6系列。
ps_3_x
DirectX像素渲染器(片断程序)汇编语法。
支持显卡有:nVidia GeForce FX 7系列。
arbfp1
这是OpenGL标准片断程序汇编格式。大体上相当于ps_2_0,意味着不是所有支持DirectX下的基本像素渲染器都支持arbfp1(例如GeForce3和GeForce4就都不支持arbfp1,但是它们都支持ps_1_1)。
fp20
这是一个nVidia特有的OpenGL片断程序语法,是ps 1.3的一个超集。它允许你为基本片断程序使用'nvparse'格式。实际上,它使用NV_texture_shader和NV_register_combiners在GL下提供相当于DirectX's ps_1_1的功能,但是仅限于nVidia显卡。然而,因为ATI显卡比nVidia早一步采用arbfp1,所以它主要用于像GeForce3和GeForce4系列的nVidia显卡。你可以在 这里找到更多有关nvparse的信息。
fp30
另一种nVidia特有的OpenGL片断渲染语法。它是ps 2.0的一个超集,被nVidia GeForce FX 5系列或更高级的显卡支持。
fp40
另一种nVidia特有的OpenGL片断渲染语法。它是ps 3.0的一个超集,被nVidia GeForce FX 6系列或更高级的显卡支持。

你可以通过调用GpuProgramManager::getSingleton().getSupportedSyntax()得到当前显卡支持的语法列表。

默认的程序参数

当定义一个顶点或片断程序时,除非特殊情况下参数被重载了,否则你也可以指定默认参数用于材质中。要使用默认参数,需要你嵌套一个'default_params'块,如下所示:

vertex_program Ogre/CelShadingVP cg
{
	source Example_CelShading.cg
	entry_point main_vp
	profiles vs_1_1 arbvp1
      //默认参数块开始
	default_params
	{
		param_named_auto lightPosition light_position_object_space 0
		param_named_auto eyePosition camera_position_object_space
		param_named_auto worldViewProj worldviewproj_matrix
		param_named shininess float 10 
	}
      //默认参数块结束
}

参数定义的语法与使用程序定义参数是完全一样的,参看:程序参数规格。定义默认参数可以使你避免重复绑定公用的参数(如上面例子清楚地显示:除'shininess'外,其他所有参数在程序的使用中间都不会发生改变),同时也可以使你的材质声明更短些。 高级程序 通过插件提供对于高级的顶点和片断程序的支持;这是为了确保使用OGRE的应用程序可以随意少用或多用高级程序功能。OGRE现在支持3种高级程序,Cg(3.1.5 Cg程序)(一种API独立且显卡独立的高级程序语言,可以让你对于许多显卡在OpenGL和DirectX上编写程序),DirectX9高级渲染语言(3.1.6 DirectX9 HLSL),OpenGL 图形库渲染语言(3.1.7 OpenGL GLSL)。HLSL只能与DirectX渲染系统共同使用,而GLSL只能与GL渲染系统一起使用。Cg两种都可使用。根据使用经验显示,再针对特定渲染系统的渲染语言中,程序越高级,特别是在有大量纹理获取的片断程序中,能够产生出的代码越好。

要既支持HLSL又支持GLSL,一种方法是在材质脚本中分别包括各自的技术,各自引用各自的技术。但是,如果程序基本一样,参数相同,同时技术又十分复杂,只就会使你的材质脚本在快速复制中变得臃肿不堪。替代这种方法的是,如果唯一的不同就是顶点和片断程序的语言,你可以使用OGRE的3.1.8 统一高级程序自动地挑选一个最适合你渲染系统的程序,这样你只需要使用一个技术就可以了。

顶点程序中的骨骼动画
你可以通过写一个顶点程序,在这段程序中利用一组世界矩阵(如果你绑定了自动参数'world_matrix_array_3x4',那么这个矩阵会由OGRE提供)使用每顶点混合索引和混合权重的方法在硬件中实现骨骼动画。由于需要你与OGRE交流这个支持,所以不能实现软件骨骼动画。要想实现骨骼动画,需要在你的vertex_program定义中增加如下属性:
includes_skeletal_animation true
当你做了如上设置,任何使用这个材质的骨骼动画实体都将放弃原定的混合渲染,而是期望顶点程序完成渲染,不仅是顶点还有法线。注意,所有子网格必须被指定一个这里使用的材质,并且如果你将骨骼动画与顶点动画组合在一起(参看 8. 动画部分),那么所有技术应当被硬件加速。
顶点程序中的变形动画
你可以通过编写一个顶点程序硬件实现变形动画,即在第一个位置关键帧和第二个位置关键帧之间线性混合,传递的关键帧包括位置和第一个的空纹理坐标集,并且将animation_parametric值绑定到一个参数上(就是告诉你在二者之间多远的地方插值)。但是,由于你需要和OGRE交流这一支持,所以不能软件实现变形动画。要想实现变形动画,需要在vertex_program定义中增加如下属性:
includes_morph_animation true
当你做了如上设置,任何使用这个材质的骨骼动画实体都将放弃原定的形状,转而期望顶点程序完成它。注意如果你的模型既包括骨骼动画又包括变形动画,其中一个使用硬件加速,那么他们必须在顶点程序中都被实现。注意,所有子网格必须被指定一个这里使用的材质,并且如果你将骨骼动画与顶点动画组合在一起(参看 8. 动画部分),那么所有技术应当被硬件加速。
顶点程序中的姿势动画
你可以依靠拉动原始的顶点数据(某一位置)在一个顶点程序中实现姿势动画(根据权重在多个姿势之间混合),'includes_pose_animation'声明中定义的那些姿势偏移量缓冲区将在从第一个空的纹理单元开始的那些纹理单元中。你必须也使用animation_parametric参数,定义要包含姿势权重的常量的开始点;它们从你定义的参数开始,填入'n'个常量,其中'n'是这个渲染器所能混合的姿势的最大数,即includes_pose_animation参数。
includes_pose_animation 4
注意,所有子网格必须被指定一个这里使用的材质,并且如果你将骨骼动画与顶点动画组合在一起(参看 8. 动画部分),那么所有技术应当被硬件加速。
顶点程序中的顶点纹理拾取
如果你的顶点程序使用了 3.1.10 顶点纹理拾取(Vertex Texture Fetch),你需要用'uses_vertex_texture_fetch'指令声明。这足以告诉OGRE,你的程序使用了这一特性,且硬件对这一特性的支持应该被检查。
uses_vertex_texture_fetch true
带有阴影的顶点程序
当你使用阴影时(参见 7. 阴影部分),运用顶点程序可能会增加额外的复杂度,因为当使用固定功能管线时,OGRE只能自动处理所有的事。如果你使用了顶点程序,同时也使用了阴影,你可能需要做出一些调整。
如果你使用了模板阴影,那么任何执行顶点改变的顶点程序可能会有问题,因为模板阴影在CPU上计算,但是CPU并没有访问过这些被修改过的顶点。如果正在执行标准的骨骼动画,那么一切还好,因为OGRE知道如何软件复制效果,但是任何其它的顶点改变都不能被复制,并且你将或者不得不接受阴影没有反映到这次改变上的事实,或者干脆关闭这个物体的阴影。
如果你使用了纹理阴影,那么顶点改变是可接受的。但是,当渲染一个物体的阴影纹理时(阴影施放者渲染通路),阴影不得不渲染成实心的颜色(链接到调制阴影的环境色,对于额外的阴影渲染为黑色)。因此你必须提供一个供选择的顶点程序,所以OGRE为你提供了一个方法,指定一个解决方案当渲染阴影施放者时使用,详情请参看: 阴影和顶点程序

3.1.5 Cg程序

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

fragment_program myCgFragmentProgram cg
{
    source myCgFragmentProgram.cg
    entry_point main
    profiles ps_2_0 arbfp1
}

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

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

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

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

 

3.1.6 DirectX9 HLSL

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

vertex_program myHLSLVertexProgram hlsl
{
    source myHLSLVertexProgram.txt
    entry_point main
    target vs_2_0
}

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

重要注释——矩阵的顺序:有一件事需要牢记,HLSL允许你使用2种不同方式处理矩阵和向量相乘——mul(v,m)或者mul(m,v)。二者之间唯一的区别就是矩阵被有效地变换。在OGRE中传递矩阵你应该使用mul(m,v)——因为这与渲染器从像RenderMonkey一样的工具中生成的结果保持一致,并且也和Cg一致,但是与使用mul(v,m)的Dx9 SDK和FX合成器不一致——在使用那些渲染器时,你不得不转换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个作用:它自动转换成4x4矩阵并且在渲染编译中设置好/Zpr(行主)选项。这意味着你仍然可以使用mul(m,v),但是矩阵的排布已经替换成了行主的。这只在你需要使用骨骼矩阵(float3x4)时有用,因为它为包含的每一个骨骼都节省了一个float4常量的空间。

3.1.7 OpenGL GLSL

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

vertex_program myGLSLVertexProgram glsl
{
    source myGLSLVertexProgram.txt
}

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

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

vertex_program myExteranalGLSLFunction1 glsl
{
    source myExternalGLSLfunction1.txt
}
vertex_program myExteranalGLSLFunction2 glsl
{
    source myExternalGLSLfunction2.txt
}
vertex_program myGLSLVertexProgram1 glsl
{
    source myGLSLfunction.txt
    attach myExteranalGLSLFunction1 myExteranalGLSLFunction2
}
vertex_program myGLSLVertexProgram2 glsl
{
    source myGLSLfunction.txt
    attach myExteranalGLSLFunction1
}

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

GLSL纹理取样器

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

varying vec2 UV;
uniform sampler2D diffuseMap;
void main(void)
{
	gl_FragColor = texture2D(diffuseMap, UV);
}

在材质脚本中:

fragment_program myFragmentShader glsl
{
  source example.frag
}
material exampleGLSLTexturing
{
  technique
  {
    pass
    {
      fragment_program_ref myFragmentShader
      { 
        param_named diffuseMap int 0
      }
      texture_unit 
      {
        texture myTexture.jpg 2d
       }
    }
  }
}

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

矩阵参数

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

material exampleGLSLmatixUniforms
{
  technique matrix_passing
  {
    pass examples
    {
      vertex_program_ref myVertexShader
      { 
        // mat4 uniform
        param_named OcclusionMatrix matrix4x4 1 0 0 0  0 1 0 0  0 0 1 0  0 0 0 0 
        // or
        param_named ViewMatrix float16 0 1 0 0  0 0 1 0  0 0 0 1  0 0 0 0        
       // mat3
        param_named TextRotMatrix float9 1 0 0  0 1 0  0 0 1  
      }      
      fragment_program_ref myFragmentShader
      { 
        // mat2 uniform
        param_named skewMatrix float4 0.5 0 -0.5 1.0
      }
    }
  }
}

在GLSL中访问OpenGL状态

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

绑定顶点属性
GLSL原生支持自动绑定大多数普通的每顶点输入属性(例如:gl_Vertex,gl_Normal,gl_MultiTexCoord0等)。但是,也有一些不是自动绑定的。必须在渲染中使用'attribute <type> <name>'语法声明,然后OGRE才将顶点数据绑定到它上面。
关于内建的属性的详细介绍,请参见GLSL手册的7.3节,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。例如:
// in your GLSL
#ifdef CLEVERTECHNIQUE 
	// some clever stuff here
#else 
	// normal technique
#endif
#if NUM_THINGS==2
	// Some specific code
#else
	// something else
#endif
// in  your program definition
preprocessor_defines CLEVERTECHNIQUE,NUMTHINGS=2
这种方法你可以使用相同的源代码又可以包括少许变化,每一个都定义为不同的OGRE程序名,但是基于相同的源代码。

3.1.8 统一高级程序

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

vertex_program myVertexProgram unified
{
	delegate realProgram1
	delegate realProgram2
	... etc
}

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

vertex_program myVertexProgramHLSL hlsl
{
	source prog.hlsl
	entry_point main_vp
	target vs_2_0
}
fragment_program myFragmentProgramHLSL hlsl
{
	source prog.hlsl
	entry_point main_fp
	target ps_2_0
}
vertex_program myVertexProgramGLSL glsl
{
	source prog.vert
}
fragment_program myFragmentProgramGLSL glsl
{
	source prog.frag
	default_params
	{
		param_named tex int 0
	}
}
material SupportHLSLandGLSLwithoutUnified
{
	// HLSL technique
	technique
	{
		pass
		{
			vertex_program_ref myVertexProgramHLSL
			{
				param_named_auto worldViewProj world_view_proj_matrix
				param_named_auto lightColour light_diffuse_colour 0
				param_named_auto lightSpecular light_specular_colour 0
				param_named_auto lightAtten light_attenuation 0
			}
			fragment_program_ref myFragmentProgramHLSL
			{
			}
		}
	}
	// GLSL technique
	technique
	{
		pass
		{
			vertex_program_ref myVertexProgramGLSL
			{
				param_named_auto worldViewProj world_view_proj_matrix
				param_named_auto lightColour light_diffuse_colour 0
				param_named_auto lightSpecular light_specular_colour 0
				param_named_auto lightAtten light_attenuation 0
			}
			fragment_program_ref myFragmentProgramGLSL
			{
			}
		}
	}
}

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

vertex_program myVertexProgramHLSL hlsl
{
	source prog.hlsl
	entry_point main_vp
	target vs_2_0
}
fragment_program myFragmentProgramHLSL hlsl
{
	source prog.hlsl
	entry_point main_fp
	target ps_2_0
}
vertex_program myVertexProgramGLSL glsl
{
	source prog.vert
}
fragment_program myFragmentProgramGLSL glsl
{
	source prog.frag
	default_params
	{
		param_named tex int 0
	}
}
// Unified definition
vertex_program myVertexProgram unified
{
	delegate myVertexProgramGLSL
	delegate myVertexProgramHLSL
}
fragment_program myFragmentProgram unified
{
	delegate myFragmentProgramGLSL
	delegate myFragmentProgramHLSL
}
material SupportHLSLandGLSLwithUnified
{
	// HLSL and GLSL technique
	technique
	{
		pass
		{
			vertex_program_ref myVertexProgram
			{
				param_named_auto worldViewProj world_view_proj_matrix
				param_named_auto lightColour light_diffuse_colour 0
				param_named_auto lightSpecular light_specular_colour 0
				param_named_auto lightAtten light_attenuation 0
			}
			fragment_program_ref myFragmentProgram
			{
			}
		}
	}
}

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

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值