Ogre参考手册(四)3.1.4-3.1.14 声明顶点、几何、片段程序(Ogre着色器脚本)

 

3.1.4 声明顶点、几何、片段程序

使用着色程序前需要先对其定义,一个程序定义可以用于多个材质,这仅需要在所使用的材质定义之前定义该程序。

程序定义可以内嵌在.material脚本中(需要放在所有引用的材质之前),或者希望可以在多个.material中使用,可以在外部.program脚本中定义。在.material和.program中的定义完全相同,区别仅在于.program文件会在所有.material之前解析,因此可以确保程序定义会先于任何使用它的材质定义。

程序可以是底层的(依据具体规范如vs_1_1或arbfp1的汇编码)可以使高层的如DirectX9 HLSL、GlSL或者nVidia的Cg。高层语言提供很多好处,如更直观的代码、更易于支持多个架构(比如,CG可以在D3D和GL上使用)。高层程序允许使用命名参数而不是简单的索引方式。

简单的底层顶点程序示例:

vertex_program myVertexProgram asm

{

    source myVertexProgram.asm

    syntax vs_1_1

}

如上,定义片段和几何程序类似,仅需要将vertex_program替换为相应的fragment_program或geometry_program。标题给出程序名称,后跟’asm’指明是一个底层汇编程序。source指明程序源代码位置,syntax指明语法,语法用于引擎编译材质时快速确定程序的语法,避免先加载程序。

支持的语法包括:

vs_1_1 vs_2_0 vs_2_x vs_3_0       DirectX的顶点程序

ps_1_1 ps_2_0 ps_2_x ps_3_0 ps_3_x DirectX pixel shader 片段程序

 

arbvp1 vp20 vp30 vp40             OpenGL的顶点程序

arbfp1 fp20 fp30 fp40                OpenGL片段程序

 

gpu_gp gp4_gp vVidia的opengl 几何程序

 

glsles opengl嵌入系统着色器

 

你可以通过GpuProgramManager::getSingleton().getSupportedSyntax()获取当前图形卡所支持的语法

为汇编着色程序定义命名常量

汇编着色器没有命名常量(uniform参数),因为语言并不支持。但如果你为了性能或混淆(保密)的原因决定将高层程序预编译为底层程序,你可能仍想使用这些命名参数,这可以通过GpuNamedConstants类的save方法,将包含的命名参数表保存为磁盘文件,然后可以在汇编程序中通过manual_named_constants指令引用:

vertex_program myVertexProgram asm

{

    source myVertexProgram.asm

    syntax vs_1_1

manual_named_constants myVertexProgram.constants

}

上例中,myVertexProgram.constants文件由准备阶段,通过调用原始的高层程序highLevelGpuProgram->getNamedConstants(). save(“myVertexProgram.constants”)生成。可以通过这个指令使用命名参数,汇编程序对此一无所知。

默认程序参数

定义程序时,可以使用指令”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,其它参数都不大可能在使用程序时改变),这可以让材质声明更简短

声明共享参数

你可能会给多个程序和应用程序的材质传递相同的参数。共享参数用于在一个地方定义参数值,以供多个特定着色器使用。定义共享参数:

shared_params YourSharedParamsName

{

        shared_param_named mySharedParam1 float4 0.1 0.2 0.3 0.4

        ...

}

通过shared_params声明共享参数,然后通过类似param_named的语法定义各参数:

格式:shared_param_name <param_name> <param_type> [<[array_size]>] [<initial_values>]

param_name必须唯一,param_type可为:float\float2\float3\float4\int\int2\int3\int4\matrix2x2\ matrix2x3\matrix2x4\matrix3x3\matrix3x4\matrix4x2\matrix4x3\matrix4x4。array_size选项允许定义数组,如果提供必须以方括号括起来。

定义后的共享参数,可以在default_params块内通过shared_param_ref引用;也可以在代码中通过GpuProgramManager::getSharedParameters获取引用,并可以通过引用更新参数值。

高层程序

高层的顶点、片段程序通过插件方式提供支持,这是为了保证使用Ogre的应用可以选择一个或多个高层程序支持。Ogre当前支持3个高层程序类型:CG(API及显卡无关的高层语言,支持OpenGL、DirectX和大多数显卡)、DirectX9 HLSL和OpenGL GLSL。HLSL只能用于DirectX渲染系统,GLSL只能用于OpenGL渲染系统。Cg支持两种渲染系统,不过经验表明,更先进的程序特别是使用了大量纹理访问的片段程序,使用渲染系统特定的着色语言可以生成更好的代码。

同时支持HLSL和GLSL的一种方式是使用两个独立的技术,各自引用对应的程序,不过这种方式比较笨。作为替换可以使用Ogre的一致的高层程序使用单个技术选择适合渲染系统的程序

顶点程序中的骨骼动画

