您的位置:首页 > 其它

o3d教程4 - 纹理映射

2010-03-25 09:58 239 查看
这一章讲纹理,纹理,不能顾名思义了,其实就是一张图片,我们要做的就是把这张图片贴到模型上面,
从而让模型一下子生动起来,说得有文采点就是栩栩如生,这个过程就叫纹理映射(也可以叫贴图)。纹理映射有时候能产生非常神奇的效果,比如说凹凸贴图,和
凹凸贴图衍生出来的法线贴图,能够让只有几百个几千个多边形的模型产生几万个,几十万个多边形的模型的效果。

接下来就要介绍怎么创建一个纹理采样器
(texture
sampler)
,如何设置采样的属性,然后把一张图片(纹理)成功地
贴到那个立方体上面,图片的格式可以是
TGA


JPEG


PNG


DDS

,其中像
TGA,PNG

这样的格式是支
持半透明的,可以用来模拟阴影(当然只是简单地模拟)。

纹理采样器负责怎么把一张图片上的各个像素映射到模型的像素上,反过来说,就是为每个像素选取纹理像
素。看似很简单,但是当显示的图片大于(或小于)要覆盖的那个面时,就得就结了,这个不能一一映射了,那得怎么做呢,这是门学问,我们可以通过设置这个纹
理采样器的各个属性来达到较好的效果。

Address Mode

首先是
addressModeU



addressModeV


