如何解决.ts两边没有图像的问题,不能全全屏的动画图像?

五、关于WBMP的常见问答

六、关于WAP网关的常见问答

七、关于WAP浏览器的常见问答

八、关于WAP手机的常问答

九、关于WAP安全的常见问答

十、关于WAP其他方问答

十一、关于WAP站点建设的常见问答

免费和独立的移动Internet操作

免费的WAP站点和重导向服务

真正免费的HTML服务,但是他们支持PHP3来提供WAP内容服务

免费提供商(在土尔其和英国)。包括字典,游戏等

Today)中发现一些如何书写WMLScript的文章。许多人都会发现在阅读了一些文档之后能很容易的上手。笔者也建议你在阅读了一些文章之后再开始做。

哪儿有一个WAP词汇表?

这里有一个词汇表(表10-4

Server。其实是一个内容提供服务器和网关。网关完成网关的内容,内容提供服务器完成内容提供服务器的功能

Gateway是一个两种模式的设备(像许多网关一样)。从WAP设备这边来看,WAP设备只懂得二进制格式的WMLWAP网关的功能就是转换内容为这种格式。从HTTP服务器这边来看,WAP网关可以通过HTTP头提供附加的有关WAP设备的信息,例如WAP设备的电话号码,电话ID甚至是位置信息

一个在WML Deck中包含导航、用户交互的完整的WML块。一个或者多个WML卡片必须包含在WML Deck中。WML Deck就是XML文档。(Deck就是扑克牌盒,Card就是每张牌)

一套WML卡片。整个Deck在请求的时候都将装入到浏览器中,然后针对其中的每个卡片进行处理

)的公司发布一些有关Mobicast的信息之前,这被认为是不可能的。Sontora的一些有关Mobicast的信息将可以在任何WML

SDKIDE列表,可以下载一个来用。任何文本编辑器都可以书写一个简单的WML页面,当然HTML编辑器也可以(特别是那些支持个人定义标签的),例如:Allaire )。可以使用SDK来做简单的测试,但是对于大的项目可能要困难些。/tools/),测试工具是用Perl写的。里面还有其他的工具可供下载。

Amaro)提供的列表。
注意:由于只需要四个字符串就可以辨别,因此例如:"WapIDE-SDK/)也有一个在线的基于WML的工具BrowserSpy,来显示更多关于HTTP头的信息、服务器环境和用户的浏览器等等。有关这个工具的详细情况可以浏览,

Number”。它可以通过WML卡片查找一个类似于电话号码的列表,然后用户可以选择进行呼叫。注意用户必须分离这些数字以便它能正常工作。

    虽然有少量网关支持非常有限的META标记。但是测试显示,如果使用了它们,网关就会出问题。例如某网关不支持普通的HTTP Cache控制,如果要实现Cache控制只好使用特殊的META标记。显然从其他网关来的用户就可能不支持这个META。注意:不要使用META tags。肯定有其他的方式来完成你的想法。

    )已经开发出了一个Perl工具包。它还在为管道式的WML编译器工作。

是一个依赖于新的W3C技术(例如DOMXML,和XSL)框架。Cocoon计划在于改变Wen信息创建,生成和提供的方式。文档内容、风格和逻辑经常因为个人或者工作组的不同而不同。 Cocoon目标在于将这三层分离,允许三层次之间进行独立的设计,创建和管理,减少相互之间的影响,增加工作的可复用性以及缩短上市的时间。Web内容的产生大多数是基于HTML的,但是HTML并不能将三者分离开来,混合着各种格式标签,程序逻辑等等。而Cocoon计划将要改变这种情况,允许内容,逻辑和风格相互分离。使用XML来保存,但是使用XSL来将它们混合。”
   
基本上来说,Cocoon将解读HTTP头,判断使用的是什么浏览器,然后使用不同的风格来选择正确的页面,使用XSL进行混合。

)提供了一种欺骗浏览器,让它装入图片但不显示的办法。对于图片,如果足够小,可以事先读入到WAPCache中。如果所有的图像都能够装入的话,就不需要连接到服务器上了。
   
首先需要一个能够撑满屏幕的透明图片,因此它们是一个像素宽,并且和显示屏幕具有相同的高度。将图片做成透明的,这样它将占据整个屏幕,然后装载剩下的图片,等图片装载完后timer启动,开始动画。
   
在下面的例子中,可能需要改变一下timer的数值,让它有时间来装入图片。

如果查看从 Developer站点有这样一个列表 。但是必须注册后才能得到这个列表。

有一个完整的WAP设备列表。

十、关于WAP其他方面问答

Benefon 只要简单的注册就可以得到。Nokia只允许开发者使用Nokia Toolkits,而这些版本很难和WAP环境搭配。
一个非常重要的事情就是要记住让HTTP服务器告诉WML浏览器,它接收到的是一个WML页面,而不是一个HTML页面,这个可以通过配置MIME来完成。

,典型的WAP站点名是
,你注册了一个的主机IP地址是多少?”,然后DNS回答IP地址,例如:“ 将接收到WAP主机的IP地址。
WAP
主机可以和Web主机拥有同样的IP地址。那就意味着该主机既提供Web内容也提供WAP内容。因为Web浏览器接收HTMLWAP浏览器接收WMLWeb服务器可以通过简单的脚本来判断浏览器的类型,并提供适当的内容。因为 主机的名字都指向同一个IP地址,所以WAP用户可以操作Web用户也可以操作。毕竟文本主机名字是机器IP地址的代表。
Server
,使用WAP名()指向WAP内容服务器。

纹理是增强计算机生成的三维图像的真实感的有力工具。Microsoft? Direct3D?支持广泛的纹理特性,并使开发人员可以很方便地使用高级纹理技术。

本节讲述如何使用纹理。

以下主题将更详细地介绍另外的纹理功能。

要提高性能,可以考虑使用动态纹理。动态纹理在每一帧都可以被锁定,写入及解锁。更多信息请参阅使用动态纹理

早期计算机生成的三维图像看起来往往像是发亮的塑料,虽然这在当时也是比较先进的,但是它们缺乏各种纹路——如磨损、裂痕、指纹和污渍等,而这些纹路会增加三维物体的真实感。近年来,纹理已经在开发人员中得到普及并作为增强计算机生成的三维图像的真实感的工具。

词语“纹理”在日常使用中表示物体的光滑度或粗糙度,但是在计算机图形学中,纹理指的是一张表示物体表面细节的位图。

因为Direct3D中所有纹理都是位图,所以可以把任何位图贴到Direct3D图元的表面。例如,应用程序可以创建物体并使它们的表面看起来有木纹的样式。可以把草、泥土和岩石等纹理贴在构成山的图元的表面,这样就能得到看起来很真实的山坡。应用程序也可以用纹理创建其它的效果,如:路边的路标,悬崖边的岩层,或是地面上的大理石。

另外,Direct3D支持更高级的纹理技术,如纹理混合(包含或不含透明度)和光照贴图。更多信息请参阅纹理混合用纹理实现光照贴图

如果应用程序创建一个HAL设备或软件设备,那么可以使用8、16、24或是32位纹理。

以下主题包含了更多的信息。

Microsoft? Direct3D?应用程序可以把纹理坐标值赋给任何图元的任何顶点。更多细节,请参阅纹理坐标。一般来说,应用程序赋给顶点的u、v纹理坐标值在0.0到1.0范围内,闭区间。但是,通过把纹理坐标值赋为此范围外的值,应用程序可以创建某些特殊纹理效果。

通过设置纹理寻址模式,应用程序可以控制当纹理坐标位于范围[0.0, 1.0]外时希望Direct3D执行何种操作。例如,应用程序可以设置寻址模式,使纹理平铺于图元表面。下面的主题包含了更多的细节。

Direct3D使应用程序可以进行纹理环绕,很重要的一点是要注意把纹理寻址模式设为D3DTADDRESS_WRAP与进行纹理环绕并不相同。把纹理寻址模式设为D3DTADDRESS_WRAP会使源纹理的多个复本被贴到当前图元的表面,而启用纹理环绕则会改变系统对贴有纹理的多边形进行光栅化的方式。更多细节,请参阅纹理环绕

启用纹理环绕实际上使位于[0.0, 1.0]范围之外的纹理坐标无效,在这种情况下,对无效的纹理坐标进行光栅化操作将导致未定义的结果。当启用纹理环绕时,不会使用纹理寻址模式,同时应用程序应该注意不要给出小于0.0或大于1.0的纹理坐标。

虽然系统允许纹理坐标位于闭区间0.0到1.0之外,但硬件限制通常会决定纹理坐标究竟可以超出该范围多少。当应用程序取得设备能力时,渲染设备通过D3DCAPS9结构的MaxTextureRepeat成员表明这个限制,这个成员的值描述了设备允许的纹理坐标的全部范围。例如,若这个值为128,则输入的纹理坐标必须保持在从-128.0到+128.0之间,若输入顶点的纹理坐标位于这个范围外,则纹理坐标是无效的。对自动生成的纹理坐标和由纹理坐标变换得到的纹理坐标也有同样的限制。

MaxTextureRepeat的解释同时还受D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE能力位的影响。若设置了这个能力位,则D3DCAPS9结构的MaxTextureRepeat成员的值正如前面描述的一样。但是,若没有设置该能力位,则纹理循环的限制还取决于纹理坐标寻址的那个纹理的大小。在这种情况下,MaxTextureRepeat必须除以当前mipmap中最大纹理的大小。例如,若纹理大小为32,而MaxTextureRepeat的值为512,则实际有效的纹理坐标的范围是512/32 = 16,因此传给该设备的纹理坐标必须在范围-16.0到+16.0之间。

这种纹理寻址模式的效果与镜像纹理寻址模式有些相似,却又明显不同。更多信息,请参阅镜像纹理寻址模式

镜像纹理寻址模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_MIRROR成员表示,它会使Microsoft? Direct3D?在纹理坐标的整数边界先对纹理进行镜像然后再重复使用。例如,设想应用程序创建了一个方的图元并把纹理坐标指定为(0.0,0.0), (0.0,3.0), (3.0,3.0)和(3.0,0.0),把纹理寻址模式设置为D3DTADDRESS_MIRROR会使纹理在u和v方向都重复三次,每一行和每一列的纹理都是相邻行和列的纹理的镜像。

这种纹理寻址模式的效果与环绕纹理寻址模式有些相似,却又明显不同。更多信息,请参阅环绕纹理寻址模式

截取纹理寻址模式由D3DTEXTUREADDRESS枚举类型的D3DTADDRESS_CLAMP成员表示,它会使Microsoft? Direct3D?把纹理坐标截取到[0.0, 1.0]范围内,也就是说,这种模式只应用纹理一次,然后就重复使用纹理边缘处像素的颜色。例如,设想应用程序创建了一个方的图元并把纹理坐标指定为(0.0,0.0), (0.0,3.0), (3.0,3.0)和(3.0,0.0),把纹理寻址模式设置为D3DTADDRESS_CLAMP会使纹理只被应用一次,列的顶端和行的末端处像素的颜色被相应地延伸至图元的顶端和右边。

下图描绘了截取寻址模式。

下图描绘了边框颜色纹理寻址模式,这里应用程序指定红色为纹理的边框颜色。

应用程序可以通过调用IDirect3DDevice9::SetSamplerState方法设置边框颜色。在调用时要把第一个参数设为想要设置的纹理层的标识,把第二个参数设为D3DSAMP_BORDERCOLOR纹理层状态值,并把第三个参数设为以RGBA形式表示的新的边框颜色。

通过给纹理指定无效区域,应用程序可以对需要复制纹理的哪些子集进行优化,只有那些被标记为无效的区域才会被IDirect3DDevice9::UpdateTexture方法更新。当创建纹理时,整个纹理被标记为无效的。只有以下几种操作可以改变纹理的无效状态。

  • 给一个纹理添加一个无效区域。
  • 锁定纹理中的一些区域。此操作会把被锁定的区域添加到无效区域中,如果应用程序明确知道哪些是真正的无效区域,那么也可以关闭对无效区域的自动更新。
  • 将纹理作为目标表面进行更新的话会把整个纹理标记为无效的。

对于mipmap纹理而言,无效区域被设在最高一级的纹理上,为了最小化对mipmap纹理中每一级的纹理更新所需复制的字节数,IDirect3DDevice9::UpdateTexture方法可以扩展无效区域并沿mipmap链更新子纹理。注意子级中无效区域的纹理坐标被向上舍入,也就是说,它们的小数部分被向上取整到纹理中最近的像素。

因为每种类型的纹理具有不同类型的无效区域,所以每种类型的纹理都有相应的方法表示无效区域。二维纹理使用矩形,立体纹理使用立方体。

把以上方法的pDirtyRectpDirtyBox参数设置为NULL会扩大无效区域并使之覆盖整个纹理。

每种锁定方法都有D3DLOCK_NO_DIRTY_UPDATE标志,使用这个标志可以防止对纹理无效区域的改变。更多信息,请参阅锁定资源

如果在锁定操作时可以得到已改变区域的完整集合,那么应用程序应该使用D3DLOCK_NO_DIRTY_UPDATE标志。注意,对纹理一个的子级的锁定或复制操作(也就是说,未对纹理的最高一级进行锁定或复制操作)不会更新该纹理的无效区域。当应用程序锁定了纹理的子级而没有锁定纹理的最高一级时,它同样有责任对无效区域进行更新。

IDirect3DDevice9的调色板包含了一个阿尔法通道。若设备设置了D3DPTEXTURECAPS_ALPHAPALETTE能力位,则表示该设备支持调色板阿尔法,并可以使用该阿尔法通道。当纹理格式不含阿尔法通道时,就使用调色板阿尔法通道。若设备不支持调色板阿尔法,同时纹理格式也不含阿尔法通道,则使用0xFF作为阿尔法值。

系统中最多可以有65,536个调色板。因为调色板占用的内存资源与应用程序引用到的最大的调色板编号成正比,所以最好使用从零开始且连续的编号。

大多数纹理,如位图,都是一个存放颜色值的二维数组,但立方体环境贴图除外,具体细节请参阅立方体环境贴图。数组中的每个颜色值被称为texel。每个texel在纹理中有唯一的地址,可以认为这个地址是行和列的编号,它们分别被标记为u和v。

纹理坐标位于纹理空间中,也就是说,它们相对于纹理中的位置(0,0)点。当把纹理贴到三维空间中图元的表面时,纹理的texel必须先被映射到对象坐标系,然后再变换到屏幕坐标系,或像素的位置。

Texel映射到屏幕空间

Microsoft? Direct3D?直接把纹理中的texel映射到屏幕空间,这样就省略了中间步骤并极大地提高了效率。这个映射的过程实际上是一个反向映射,也就是说,系统根据每个像素在屏幕空间中的位置计算该像素在纹理空间中相应的texel的位置,然后对位于该点或该点附近的纹理颜色进行取样。取样的过程被称为纹理过滤。更多信息请参阅纹理过滤

纹理中每个texel的位置可以用它的texel坐标表示。但是为了把texel贴到图元表面,Direct3D需要所有的纹理中的texel具有相同的地址范围,所以Direct3D使用了一种通用的寻址方法。在这种寻址方法中,所有texel的地址都在闭区间0.0到1.0内。Direct3D用u,v值表示纹理坐标,这和用x,y坐标表示二维笛卡尔坐标系非常相似。从技术上讲,系统事实上可以处理0.0到1.0范围外的纹理坐标,系统根据应用程序设置的纹理寻址模式来进行此类处理。更多信息,请参阅纹理寻址模式

采用这种方法的结果是相同的纹理地址在不同的纹理中会映射到不同的texel坐标。在下图中,正在使用的纹理地址是(0.5,1.0)。但是,因为纹理的大小不同,所以该纹理地址映射到不同的texel。左边纹理的大小为5x5,纹理地址(0.5,1.0)映射到texel (2,4)。右边纹理的大小为7x7,纹理地址(0.5,1.0)映射到texel (3,6)。

下图描述了一个经简化的texel映射过程。这个示例显然非常简单,要了解更多细节信息,请参阅。

本例中,图的左边显示了一个被理想化为正方形色块的像素。像素四角的地址被映射到对象空间中的三维图元,因为三维场景中图元的形状及观察角度的不同,像素的形状常常会被扭曲。像素四角所对应图元表面的区域然后被映射到纹理空间,这个映射过程会再次扭曲像素的形状。像素的最终颜色根据像素映射的区域所覆盖的texel计算得到。通过设置纹理过滤方法,应用程序可以控制让Direct3D使用何种方法计算像素颜色。更多信息,请参阅纹理过滤

应用程序可以直接给顶点指定纹理坐标,这使应用程序可以控制把纹理的哪些部分贴到图元上。例如,设想应用程序创建了一个与下面的纹理大小完全相同的图元,本例中,如果应用程序希望把整张纹理贴到整面墙上,那么应用程序给图元的顶点指定的纹理坐标就应该是(0.0,0.0), (1.0,0.0), (1.0,1.0), 和 (0.0,1.0)。

如果应用程序决定把墙的高度减半,应用程序仍可以把整张贴图贴到稍小的墙上,但这会挤压纹理并使之扭曲,或者应用程序也可以重新指定纹理坐标,使Direct3D使用纹理的下半部分。

如果应用程序为了把纹理贴到稍小的墙上而决定挤压或拉伸纹理,那么应用程序使用的纹理过滤方法会影响最终图像的质量。更多信息,请参阅纹理过滤

如果应用程序决定重新指定纹理坐标并使Direct3D使用纹理的下半部分,那么在本例中应用程序给图元的顶点指定的纹理坐标应该是(0.0,0.5), (1.0,0.5), (1.0,1.0), 和 (0.0,1.0),这样Direct3D就会把纹理的下半部分贴到墙上。

顶点的纹理坐标有可能大于1.0,如果应用程序给顶点指定的纹理坐标不在闭区间0.0到1.0范围内,那么应用程序还应该设置纹理寻址模式。更多信息,请参阅纹理寻址模式

一个弹性顶点格式码最多可以定义八组纹理坐标,纹理坐标数据由用户在顶点数据中提供,数据通过索引值0到7来引用。最多可以有八个纹理混合层,一张纹理通过SetTexture(stageIndex, pTexture)与某一纹理层联系在一起。

textureCoordinateIndex)与某一纹理层联系在一起。请参阅IDirect3DDevice9::SetTextureStageState。通过这种方法,可以设置纹理混合层使它们使用任意一张纹理和任意一组纹理坐标。多个纹理层可以使用同一张纹理,或同一组纹理坐标。

以下主题包含了更多的信息。

直接把Texel映射到像素

应用程序经常需要把纹理贴到几何体上并使texel直接映射到屏幕上的像素。例如,以一个需要在纹理中显示文本的应用程序为例,为了使纹理中的文本能清晰地显示,应用程序需要以某种方式确保映射到几何体上的texel不受纹理过滤的影响。如果无法保证这一点,那么得到的图像通常会是模糊的,如果纹理过滤方法为最近点取样,那么可能会产生粗糙边缘。

为了统一像素和纹理取样,并同时支持图像和纹理过滤,Microsoft? Direct3D?的像素和纹理取样规则经过了精心定义,但这也使得把纹理中的texel直接映射到屏幕上的像素成为一个相当有意义却又艰难的挑战。要战胜这个挑战,需要透彻地理解Direct3D如何把用浮点数表示的纹理坐标映射到光栅化器使用的整数像素坐标。

为了把用浮点数表示的纹理坐标映射到texel地址,Direct3D执行下面的计算。

在这些公式中,TxTy为水平/垂直方向的输出texel坐标,uv为顶点提供的水平/垂直方向的纹理坐标。MxMy元素表示当前mipmap级水平/垂直方向的texel的数量。本节剩余部分将主要讨论在水平方向上从texel到像素的映射,垂直方向上的映射与水平方向完全相同。

把纹理坐标0.0和1.0代入以上公式,会使纹理坐标0.0映射到本次纹理迭代的第一个texel和上次纹理迭代的最后一个texel的中间,纹理坐标1.0会被映射到本次纹理迭代的最后一个texel和下次纹理迭代的第一个texel的中间。对于一个宽度为4的迭代纹理,在mipmap的第0级,下图显示了系统把坐标0.0和1.0映射到哪里。

理解了这种映射方式,应用程序只需给几何体的屏幕空间坐标加上一个偏移量,就可以强制系统把每个texel映射到相应的像素。例如,要绘制一个四边形并使前面的纹理中的每个texel一一映射到屏幕上唯一的像素,应用程序必须使几何体坐标覆盖所有像素,并使每个texel的中心正好对应每个像素的中心,这样得到的结果就是应用程序常要追求的一对一映射。

为了把宽度为4的纹理映射到像素坐标0到3,可以用两个三角形绘制一个四边形,三角形在屏幕空间的坐标为-0.5到3.5,纹理坐标为0.0到1.0。以屏幕空间坐标为0.0的像素为例,因为0.0与第一个顶点,位于屏幕空间-0.5,相距半个像素,而总的宽度为4.0,迭代后的纹理坐标为0.125(译注:每个像素的宽度为0.25=1/4,半个像素的宽度为0.125),然后用纹理的大小,此处为4,对纹理坐标进行缩放,得到的结果坐标为0.5。再减去偏移量0.5即得到纹理地址为0.0,该地址完全对应于贴图中的第一个texel。

再概括一下,纹理坐标覆盖纹理贴图的两边,并平均分布在它们之间。下图显示了这种映射,纹理的宽度为4。

系统以相同的方法归一化像素坐标和纹理坐标,因此,如果顶点与要渲染的像素重叠,且顶点使用的纹理坐标为0.0和1.0,那么像素和顶点就可以对齐。如果它们的大小相同且排列整齐,那texel和像素就可以完全对应,如下图所示。

Direct3D?中的纹理坐标可以包含一个、两个、三个或四个用浮点数表示的元素,用来寻址不同大小的纹理。一维纹理——纹理表面的大小为1xn个texel——通过一个纹理坐标寻址。最常见的情况是二维纹理,通过两个被称为uv的纹理坐标寻址。Direct3D支持两种三维纹理,立方体环境贴图立体贴图。立方体环境贴图不是真正三维的,但使用一个三元素向量寻址。更多细节,请参阅立方体环境贴图

顶点格式中所述,应用程序把纹理坐标编码在顶点格式中。顶点格式可以包含多组纹理坐标。可以用FVF码D3DFVF_TEX0到D3DFVF_TEX8描述不包含纹理坐标或最多可包含八组纹理坐标的顶点格式。

每组纹理坐标可以有一到四个元素。D3DFVF_TEXTUREFORMAT1到D3DFVF_TEXTUREFORMAT4标志用来描述一组纹理坐标中元素的个数,但这些标志不能直接使用,D3DFVF_TEXCOORDSIZEn系列宏使用这些标志创建位掩码,用来在顶点格式中描述某组纹理坐标中元素的个数。这些宏带一个参数,表示要设置元素个数的那组纹理坐标的索引值。以下示例代码显示了如何使用这些宏。

// 这个顶点格式包含两组纹理坐标。第一组(索引为0)包含2个元素,

// 第二组包含一个元素。顶点格式描述应该是:

注意 除了立方体贴图和立体贴图外,光栅化器无法使用两个以上的元素寻址纹理。应用程序最多可以提供三个元素给一组纹理坐标,但只有当纹理是立方体贴图或立体贴图,或使用了D3DTTFF_PROJECTED纹理变换标志时多余的元素才会被用到。D3DTTFF_PROJECTED标志会使光栅化器把前两个元素除以第三个(或第n个)元素。更多信息,请参阅纹理坐标变换

下图显示了纹理坐标从数据源,经过处理然后到达光栅化器的流程。

系统可以从两个数据源得到纹理坐标。对于某一层纹理,应用程序可以使用包含在顶点格式(D3DFVF_TEX1到D3DFVF_TEX8)中的纹理坐标,也可以使用Microsoft? Direct3D?自动生成的纹理坐标。对于后一种情况,请参阅自动生成的纹理坐标。如果当前纹理层的D3DTSS_TEXTURETRANSFORMFLAGS纹理层状态为D3DTTFF_DISABLE(默认值),那么系统不会对输入的纹理坐标进行变换。如果D3DTSS_TEXTURETRANSFORMFLAGS为任何其它值,那么系统会用该纹理层的变换矩阵对该输入纹理坐标进行变换。

D3DTEXTURETRANSFORMFLAGS枚举类型定义了D3DTSS_TEXTURETRANSFORMFLAGS纹理层状态的有效值。除了D3DTTFF_DISABLE标志不进行纹理坐标变换外,该枚举类型值用于设定系统传送至光栅化器的输出坐标的数量。D3DTTFF_COUNT1到D3DTTFF_COUNT4标志告诉系统把输出纹理坐标中的一个、两个、三个或四个元素传送至光栅化器。

D3DTTFF_PROJECTED标志有些特别:它告诉系统纹理坐标将用于经过投影的纹理。把D3DTTFF_PROJECTED标志与D3DTEXTURETRANSFORMFLAGS的其它成员一起使用可以告诉系统在光栅化操作前把所有元素除以最后一个元素。例如,当显式使用三元素纹理坐标,或纹理变换产生三元素纹理坐标时,应用程序可以同时使用D3DTTFF_COUNT3和D3DTTFF_PROJECTED标志,这会使光栅化器把前两个元素除以最后一个元素,并得到寻址二维纹理所需的二维纹理坐标。

注意 除了立方体贴图和立体贴图外,光栅化器无法使用多于两个元素的纹理坐标。如果应用程序提供的元素比寻址当前纹理层所需的多,那么多余的元素会被忽略。当把二维纹理坐标用于一维纹理时也是这样。

以下主题包含了更多的信息。

系统可以使用经过变换的摄像机空间中的位置或顶点的法向量作为纹理坐标,也可以计算用于寻址立方体贴图的三元素向量。与应用程序在顶点数据中明确给出的纹理坐标一样,应用程序可以使用自动生成的纹理坐标作为纹理变换的输入。

通过无需在顶点格式中显式地给出纹理坐标,自动生成的纹理坐标可以显著降低几何数据所需的带宽。在许多情况下,系统生成的纹理坐标可以和纹理变换一起使用以生成特效。当然这只是一种特殊用途,大多数情况下应用程序还是要用显式给出的纹理坐标。

设定自动生成的纹理坐标

一般来说,这个状态告诉系统使用编码在顶点格式中的某组特定的纹理坐标。当应用程序给这个状态指定的值包含D3DTSS_TCI_CAMERASPACENORMAL,D3DTSS_TCI_CAMERASPACEPOSITION,或D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR标志时,系统执行的操作会完全不同。如果使用了这些标志中的任意一个,那么纹理层会忽略在顶点格式中的给出的纹理坐标,并优先使用系统生成的坐标。下表列出了每个标志的意义。

使用变换到摄像机空间的顶点法向作为输入纹理坐标。

使用变换到摄像机空间的顶点位置作为输入纹理坐标。

使用变换到摄像机空间的反射向量作为输入纹理坐标。反射向量根据输入顶点位置和法向量计算得到。

前面的这些标志是互斥的。如果应用程序指定了其中一个标志,那么应用程序还可以指定一个索引值,系统用这个索引值决定纹理环绕模式。

以下示例代码显示了如何在C++应用程序中使用这些标志。

 * 在当前纹理层使用顶点位置(摄像机空间)作为输入纹理坐标,

自动生成的纹理坐标在作为纹理坐标变换的输入,或使应用程序无需计算用于寻址立方体环境贴图的三元素向量时最为有用。

球形贴图使用一张预计算的(在建模时)纹理贴图,该贴图包含了一个反光的球体反射的整个环境。Microsoft? Direct3D?有一个纹理坐标自动生成特性,使用了D3DTSS_TCI_CAMERASPACENORMAL渲染状态,该特性会取得变换到摄像机空间的顶点法向,并对它进行纹理变换生成纹理坐标。更多信息请参阅Sphere

Microsoft? Direct3D?设备可以用一个4x4矩阵对顶点的纹理坐标进行变换。系统使用相同的方法对纹理坐标和几何体进行变换。任何变换(缩放、旋转、投影、shear或这些变换的组合)可以用一个4x4矩阵完成。

注意 Direct3D不改变经过变换和光照处理的顶点,因此,使用经过变换和光照处理的顶点的应用程序无法让Direct3D变换顶点的纹理坐标。

支持硬件变换和光照的设备(TnLHAL设备)也会对纹理坐标变换进行硬件加速。如果设备不支持硬件变换和光照,那么Direct3D会使用几何流水线中与平台相关的优化进行纹理坐标变换。

纹理坐标变换非常有用,它在生成特效的同时避免了对几何体纹理坐标的直接修改。应用程序可以使用简单的平移或旋转矩阵给物体表面的纹理生成动画效果,也可以对Direct3D自动生成的纹理坐标进行变换,这样可以简化并可能加速如投影纹理和动态光照贴图等高级特效。另外,在多层纹理中,应用程序也可以用纹理坐标变换重复使用某一组纹理坐标并将之用于多种用途。

设置及取得纹理坐标变换的信息

以下示例代码设置了一个矩阵,对纹理层0的纹理坐标进行变换。

// 为希望的变换设置矩阵。

D3DTEXTURETRANSFORMFLAGS定义的其它值用于启用纹理坐标变换,并控制把结果纹理坐标中的几个元素传送到光栅化器。以下为示例代码。

D3DTTFF_COUNT2值告诉系统对纹理层0进行变换,然后把得到的纹理坐标的前两个元素传送给光栅化器。

D3DTTFF_PROJECTED纹理变换标志表示用于投影纹理的坐标。当这个标志被设置时,光栅化器会把传入的元素除以最后一个元素。以下为示例代码。

本例告诉系统传送三个纹理坐标元素到光栅化器。光栅化器把前两个元素除以第三个元素,得到寻址纹理所需的二维纹理坐标。

本主题包含了可以用纹理坐标处理实现的特效。

给建模表面的纹理生成动画效果(通过变换或旋转)

  • 在顶点格式中定义一组二维纹理坐标。
  • 设定光栅化器,使之使用二维纹理坐标。
  • 定义并设置合适的纹理坐标变换矩阵

// M为要设置的D3DMATRIX,用于在U和V方向对纹理坐标进行变换。

把纹理坐标作为建模在摄像机空间中的位置的线性函数创建

  • 用D3DTSS_TCI_CAMERASPACEPOSITION标志告诉系统使用顶点在摄像机空间中的位置作为纹理变换的输入。
  • 告诉光栅化器使用二维纹理坐标。
  • 定义并设置生成线性函数的矩阵。

// 把纹理坐标作为线性函数创建,这样的话:

用立方体贴图实现环境贴图

  • 告诉光栅化器使用三元素的纹理坐标。
  • 使用D3DTSS_TCI_CAMERASPACEPOSITION标志告诉系统用顶点在摄像机空间中的位置作为纹理变换矩阵的输入。
  • 创建纹理变换矩阵并执行变换,这超出了本文档的范围,计算机图形工业中有许多文章讨论这个主题。
  • 告诉光栅化器使用三元素投影纹理坐标。

Microsoft? Direct3D?在渲染图元时,要把三维图元映射到二维屏幕上。如果图元贴有纹理,那么Direct3D必须用该纹理给图元在二维屏幕上对应的每个像素产生一个颜色。对于每个像素,Direct3D必须从纹理获得一个颜色值,这个过程被称为纹理过滤。

在执行纹理过滤操作时,正在使用的纹理一般会被放大或缩小,换句话说,就是纹理被贴到比它大或比它小的图元上。纹理放大会使多个像素映射到一个texel,得到的图像可能会有马赛克。纹理缩小会使一个像素映射到多个texel,得到的图像可能会模糊不清或有锯齿。要解决这些问题,必须在计算像素的颜色时对texel的颜色进行一些混合操作。

Direct3D把复杂的纹理过滤过程简化了,它给应用程序提供了三种类型的纹理过滤——线性过滤、各向异性过滤和mipmap过滤。如果应用程序不选择以上三种纹理过滤,那么Direct3D使用一种被称为最近点取样的技术。

每种类型的纹理过滤都各有优缺点。例如,线性纹理过滤可能会在最终图像中产生锯齿边缘或马赛克,但它是三种纹理过滤方法中计算量最小的。用mipmap纹理过滤通常可以得到最好的效果,尤其是和各向异性过滤一起使用的时候,但是在Direct3D支持的纹理过滤技术中,它对内存的需求也最大。

本节介绍了Direct3D支持的纹理过滤方法,并被划为以下主题。

注意 虽然D3DRENDERSTATETYPE枚举类型中定义的纹理过滤渲染状态已经被纹理层状态取代,但是如果应用程序试图使用这些渲染状态的话,IDirect3DDevice9与IDirect3DDevice2不同的是,IDirect3DDevice9::SetRenderState方法不会失败。相反,系统会把这些渲染状态映射到多重纹理的第一层,也就是索引值为0的那层。应用程序不应该把老的渲染状态和它们对应的纹理层状态混在一起,这样可能会产生无法预知的结果。

应用程序不一定要使用纹理过滤。应用程序可以让Microsoft? Direct3D?先计算纹理地址(通常都不是整数),然后使用离该值最近的整数地址处的texel的颜色,这个过程被称为最近点取样。如果纹理的大小与图元在屏幕上的大小相近的话,那么这将是快速且有效的纹理处理方法,但如果不是这样的话,得到的图像可能会有马赛克、锯齿或模糊不清。

应用程序在使用最近点取样时应该小心,因为当在两个texel间的边界处进行纹理取样时,这种方法有时会产生图形残留物。当使用最近点取样时,系统要么取样一个texel,要么取样另一个,这样当纹理地址从一个texel移向下一个texel时,取样得到的texel会突然改变。这种效果会导致在最终显示的纹理中出现不希望的图形残留物。当使用线性过滤时,取样得到的texel是根据所有邻近的texel计算得到的,当纹理地址在邻近的texel间移动时,线性过滤会根据当前纹理地址与邻近texel间的位置关系,把相邻texel混合。

当把非常小的纹理贴到非常大的多边形表面时可以看到这种效果:这个操作通常被称为纹理放大magnification)。例如,当使用的纹理看起来像西洋跳棋的棋盘时,最近点取样会得到一个非常大的棋盘,格子之间有清晰的边缘,相比之下,线性纹理过滤得到的图像中棋盘的颜色会沿着多边形逐渐改变。

大多数情况下,为了得到最好的效果,应用程序应该尽量避免使用最近点取样。当今的大多数硬件都为线性过滤做了优化,所以应用程序不必担心因此导致的性能下降。如果应用程序想要的效果一定要用最近点取样——比如用纹理显示可读的文本——那么应用程序应该极度小心,避免在texel边界取样,因为那样会导致不想得到的效果。下图显示了这些图形残留物可能的样子。

注意这组图片中右上角的两个方块与其余的不同,可以在它们的对角线上看到明显的偏移。要避免此类图形残留物,开发人员必须熟悉Direct3D在最近点取样时使用的纹理取样规则。Direct3D把闭区间[0.0, 1.0]范围内的浮点纹理坐标映射到texel空间中的整数地址[–0.5, n – 0.5]范围内,这里n为给定纹理的大小。得到的纹理地址被舍入到最近的整数,这种映射方法在texel边界会产生取样误差。

举个简单的例子,设想应用程序用D3DTADDRESS_WRAP纹理寻址模式渲染多边形。根据Direct3D使用的映射方法,对于宽度为4个texel的纹理,纹理在u方向上的映射如下。

注意这张图中的纹理坐标0.0和1.0,正好在texel之间的边界。根据Direct3D的映射方法,纹理坐标的范围为[–0.5, 4  0.5],这里4为纹理的宽度。在这个例子中,纹理坐标为1.0处取样得到的texel是texel 0。但是,如果纹理坐标只比1.0稍微小一点,那么取样得到的就会是texel n而不是texel 0。

这就意味着用正好等于0.0和1.0的纹理坐标去放大较小的纹理,并把它贴到整齐排列在屏幕上的三角形时,如果过滤方法为最近点取样方法,那么得到的像素可能会在texel之间的边界进行取样。在纹理坐标计算过程中的任何误差,无论多小,都可能在渲染得到的图像上与texel边界对应的部分出现图形残留物。

要完全精确地执行从浮点纹理坐标到整数texel地址的映射是很难的,也很耗时,并且通常是不必要的。大多数硬件实现在给三角形内的每个像素计算纹理坐标时使用迭代法。迭代法趋向于隐藏误差,因为误差在迭代过程中被均匀地累积起来。

Direct3D参考光栅化器在给每个像素计算纹理地址时使用直接赋值法。直接赋值法与迭代法的不同之处在于这种方法产生的误差分布更随机。因为参考光栅化器不进行完全精确的计算,所以这种方法会导致在边界处的取样误差更容易被察觉。

最好的方法是只在必要的时候使用最近点取样。如果应用程序必须使用这种方法,那么最好把纹理坐标稍微偏移一些使之离开边界位置,这样就可以避免残留物的产生。

Microsoft? Direct3D?使用一种被称为双线性过滤的线性纹理过滤方法。和最近点取样一样,双线性过滤首先计算一个texel地址,这通常都不会是整数,然后找到离该地址最近的整数地址。另外,Direct3D渲染模块还会根据最近取样点上、下、左、右的texel计算它们的加权平均值。

因为三维物体表面与屏幕间的夹角而造成的纹理扭曲被称为各向异性。当把一个各向异性的图元所对应的像素映射到texel时,像素的形状会被扭曲。Microsoft? Direct3D?根据像素被反向映射到纹理空间中的伸长率——也就是长度除以宽度——计量屏幕上像素的各向异性属性。

为了提高渲染质量,应用程序可以把各向异性过滤与线性纹理过滤或mipmap纹理过滤结合在一起使用。应用程序可以调用IDirect3DDevice9::SetSamplerState方法启用各向异性纹理过滤,只需把第三个参数设为D3DTEXF_ANISOTROPIC即可。

Mipmap进行纹理过滤

Mipmap是一系列纹理,每一张纹理都表示同一幅图像,但是分辨率逐渐变低。Mipmap中的每张图像,或每一级,都比前一级小一半。Mipmap不必是正方形的。

较高分辨率的mipmap图像用于离用户近的物体,而较低分辨率的图像则用于远处的物体。使用Mipmap在消耗更多内存的情况下,提高了渲染得到的纹理的质量。

Microsoft? Direct3D?用一连串从属表面表示mipmap。分辨率最高的纹理在链的最前端,下一级mipmap是它的从属表面。依次,每一级mipmap的从属表面是它在mipmap中的下一级,一直到mipmap中分辨率最低的那级。

下图显示了这样的例子。该纹理表示在一个三维第一人称游戏中的一个容器上的标记。创建mipmap时,最高分辨率的纹理是mipmap中的第一个,mipmap中每个随后的纹理的宽度和高度都是原来的一半,在这个例子中,最高分辨率的mipmap为256x256。下一级纹理为128x128,最后一级纹理为64x64。

这个标记有一个最远可见距离。如果用户离标记很远,那么游戏就用mipmap链中最小的纹理显示,在这个例子中就是64x64的纹理。

随着用户移动视点并离标记越来越近,游戏会逐渐使用mipmap链中更高分辨率的纹理。下图中纹理的分辨率为128x128。

当视点离标记的距离为所允许的最近距离时,游戏就使用最高分辨率的纹理。

对于纹理而言,这是一种更有效的模拟透视的方法,与在不同的分辨率下用单张纹理进行渲染相比,在不同分辨率下使用多张纹理会更快。

Direct3D可以确定mipmap链中哪一级纹理的分辨率与当前需要的最为接近,并把像素映射到那一级纹理的texel空间。如果最终图像需要的分辨率位于mipmap链中两级纹理的分辨率之间,Direct3D会取得这两级mipmap中的texel并把它们的颜色值混合在一起。

要使用mipmap,应用程序必须创建一个mipmap链。应用程序只需把mipmap链设为当前纹理可以使用mipmap。更多信息,请参阅纹理混合

下一步,应用程序必须设置Direct3D用于取样texel的纹理过滤方法。Mipmap过滤最快的方法就是让Direct3D选择最近的texel,D3DTEXF_POINT枚举类型值就是用来选择这种方法的。如果应用程序使用D3DTEXF_LINEAR枚举类型值,那么Direct3D可以产生更好的过滤效果,这会使Direct3D选择最近的那级mipmap,然后根据当前像素在那一级mipmap中所映射的texel及其附近的texel计算加权平均值。

Mipmap纹理用于减少渲染三维场景所需的时间,同时提高了场景的真实感。但是,mipmap通常需要大量的内存。

IDirect3DDevice9::CreateTexture的前两个参数为最高一级的纹理的宽和高。第三个参数为mipmap纹理的级数,如果应用程序把它设为零,那么Direct3D会创建一系列表面,每个都是前一个的一半,直到大小为1x1为止。第四个参数指定该资源的用途,本例中,零表示不为该资源指定特殊的用途。第五个参数指定纹理的表面格式,该参数为D3DFORMAT枚举类型值。第六个参数为D3DPOOL枚举类型值,表示在把创建的资源放在哪种类型的内存中,除非应用程序使用动态纹理,否则建议使用D3DPOOL_MANAGED。最后一个参数为指向IDirect3DTexture9接口指针的地址。

注意    Mipmap链中的每个表面的大小都是前一个表面的一半。如果最高一级mipmap的大小为256x128,那么第二级的mipmap就是128x64,第三级为64x32,依次类推,直到1x1(译注:最后几级分别为:4x2,,2x1,1x1)。应用程序在Levels中要求的mipmap级不能使链中的任何mipmap的宽和高小于1。举个简单的例子,如果最高一级的mipmap表面为4x2,那么Levels的最大允许值就是三,第三层的大小为1x1。如果Levels的值大于3,那么会导致第二级mipmap的高度值出现小数,而这是不允许的。(译注:原文表述不够准确,应该是log2

可以调用IDirect3DDevice9::SetTexture方法把mipmap纹理设置为当前纹理中的第一个纹理,更多信息请参阅纹理混合

Direct3D通过纹理层的概念支持多重纹理混合,每个纹理层包含一张纹理以及可以在这张纹理上执行的操作。纹理层中的纹理组成了一个当前纹理的集合。更多信息请参阅纹理混合。每张纹理的状态被封装在对应的纹理层中。

在使用纹理接口指针进行渲染时,应用程序最多可以把八张纹理混合。应用程序通过调用IDirect3DDevice9::SetTexture方法设置当前纹理。Direct3D会先把所有当前纹理混合,然后再贴到正在渲染的图元的表面。

注意 因为IDirect3DDevice9::SetTexture方法会增加正在设置的纹理表面的参考计数(reference count),所以当不再需要该纹理时,应用程序应该把相应纹理层的纹理设置为NULL。如果应用程序不这样做,那么表面就不会被释放,并造成内存泄漏。

或w方向上的纹理环绕。

应用程序还可以设置纹理透视和纹理过滤状态。请参阅纹理过滤

简而言之,纹理环绕用来改变Microsoft? Direct3D?用每个顶点的纹理坐标对贴有纹理的多边形进行光栅化的基本方法。在光栅化一个多边形时,为了确定多边形所覆盖的每个像素所需使用的 texel,系统要在每个多边形顶点的纹理坐标之间进行插值。一般来说,系统把纹理当做二维平面,为了在纹理中的点A和点B之间插值得到新的texel,系统会取两点间的最短路径。如果点A表示的u, v坐标为(0.8, 0.1),点B表示的u, v坐标为(0.1,0.1),那么插值的路径会如下图所示。

注意这张图中点A和点B间的最短路径大致穿越纹理的中央。启用u方向或v方向上的纹理坐标环绕会相应改变Direct3D在u方向或v方向上对纹理坐标间最短路径的理解。纹理环绕的定义使光栅化器在获取纹理坐标间的最短路径时,假设纹理坐标0.0和1.0是等价的。最后这一点是技巧所在:可以这样想象,在某一方向上启用纹理环绕会使系统把纹理当成在圆柱体表面环绕的纹理进行处理。例如,考虑下图。

这幅图显示了在u方向上的环绕是怎样影响系统对纹理坐标间的插值的。在一张普通的,或没有环绕的纹理上使用与前例中相同的点,我们会发现点A和点B间的最短路径不再穿越纹理的中央,而是穿越纹理的边框,也就是纹理坐标0.0和1.0重合的地方。在v方向上的环绕与此类似,唯一的不同在于圆柱体是平躺的。同时在u方向和v方向上进行环绕比较复杂,在这种情况下,可以把纹理想象成是一个立体圆环。

纹理环绕最通常的应用是在使用环境贴图时。通常,使用环境贴图的物体会显得比较反光,并反射出物体周围的场景。为了便于讨论,我们想象一个房间,房间有四面墙,每面墙上写着字母R, G, B, Y,分别对应颜色红,绿,蓝,黄。这样一个简单的房间使用的环境贴图可能如下图所示。

设想房屋的屋顶由一根完全反光的柱子支撑,柱子有四面。要把环境贴图贴到柱子上很简单,但是要让柱子看起来像是反射墙上的字母和颜色就没有那么容易了。下图显示了用线框模式绘制的柱子,并在顶部的顶点处列出了相应的纹理坐标。环绕将发生在纹理的接缝处,在下图中用虚线表示。

如果在u方向上启用纹理环绕,那么柱子会正确地显示出环境贴图上的颜色和字母,并且在纹理前面的接缝处,光栅化器会假设u坐标0.0和1.0是等价的并正确地选择纹理坐标间的最短路径。贴上纹理后的柱子如下图所示。

如果没有启用纹理环绕,那么光栅化器就不会产生可信的反射图像。相反,柱子前面的部分会包含经过挤压的位于u坐标0.175到0.875之间的texel,因为这些texel穿越纹理的中央。这样环绕效果被破坏了。

IDirect3DDevice9::SetRenderState的第一个参数是要设置的渲染状态,应该设为从D3DRS_WRAP0到D3DRS_WRAP7的枚举类型值,表示要设置哪一个纹理层的环绕状态。把第二个参数设为从D3DWRAPCOORD_0到D3DWRAPCOORD_3的标志可以在对应的方向上启用纹理环绕,也可以组合使用这些标志在多个方向上启用纹理环绕。如果应用程序忽略其中某个标志,那么在相应的方向上的纹理环绕就被禁用,要禁用某组纹理坐标在所有方向上的纹理环绕,只需把第二个参数设为0。

不要把纹理环绕与名字相近的纹理寻址模式相混淆。纹理环绕在对纹理进行寻址之前进行。一定要保证用于纹理环绕的数据不包含[0.0, 1.0]范围外的纹理坐标,因为那样会导致不希望的结果。有关纹理寻址的更多信息,请参阅纹理寻址模式

位移贴图由tessellation引擎解释,因为无法为tessellation引擎指定环绕模式,所以不能对位移贴图进行纹理环绕。应用程序可以用一组顶点,强制进行在任何方向上的环绕。应用程序也可以指定只进行简单的线性插值。

Microsoft? Direct3D?最多可以在一趟渲染过程中把八张纹理混合并贴到图元上。使用多重纹理可以极大地提高Direct3D应用程序的执行速度。应用程序可以用多重纹理混合在一趟渲染过程中产生纹理、影子、镜面反射光、漫反射光,以及其它特效。

要使用纹理混合,应用程序必须先检查硬件是否支持纹理混合。这个信息包含在D3DCAPAS9结构的TextureCaps成员中。有关如何查询硬件的纹理混合能力的细节,请参阅IDirect3DDevice9::GetDeviceCaps

通过使用纹理层,Direct3D支持在一趟渲染过程中完成多重纹理混合。一个纹理层有两个输入,并对它们执行一个混合操作,然后把结果用于进一步的处理或用于光栅化。可以把纹理层想象为如下图所示。

如上图所示,纹理层用一个指定的操作符把两个输入混合。常用的操作符包括对输入参数的颜色或阿尔法的简单调制或相加,但实际上Direct3D支持几十种混合操作。纹理层的输入可以是与该层关联的纹理,迭代后的颜色或阿尔法(在进行高洛德着色的过程中迭代得到),指定的颜色或阿尔法,或前一个纹理层的结果。更多信息,请参阅纹理混合操作和输入

注意 Direct3D区分颜色混合和阿尔法混合。应用程序分别设置要对颜色和阿尔法执行的混合操作及相应的输入,并且这些设置互不影响。

多重混合层的参数和操作的组合定义了一种简单的基于流程的混合语言。每一层的结果流入下一层,依次类推。这个概念,也就是混合的结果在层与层之间流动,并最终被用来对多边形进行光栅化操作,通常被称为纹理混合级联。下图显示了各独立的纹理层如何组成纹理混合级联。

设备中的每个纹理层都有一个从零开始的索引值。虽然应用程序应该总是检查设备的能力以确定当前设备支持几层纹理,但是Direct3D最多允许有八个混合层。第一层的索引值为0,第二层的索引值为1,依次类推,直到索引值7。系统根据索引值的增长混合各纹理层。

最好只使用需要的那些混合层,默认情况下没有用到的混合层被禁用。因此,如果应用程序只使用前两个混合层,那么只需设置层0和层1的操作符和参数。系统会对这两层执行混合操作,并忽略其余被禁用的层。

有关性能的注意事项    如果应用程序在不同的情况下使用不同数量的纹理层——比如对一些物体使用四层纹理,而对其它物体只使用两层纹理——那么应用程序无需显式地禁止所有以前使用过的层。一种选择是对未曾用到的纹理层的第一层,禁用其颜色操作符,这样该纹理层及其后的纹理层将不会被用到。另一种选择是设置第一层纹理(层0)的颜色操作符,禁用所有纹理贴图。第三种选择是当纹理层的D3DTSS_COLORARG1等于D3DTA_TEXTURE时,只要该层的纹理指针为空,该层及其后的纹理层都不会被处理。

以下主题包含了更多信息。

应用程序把混合层与当前纹理集合中的每张纹理相联系。Microsoft? Direct3D?按照顺序对每个混合层求值,从集合中的第一张纹理开始,至第八张结束。

Direct3D把当前纹理集合中每张纹理的信息应用于与之相联系的混合层。通过调用IDirect3DDevice9::SetTextureStageState,应用程序可以控制使用纹理层中的哪些信息。应用程序可以分别设置对颜色和阿尔法通道的操作,每个操作有两个参数。用D3DTSS_COLOROP纹理层状态指定要对颜色通道执行的操作,用D3DTSS_ALPHAOP纹理层状态指定要对阿尔法通道执行的操作,这两个纹理层状态都是D3DTEXTUREOP枚举类型值。

注意 通过把某一层的颜色操作设置为D3DTOP_DISABLE,应用程序可以禁用该纹理层及纹理混合级联中所有的后续层。禁用颜色操作会同时禁用阿尔法操作。当颜色操作被启用时,阿尔法操作无法被禁用。当颜色混合被启用时,把阿尔法操作设置为D3DTOP_DISABLE会导致不确定的结果。

要测定一个设备支持的纹理混合操作,请查询D3DCAPS9结构的TextureCaps成员。

Microsoft? Direct3D?维护着一个当前纹理列表,最多可以有八张。Direct3D会把这些纹理混合到要渲染的图元上。只有作为纹理接口指针创建的纹理可以被用于当前纹理集合。

应用程序可以调用IDirect3DDevice9::SetTexture方法把纹理设置到当前纹理集合中。第一个参数必须是闭区间0到7之间的数字,第二个参数是纹理接口指针。

以下C++示例代码显示了如何把一张纹理加入到当前纹理集合中。

注意 软件设备不支持同时把一张纹理指定到一个以上的纹理层。

一个混合层是一个纹理操作及相应参数的集合,它定义了怎样混合纹理。C++应用程序在创建混合层时调用IDirect3DDevice9::SetTextureStageState方法。第一次调用指定要执行的操作,另外两次调用指定参数,Direct3D将用这两个参数执行指定的操作。以下示例代码描述了如何创建一个混合层。

// 设置要对第一个纹理进行的操作

// 将参数1设置为纹理颜色

// 将参数2设置为迭代后的漫反射色。

纹理中的texel数据包含颜色和阿尔法值。应用程序可以在一个混合层中分别定义颜色和阿尔法操作。颜色操作和阿尔法操作分别有自己的参数。更多细节,请参阅D3DTEXTURESTAGESTATETYPE

虽然下面的宏并不是Microsoft? Direct3D?应用程序编程接口(API)的一部分,但是应用程序可以用它们简化创建纹理混合层所需的代码。

Microsoft? Direct3D?在渲染一个图元时会根据图元的材质、或图元的顶点颜色,及光照信息为该图元产生一个颜色。更多细节,请参阅光照与材质。如果应用程序启用纹理混合,那么Direct3D必须把经过处理的多边形上的像素颜色与已经储存在帧缓存中的像素颜色进行混合。Direct3D使用以下公式计算图元的(渲染得到的)图像中每个像素的最终颜色。

在这个公式中,FinalColor为输出到目标渲染表面的最终像素颜色。TexelColor为经过纹理过滤的输入颜色值,对应当前像素。有关Direct3D如何把texel映射到像素的细节,请参阅纹理过滤SourceBlendFactor为一个经过计算的值,Direct3D用它计算输入颜色值在最终颜色中所占的百分比。PixelColor为当前存储在图元的图像中像素的当前颜色。DestBlendFactor为当前像素颜色在最终渲染得到的像素中所占的百分比。SourceBlendFactorDestBlendFactor的值在闭区间0.0到1.0范围内。

经过纹理过滤后,每个像素的颜色值包含红、绿和蓝三种颜色值。默认情况下,Direct3D使用D3DBLEND_SRCALPHA作为SourceBlendFactor,使用D3DBLEND_INVSRCALPHA作为DestBlendFactor。因此,通过设置纹理中的阿尔法值,应用程序可以控制处理后的像素的透明度。

通过在多趟渲染的过程中将多个纹理贴到一个图元的表面,Microsoft? Direct3D?应用程序可以实现许多特效,这通常被称为多趟(multipass)纹理混合。多趟纹理混合的一个典型用途就是通过把几个不同纹理上的颜色混合,模拟复杂的光照和着色模型的效果。这种应用被称为光照贴图。更多信息,请参阅用纹理实现光照贴图

注意 一些设备可以在一趟渲染过程中将多张纹理贴到图元表面。细节请参阅纹理混合

如果用户的硬件不支持多重纹理混合,应用程序可以使用多趟纹理混合以达到同样的视觉效果。但是,与使用多重纹理混合相比,应用程序将无法保持相同的帧速率。

要进行多趟纹理混合,C++应用程序应该执行以下操作。

  1. 调用IDirect3DDevice9::SetTextureStageState方法设置相应的颜色和阿尔法混合操作及参数。默认的设定就很适合用于多趟纹理混合。
  2. 渲染场景中相应的物体。
  3. 将下一张纹理指定到纹理层0。
  4. 根据需要设置D3DRS_SRCBLENDD3DRS_DESTBLEND渲染状态以调整源和目的混合因子。系统根据这些参数把新的纹理和已经存在于渲染目标表面中的像素进行混合。
  5. 根据所需纹理的数量,重复步骤3,4,5。

对于想要真实地渲染一个三维场景的应用程序来说,必须要考虑光源会对渲染得到的场景产生的效果。虽然诸如平面着色和高洛德着色之类的技术在这方面也是有用的工具,但它们可能无法满足应用程序的要求。Microsoft? Direct3D?支持多趟和多重纹理混合。与仅使用着色技术相比,这些能力使应用程序能够渲染更具真实感的场景。通过使用一张或多张光照贴图,应用程序可以把光影的范围映射到图元上。

光照贴图是包含三维场景中光照信息的一张纹理或一组纹理。应用程序可以把光照信息存放在光照贴图的阿尔法值中,颜色值中,或以上两者中。

如果应用程序用多趟纹理混合实现光照贴图,应用程序应该在第一趟渲染时把光照贴图贴到图元上,在第二次渲染时使用基本纹理。镜面反射光照贴图是个例外,在这种情况下,要先渲染基本纹理,再添加光照贴图。

多重纹理混合使应用程序能一次同时渲染光照贴图和基本纹理。如果用户的硬件支持多重纹理混合,应用程序应该在进行光照贴图时利用这一特性,这将极大地提高应用程序的性能。

如果使用光照贴图,Direct3D应用程序可以在渲染图元时得到多种光照效果。应用程序不仅可以在场景中使用单色光和有色光,还可以添加诸如镜面反射高光和漫反射光之类的细节。

以下主题介绍了用Direct3D纹理混合实现光照贴图的信息。

一些老的三维加速卡不支持使用目标像素的阿尔法值进行纹理混合,更多信息请参阅阿尔法纹理混合。一般来说这些加速卡也不支持多重纹理混合,如果应用程序在此类适配器上运行,那么可以用多趟纹理混合进行单色光照贴图。

要进行单色光照贴图,应用程序应该把光照信息存放在光照贴图的阿尔法数据中。应用程序使用Microsoft? Direct3D?的纹理过滤功能把图元的图像中的每个像素映射到光照贴图中的相应texel。应用程序应该把源混合因子设为相应texel的阿尔法值。

以下C++示例代码描述了应用程序如何把一张纹理用作单色光照贴图。

// 且lptexLightMap为指向包含单色光照贴图数据的纹理的有效指针。

// 把光照贴图设置为当前纹理。

// 设置颜色操作的第一个参数。

因为不支持目标阿尔法混合的适配器一般来说也不支持多重纹理混合,这个示例把光照贴图设为第一张纹理,而这在所有三维加速卡上都是可用的。示例代码先设置纹理混合层的颜色操作,让纹理数据与图元已有的颜色进行混合,然后选择第一张纹理和图元已有的颜色作为输入数据。

如果应用程序使用有色光照贴图,那么通常会渲染得到更具真实感的三维场景。一张有色光照贴图使用RGB数据存放光照信息。

以下C++示例代码显示了如何用RGB颜色数据进行光照贴图。

// 且lptexLightMap为指向包含单色光照贴图数据的纹理的有效指针。

// 把光照贴图设为第一张纹理。

这个示例先把光照贴图设为第一张纹理,然后设置第一个混合层的状态,对输入数据进行调制(相乘),并把第一张纹理和图元的当前颜色用作调制操作的参数。

在对发亮的物体——那些使用了高反射度材质的物体——进行光照计算时会产生镜面反射高光。在一些情况下,由光照模块产生的镜面反射高光不够精确,为了产生更吸引人的镜面反射高光,许多Microsoft? Direct3D?应用程序会给图元使用镜面反射光照贴图。

要进行镜面反射光照贴图,只需把镜面反射光照贴图与图元的纹理相加,然后再和RGB光照贴图进行调制(与结果相乘)操作。

以下C++示例代码描述了这个过程。

// 设置要对基本纹理执行的操作及参数。

// 设置镜面反射光照贴图。

// 设置要对镜面反射光照贴图执行的操作及参数。

// 设置要对RGB光照贴图执行的操作及参数。

不光滑的表面在被光源照射时会显示漫反射光。漫反射光的亮度取决于表面到光源的距离及表面法向与光源的方向向量间的夹角。通过光照计算(译注:由光照模块执行)模拟漫反射光只能得到一般的效果。

应用程序可以用光照贴图模拟更为复杂的漫反射光照效果,只需在基本纹理的基础上再加一张漫反射光照贴图即可,如以下C++示例代码所示。

// 设置要对基本纹理执行的操作及参数。

// 设置漫反射光照贴图。

表面是显存的线性表示,虽然可以存在于系统内存中,但更通常都存在于显卡的显存中。IDirect3DSurface9接口包含了表面对象。

以下主题包含了更多信息。

宽度与Pitch的比较

虽然对术语宽度和pitch的使用经常不很正式,但它们有着非常重要并且完全不同的意义。因此,开发人员应该理解它们的意义,以及如何解释Microsoft? Direct3D?用于描述它们的值。

Direct3D使用D3DSURFACE_DESC结构保存描述表面的信息。其中,这个结构包含了表面的大小,以及这些大小在内存中是如何表示的。结构使用HeightWidth成员描述表面的逻辑大小,这两个成员都以像素为单位。因此,对于一个640x480表面来说,无论它是8位表面或24位RGB表面,它的HeightWidth值都是相同的。

当应用程序使用IDirect3DSurface9::LockRect方法锁定一个表面时,该方法会填写一个D3DLOCKED_RECT结构,这个结构包含了表面的pitch值及一个指向被锁定数据的指针。Pitch成员的值描述了表面在内存中的pitch,也被称为跨度。Pitch是两个内存地址间以字节为单位的距离,两个内存地址分别表示一个位图某一行的起始地址以及下一行的起始地址。因为pitch是以字节为单位而非以像素为单位,所以一个640x480x8表面的pitch值与另一个大小相同但像素格式不同的表面的pitch值会大不相同。另外,pitch值有时反映出被Direct3D保留并用作高速缓存的字节数,因此简单地认为pitch就是宽度乘以每个像素所占的字节数是不保险的。如下图所示,对宽度和pitch之间的区别做一个直观的比较会更清楚。

在这张图中,前后缓存都是640x480x8,高速缓存为384x480x8。

当直接访问表面时要小心,不要访问为表面分配的内存以外的地方,更不要访问任何为高速缓存目的而保留的内存。另外,当应用程序锁定一个表面的一部分时,应用程序必须保持在锁定表面时指定的矩形区域内。不按这些指导方针行事将会导致无法预料的结果。当直接渲染到表面内存时,应该总是使用由IDirect3DSurface9::LockRect方法返回的pitch值。不要认为pitch仅取决于显示模式。如果应用程序在一些显示适配器上运行良好,但在另一些适配器上显示不正确的话,很可能就是pitch的问题。

Microsoft? Direct3D?应用程序一般通过这种方式显示动画序列,即:先在后缓存中生成动画的各帧,然后按顺序把这些帧显示出来。后缓存是属于交换链的一部分。一个交换链是一系列后缓存,这些后缓存会一个接一个被“翻转”到屏幕上。这种方法可以用来在内存中渲染一个场景,当渲染完成后随即把场景翻转到屏幕上。这避免了画面撕裂的现象,并能生成更为平滑的动画。

当应用程序使用IDirect3DDevice9::Present方法要求一个翻转操作时,指向前缓存的指针和指向后缓存的指针被交换。翻转是通过切换显示设备用来引用内存的指针完成的,而不是复制表面的内存。当翻转链包含一个前缓存和一个以上的后缓存时,指针的切换以循环的方式进行,如下图所示。

通过调用IDirect3DDevice9::CreateAdditionalSwapChain,应用程序可以为设备创建附加的交换链。应用程序可以为每个视区创建一个交换链并将每个交换链与某个特定窗口相关联。应用程序在每个交换链的后缓存中渲染图像,然后分别显示它们。IDirect3DDevice9::CreateAdditionalSwapChain的两个参数分别为一个指向D3DPRESENT_PARAMETER结构的指针和一个指向IDirect3DSwapChain9接口的指针。应用程序可以使用IDirect3DSwapChain9::Present显示位于前缓存之后的那个后缓存的内容。注意一个设备只能有一个全屏交换链。

记住,Direct3D通过交换交换链内指向表面内存的指针翻转表面,而不是交换表面本身。这意味着应用程序总是在下次将被显示的那个后缓存上进行渲染。

很重要的一点是要注意由显卡驱动程序执行的“翻转操作”和一个用D3DSWAPCHAIN_FLIP标志创建的交换链执行的“present”操作间的区别。

按照惯例,术语“翻转”表示改变显卡用来产生输出信号的视频内存地址的范围,这样就导致原先隐藏着的后缓存的内容将被显示。在Microsoft DirectX? 9.0中,这个术语更经常地是被用来描述把任何用D3DSWAPEFFECT_FLIP标志创建的交换链中的后缓存显示出来。

而当交换链为全屏模式时,“present”操作几乎总是通过翻转操作实现,当交换链为窗口模式时,“present”操作必然通过复制操作实现。此外,显卡驱动程序可能会根据D3DSWAPEFFECT_DISCARD和D3DSWAPEFFECT_COPY标志,用翻转实现全屏交换链的present操作。

以上讨论适用于常用的情况,也就是用D3DSWAPEFFECT_FLIP标志创建的全屏交换链。

有关窗口和全屏交换链的各种不同交换效果的讨论,请参阅D3DSWAPEFFECT

页面翻转是多媒体、动画和游戏软件中的关键,它和动画师用一叠纸产生动画的方法相似。在每张纸上,动画师对图片稍做改变,因此当动画师在页与页之间快速地翻动时,图片看起来就像是动了。

软件中的页面翻转与这个过程相似。Microsoft? Direct3D?通过交换链实现页面翻转功能,而交换链是设备的一个属性。开始时,应用程序先设置一系列Direct3D缓存,这些缓存会以和动画师相同的翻页方法翻转到屏幕。第一个缓存被称为前颜色缓存,它之后的缓存被称为后缓存。应用程序可以先写入到后缓存,然后翻转颜色缓存,这样后缓存就显示在屏幕上。当系统显示图像时,应用程序又可以写入到后缓存。这个过程可以一直持续,这样应用程序就可以高效地生成活动的图像。

Direct3D使建立一个页面翻转机制非常容易——从一个双缓存机制(一个前颜色缓存和一个后缓存)到使用额外后缓存的更为复杂的机制。

当使用IDirect3DDevice9::UpdateSurface时,要传入源表面中的一个矩形,或者用NULL表示整个表面,应用程序还需要传入目标表面中的一个点,源图像的左上角将被复制到这个位置。该方法不支持裁剪,除非源矩形和对应的目标矩形分别完全被包含在源和目标表面内,否则操作将会失败。这个方法不支持阿尔法混合、color key,及格式转换。注意目标表面和源表面不能是同一个表面。

transfer)”的缩写,表示把数据块从内存中的一处传输到另一处的过程。作为在每帧——IDirect3DDevice9::Present方法背后的面向复制的机制——中移动大块矩形中的像素的主要机制,blitting设备驱动程序接口(DDI)仍在继续使用。blit操作中对纹理数据的传输由IDirect3DDevice9::UpdateTexture方法执行。在DirectX

注意 DirectX 9.0提供了Direct3D扩展(D3DX)函数,这使应用程序可以从文件载入纹理,进行颜色转换,及调整纹理的大小。有关更多可供使用的函数的信息,请参阅与纹理相关的函数

通过使用IDirect3DSurface9::LockRect方法,应用程序可以直接访问表面内存。在调用这个方法时,pRect参数为指向RECT结构的指针,描述要直接访问表面上的哪一部分。如果要锁定整个表面,只需把pRect设为NULL即可。同时,应用程序可以指定一个只覆盖表面的一部分的RECT。如果提供两个不相交迭的矩形,那么两个线程或进程可以同时锁定一个表面中的多个矩形。注意一个多重取样的(multisample)后缓存不能被锁定。

IDirect3DSurface9::LockRect方法会填写一个D3DLOCKED_RECT结构,该结构中包含了访问表面内存所需的全部信息。该结构包含了pitch信息,及一个指向被锁定的数据的指针。当应用程序完成对表面内存的访问后,应该调用IDirect3DSurface9::UnlockRect方法将表面解锁。

应用程序在锁定了一个表面后,可以直接对其中的内容进行操作。下面给出了一些提示,说明如何避免在使用直接渲染表面内存(directly rendering surface memory)时遇到的一些问题。

  • 绝对不要认为pitch是一个常数,应该总是检查IDirect3DSurface9::LockRect方法返回的pitch信息。Pitch可能会因为各种原因而不同,包括表面内存所在的位置,显卡的类型,甚至是Microsoft? Direct3D?驱动程序的版本。更多信息请参阅宽度与pitch的比较
  • 应用程序应该保证只对未锁定的表面进行复制操作,如果是锁定的表面,那么Direct3D的复制操作将会失败。
  • 当一个表面被锁定时,应用程序应该限制对它进行的操作。
  • 在复制数据时,应用程序应该总是保证和显存对齐。Microsoft Windows? 98使用了一个页故障处理器,Vflatd.386,它为使用内存单元切换(bank-switched memory)的显卡实现一个虚拟的平面帧缓存。该处理器允许此类显示设备以线性方式把帧缓存提供给Direct3D。当复制与显存不对齐的数据时,如果复制的数据跨越内存单元,那么可能会导致系统挂起。

应用程序可以在表面中存储任何类型的应用程序特有的数据。例如,在一个游戏中,一个表示地图的表面可以包含有关地形的数据。

一个表面可以有一个以上的私有数据缓存。每个缓存用一个GUID标识,该GUID由应用程序在把数据连接到表面时提供。

要存储私有表面数据,应该使用SetPrivateData,并传入源缓存,数据的大小,及应用程序为数据定义的GUID。或者,源数据也可以以COM对象的形式存在,这种情况下,应用程序只需传入对象的IUnknown接口指针,并设置D3DSPD_IUNKNOWNPOINTER标志。

SetPrivateData会为数据分配一块内部缓存并把数据复制到其中。应用程序可以安全地释放源缓存或对象。当FreePrivateData被调用时,内部缓存或对接口的引用也会被释放。当释放一个表面时,系统会自动执行这个操作。

要得到表面的私有数据,应用程序必须先分配一块大小合适的缓存,然后调用GetPrivateData方法,并把原先赋给数据的GUID传入。应用程序有责任释放任何用于这块缓存的动态内存。如果数据是COM对象,那么该方法会取得IUnknown指针。

如果应用程序不知道应该分配多大的缓存,可以先把pSizeOfData设为零并调用GetPrivateData,如果调用失败并返回D3DERR_MOREDATA,那么该方法会在pSizeOfData中返回所需的字节数。

Gamma控制允许应用程序改变系统如何显示表面的内容,同时不会影响表面本身的内容。可以认为这些控制是很简单的过滤器,在把表面数据显示在屏幕上之前,Microsoft? Direct3D?会对这些数据进行过滤。

Gamma控制是交换链的一个属性。有了Gamma控制,动态改变如何把表面的红、绿和蓝色深映射到系统最终显示的实际色深就成为了可能。通过设置Gamma level,应用程序可以使用户的屏幕闪现不同的颜色——当用户控制的角色被击中时为红色,当角色捡起了新的物品时为绿色,等等——同时不必为了达到相同的效果而把新的图像复制到帧缓存中去。

由于在Microsoft DirectX? 9.0中,交换链是设备的一个属性,因此每个Direct3D设备都至少有一条交换链(隐式交换链)。正因为gamma ramp是交换链的一个属性,所以当交换链处于窗口模式下时,gamma ramp也可以使用。Gamma ramp会立刻生效,不存在等待VSYNC的操作。

在Direct3D中,术语gamma ramp指的是一个组数值,这些数值用于把帧缓存中所有像素的某一颜色分量——红、绿、蓝——的level映射到被DAC接收并用于显示的新的色深。

ramp的工作方式:Direct3D从帧缓存中得到一个像素并分别计算每个红、绿和蓝颜色分量。每个分量由一个位于0到65535之间的值表示。Direct3D用这个原始值作为索引,在一个有256个元素的数组(即ramp)中查找,数组中每个元素包含一个值,用来替换原始值。Direct3D对帧缓存中每个像素的每个颜色分量进行这个查找并替换的过程,从而改变了所有最终显示在屏幕上的像素的颜色。

通过画图很容易就能把ramp值直观地表示出来。下面两张图中左图显示了一个完全不改变颜色的ramp,右图显示的ramp会给它所作用于的颜色分量加上负偏移。

左图中数组元素包含的值与它们的索引值相同——索引为0的元素的值为0,索引为255的元素的值为65535。这是默认的ramp类型,它不会在显示输入值之前改变它们。右图显示的ramp有较大变化,第一个元素的值为0,最后一个元素的值为32768,第一个和最后一个元素之间的元素的值在0到32768之间均匀分布。得到的效果就是使用这个ramp的颜色分量在显示器上会显得比较暗。Direct3D并没有限制必须使用线性映射,如果需要,应用程序可以指定任意的映射方式。应用程序甚至可以把所有元素都设为零,以把某一颜色分量从显示器上完全消除。

应用程序可以把IDirect3DDevice9::SetGammaRamp的第一个参数设为DDSGR_CALIBRATE,这样在设置新的gamma levels时就会调用校正器。由于校正gamma ramp会增加一些开销,因此最好不要频繁地调用。无论显卡或显示器是何类型,设置一个校正过的gamma ramp会给用户提供完全一致的gamma值。

在设置新的ramp levels时,谨记应用程序在数组中设置的levels只有当应用程序运行于全屏独占模式时才会被使用。一旦应用程序切换到正常模式,ramp levels就会被忽略,并在应用程序恢复到全屏模式时重新生效。

Mipmap的自动生成在创建纹理时利用了硬件过滤,这使得这项功能对应用程序而言是完全透明的。自动生成对mipmap渲染目标尤其有用,因为它们位于显存中,而这种情况下,软件过滤的效率很低。

如果纹理不是用D3DUSAGE_AUTOGENMIPMAP标志创建的,那么调用这些方法不会产生任何效果,也不会返回任何错误。除了D3DTEXF_NONE外,驱动程序支持的所有可用于常规纹理过滤的过滤类型都可用于自动生成。对每种资源类型而言,驱动程序应该支持它在相应的纹理、立方体纹理和立体纹理过滤能力信息中提供的过滤类型。

当源纹理是自动生成的mipmap,而目标纹理不是时,IDirect3DDevice9::UpdateTexture是非法的,调用会失败。如果源纹理不是自动生成的mipmap且目标纹理是自动生成的mipmap,那么只有目标纹理中的最高的相匹配的那层被更新,该层的sublevels会重新被生成,而源纹理的sublevels将会被忽略。与此类似,如果源纹理和目标纹理都是自动生成的mipmap,那么只有目标纹理中的最高的相匹配的那层被更新,该层的sublevels会被重新生成,而源纹理的sublevels将被忽略。

在创建一个自动生成的mipmap时,Levels参数必须被设置为零或一。

纹理管理是确定在某一特定时刻需要用哪些纹理进行渲染,并确保这些纹理已经被载入显存的过程。同任何算法一样,不同的纹理管理机制在复杂度上会有所不同,但任何纹理管理机制都会涉及到以下一些关键任务。

  • 计算哪些纹理需要被用于渲染,而哪些不需要。
  • 确定哪些现存(于显存中)的纹理资源可以重新载入其它纹理图像,以及哪些表面应该被销毁并被新的纹理资源代替。

为了保证纹理载入具有最佳的性能,Microsoft? Direct3D?内建了对纹理管理的支持。由Direct3D管理的纹理资源被称为由系统管理的资源

纹理管理器用时间戳对纹理进行跟踪,时间戳记录了纹理最后被使用的时间。管理器然后用最近最少使用(least-recently-used)算法确定哪些纹理应该被移除。在准备把两张纹理从显存中移除时,纹理的优先级用来仲裁。如果两张纹理具有相同的优先级,那么最近最少使用的那张纹理会被移除。如果两张纹理具有相同的时间戳,那么优先级较低的那张纹理会先被移除。

应用程序可以在创建纹理表面时要求自动纹理管理。要在C++应用程序中得到一个由系统管理的纹理,应该调用IDirect3DDevice9::CreateTexture创建纹理资源,并把Pool参数指定为D3DPOOL_MANAGED。Direct3D不允许应用程序指定要在何处创建纹理。在创建由系统管理的纹理时,应用程序不能使用D3DPOOL_DEFAULT或D3DPOOL_SYSTEMMEM标志。创建完由系统管理的纹理后,应用程序可以调用IDirect3DDevice9::SetTexture方法把纹理设到渲染设备的纹理级联中。

Direct3D根据需要自动把纹理载入显存。系统可能会根据非本地视频内存的可用性或其它因素把由系统管理的纹理放在本地或非本地视频内存中作为高速缓存。系统不会把由系统管理的纹理所用的缓存的位置和大小告诉应用程序,而且对使用自动纹理管理而言也无需了解该信息。如果应用程序使用的纹理超过了显存所能容纳的数量,那么Direct3D会把旧的纹理从显存中移除以给新的纹理腾出空间。如果应用程序再次用到被移除的纹理,那么系统会用原始的系统内存纹理表面把纹理重新载入到显存的高速缓存中。虽然重新载入纹理是必须的,但它同时降低了应用程序的性能。

通过更新或锁定纹理资源,应用程序可以动态地修改纹理位于系统内存中的原件。当系统检测到一个无效表面时——在更新操作完成后,或当表面被解锁时——纹理管理器会自动地更新纹理位于显存中的复本。由此导致的性能下降与重新载入一个被移除的纹理相似。

当进入游戏中新的一关时,应用程序可能需要清空显存中所有由系统管理的纹理,此时应该调用IDirect3DDevice9::EvictManagedResources

有关资源管理的更多信息,请参阅管理资源

纹理贴图是画在三维物体上的数字化图像,用来添加可视细节。它们在光栅化时被贴到物体表面,这个过程会消耗大量的系统带宽和内存。为了减少纹理所消耗内存的数量,Microsoft? Direct3D?支持对纹理表面的压缩。一些Direct3D设备本身就支持压缩纹理表面。在这些设备上,只要应用程序创建了压缩表面并将数据载入其中,该表面就可以和其它任何纹理表面一样,在Direct3D中使用。在把压缩纹理贴到三维物体表面时,Direct3D会进行解压。

所有纹理压缩的格式都是二的乘方。虽然这并不表示纹理一定要是方的,但确实表示X和Y都是二的乘方。例如,如果一个纹理原来是512×128,那下一级mipmap应该是256×64,依次类推,每一级都以两倍递减。到最低两级,纹理被过滤成16×2 和8×1,因为压缩块总是一个4×4的texel块,所以这里会浪费一些数据位。块中没有用到的部分被填满。虽然在最低几级会浪费一些数据位,但总体的收获还是显著的。理论上最差的情况是,一个2K×1的纹理。这里,每一块只用到一行像素,其余的都没有用到。

在单个纹理内的混用不同格式

需要特别注意的是任何单个的纹理必须指明它的数据——每组16个texel——是以64位还是以128位存储的。如果是64位块——也就是说,纹理用了DXT1格式,那么在同一纹理内以块为单位,混用不透明和一位阿尔法格式是可以的。换句话说,对每个由16个texel组成的块,对color_00和color_1两个无符号整数的比较是单独进行的。

一旦使用了128位块,整个纹理的阿尔法通道必须被指定为直接模式(DXT2和DXT3格式)或插值模式(DXT4和DXT5格式)。和颜色一样,一旦选择了插值模式,就可以以块为单位,混合使用八位或六位插值阿尔法。对alpha_0和alpha_1大小的比较仍然是以块为单位进行的。

对用于三维建模的纹理,Direct3D提供了压缩表面的服务。本节提供了有关创建压缩纹理表面及操控表面中的数据的信息。

不透明和一位阿尔法纹理

DXT1纹理格式用于不透明的或只有一个透明色的纹理。

每个不透明或一位阿尔法块保存了两个16位颜色值(RGB 5:6:5格式)和一个4x4的位图,位图中的每个像素占用2位。这样16个texel一共占用64位,或每个像素占用四位。在位图块中,每个texel占用2位,可以选择四个颜色,其中两个直接存储在经过编码的数据中,另两个则通过线性插值从存储的颜色值导出。下图显示了这种布局。

可以通过对存储在块中的两个16位颜色值进行比较来区分一位阿尔法格式和不透明格式。两个16位颜色值被当作无符号整数。如果第一个颜色值大于第二个,那么就暗示这一块只定义了不透明texel。这意味着有四个颜色可以用来表示texel。在四色编码中,有两个是导出的颜色,四个颜色值在RGB颜色空间中均匀分布。这种格式和RGB 5:6:5格式相似。否则(第一个颜色值小于等于第二个),就是一位阿尔法格式,一位阿尔法格式可以使用三个颜色,第四个颜色被保留,用来表示透明的texel。

在三色编码中,有一个导出的颜色,第四个2位编码被保留,用来表示透明的texel(阿尔法信息)。这种格式与RGBA 5:5:5:1格式相似,RGBA 5:5:5:1格式的最后一位被用来编码阿尔法掩码。

以下示例代码描述了用来决定当前块是使用了三色编码还是四色编码的算法。

应用程序在进行混合操作之前,最好把透明像素的RGBA成员设为零。

下面这些表显示了八字节块的内存布局,这里假设第一个索引值对应y坐标,第二个索引值对应x坐标。例如,Texel[1][2]指的是纹理贴图中位于(x,y) = (2,1)处的像素。

下表显示了八字节(64位)块的内存布局。

Color_0和Color_1为位于两端的颜色,它们的布局如下所示。

位图数据Word_0的布局如下所示。

位图数据Word_1的布局如下所示。

作为不透明编码的一个例子,假设位图左右两边的颜色为红色和黑色。红色为color_0,黑色为color_1。在它们之间有两个插值得到的颜色,四个颜色一起形成了均匀的颜色变化。以下计算用来确定4x4位图的值。

位图看起来如下图所示。

这看起来就是下面的一系列颜色。

当16位无符号整数color_0小于color_1时,就表示选择一位阿尔法格式。举个例子,这种格式可以用来显示在蓝天背景前的树叶,可以把一些texel标记成透明的,而树叶还可以使用三种深度的绿色。其中两个颜色位于两端,第三个颜色通过插值得到。

这里显示了这样一幅图片。

注意图像中白色的地方,texel会被编码成透明


※右侧文本列表可以找到全部手册


       是一款模拟手机触摸、按键操作的软件。通过制作脚本,可以让触动精灵代替双手,自动执行一系列触摸、按键操作。触动精灵简单、易用,不需要掌握任何编程知识就可以录制出功能强大的脚本;还可以使用编程知识,编写出功能更为复杂,交互更为灵活的脚本;只要能够在手机上完成的人为操作,触动精灵都可以代替完成,不仅省力,而且高效。

访问 iOS 系统功能页面

  1. 默认情况下调用的浏览器为系统默认浏览器。

函数名称:安装、卸载应用
函数功能:用于安装或卸载 ipa 类型的应用程序。

    函数名称:查询应用程序是否安装
    函数功能:用于查询设备上指定应用程序是否安装。
    支持版本:引擎版本 Android 安装)。
  • 加速插件有两个版本,触动精灵 iOS
    1. 如果系统是 iOS 11 则 tsp 自带 so 文件释放到该路径但 lua 文件释放路径保持不变

    Lua 配合 os.execute 命令,可以使用触动精灵对 iOS 设备进行注销、关机、重启、清空缓存、解压、移动、复制、删除文件、创建文件夹等系统操作
    帮你玩平台禁用此函数。

    要删除文件的路径,支持*通配符

    如要删除1.lua的文件,则输入:

    要解压到的文件夹路径,默认不覆盖

    如要解压名为 1.zip 的文件,则输入:

    待移动文件的路径,支持*通配符
    要移动到的文件路径,注意先判断是否有重名文件或文件夹

    待复制文件的路径,支持*通配符
    要复制到的文件路径,注意先判断是否有重名文件或文件夹。

    如要创建test文件夹,则输入:

    触动精灵中"io库"应用

    readFile 将指定文件中的内容按行读取

    1. -将指定文件中的内容按行读取

    要列举文件的文件夹的路径

    如要列举触动精灵lua文件夹下所有的脚本文件,则输入:

    要查找文件的路径,支持*通配符

    如要查找后缀为.lua的文件,则输入:

    1. --检测指定文件是否存在

    函数功能:将二维码图片解析为字符串,仅支持 Android v2.3.5.3 以上版本

    解析二维码图片的路径,支持 jpg,png 等格式
    解析二维码得到的字符串
    1. --"1.jpg"(如只填文件名,默认为图片在触动 res 目录下)

    并不是所有二维码都可以解析,推荐使用

    • 本扩展提供二维码识别的功能,以方便开发者可广泛适用于各类二维码
    • 暂不支持微信面对面红包二维码的识别

函数功能:将二维码图片解析为字符串,需要1.2.1及以上版本

解析二维码图片的路径,支持jpg,png等格式
解析二维码得到的字符串
  1. --"1.jpg"(如只填文件名,默认为图片在触动res目录下)

触动精灵ts.so扩展库

  • 本扩展库封装了大部分开发过程中需要的功能,适合有一定基础的开发者研究使用,使用得当可以以此开发出功能十分强大的脚本。

为了进一步降低脚本开发者门槛,触动精灵iOS 2.x 以上版本集成了苏泽的扩展库,提供了一系列实用函数供开发者使用。

iOS 设备分辨率一览表

标准模式分辨率(px) 放大模式分辨率(px)

触动引擎使用的是逻辑分辨率而不是物理分辨率

计算10为底,x的对数

已知与触动精灵/帮你玩/小精灵/企业版 iOS 冲突的插件列表

如果您安装了以下插件导致触动精灵服务使用异常,请在Cydia 中卸载该插件后重新安装客户端。

会导致帮你玩无法注册和登录账号,提示文件获取失败
会导致脚本showUI无法弹
PS/易天行(伪装地理位置插件) 会导致点击失效或服务无法启动
CCSettings(修改美化控制中心插件) 会导致脚本showUI无法弹出
会导致UI弹出后点击【取消】【确定】无反应
会导致点击失效或服务无法启动
会导致点击失效或服务无法启动


安卓手机如何开启系统悬浮窗权限

  • 设置 - (界面底部)其他应用管理 - 触动精灵 - 应用详情界面上滑 - (底部)权限管理 - 悬浮窗管理 - (弹出的底部菜单)选择允许
  • 安全中心 - 授权管理 - 应用权限管理 - 小精灵名称 - 显示悬浮窗 - 开启
  • 设置 - 全部设置 - 隐私和安全- 通知管理 - 悬浮窗管理 - 小精灵名称 - 打开开关
    -手机管家 - 悬浮窗管理 - 小精灵名称 - 开启悬浮窗
  • 设置 - (左侧栏)应用管理 - 小精灵名称 - 权限管理- 弹框消息一览 - 点击右侧按钮 - 按钮为绿色时为打开状态
    -安全中心 - 授权管理 - 小精灵名称 - 悬浮窗 - 开启
  • 安全中心 - 权限隐私 - 应用权限管理 - 悬浮窗管理 - 小精灵名称 - 打开开关
  • 管家 - 权限管理 - 应用权限管理 - 权限管理 - 小精灵名称 - 显示悬浮窗 - 开启
  • 安全中心 - 应用程序权限管理 - 其他 - 桌面悬浮窗 - 小精灵名称 - 打开开关

默认开启悬浮窗权限的手机

设备 SSH 连接工具

  1. 简体中文语言包:链接: 密码:jd9z

OCR(光学字符识别)相关

  1. 触动精灵本地 OCR 简体中文识别库: 密码:hy56
  2. 触动精灵本地 OCR 英文数字识别库: 密码:9ewt

iOS 系统设置参数对照表

按键码表[更多请自行尝试]

我要回帖

更多关于 全全屏的动画图像 的文章

 

随机推荐