可以使用顶点程序通过硬件实现骨骼动画,使用各顶点的混合指示器、混合权重以及世界矩阵数组(通过自动参数world_matirx_array3x4绑定)。你需要通知Ogre不要在软件中处理骨骼动画:

includes_skeletal_animation true

使用这个语句,Ogre将不再处理动画混合,包括顶点位置和法线。注所有的子mesh都需要应用这样的材质,如果你混合骨骼和变形动画,在任一技术采用硬件加速时所有技术都应该硬件加速

顶点程序中的变形动画

你可以使用顶点程序在两个关键帧之间线性插值实现变形动画,两个关键帧数据通过位置寄存器和第一个空闲的纹理坐标寄存器传入,插值系数通过animation_parametric参数绑定。你还需要告诉Ogre不要使用软件处理变形动画,可通过顶点程序定义:

includes_morph_animation true

这样任何使用此材质的实体不会使用软件处理变形动画。如果你的模型同时使用了骨骼和变形动画,需要同时在顶点程序中实现。(所有的子mesh都需要应用这样的材质,如果你混合骨骼和变形动画,任一技术采用硬件加速时所有技术都应该硬件加速)

顶点程序中的姿态动画

你可以在顶点程序中通过权重混合多个姿态;原始顶点数据通过position寄存器绑定,姿态偏移缓冲区通过第一个空闲的纹理坐标寄存器依次绑定,个数最多由'includes_pose_animation声明指定,混合权重常量由animation_parametric参数绑定(第一个,并依次填充n个),最大的姿态个数n由'includes_pose_animation’声明指定:

includes_pose_animation 4

(所有的子mesh都需要应用这样的材质,如果你混合骨骼和变形动画,任一技术采用硬件加速时所有技术都应该硬件加速)

顶点程序中的纹理获取

如果你的顶点程序需要使用顶点纹理获取,你需要使用’uses_vertex_fetch’指令声明,以便其进行硬件能力检查: users_vertex_fetch true

几何程序中的相邻信息

有些几何程序需要相邻信息。需要使用指令让Ogre将相关信息发送到几何着色器:

uses_adjacency_information true

支持阴影的顶点程序

使用阴影时,顶点程序会增加额外的复杂性,因为Ogre只能处理所有固定管线的内容。如果在使用顶点程序的同时使用阴影,你需要做一些调整。

如果使用模板阴影,任何顶点变形都会导致问题,因为模板阴影(阴影体)通过CPU计算,并不能访问到修改后的顶点。如果顶点程序处理标准的骨骼动画,则没有问题,因为Ogre知道如何在软件中复制这种效果,但其它变形不能通过软件复制,你只能接受不能反映变形的阴影或者关闭该对象的阴影。

如果使用纹理阴影,顶点变形可以接受;不过在将对象渲染到阴影纹理时(阴影投射通道),阴影需要渲染为固定的颜色(调制阴影为关联的环境光颜色,叠加阴影为黑色)。为此你需要提供替代的顶点程序,Ogre提供了为渲染阴影投射时(生成阴影纹理)指定顶点程序的方式,参考:阴影和顶点程序

3.1.5 Cg程序

为了定义Cg程序,你需要通过plugins.cfg或者通过代码在启动时加载Plugin_CgProgramManger.so/dll。cg定义很简单:

fragment_program myCgFragmentProgram cg

{

    source myCgFragmentProgram.cg

    entry_point main

    profiles ps_2_0 arbfp1

}

cg 指明程序为Cg高层程序

source cg程序源文件

entry_point用于定义片段程序调用函数,和汇编程序从上到下执行不同,Cg程序支持包含多个函数,因此需要指定调用的函数名

profiles 指明一个或多个cg编译的底层汇编的profile(功能集)。profile与汇编中的语法(syntax)代码相同,区别是这里可以指定多个,因此你可以写一个高层程序而可以同时运行在D3D和GL之上。建议你仅设置最简单的profile以提供最大的硬件兼容性。顺序也很重要,如果图形卡支持多个profile时,将会使用第一个。

compile_argument 指定cgc编译器命令行参数

3.1.6 DirectX9 HLSL

绑定到DirectX的HLSL(higl level shader language),相比CG仅需要DirectX渲染系统

vertex_program myHLSLVertexProgram hlsl

{

    source myHLSLVertexProgram.txt

    entry_point main

    target vs_2_0

}

target用于指定DirectX相关的语法

矩阵顺序说明: HLSL提供两种不同的方式相乘vector与matrix, mul(v,m)和mul(m,v)。唯一的区别是实际是转置矩阵。使用Ogre传入的矩阵时,需要使用mul(m,v),这与RenderMonkey制作的着色器以及Cg一致,但与DirectX SDK和FX不一致,其使用mul(v,m)。使用那些shader时你需要切换mul()中的参数顺序。