性,这两个属性决定了当纹理坐标超出(

0



1


后该怎么做。纹理坐标,顾名思义,就是在纹理上的坐标,这是我们截取纹理中的一部分是要用到的。它的范围是(

0



1

)。
其中左下角的坐标是

(0.0 , 1.0)

,右
上角的坐标是

(1.0 , 1.0)

这两个属性有下面四种可能值

Value


Meaning


WRAP

(
默认为此值)重复贴图来填充贴图区域

MIRROR

重复贴图,当遇到
UV
的边界时反向(
UV
边界为
0.0
或者
1.0


CLAMP

用贴图的最后一行像素,重复覆盖没贴到的区域

BORDER

超过的贴图区
域,用一种特殊颜色的边标记出来

Minification Filter


Minification
filter,

minFilter


个属性具体说明了怎么把纹理贴到一个像素比它少的模上面(这个上面有提到过),这个属性可能有下面

3

个值

Value


Meaning


POINT

用最近的那个像素

LINEAR

线性插值

ANISOTROPIC

各向异性过滤

这三个滤镜效果是单调递增的,具体是怎么实现的,这里不多讲了
(
其实也不会讲
- -)

想了解的话可以去看图像处理方面的书籍。。。。

Mipmap
Filter



于处理缩小纹理比处理放大纹理复杂多了,如果只是简单地取最近的那个像素,或者说只是和这个像素的周围几个像素简单的比较一下,获得平均值就插进去的话,
会严重降低图片缩小后的质量,而如果去周围大量的像素,做大量的计算又会严重降低程序效率。于是有才的人就想到了
mipmap
这个方法。它先将这张图片按原来尺寸一半一半地压缩,举个例子,原来的

64*64
的图片,就压缩成一张
32*32
的,一张
16*16
的,一张
8*8
的......当这张图片需要映射成
20*20
的大小的,就取
32*32

16*16
这两张图片来计算出
20*20
大小的图片,这比只是计算单张图片的效率和效果要好得多
.


面是这个参数可能的值

Value of

mipFilter


Which Mipmap Is Used


NONE

不用mipmap

POINT

取与需要映射的大
小最近的那张图片,然后依据上面的minification filter
进行过滤

LINEAR

取与需要映射的大
小最近的两张图片,为每张图片按照上面的miniFilter
进行过滤,然后把这两张图片一起进行
线性插值等到最终的图片


Magnification
Filter



大纹理的处理就比较简单了,有下面两种可能的值。

Value


Meaning


POINT

Use the closest pixel.

LINEAR

Perform a linear interpolation between neighboring pixels
and use the result.


minFilter
差不多。


Border
Color



前面的
address mode
设成
border
时,这个属性就派上用场了,它可以用来设置那个边框的颜色。


Anisotropy


前面的
minFilter

Anisotropy
时,这个值就是决定了各向异性过滤的质量。


些属性介绍完了,下面就举个实例,把那张求是潮的
logo
贴到那个立方体上。


先要建立一个
texture sampler
,同
shape

material
一样,这也是一个
Object
,非常好地体现了"面向对象"的思想。

g_sampler

=

g_pack

.

createObject

(

'Sampler'

);

g_sampler
.
minFilter

=
g_o3d
.
Sampler
.
ANISOTROPIC
;

g_sampler
.
maxAnisotropy

=

4
;

可以看到第一句就是建立
sampler
对象,后面两句就是设置上面提到的属性,
minFilter
设为各向异性过滤,
maxAnisotropy
设为
4


这样一个简单的
sampler
就建立了,但是比较打击人的是这个还只是设了下最基本的参数,这个参数设了给谁用呢,又是在哪里把
图片贴到那个模型上面去的呢


~

o3d
里面纹理贴图就是在
pixel
shader
里面用了一个函数
tex2D
把图片像素一个个根据上面设好的各
个参数填进已经经过
vertex shader
变换和
primitive assembly
(就是
shape
一章里讲过的把各个顶点按照一定规则连接成图元的操作)了的东西里面。而传给
tex2D
的参数有两个,一个是一开始提到
的纹理坐标(
texCoord
),还有一个就是采样器的各个参数了(这里面也包括了整个纹理素材),要把
js
中设的参数传到
shader
里面,
o3d
中的做法是先在
shader
里面建一个变量,比如
texSampler0
,然后在
js
中用
material

getParam
方法获取这个
texSampler0
变量,具体的如下:

effect

.

createUniformParameters

(

material

); //

这句话是不可少的,否则就不能
获取shader

里面设的变量了

var

samplerParam

=

material

.

getParam

(

'texSampler0'

);

samplerParam

.

value

=

g_sampler

; //


g_sampler

的参数赋给
samplerParam

这里的
material

effect
就是前面几章为那个立方体建立的材质对象。所以可把上面几句代码加在原来的建立
material

effect
的代码的后面
(
具体的
shader
代码在最后放出来
)

下面要做的是把纹理资源载入内存。

o3djs

.

io

.

loadTexture

(

g_pack

,

textureUrl

,

function

(

texture

)

{

// set the texture on the sampler object to the newly created
texture

// object returned
by the request.

g_sampler
.
texture
=

texture
; //

可以看到这里把纹理资源也附到sampler


了以供shader
使用

})

其中
function(texuture)

。。。。。是回调函数,这里声明成匿名函数了(
js

非常好用的一个特性),如果要处理的量比较大的话,可以独立
出来写成一个函数。也可以在其它纹理载入的时候使用。
textureURL

顾名思义就是图片地址了。

最后是声明各个顶点的纹理坐标,前面说到过要传给
shader

的,这个和声明顶点坐标差不多(顶点坐标数组也得相应的改过,不能几个面公用同一个顶点了,具体的建
sample

里的代码吧,再放出来就太长了
= =



var

texCoordsArray

=

[

0
,

0
,

1
,

0
,

1
,

1
,

0
,

1
,

0
,

0
,

1
,

0
,

1
,

1
,

0
,

1
,

1
,

1
,

0
,

1
,

0
,

0
,

1
,

0
,

0
,

0
,

1
,

0
,

1
,

1
,

0
,

1
,

0
,

0
,

1
,

0
,

1
,

1
,

0
,

1
,

0
,

0
,

1
,

0
,

1
,

1
,

0
,

1

];

var

texCoordsBuffer

=

g_pack

.

createObject

(

'VertexBuffer'

);

var
texCoordsField
=
texCoordsBuffer
.
createField
(
'FloatField'
,

2
);

texCoordsBuffer
.
set
(
texCoordsArray
);

streamBank

.

setVertexStream

(

g_o3d
.
Stream
.
TEXCOORD
,

//
semantic

0
,

// semantic index

texCoordsField
,

// field

0
);

// start_index

不多做解释了。

最后的最后:

Shader
代码

// World View
Projection matrix
that will transform the input vertices

// to screen space.

float4x4 worldViewProjection : WorldViewProjection;

// The texture sampler is used to access the texture
bitmap in the fragment

// shader.

sampler texSampler0;

// input for our vertex shader

struct VertexShaderInput {

float4 position : POSITION;

float2 tex : TEXCOORD0; // Texture
coordinates

};

// input for our pixel shader

struct PixelShaderInput {

float4 position : POSITION;

float2 tex : TEXCOORD0; // Texture
coordinates

};

/**

* The vertex shader simply transforms the input
vertices to screen space.

*/

PixelShaderInput
vertexShaderFunction(VertexShaderInput
input) {

PixelShaderInput output;

// Multiply the vertex positions by the
worldViewProjection matrix to

// transform them to screen space.

output.position = mul(input.position,
worldViewProjection);

output.tex = input.tex;

return output;

}

/**

* Given the texture coordinates, our pixel shader
grabs
the corresponding

* color from the texture.

*/

float4 pixelShaderFunction(PixelShaderInput input):
COLOR {

return tex2D(texSampler0, input.tex);

}

// Here we tell our effect file *which* functions
are

// our vertex and pixel shaders.

// #o3d VertexShaderEntryPoint vertexShaderFunction

// #o3d PixelShaderEntryPoint pixelShaderFunction

// #o3d MatrixLoadOrder RowMajor

Shader
的代码就不解释了,下一章会比较详细地讲下
shading
language
和图形渲软管线到底是怎么样的,下下章可能会讲光照,光
照就是都在
shader
里面计算了,这个纯考数学物理知识啊,不过幸好已经有前人弄好的公式给我们套了。然后就是讲下阴影
(shadow)
的生成了,注意的是并不是有
光照就会自然而然地产生阴影了,阴影的处理是游戏中比较关键的,也是很占资源的一个地方。阴影处理的好的话游戏的真实性倍增啊啊。。。。

还有要说的就是
shapes
和这章的纹理映射以后不会这么详
细地用到,不会让你一个个顶点地去定义,更多的是载入一个用
3d
软件诸如
3DMAX

maya
做的模型,或者是用自带的函数简单地创个球,毕竟像这次这样创建一个带有贴图的立方体会让人崩溃的。

刚刚在整
sample
的时候发现纹理素材载入的时候总
是出现未知错误,折腾了半天都没找到原因,后来复制到别的地方发现又莫名其妙地可以用了,总算找到了原因:路径中不能有中文,哎,感叹一下,其实很多游戏
安装路径中也是不允许有中文的
= =
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: