这一章介绍如何创建一个纹理采样器(Sampler)并应用到一个Shape上。简单的来说,纹理就是一个图像(一个像素信息的2D数组),这个图像可以应用到3D物体的表面。O3D中Texture的图像支持TGA、JPEG、PNG、DDS格式。使用Texture Sampler我们可以设置参数以说明如何将Texture贴到物体表面。

关于Texture

O3d用u表示Texture的水平坐标,用v表示其垂直坐标,坐标(u,v)的取值从(0.0,0.0)到(1.0,1.0),如下:

o3d_3_1

Texture Samplers

Texture Sampler封装一个texture object的指针和一系列状态参数(states),这些参数用于定义texture bitmap如何贴到表面。Sampler status可以通过定义Sampler object或者直接指定Sampler类的方法来设置。Sampler类定义了如下属性(括号里是默认值):

  • addressModeU (WRAP)
  • addressModeV (WRAP)
  • minFilter (LINEAR)
  • magFilter (LINEAR)
  • mipFilter (POINT)
  • borderColor (Float4(0,0,0,0)
  • maxAnisotropy (1)

Address Mode

addressModeUaddressModeV 属性指定当texture坐标超过0.0到1.0时如何处理。u、v方向可以使用不同的address mode,下面是参数说明:

Value Meaning
WRAP Repeat the texture to fill in the area (default)
MIRROR Repeat the texture, inverting it when it crosses a uv boundary (0.0 or 1.0 in either direction)
CLAMP The last row of pixels in the texture is repeated to cover the rest of the face
BORDER A border color is used for the pixels that fall outside the range of the texture coordinates specified

Minification Filter

这个参数用于指定当贴图区域的像素比texture少时如何处理。参数如下:

Value Meaning
POINT Use the closest pixel.
LINEAR Perform a linear interpolation between neighboring pixels and use the result.
ANISOTROPIC Stretch the texture according to its orientation in screen space (may be more in one direction than in the other). See Anisotropy, below.

Mipmap Filter

创建缩小纹理要比创建放大纹理困难,要防止不同颜色边界的图形失真。Mipmapping通过特殊的步骤创建缩小的纹理替代原先完整的纹理,通常的技术是这样的:从原始的完整纹理开始,然后创建一个一半大小的纹理,然后继续压缩成一半的一半,反复这个步骤直到压缩到只有一个像素为止。比如原先是64*64的图片,那么就压缩成32*32、16*16…… 1*1,当我们需要把纹理贴到20*20大小的区域时,就取出32*32和16*16这两个level的值来计算插入结果。至于如何选择这个level,我们根据下面的值来决定:

Value Which Mipmap Is Used
NONE Don’t use a mipmap at all.
POINT Use the mipmap level that is closest to the size of the triangle on the screen. Within that level, filter the pixels based on the minification filter (minFilter).
LINEAR Start with the two mipmap levels that are closest in size to the triangle on the screen. Filter each level with the minFilter. Then perform a linear interpolation between these two levels to produce the final color values.

Magnification Filt

这个参数指定如何将纹理贴到像素值比它大的区域,值如下:

Value Meaning
POINT Use the closest pixel.
LINEAR Perform a linear interpolation between neighboring pixels and use the result.

Border Color

address mode设成BORDER时,borderColor就会应用到所有超出前面定义的纹理坐标范围的像素上。

Anisotropy

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

下面是例子是取不同参数时的不同效果:

o3d_3_2


Top Left Top Middle Top Right
  • addressModeU = Sampler.WRAP
  • addressModeV = Sampler.WRAP
  • minFilter = Sampler.LINEAR
  • magFilter = Sampler.LINEAR
  • mipFilter = Sampler.POINT
  • borderColor = Float4(0, 0, 0, 0)
  • maxAnisotropy = 1
  • minFilter = Sampler.ANISOTROPIC
  • maxAnisotopy = 4
  • addressModeU = Sampler.BORDER
  • addressModeV = Sampler.BORDER
  • borderColor = Float4(1, 0, 0, 1)
Bottom Left Bottom Middle Bottom Right
  • minFilter = Sampler.POINT
Uses default (LINEAR) filtering; compare to texture above
  • addressModeU = Sampler.MIRROR
  • addressModeV = Sampler.MIRROR

例子

下面我们来将上一章的立方体贴上纹理。我们要增加的工作如下:

1. 定义纹理坐标

2. 创建纹理采用器(Testure Sampler),设置参数

3. 从指定的URL获取纹理

4. 创建shaders以取出纹理

Step 1: 定义纹理坐标

首先为每个顶点指定纹理的UV坐标。

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

然后创建一个vertex buffer来存储纹理坐标(texCoordsBuffer),将纹理坐标的数组赋值给buffer:

var texCoordsBuffer = g_pack.createObject(‘VertexBuffer’);
var texCoordsField = texCoordsBuffer.createField(‘FloatField’, 2);
texCoordsBuffer.set(texCoordsArray);

调用setVertexStream()将buffer和streambank连接起来,这个函数指定如何从这个stream里读取数据:

streamBank.setVertexStream(
g_o3d.Stream.TEXCOORD,  // semantic
0,                      // semantic index
texCoordsField,         // field
0);                     // start_index

Step 2: 创建纹理采用器

这一步调用Effect.createUniformParams() 创建材质参数然后设置参数值。

cubeEffect.createUniformParameters(cubeMaterial);
var samplerParam = cubeMaterial.getParam(‘texSampler0′);
g_sampler = g_pack.createObject(‘Sampler’);
g_sampler.minFilter = g_o3d.Sampler.ANISOTROPIC;
g_sampler.maxAnisotropy = 4;
samplerParam.value = g_sampler;
Step 3: 载入纹理
首先初始化URL值(在initStep2()函数里):

var path = window.location.href;
var index = path.lastIndexOf(‘/’);
path = path.substring(0, index+1) + ‘assets/texture_b3.jpg’;
var url = document.getElementById(“url”).value = path;
下面的changeTexture()函数当用户改变纹理时调用:function changeTexture()

var textureUrl = document.getElementById(‘url’).value;
try {
o3djs.io.loadTexture(g_pack, textureUrl, function(texture) {
// Remove the currently used texture from the pack so that when it’s not
// referenced anymore, it can get destroyed.
if (g_sampler.texture)
g_pack.removeObject(g_sampler.texture);

g_sampler.texture = texture;

g_cubeTransform.parent = g_client.root;
}

Step 4: 创建Shaders
这部分的内容暂时不单独讲了,主要是关于shading language和图形渲软管线的知识,以后再详细介绍。
下面是效果图:
o3d_3_3
若想查看本章Demo的全部代码,点击下面的链接: http://code.google.com/intl/zh-CN/apis/o3d/docs/prettyhellocube-textures.html

O3D基础教程2 绘制简单几何图元

上一篇我们调用O3D的createSphere函数绘制了一个球体,这一次我们将自己来完成这个几何体绘制过程,这将加深我们对O3D渲染过程的了解。 如同OpenGL绘制过程一...

阅读全文

O3D基础教程1 简明介绍和程序框架

O3D是google公司开发的一套用于web3D开发的javascript API,是为了创建基于网页的3D图形操作界面和3D游戏而开发。网上经常有人把它拿来和OpenGL作比较,实际...

阅读全文

4则回应给“O3D基础教程3 纹理Texture”

  1. cfanlds说道:

    呵呵,看不懂啊.

    [回复]

  2. liuhua说道:

    顶一下 多发点就好了

    [回复]

  3. liuhua说道:

    要看懂这个需要学习些什么

    [回复]

  4. liuhua说道:

    对了 可以说说 外部文件怎么载入了

    [回复]

发表评论