Texture

本文详细介绍了Starling框架下Texture对象的API及其使用方法,包括如何创建、配置Texture对象以及Mip映射的概念与实现。重点讨论了不同文件格式在Texture对象中的应用以及如何优化内存使用。同时,阐述了Mip映射在2D内容缩放中的作用,以及Starling框架如何自动处理Mip映射生成。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

如果你创建了一个 Image 对象,那你必须为其传入一个 Texture 对象作为外观。这两者的关
系就像原生Flash中Bitmap和BitmapData的关系【PS:嗯……有基情】。下面来看看Texture
对象提供的 API:
* base : 该Texture对象所基于的Stage3D texture对象
* dispose : 销毁该Texture对象的潜在纹理数据
* empty : 静态方法。创建一个指定大小和颜色的空Texture对象
* frame : 一个Rectangle矩形对象,用于指示一个Texture对象的范围
* fromBitmap : 静态方法。从一个Bitmap对象创建一个外观与其一致的Texture纹理对
象。
* fromBitmapData : 静态方法。从一个BitmapData对象创建一个外观与其一致的
Texture纹理对象。
* fromAtfData : 静态方法。允许运用ATF (Adobe Texture Format)格式创建一个压缩
过的材质。经过压缩的材质能让你节省大量空间,尤其是在像移动设备这样对存储空间
异常苛刻的环境中尤为有用。
* fromTexture : 静态方法。从一个Texture对象创建一个外观与其一致的Texture纹理
对象。
* height 、width: 我想这两个属性就不用多说了
* mipmapping : 此属性用以指示该材质是否包含了mip映射
* premultipliedAlpha : 此属性用以指示该texture对象的透明度是否被预乘到了RGB
值中(premultiplied into the RGB values).
* repeat : 用以指定当前材质是否启用重复平铺模式,就像铺壁纸那样。
【PS:API 功能翻译有时会有曲意,在使用时还请以英文 API 介绍为参考】
有很多不同格式的文件可被用作 Texture 对象的数据提供源,下面列出了所有可用的文件格
式:
* PNG : 由于所需素材中经常需要保留透明通道,因此PNG格式的文件是Texture最
常用的素材格式。
* JPEG : 经典的JPEG格式文件也可以为Texture所用。有一点需要注意,就是在GPU
中该格式的图片会被解压缩,这意味着JPEG格式的文件将无法发挥其节省空间的优
势,且其不保留透明通道哦
* JPEG-XR : JPEG XR是一个为了让图片色调更加连贯,视觉效果更加逼真而存在的
图片压缩标准及图片文件格式,它是基于一种被称作HD Photo的技术(起初由
Microsoft微软公司开发并拥有专利,曾用名为Windows Media Photo)。它同时支持
有损和无损压缩,且它是Ecma-388 Open XML Paper Specification文档标准推荐的
图片存储优先格式。
* ATF : Adobe Texture Format. 这是一种能提供最佳压缩效果的文件格式。ATF文件
主要是一个存储有损纹理数据(lossy texture data)的文件容器。它主要使用了两种
类似技术:JPEG-XR1压缩技术和基于块的压缩技术(简称块压缩技术),来实现它
的有损压缩。
JPEG-XR压缩技术提供了一种非常有竞争力的方式来节省存储空间及网络带宽。而
块压缩技术则提供了一种能够在客户端削减纹理存储空间(与一般的RGBA纹理文件
所占存储空间的比例为1:8)的方式。 ATF提供了三种块压缩技术:DXT12, ETC13 及

PVRTC4.

 

接下来让我们再更加深入地了解一些有关材质的概念并探索一下 GPU 中的一个基本概念:
Mip 映射。Mip 映射是一个重要却简单易懂的概念。将一个纹理保存多个缩小版本的方式就
叫做 Mip 映射【PS:如一个 256*256 尺寸的纹理被保存了 128*128、64*64….1*1 这么多版
本的纹理于内存中】。在GPU中工作时,一个图片若将被缩放,那么它将被缩放到的大小将
取决于其原始尺寸。缩放行为一般会发生在镜头向物体移动或者物体向镜头移动时,这两种
情况下都会对你的图片(在 GPU中表现为纹理)产生缩放。

