OGRE 學習 - 材質 Material
材质是一个很基本的术语,表示你的物体对光的反射方式。 材质定义了物体对光线反射的处理方法。这里暗示了材质的表现与光源的类型相关: 聚光(Spotlights)、点光源(point lights)以及有向光(directional lights)对材质的表现有着完全不同的影响。 简单来讲,它们都是对物理世界真实光源类型的模拟,所以材质对它们的反射也遵守着其在物理世界中的规则。 Note: 虽然在Ogre里面,材质定义了物体如何反射光线的方法,但实际上并没有真的把光反射到附近的物体上。 换句话说,场景中物体的辐射和反射属性并没有给场景增加任何光照。 这是因为Ogre(以及目前绝大多数的即时渲染算法中)使用了局部辐射的算法来处理光照效果。 所谓全局辐射光照模型,指的是通过光线跟踪等技术,计算场景中所有包括反射、辐射等所有光线的照明结果的算法模型。 虽然全局光照模型可以产生和真实照片媲美的渲染结果,但因为其算法相对比较消耗时间, 所以目前仍然无法应用于即时渲染领域(即时运算的3D应用程序,至少要每秒产生30帧画面)。 所以全局光照模型现在只活跃于用来产生照片质量动画的“离线”渲染工具中,比如Pixar’s RenderMan(http://www.pixar.com), Mental ray(http://www.mentalimages.com,包括3D Studio Max 等商业软件所使用的工具), POV-Ray(http://www.povray.org,一个开源的光线跟踪渲染工具)以及 Aqsis(一个免费开源的符合RenderMan标准的离线渲染器)中。 Ogre作为一个典型的渲染引擎,把物体上的颜色分解成四种不同的光照作用:环境反射(Ambient)、漫反射(Diffuse)、放射(Emissive)以及镜面反射(Specular)。 物体着色的基础
在这里镜面反射的高光的颜色是可以被用户定义的。 图6-1展示了在3D Studio Max软件中材质编辑中的镜面高光的属性调整对话框,同时也有调整之后的渲染结果。 纹理贴图(Texture Mapping) 大部分的图形硬件都会至少支持一两个纹理处理单元(Texture units)。 提示:纹理贴图的制造通常可以被分成两个步骤。可编程着色技术(Programmable Shading) ******* 可编程图形管线(programmable graphics pipeline)的出现,是到目前为止实时渲染3D图形加速技术中最大的飞跃。 材质和程序设计 批次(Batching) Ogre最基本的渲染单元被称为可渲染对象(Renderable),它们通过不同的渲染状态被分类传递到渲染队列中去。 注意:通常而言,在你设定了渲染场景之后,所有的纹理都会被一次性的载入显存,除非你的纹理占用了过多的显存,否则不会在每一帧都传递纹理数据到显存中去。 Ogre引擎在力所能及的范围内尽量把相同渲染状态的物体一起渲染,进而减少渲染状态改变。 材质克隆 在Ogre中材质是被所有引用所共享的。当你从材质管理器重得到了一个指向材质的指针的时候,其他的使用相同材质对象也在处理一样的指针。
GPU着色 GPU(图形处理器)在设计之初就有着明确的目标,提供高性能的并行向量计算以供针对3D图形处理使用。而具体如何使用和怎么使用的权力都交给了用户。 技术(Technique) 和方案(Scheme) 可以说技术和方案是Ogre引擎材质中最强大和活跃的两个特性。在Ogre中,每个材质中都至少包含了一种“技术”实现,这种实现允许你对不同性能显示卡和硬件平台使用不同的材质属性组合。 材质细节等级(Material LoD) 计算机图形学中的细节等级(Level of detail)这个术语经常是用来描述几何体复杂度等级和摄像机距离的关系。同样的,这种描述也可以类似的用在材质上。 材质的组成 在下图6-2中,展示了Ogre的材质之中各种组成成分之间的关系。一份完整的材质至少有一种技术实现,每种技术实现中至少要有一个渲染通路。 通路(Pass) 在Ogre中通路是最基本的渲染单位,同时也是可渲染对象(Renderable)用来标示自己渲染状态的基本单元。 纹理单元(Texture Unit) 在Ogre对材质的定义中,纹理单元的概念对应于图形硬件中的纹理采样(texture sampler)。为了运行Ogre程序,至少需要一个硬件纹理采样支持。 纹理压缩 很多现代图形硬件都会支持压缩纹理(比如DXTC方案),不过Ogre只是简单的载入纹理然后把它传到图形硬件上,并没有执行纹理的任何压缩过程。 视频流 虽然Ogre并没有在纹理单元中内置对视频流的支持,不过因为纹理单元可以支持外部数据源的处理,所以通过这个这个简单的机理可以帮助实现对视频流的支持。 实体(Entity) 实体是Ogre中比较神奇和复杂的概念之一。在每个实体中都包含着一些子实体(SubEntity)的实现,这些子实体是真正的可渲染对象,它们维护着具体的材质特性。 材质的例子 材质与固定功能管道(Fixed-Function Pipeline) 代码6-1展示了一个最简单的材质脚本,里面包含一个最简单的技术实现,技术实现里只有一个通路。如果你用它对你的物体进行渲染,会得到一个灰色的结果。
上面代码6-1中定义的材质,并没有什么特殊漂亮的地方,但是对于我们用来介绍Ogre材质脚本层次和结构来说已经足够了。
代码6-2已经很接近在实际中使用的材质定义了。在其中第一个技术的通路里面使用了texture_unit标记来定义所使用的纹理贴图,这里假设有一张叫做ReallyCool.jpg的图片。 注意:在你造成上面的问题之前,可能还有更严重的问题会出现。如果你的硬件真的很“老”,以至于无法支持纹理贴图属性, 代码6-3是一个真正在Ogre例子里面使用的材质脚本——Example.material。你在Ogre目录下面的Samples\Media\materials\scripts 子目录下面可以找到这个文件。
上面代码和之前最大的不同就是增加了材质的命名:Examples/EnvMappedRustySteel。虽然看起来似乎好像存在着一个目录结构,但事实上并不真的存在任何层级关系,
材质的继承(Material Inheritance) Ogre提供了体面的纹理继承机制,可以帮助我们更简单的改变纹理的某些部分。 命名的重要性 虽然大多数情况可以依赖系统对材质中成员的默认名称。但如果你使用了继承,并且准备在新的材质中增加技术,通道或者新的纹理单元。 纹理覆盖(Texture Aliases) 在很多情况下,派生材质的目的可能只是需要改变已有脚本中的纹理图片。这时候可以通过简单的纹理覆盖机制来实现。
上面代码实现了我们需要的功能,现在Examples/EnvMappedCompressedRustySteel的使用的纹理已经不同于Examples/EnvMappedRustySteel,其他属性仍然继承了下来。
虽然图6-6所展示的水纹是有流动的,但是在书中的静态图片却看不出来实际效果。 图6-6:在Demo_TextureFX演示程序中把当前纹理改成Examples/TextureEffect4之后的效果 在默认的情况下,Ogre会使用硬件拣选来过滤掉逆时针的表面(也就是说图形硬件只渲染那些边是面向摄像机顺时针排列的三角形)。 材质和可编程渲染管线 在之前所提及的所有材质都使用了固定的渲染管线。而现在我们要接触更复杂一些的可编程渲染管线。
就算你不了解6-5这个程序具体是什么意思也不要紧,现在你只要简单的注意一下用黑体字标明的函数名称就好了。 注意:在这本书里面并没有要讲解GPU程序设计的计划。这里所列出的所有GPU程序代码都只是为了作为实际的例子,如果你不理解这些代码的意思又对其有兴趣,就需要找一些资料来学习一下相关的知识了。 一旦你完成了上面的程序定义,你接下来需要做的工作是建立一个程序声明(declaration)。这种声名被用来给材质脚本中使用,下面代码6-6就是对上面程序的声明。
代码6-6中列出了叫做Ogre/HardwareSkinningOneWeight的顶点程序声明。
代码6-7中主要介绍了GPU程序中常用的参数。整个材质脚本中包含了两个不同的技术实现,第一个就是硬件蒙皮用的技术; 注意:虽然两种技术都把r2skin.jpg作为纹理使用。不过其中的区别是,当使用可编程渲染管线的技术实现, 而上面的材质中到底处理了哪些事情呢?在第一个技术中的第一个通路里面,我们告诉了Ogre我们希望使用shado_caster_vertex_program_ref这个GPU顶点程序 GPU程序参数类型 为了进一步了解Ogre材质,我们必须在这里介绍一些Ogre中GPU程序所使用的不同的参数类型,在GPU程序里面这些参数通常被称为Constant(常量); 图6-7:分别展示了在同一块储存区域中5块相同大小数据和两块不同大小数据的储存方式和索引地址 相对于位置索引的参数,名称定位的设置方式要简单且清晰很多。只需要在材质和GPU程序中使用相同的参数名称,Ogre就会帮你把它们关联起来。 GpuProgramParametersSharedPtr params = entity->getSubEntity(0)->getMaterial()-> 虽然上面只写了顶点着色程序的方法,不过对于片断着色程序(也有人称之为像素着色程序)而言,也有类似的方法和机制帮助你完成参数的传值过程。 定制的自动参数 通过Renderable(可渲染对象)的接口,你可以实现把CPU应程序中的参数变量,绑定到相应的GPU程序参数上面; //改变投影参数 后面额外的参数(“12”)是用来传递给Ogre程序来辨认到底是绑定到哪个参数上面。 Vector4 myColor; 现在,当GPU程序开始执行渲染到这个通路的时候,Ogre会自动的提供当前的myColor变量的值作为参数。 比较复杂的例子:视差帖图 我将要通过一个高级一点的例子作为这个章节的结尾,整个程序中既包含顶点程序也包含片断程序。 图6-9:从另外的角度观察视差贴图 代码6-8提供了Demo_Dot3Bump中使用的视差贴图例子的材质脚本。
在上面代码中不仅有材质脚本本身,同时提供了被材质脚本所引用的所有着色程序的声明。
这里的可编程通路中只支持了一个光源的处理(通常指的事场景中第一个光源)。 注意:你可能注意到了通过纹理传递任意数据类型到片断程序。这种使用方法并不只是Ogre所专有的; Material .VS. Texture |
沒有留言:
張貼留言