注:如果你在着色器中使用float3x4/matrix3x4绑定到Ogre自动定义参数(比如骨头矩阵),你需要在程序定义时使用column_major_matrixes = false选项。这是因为Ogre以行序解析float3x4以节省常量空间。这会告诉Ogre以此种方式传递所有矩阵,以保证mul(m,v)对于所有计算一致。同时Ogre也会告诉着色器采用行序编译(你不需要使用/Zpr或者#pragma parck(row-major)选项,Ogre自动处理这些)。Ogre不支持以float4x3传递骨头矩阵,不过有了以上内容,你也不需要那么做。

 

其它高级选项:

preprocessor_defines <defines>

预处理器定义,用于#ifdef 或者#if语句。定义以’;’或’,’分割,提供可选的’=’以指定具体的值。没有’=’的定义隐含值为1

column_major_matrices <true|false>

默认为true, 这样Ogre传递的所有自动绑定的矩阵都支持mul(m,v)。设置选项为false时会做两件事:转置所有4x4矩阵,同时设置/Zpr(行序)编译选项。这意味着你仍可以使用mul(m,v)但矩阵为行序。这仅在需要使用骨头矩阵(float3x4)时为每个骨头节省1个float4常量

optimisation_level <opt>

优化级别,可以为’default’,’none’,’0’,’1,’2’,’3’,对应于fxc.exe的/O参数,除了default参数(debug模式下关闭,release下为1,fsx.exe永远使用1)。毫无疑问,默认值为’default’。你可能需要调整优化选项,比如你的着色器太复杂,以至于只能使用最小的优化才能编译。

3.1.7 Opengl GLSL

类似Cg,但仅需要Opengl渲染系统插件,例:

vertex_program myGLSLVertexProgram glsl

{

    source myGLSLVertexProgram.txt

}

GLSL不需要entry_point,因为永远是’main()’,也不需要target定义,因为GLSL源代码编译为天然的GPU代码而不是中间的汇编码。

GLSL支持模块化shader文件,即你可以编写GLSL外部函数以在多个Shader文件中使用:

vertex_program myExternalGLSLFunction1 glsl

{

    source myExternalGLSLfunction1.txt

}

 

vertex_program myExternalGLSLFunction2 glsl

{

    source myExternalGLSLfunction2.txt

}

 

vertex_program myGLSLVertexProgram1 glsl

{

    source myGLSLfunction.txt

    attach myExternalGLSLFunction1 myExternalGLSLFunction2

}

外部程序通过attach指令定义,支持空格关联多个。可用于顶点或片段程序

GLSL纹理采样

材质中需要使用int型命名参数传递纹理索引值到glsl纹理采样器,例:

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 }

} } }

index值0引用通道的第一个纹理单元,1对应第二个…..等等

矩阵参数

传递GLSL mat2, mat3, mat4 uniforms示例:

material exampleGLSLmatrixUniforms

{  technique { pass {

      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支持一些自定义顶点属性绑定。有些驱动不能混合内嵌顶点属性如gl_Normal和自定义顶点属性,因为为了最大的兼容性,你可能需要在至少需要一个自定义属性(如骨骼动画)时全部使用自定义属性

Ogre自动自定义绑定声明:

vertex  绑定VES_POSITION,’attribute vec4 vertex’

normal  绑定VES_NORMAL,’attribute vec3 normal’

colour  绑定VES_DIFFUSE,’attribute vec4 colour’

secondary_color  绑定VES_SPECULAR,’attribute vec4 secondary_colour’

uv0-uv7  绑定VES_TEXTURE_COORDINATES,’attribute vec4 uv0’。注uv6\uv7共享属性tangent和binormal,不能同时使用

tangent  绑定VES_TANGENT,’attribute vec3 tangent’

binormal 绑定VES_BINORMAL,’attribute vec3 binormal’

blendIndices  绑定VES_BLEND_INDIES,’attribute vec4 blendIndices’

blendWeights  绑定VES_BLEND_WEIGHTS,’attribute vec4 blendWeights’

预处理器定义

GLSL支持预处理器定义(),用于#ifdef 或者#if SYMBOL==2等等。定义以’;’或’,’分割,提供可选的’=’以指定具体的值,没有’=’的定义隐含值为1。在程序定义处,可通过preprocessor_defines定义预处理器值。例:

// in your GLSL(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程序名

GLSL几何着色器(geometry shader)规范

GLSL允许在不同的图元上运行相同的着色器。为了正确的链接多个着色器,你需要指定输入图元类型、忽略图元类型以及一次运行可以产生多少各顶点。GLSL geometry_program定义需要以下三个格外的参数:

input_operation_type 着色器接受的图元类型,包括:point_list\line_list\line_strip\triangle_list和 triangle_fan

out_operation_type 产生的图元类型,包括:point_list/line_strip/triangle_strip

max_output_vertices 最大产生的顶点数量。最大输出的顶点值受渲染系统限制

例:

geometry_program Ogre/GPTest/Swizzle_GP_GLSL glsl

{

        source SwizzleGP.glsl

        input_operation_type triangle_list

        output_operation_type line_strip

        max_output_vertices 6

}

 

3.1.8 一致的高层程序(Unified High-level Programs)

像之前提到的,同时提供HLSL和GLSL程序以支持不同平台是很有用的,但如果通过多个技术实现会导致重复的材质定义。可以通过另一种式,使用’unified’程序定义,以支持自动根据硬件和渲染系统选择合适的程序。

vertex_program myVertexProgram unified

{

        delegate realProgram1

        delegate realProgram2

        ... etc

}

如上,通过多个delegate指定多个程序,Ogre在运行时可自动选择第一个适合平台的程序,例:

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 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

                         {

                         }

                 }

        }

}

3.1.9 在通道中使用顶点、几何和片段程序

在材质脚本的pass部分,你可以引用.program脚本中定义的程序。程序的定义和在通道中的使用分开,是为了使同一个程序可用于过个材质。

使用程序除了需要指定引用程序的名称,还需要提供参数,例:

vertex_program_ref myVertexProgram

{

        param_indexed_auto 0 worldviewproj_matrix

        param_indexed      4 float4  10.0 0 0 0

}

以上为通道绑定一个顶点程序myVertexProgram(别处定义),设置了两个参数,’auto’参数表明不需要提供(如例中的world/view/projection矩阵由Ogre自动更新)。第二个是手动指定的参数,索引(index)后面再解释。

顶点、片段和几何程序的语法是相同的,仅需要相应的把vertex_program替换为对应的fragment_program_ref\geometry_program_ref.

多数情况下,顶点、片段和几何程序在同一通道中相互关联,不过并不绝对。你可能提供一个顶点程序供多个片段程序使用。还有一种情况是你可以混合使用固定管线与可编程管线。你可以在使用固定的顶点管线同时在通道中使用fragment_program_ref,即没有vertex_program_ref,此时使用的片段程序需要符合相关的API以便从固定顶点管线中读取输出。你同时还可以使用顶点程序输出结果到固定的片段管线。

从固定管线读取或写入对于不同的渲染API(DiretX和OpenGL)都类似,不过真正的处理依据不同的着色语言(顶点、几何、片段)。HLSL和相关的asm参考MSDN:http://msdn.microsoft.com/library, GLSL参考GLSL规范1.1 的7.6章节:http://developer.3dlabs.com/documents/index.htm。 GLSL提供各种变量供程序读写固定管线变量。CG可参考伴随Cg Toolkit提供的CgUsersManaual.pdf的语言Profiles章节: http://developer.nvidia.com/object/cg_toolkit.html。 HLSL和CG提供变量绑定支持读写固定管线变量。

参数说明

参数可以使用以下四种命令指定,使用程序时参数定义语法与定义程序默认参数一致。程序使用参数设置将覆盖程序定义中的参数值。

param_indexed

通过索引设置参数值

格式:param_indexed <index> <type> <value>

例:param_indexed 0 float4 10.0 0 0 0

index 简单的数字,代表参数的位置,需要依据程序定义推导。index依赖于图形卡中常量存储方式:4个元素一块。如果你定义了一个float4在index 0,则下一个index为1。如果你定义的是一个matrix4x4,下一个可用的index则是4,因为4x4矩阵占用了4个索引。

type 参数类型,可以是float4\matrix4x4\float<n>,int4,int<n>。注:int类型参数仅在一些先进的程序语法中可用,详细参考D3D或GL顶点、片段程序。典型的情况下,最有用的是float4和matrix4x4。注:如果你使用了一个大小不是4倍数的类型,剩余的补齐4倍数的值将被填充为0(GPU总是按4个float使用常量)

value 空格或tab分割的值列表

 

param_indexd_auto

通过索引自动绑定参数值,指令告诉Ogre自动更新参数值,避免参数变化的时候每帧都要手工设置参数值

格式:param_indexed_auto <index> <value_code> <extra_params>

例:parem_indexed_auto 0 worldviewproj_matrix

index 与param_indexed相同。不需要指定类型,因为Ogre根据value_code自动判断

value_code 包括以下识别码:

 

world_matrix世界矩阵

inverse_world_matrix.世界矩阵逆

transpose_world_matrix 世界矩阵转置

inverse_transpose_world_matrix 世界转置矩阵逆

 

world_matrix_array_3x4.世界矩阵数组,每个代表一个3x4矩阵,通常用于硬件皮肤。你应该在顶点程序中为使用的骨头提供足够的个数:numBones * 3 * float4

 

view_matrix. 视图矩阵

inverse_view_matrix.

transpose_view_matrix

inverse_transpose_view_matrix

 

projection_matrix 投影矩阵

inverse_projection_matrix

transpose_projection_matrix

inverse_transpose_projection_matrix

 

worldview_matrix 世界视图矩阵

inverse_worldview_matrix

transpose_worldview_matrix

inverse_transpose_worldview_matrix

 

viewproj_matrix 视图投影矩阵

inverse_viewproj_matrix

transpose_viewproj_matrix

inverse_transpose_viewproj_matrix

 

worldviewproj_matrix 世界视图投影矩阵

inverse_worldviewproj_matrix

transpose_worldviewproj_matrix

inverse_transpose_worldviewproj_matrix

 

texture_matrix 纹理矩阵

纹理单元的转换矩阵,常用于固定管线。需要使用'extra_params'指定通道内所使用纹理单元的索引。 如果索引值超出了可用纹理单元个数,参数将设置为Matrix4::IDENTITY.

render_target_flipping

用于绕过投影矩阵转换时调整y值。-1表示需要纹理翻转,否则为1

The value use to adjust transformed y position if bypassed projection matrix transform. It's -1 if the render target requires texture flipping, +1 otherwise.

vertex_winding

顶点换号方式;  -1表示反转 (用于反射),否则为1.

light_diffuse_colour 漫反射光

需要用'extra_params' 设置最近的灯光索引。 ( 0代表最近,方向灯永远在前面).如果没有灯光参数值将为黑色。

light_specular_colour 镜面光

light_attenuation 灯光衰减

float4类型,无灯光时全为0

spotlight_params 聚光灯参数

float4类型,顺序为cos(inner angle /2 ), cos(outer angle / 2), falloff, w为固定1.0f。非聚光灯时为float4(1,0,0,1)。

light_position 灯光位置

世界空间,方向灯为(-dir.x, -dir.y, -dir.z, 0.0f)

light_direction 灯光方向

light_position_object_space 物体空间灯光位置h.

light_direction_object_space

light_distance_object_space

light_position_view_space

light_direction_view_space

 

light_power

The 'power' scaling for a given light, useful in HDR rendering.

light_diffuse_colour_power_scaled

As light_diffuse_colour, except the RGB channels of the passed colour have been pre-scaled by the light's power scaling as given by light_power.

light_specular_colour_power_scaled

As light_specular_colour, except the RGB channels of the passed colour have been pre-scaled by the light's power scaling as given by light_power.

light_number 灯光号

通道渲染时并不一定会使用所有灯光,此参数为当前使用灯光在所有灯光中的索引值,比如在灯光迭代时。

light_diffuse_colour_array 漫反射光矩阵

'extra_params'指定处理的灯光个数,用于单通道光照,不能用于灯光迭代通道

light_specular_colour_array

light_diffuse_colour_power_scaled_array

light_specular_colour_power_scaled_array

light_attenuation_array

spotlight_params_array

light_position_array

light_direction_array

light_position_object_space_array

light_direction_object_space_array

light_distance_object_space_array

light_position_view_space_array

light_direction_view_space_array

light_power_array

 

light_count 当前通道灯光个数

 

light_casts_shadows 1表示投射阴影, 0不投影

 

ambient_light_colour 环境光

surface_ambient_colour 环境光反射属性

surface_diffuse_colour

surface_specular_colour

surface_emissive_colour

surface_shininess

 

derived_ambient_light_colour surface_ambient_colour * ambient_light_colour

derived_scene_colour derived_ambient_light_colour + surface_emissive_colour

derived_light_diffuse_colour

derived_light_specular_colour

derived_light_diffuse_colour_array

derived_light_specular_colour_array

 

fog_colour 雾颜色

fog_params  雾参数(exp_density, linear_start, linear_end, 1.0 / (linear_end - linear_start))

 

camera_position 相机位置

camera_position_object_space

lod_camera_position

lod_camera_position_object_space

 

time 当前时间*可选参数(未提供为1.0f).

time_0_x 依据'extra_params' 设置的参数循环

costime_0_x cos(time_0_x)

sintime_0_x sin(time_0_x)

tantime_0_x tan(time_0_x)

time_0_x_packed float4 ( time0_x, sintime0_x, costime0_x, tantime0_x)

 

time_0_1 time0_x,但缩放到[0..1]

costime_0_1

sintime_0_1

tantime_0_1

time_0_1_packed

 

time_0_2pitime0_x,但缩放到[0..2*pi]

costime_0_2pi

sintime_0_2pi

tantime_0_2pi

time_0_2pi_packed

 

frame_time 当前帧时间*可选参数(未提供为1.0f).

fps 帧速

 

viewport_width    视口大小

viewport_height

inverse_viewport_width

inverse_viewport_height

viewport_size float4(viewport_width, viewport_height, inverse_viewport_width, inverse_viewport_height)

 

texel_offsets 渲染系统相关的纹理偏移

float4(horizontalOffset, verticalOffset, horizontalOffset / viewport_width, verticalOffset / viewport_height).

 

view_direction 模型空间视角方向

view_side_vector view_direction.X axis

view_up_vector view_direction.Y axis

 

 

fov

near_clip_distance

far_clip_distance

 

texture_viewproj_matrix 纹理视图投影矩阵

适应于阴影接收”shdow receiver”的顶点程序,或者content_type shadow类型纹理,'extra_params' 指定灯光索引(content_type shadow可能会在单通道中使用多个阴影纹理)

texture_viewproj_matrix_array

texture_worldviewproj_matrix

texture_worldviewproj_matrix_array

 

spotlight_viewproj_matrix

spotlight_viewproj_matrix_array

spotlight_worldviewproj_matrix

 

scene_depth_range 当前场景深度范围float4(minDepth, maxDepth, depthRange, 1 / depthRange).

shadow_scene_depth_range 阴影场景深度范围,需要'extra_params' 指定灯光索引

 

shadow_colour 阴影色

shadow_extrusion_distance

 

texture_size 纹理大小float4(width, height, depth, 1). 2D纹理, depth为1, 1D纹理, height和depth 为1,需指定纹理索引

inverse_texture_size float4(1 / width, 1 / height, 1 / depth, 1)

packed_texture_size float4(width, height, 1 / width, 1 / height).

 

pass_number 通道号

pass_iteration_number 通道迭代号

 

animation_parametric 动画参数,用于硬件顶点动画

对于变形动画(morph),设置参数为 (0..1)代表第一位置关键帧 (绑定到position寄存器) 和第二位置关键帧 (绑定到第一个空闲的纹理坐标) 间的插值系数,用于顶点程序插值。对于姿态动画(pose),代表一组四个权重参数分别用于4个姿态 (每个分别对应到x, y, z和w成份),原始位置位于position寄存器,未插值偏移量依次位于第n个空闲的纹理坐标寄存器,n由includes_pose_animation决定。当同时使用超过4个姿态时,你需要多次绑定到不同的条目,第二个绑定到姿态5-8, 第三个绑定姿态9-12...

custom 自定义参数

对于程序运行时变化的参数,同时Ogre又没有自动绑定支持,需要使用自定义参数。Ogre允许通过Renderable::setCustomParameter设置自定义参数值,使用自定义参数需要使'extra_params'值与Renderable::setCustomParameter 中的index参数保持一致(index仅用于保持一致,与GPU的参数index无关)。

一般自定义参数应在Renderable::getRenderOperation或Movable::_updateRenderQueue时调用setCustomParameter设置。应用了自定义参数材质的Renderable但没设置参数时程序将会出错

 

param_named

通过参数名称直接设置参数值,与param_indexed类似。只能用于高层程序,因为asm程序只能通过索引,对于高层程序则建议使用param_named。

格式:param_named <name> <type> <value>

例:param_named shininess float4 10.0 0 0 0

param_named_auto

通过参数名称自动绑定Ogre预定义值,与param_indexed_auto类似,用于高层程序。

格式:param_named_auto <name> <value_code> <extra_params>

例:param_named_auto worldViewProj WORLDVIEWPROJ_MATRIX

value_code与extra_params参考param_indexed_auto

 

shared_params_ref

引用共享参数,参考声明共享参数

格式:shared_params_ref <shared_set_name>

 

阴影和顶点程序

使用阴影时,顶点程序会增加额外的复杂性,因为Ogre只能处理所有固定管线的内容。如果在使用顶点程序的同时使用阴影,你需要做一些调整。

如果使用模板阴影,任何顶点变形都会导致问题,因为模板阴影(阴影体)通过CPU计算,并不能访问到修改后的顶点。如果顶点程序处理标准的骨骼动画,这没有问题,因为Ogre知道如何在软件中复制这种效果,但其它变形不能通过软件复制,你只能接受不能反映变形的阴影或者关闭该对象的阴影。

如果使用纹理阴影,顶点变形可以接受;不过在将对象渲染到阴影纹理时(阴影投射通道),阴影需要渲染为固定的颜色(调制阴影为关联的环境光颜色,叠加阴影为黑色)。为此你需要提供替代(alternate)顶点程序,语法与普通的顶点程序引用相似:

shadow_caster_vertex_program_ref myShadowCasterVertexProgram

{

        param_indexed_auto 0 worldviewproj_matrix

        param_indexed_auto 4 ambient_light_colour

}

当渲染阴影投射时,Ogre自动使用这个替代程序。你可以绑定相同或不同的参数,最重要的是你需要绑定ambient_light_colour,因为这决定了调制阴影纹理颜色。如果你不指定替代程序,Ogre将使用不能反映顶点变形的固定管线材质。