-----------------------------------------------------------------------------------------------------------------------------
需要注意的是,若要使用Mip映射,那么你的纹理尺寸必须保证为2的倍数(1,
2, 4, 8, 16, 32, 64, 128, 256,512, 1024, 2048), 但形状不一定必须是矩形。如
果你没有遵守这个规则,那么Starling将会为你自动创建一个与当前纹理尺寸
最接近的能被2整除的数值作为尺寸的纹理(如你使用的纹理尺寸为31*31,那
么Starling会为你创建一个32*32尺寸的纹理),但这可能会对内存有一点消耗。
为了确保尽可能地优化纹理的内存占用,我们建议您最好使用texture atlases
(翻译成中文叫做纹理贴图集,但是没多少人会用中文称呼之),也被广泛称
作SpriteSheet(翻译成中文叫做精灵表,但是也没人这么叫它,都直接用英文
名称呼的)的素材集成、使用方式。稍后我们会接着讨论它。
-----------------------------------------------------------------------------------------------------------------------------

为了保证最佳的呈现品质,GPU 需要一个图片的全部 Mip 映射等级,即由原始尺寸依次除
以二直到除不尽 2 了为止。【PS:对于一个 128*128 尺寸的纹理来说,它的全部 Mip映射等
级为:64*64,32*32,16*16,8*8,4*4,2*2以及 1*1】Starling框架能够自动替你生成全部 Mip 映
射等级,若是你不用 Starling框架的话,那你就得通过使用 BitmapData.draw 这个 API 并使
用一个缩小一倍的 Matrix 作为参数来手动地生成全部的映射等级。
--------------------------------------------------------------------------------------------------------------------------
我们建议为2D内容使用Mip映射,这样可以使它们在缩放时能够减少锯齿的产

-----------------------------------------------------------------------------------------------------------------------------
幸运的是,之前我们提到过,Starling 能够自动替你生成全部的 Mip 映射等级,它其实也是
用了 BitmapData.draw 来做的,下面是 Starling中用以生成 Mip 映射的代码:

if (generateMipmaps) 
{ 
var currentWidth:int = data.width >> 1; 
var currentHeight:int = data.height >> 1; 
var level:int = 1; 
var canvas:BitmapData = new BitmapData(currentWidth, currentHeight, t
var transform:Matrix = new Matrix(.5, 0, 0, .5); 
while (currentWidth >= 1 || currentHeight >= 1) 
{ 
canvas.fillRect(new Rectangle(0, 0, currentWidth, currentHeight), 0); 
canvas.draw(data, transform, null, null, null, true); 
texture.uploadFromBitmapData(canvas, level++); 
transform.scale(0.5, 0.5); 
currentWidth = currentWidth >> 1; currentHeight = currentHeight >> 1; 
} 
canvas.dispose(); 
} 


 

【PS:要在 Starling中使用 Mip 映射只需要设置某个 Texture 对象的 mipmapping属性为 true
即可】
当你使用 ATF格式文件(Adobe Texture Format)作为素材时,你就不需要为它的 Mip 映射
问题操心了,它内部已经包含了全部的 Mip 映射等级,且不是在运行时才去生成的,而是
已经预生成好的。这是非常有价值的一点,因为这样可以为你在运行时节省生成 Mip 映射
的时间。特别是在需要使用大量纹理的时候,使用 ATF格式作为素材可以为你节省大量的初
始化时间。
注意到,在 Texture 对象中存在一个 frame 属性,此属性允许我们设置一个 Texture 对象在
Image 对象【PS:如果把 Texture 对象理解成原生 Flash 中的 BitmapData,那么 Image 对象
就可以理解成Bitmap,用以承载Texture并将其显示出来】中的位置。假设你需要让一个Image
对象存在一点边距,你只需要用一个稍小一些的 Texture 纹理,然后将其位置置于 Image 的
中心就好了:
texture.frame = new Rectangle(5, 5, 30, 30);
var image:Image = new Image(texture);
刚才说到了 Image 对象,那么现在就来详细地探讨一下此对象。

 

### 关于OpenGL中的纹理用法及相关问题 在OpenGL中,纹理映射是一种重要的技术,用于增强图形的真实感和细节表现力。以下是关于OpenGL纹理的一些基本概念以及常见问题的解决方案。 #### 基本纹理设置 为了在OpenGL中使用纹理,通常需要完成以下几个步骤: 1. **加载纹理数据** 使用外部库(如SOIL、stb_image等)来加载图像文件并将其转换为适合OpenGL使用的格式。 2. **生成纹理对象** 调用`glGenTextures()`函数创建一个或多个纹理对象,并绑定到特定的目标(如 `GL_TEXTURE_2D`)。 ```c++ GLuint textureID; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); ``` 3. **配置纹理参数** 设置纹理过滤方式(线性插值/最近邻)、环绕模式以及其他属性。例如: ```c++ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // 缩小时使用三线性滤波 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // 放大时使用双线性滤波 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // S方向重复纹理 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // T方向重复纹理 ``` 4. **上传纹理数据至GPU** 将像素数据传递给OpenGL并通过`glTexImage2D()`定义纹理的内容。如果启用了mipmap,则可以调用`glGenerateMipmap()`自动生成不同级别的缩略图[^1]。 5. **激活纹理单元并与着色器关联** 在现代OpenGL中,通过统一变量将纹理分配给片段着色器中的采样器位置。例如,在顶点缓冲区绘制之前执行以下操作: ```c++ glActiveTexture(GL_TEXTURE0); // 激活第一个纹理单元 glBindTexture(GL_TEXTURE_2D, textureID); glUniform1i(glGetUniformLocation(shaderProgram, "u_texture"), 0); // 绑定到uniform sampler2D u_texture ``` #### 解决常见的纹理问题 1. **纹理显示为空白或黑色** 这可能是由于未正确指定纹理坐标或者未能成功加载纹理数据所致。可以通过调试工具验证纹理是否已正确加载,并确认顶点数组中的纹理坐标范围是否合理(通常是 `[0, 1]` 的标准化设备坐标系)[^3]。 2. **无法应用mipmapping** 如果启用mipmap但仍然看到模糊效果,可能是因为缺少必要的扩展支持或忘记生成mipmap层次结构。确保硬件驱动程序兼容,并显式调用`glGenerateMipmap()`之后再渲染场景。 3. **跨平台移植困难** 对于希望构建跨平台应用程序的情况,推荐采用托管框架简化开发流程。比如ManagedGL是一个.NET游戏库项目,尽管其版本1已被废弃而专注于更先进的功能集上,但它仍提供了良好的基础架构供开发者参考实现自己的解决方案[^2]。 ```python import OpenGL.GL as gl from PIL import Image def load_texture(path): img = Image.open(path).transpose(Image.FLIP_TOP_BOTTOM) img_data = numpy.array(list(img.getdata()), dtype=numpy.uint8) texture_id = gl.glGenTextures(1) gl.glBindTexture(gl.GL_TEXTURE_2D, texture_id) # 配置纹理选项... gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR_MIPMAP_LINEAR) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_S, gl.GL_REPEAT) gl.glTexParameterf(gl.GL_TEXTURE_2D, gl.GL_TEXTURE_WRAP_T, gl.GL_REPEAT) # 提交原始图片数据到当前绑定的纹理目标 gl.glTexImage2D(gl.GL_TEXTURE_2D, 0, 3, img.size[0], img.size[1], 0, gl.GL_RGB, gl.GL_UNSIGNED_BYTE, img_data) gl.glGenerateMipmap(gl.GL_TEXTURE_2D) # 自动生成各层mipmap return texture_id ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值