另外,在渲染阴影接收时。Ogre需要映射阴影纹理,这可以在固定管线下实现,但如果接收者使用了顶点程序,就需要阴影接收程序即处理顶点变换同时又处理纹理坐标映射。附加的程序类似于:

shadow_receiver_vertex_program_ref myShadowReceiverVertexProgram

{

        param_indexed_auto 0 worldviewproj_matrix //顶点变换

        param_indexed_auto 4 texture_viewproj_matrix //纹理映射

}

为了编写替代程序,Ogre提供了自定绑定参数’texture_viewproj_matrix’传递纹理映射矩阵。顶点程序除了做正常的顶点处理外,还需要使用该矩阵计算纹理坐标并放置到texturecorrd set0和1,因为有些阴影(聚光灯)需要使用两个纹理单元,顶点的颜色输出应该为白色,以避免影响最终的渲染阴影色。

当使用叠加纹理阴影时,阴影渲染道实际上就是光照渲染。所以如果你实现了任何片段程序,光照都需要在自定义的片段程序中处理。你需要使用shadow_receiver_fragment_program_ref:

shadow_receiver_fragment_program_ref myShadowReceiverFragmentProgram

{

        param_named_auto lightDiffuse light_diffuse_colour 0

}

你需要从自定义顶点程序传递投影纹理坐标。对于纹理应用,纹理单元0将始终是阴影纹理,其它为通道绑定的纹理将从1开始后续排列。所以你的纹理接收片段程序与正常的光照通道基本相同,除了在index 0增加了额外的阴影纹理,用于调整最终结果(调制漫反射和镜面光成份)

3.1.10 顶点纹理读取

新一代的显卡支持在顶点程序中读取纹理,而不是仅仅是传统的片段程序。这允许,举个例子来说,通过纹理的数据移动顶点

顶点纹理访问声明

因为硬件并不普遍支持顶点纹理获取,你需要使用uses_vertex_texture_fetch指令(参考顶点程序中获取纹理)声明需要使用纹理的顶点程序,如果不支持,将会产生技术退化。这对于基于D3D的着色器不是必须的,因为顶点纹理仅在vs_3_0中支持,因此可以在着色器定义时通过语法声明。但是对于OpenGL,很多支持GLSL的显卡不支持顶点纹理,因为需要显式声明。

不同渲染系统纹理绑定差异

为顶点程序绑定纹理的方法并未标准化。到本文编写时间为止(2006年第三季度),基于DirectX9的SM3.0硬件支持4个独立的采样器绑定。OpenGL支持在GLSL中访问顶点纹理,不过顶点纹理与片段纹理共享(汇编程序通过NV_vertex_program_3,不过并不流行)。个人期望DirectX10可以采用GL模式,因为一致的着色器架构隐含在两个阶段共享纹理。不过到目前为止,我们仍处于不一致的状态

因为这个原因,需要使用纹理单元的binding_type属性标明纹理的使用,’fragment’默认方式,或者’vertex’。

对于不独立绑定的渲染系统,这并不需要。但对于需要的,这可以保证你的纹理绑定到正确的处理单元。

注:尽管DirectX9为顶点和片段采用了独立的绑定,但为顶点所做的绑定虽然不能被片段程序使用,但仍然占据了位置。我并有去找相应的文档说明,但nVidia的例子确实都避免在顶点和片段单元中使用相同的索引,我试着这么做的时候,片段程序将不能正确的显示该纹理,而如果移到下一索引单元就立刻好了。

纹理格式限制

到目前位置,顶点程序访问纹理的类型仍限制为1或4个成份,全精度的浮点数格式。编码上对应于PF_FLOAT32_R或者PF_FLOAT32_RGBA。其它格式都不支持。另外,纹理必须是常规的2D纹理(不支持立方或体纹理),不支持mipmap和过滤,不过你可以在顶点程序中通过多次采样实现过滤

硬件限制

目前位置,ATI当前显卡(Radeon X1n00)不支持顶点纹理获取。nVidia在6n00和7n00系列支持。ATI支持对应的代替物“渲染到顶点缓冲区”,不过并没有标准化,并有很大的不同,因为不能作为替换的选择。这是事实,虽然Radeon X1n00显卡声称支持vs_3_0(需要支持顶点纹理获取)

3.1.11 脚本继承

当创建与其它脚本仅微小差别的新脚本时,最好可以避免复制粘贴。通过脚本继承可以实现这个目的。这一部分使用材质脚本作为例子,不过Ogre1.6以后,所有脚本编译器解析的脚本都支持继承。

可通过‘:’基于已有的脚本定义新脚本,如:

格式:material <ChildName> : <ReferenceParentMaterial>

唯一需要说明的时父材质必须在子材质之前解析。最简单的方式是将父材质放在材质脚本文件的开头,或者通过import指令导入(参考脚本导入)。注:继承在脚本加载到Ogre后相当于拷贝,对象并没有继承关系,运行时通过代码修改父材质对子材质没有影响。

通过脚本实现拷贝(继承)可减轻无聊的拷贝粘贴工作,同时指定技术、通道、纹理的能力也使继承拷贝更容易。技术、通道、纹理可以直接区分,而不需要指定父材质中的名称。你还可以使用变量,参考脚本变量

名称在材质拷贝时很有用。为了重载,需要保证值位于正确的技术、通道或纹理单元等等,脚本可以在子材质中依照排列顺序一一对应。但如果只有一个参数需要修改,比如第五个通道,这么做就需要像这样:

material test2 : test1

{  technique  {

    pass

    {   }

pass

{  }

 pass

{  }

pass

{  }

    pass

    {      ambient 0.5 0.7 0.3 1.0

    }

}}

这样比较乏味,简单的办法是直接为通道指定名称,避免罗列前面的通道:

material test2 : test1

{  technique 0

  {

    pass 4

    {

          ambient 0.5 0.7 0.3 1.0

    }

 }}

这么做需要知道父材质的通道名称,同时通道必须在正确的技术内。指定技术名和通道名是最佳的做法。如果技术和通道没有指定名称,可以向上面的例子一样使用索引值作为名称

增加新的技术、通道

在子材质增加新的技术通道可以通过指定唯一的名称(父材质中不存在),或者使用比父材质中最大索引值加1作为索引名称。新的技术和通道将放在最后。

覆盖纹理单元属性

可以为纹理单元指定名称以实现继承。使用唯一的名字将添加新的纹理单元:

material BumpMap2 : BumpMap1

{  technique ati8500

  {  pass 0

    {

      texture_unit NormalMap

      {

        texture BumpyMetalNM.png

      }

    }

}}

高级材质继承

从Ogre1.6开始,继承可以更普遍的使用。之前的继承:材质拷贝,限制在顶级材质对象。现在任何层次对象都可以继承(比如技术、通道、合成器目标):

material Test

{ technique

    {

        pass : ParentPass

        {

        }

}}

为了实现这种继承需要使用关键字:”abstract”。该关键字用于顶级声明(不在任何对象内部),表明只能用于继承而不能编译为实际对象。比如声明为abstract的材质不能作为实际纹理使用。所有非顶级对象(比如pass)用于继承时需要使用abstract关键字:

abstract pass ParentPass

{

    diffuse 1 0 0 1

}

通配符继承

使用通配符’*’可以一次匹配多个对象,而不需要知道确切的名称:

abstract technique Overrider

{

   pass *colour*

   {

      diffuse 0 0 0 0

   }

}

如上例,(此技术被继承时)将覆盖多有含有color名称通道的diffuse属性

3.1.12 纹理别名

纹理别名在clone材质且仅需要改变纹理时很有用。纹理别名属于比较特殊的脚本变量,便于将其修改为其它值。纹理单元可以指定纹理别名:

格式:texture_aliase<name>,未指定时,默认值为纹理单元名(texture_unit)

例:以下texture_aliase默认为DiffuseTex

texture_unit DiffuseTex

{

   texture diffuse.jpg

}

 

拷贝材质时,可通过纹理别名修改纹理

格式:set_texture_alias <alias name> <texture name>

例:

material TSNormalSpecMapping

{  technique GLSL  {    pass     {

      // Normal map

      texture_unit NormalMap //默认别名

      {

        texture defaultNM.png

      }

} }

  technique HLSL_DX9

  {   pass     {

      // Normal map

      texture_unit

      {

        texture_alias NormalMap  //直接指定别名

        texture defaultNM.png

      }

}}}

 

material fxTest : TSNormalSpecMapping

{

  set_texture_alias NormalMap fxTestNMap.png //修改NormalMap纹理单元纹理

}

如上,材质fxTest的两个通道纹理NormalMap都将改变为fxTestNMap.png

3.1.13 脚本变量

Ogre1.6开始支持脚本变量(个人感觉没什么用),例:

abstract pass ParentPass

{

   diffuse $diffuse_colour //定义变量

}

 

material Test

{  technique

   {  pass : ParentPass

       {

           set $diffuse_colour "1 0 0 1" //使用时设置值

       }

}}

 

material Test

{

    set $diffuse_colour "1 0 0 1" //设置材质内所有变量值

    technique

    { pass : ParentPass

        { }

    }

}

3.1.14 脚本导入

导入其它脚本,以解决解析先后顺序,比如继承时要保证父定义先解析,或者先加载在.material而不是在.program中定义的程序,例:

import Parent from "parent.material" //导入单个定义

import * from "parent.material" //导入整个文件

posted @ 2015-07-19 10:15  wiki3D  阅读(1204)  评论(0编辑  收藏  举报