OpenGLEs 纹理的基础知识

纹理的基础知识

2D 纹理

2d纹理是OpenGlES中最基础和普遍的一种纹理结构。一个2d纹理,就是图片的数据的一个二维数组。纹理中每一个独立的数据单元被称为texels(“texture pixels”的缩写)。OpenGLES中纹理图像数据可变被许多种不同的基本格式描绘。

根据图像的基本类型和图像的数据类型,决定了图像中的每一个texel。

当渲染2D纹理是,纹理的坐标将成为索引。2D纹理的坐标轴别是(s,t)或者是(u,v)。这个坐标轴是规范化的,即坐标的大小在0.0~1.0之间。取纹理图像的左下角为坐标原点(0.0,0.0)

坐标超过[0.0,1.0]的范围是允许的,而对与超出范围的内容的操作,取决于纹理的包装方式(wrapping mode)

立方体贴图纹理(Cubemap Texttures

OpenGL ES 3.0 支持立方体贴图纹理。最基本的,一个立方体纹理由6个独立的2D纹理面组成。每一个2D纹理都是立方体的一个平面。虽然立方体贴图在3D渲染中有了多元化的进步,但是最普遍的还是被用在环境贴图中。典型的,在环境贴图中,将一台摄像机放置场景的中心点,拍摄6个方位的图像并保存。

立体贴图中的Texels通过使用一个3D的向量(s,t,r)来定位。定位时,先根据r确定是6个平面的哪一个平面,在根据(s,t)确定平面上的一点。

立体贴图纹理的每一个平面都必须是正方形的。

3D纹理

3D纹理可以看做是2D纹理多个切片的一个数组。将2D纹理当做的一个面,将面叠加起来,便是一个立体。这个立体就是3D纹理。3D纹理使用一个3元坐标(s,t,r),r坐标决定哪一个切面,(s,t)决定在这个切面中的坐标。

2D纹理数组

2D纹理数组和3D纹理很类似,当时一个3D纹理是表示一张图像,而一个2D纹理数组,则是表示一组2D图像形成的动画序列。

纹理对象和加载纹理

一个纹理对象是一个存储将要被渲染的纹理数据的容器,包括了图片数据,过滤方式和封装方式。在OpenGLES中,一个纹理对象通过一个非负整数来标识,这个数是这个纹理对象的一个句柄。生产纹理的函数是glGenTextures

void glGenTextures(GLsizei n, GLuint *textures)

n   指定生产的纹理对象的数量
textures 一个非负整数数组,用了存储n个纹理对象的ID

通过glGenTextures创建了空的容器,将会被拿去加载纹理数据和参数。当程序不在需要时,需要将纹理对象删除。通过glDeleteTextures实现。

void glDeleteTextures(GLsizei n, Gluint *textures)
n   指定删除的纹理对象的数量
textures 一个非负整数数组,用了存储n个纹理对象的ID

当一个纹理对象的id被glGenTextures创建后,程序必须将该纹理进行绑定。只有该纹理被绑定后,后续的操作例如glTexImage2DglTexParameter才能影响到绑定的纹理对象。执行绑定功能的函数是glBindTexture

void glBindTexture(GLenum target, GLuint texture)

target  将纹理对象和目标GL_TEXTURE_2D,              GL_TEXTURE_3D,GL_TEXTURE_2D_ARRAY或GL_TEXTURE_CUBE_MAP进行绑            定
texture     进行绑定的纹理的句柄

一旦纹理被绑定到一个指定的纹理目标,这个纹理对象将会一直维持对这个目标的绑定直到被删除。在创建一个纹理目标并绑定后,下一步便是使用纹理去加载图片数据。一个基本的加载2D和立体贴图纹理的函数是glTexImage2D。另外,在OpenGl ES 3.0 中有几个可以替代的函数,这些函数被用于指定的2D纹理,包括使用不可变纹理glTexStorage2DglTexSubImage2D的结合。

void glTextImage2D (GLenum target, GLint level,
                        GLenum internalFormat, GLsizei width,
                        GLsizei height, GLint border,
                        Glenum formate, Glenum type
                        const void * pixels)

target  指定纹理的目标,包括GL_TEXTURE_2D或立体贴图面目标中的一个(GL_TEXTURE_CUBE_MAP_POSITIVE_X,GL_TEXTURE_CUBE_MAP_NEGATIVE_X,等等).
level       指定哪一个级别的mip将被加载。第一个等级被指定为0
internalFormat 纹理存储的内部格式。包括了无大小限制的内部格式和有大小限制的格式。无大小内部格式包括 GL_RGBA, GL_RGB, GL_LUMINANCE_ALPHA GL_LUMINANCE, GL_ALPHA 有大小的内部格式包括 GL_R8, GL_R8_SNORM, GL_R16F, GL_R32F
GL_R8UI, GL_R16UI, GL_R32UI, GL_R32I
GL_RG8, GL_RG8_SNORM, GL_RG16F, GL_RG32F GL_RG8UI, GL_RG8I, GL_RG16UI, GL_RG32UI GL_RG32I, GL_RGB8, GL_SRGB8, GL_RGB565 GL_RGB8_SNORM, GL_R11F_G11F_B10F
GL_RGB9_E5, GL_RGB16F, GL_RGB32F
GL_RGB8UI, GL_RGB16UI, GL_RGB16I, GL_RGB32UI GL_RGB32I, GL_RGBA8, GL_SRGB8_ALPHA8 GL_RGBA8_SNORM, GL_RGB5_A1, GL_RGBA4 GL_RGB10_A2, GL_RGBA16F, GL_RGBA32F GL_RGBA8UI, GL_RGBA8I, GL_RGB10_A2UI GL_RGBA16UI, GL_RGBA16I, GL_RGBA32I GL_RGBA32UI, GL_DEPTH_COMPONENT16 GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32F GL_DEPTH24_STENCIL8, GL_DEPTH24F_STENCIL8

width  图片的像素宽度
heigth 图片的像素高度
border 必须为0
formate 输入纹理数据的格式,可能是GL_RED 
GL_RED_INTEGER
GL_RG
GL_RG_INTEGER
GL_RGB
GL_RGB_INTEGER
GL_RGBA
GL_RGBA_INTEGER
GL_DEPTH_COMPONENT
GL_DEPTH_STENCIL
GL_LUMINANCE_ALPHA
GL_ALPHA

type 输入的像素数据的类型;可能是
                  GL_UNSIGNED_BYTE
               GL_BYTE
               GL_UNSIGNED_SHORT
               GL_SHORT
               GL_UNSIGNED_INT
               GL_INT
               GL_HALF_FLOAT
               GL_FLOAT
               GL_UNSIGNED_SHORT_5_6_5
               GL_UNSIGNED_SHORT_4_4_4_4
               GL_UNSIGNED_SHORT_5_5_5_1
               GL_UNSIGNED_INT_2_10_10_10_REV
               GL_UNSIGNED_INT_10F_11F_11F_REV
               GL_UNSIGNED_INT_5_9_9_9_REV
               GL_UNSIGNED_INT_24_8
               GL_FLOAT_32_UNSIGNED_INT_24_8_REV
               GL_UNSIGNED_SHORT_5_6_5

pixels 包含了图片的像素数据。这个数据必须包含了(width*height)个像素,每个像素根据指定的格式和类型占用一定的字节,像素行必须用GL_UNPACK_ALIGNMENT设置glPixelStorei设置对齐

和纹理加载相关的函数,还有一个glPixelStorei,该函数决定了像素数据存储方式。


void glPixelStorei(GLenum pname , GLint param)

pname 指定像素存储类型。下面的可选参数将影响当glTexImage2D, glTexImage3D, glTexSubImage2D, 和 glTexSubImage3D被调用时,数据如何从内存中被解包:GL_UNPACK_ROW_LENGTH, GL_UNPACK_IMAGE_HEIGHT, GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS, GL_UNPACK_SKIP_IMAGES, GL_UNPACK_ALIGNMENT
    下列可选参数将影响glReadPixels被调用时,数据如何被打包读入内存:GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_ROWS, GL_PACK_SKIP_IMAGES, GL_PACK_ALIGNMENT
    
param 为打包或解包指定的整形数值。

GL_PACK_xxxxx对纹理的更新没有任何影响。实际上,除了GL_UNPACK_ALIGNMENT,其他的可选选项很少被使用

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

意味着每一个像素行从字节边界开始,换而言之,数据被紧密打包。该值的默认值是4,表示像素行被认定从4字节的边界开始。

纹理过滤和mip贴图

纹理坐标用于生成一个2D索引,从纹理贴图中读取。当缩小和放大过滤器设置为GL_NEAREST时,就会发生这样的情况:一个texels将在提供的纹理坐标位置上读取。这样称作点采样或最近采样。

然而,最近采样可能产生视觉伪像。一个伪像的产生是因为一个图像在屏幕中变小,导致像素之间的纹理坐标产生了巨大跳跃。这造成了从一个张巨大的纹理图中读取了少量的采用点,从而导致了锯齿伪像的产生。

解决这一问题的方法是,采用mip贴图。所谓的mip贴图,就是通过当前的屏幕分辨率,生成较低的屏幕分辨率的图片,形成一个图片链。比如现在有一张64*64的图片,采用mip贴图,会生成32*32,16*16,8*8,4*4,2*2,1*1,等低分辨率的图片。这些图片中,最原始的被称为0级层。每低一个低级的层,都是由上等级的图片生成的,像素合并规则是,将每个图层的2*2的像素点相加取平均值,作为下一层的一个像素点。

缩小过滤发生在屏幕中的多边形小于纹理大大小时。放大过滤发生在屏幕中多边大于纹理的大小时。对于放大过滤,mip贴图没有影响。对于缩小过滤,mip贴图可以保证像素的平滑

通过glTexParameter[i|f][v]来设置纹理的的参数

void glTexParameteri(GLenum target, GLenum pname, GLint param)
void glTexParameteriv(GLenum target, GLenum pname, const GLint *params)
void glTexParameterf(GLenum target, GLenum pname, GLfloat param)
void glTexParameterfv(GLenum target, GLenum pname, const GLfloat *params)

target 纹理目标
pname 进行设置的纹理属性,可以包括
        GL_TEXTURE_BASE_LEVEL
GL_TEXTURE_COMPARE_FUNC
GL_TEXTURE_COMPARE_MODE
GL_TEXTURE_MIN_FILTER
GL_TEXTURE_MAG_FILTER
GL_TEXTURE_MIN_LOD
GL_TEXTURE_MAX_LOD
GL_TEXTURE_MAX_LEVEL
GL_TEXTURE_SWIZZLE_R
GL_TEXTURE_SWIZZLE_G
GL_TEXTURE_SWIZZLE_B
GL_TEXTURE_SWIZZLE_A
GL_TEXTURE_WRAP_S
GL_TEXTURE_WRAP_T
GL_TEXTURE_WRAP_R

params 指定属性的参数

对于放大过滤GL_TEXTURE_MAG_FILTER,可以设置为GL_NEAREST或者是GL_LINEAR
对于缩小过滤GL_TEXTURE_MIN_FILTER,可以设置的值如下

  • GL_NEAREST 表示根据纹理坐标,获取最近的一个纹理样本
  • GL_LINEAR 根据纹理坐标,采用2次采样方法,获取纹理样本
  • GL_NEAREST_MIPMAP_NEAREST 根据纹理坐标,从最近的mip贴图层中获取一个点样本
  • GL_NEAREST_MIPMAP_LINEAR 根据纹理坐标,获取2个最近的mip图层的采样点,并取2个样本之间的插值
  • GL_LINEAR_MIPMAP_NEAREST 根据纹理坐标,采用二次线性插值从最近的mip层中获取一个点样本
  • GL_LINEAR_MIPMAP_LINEAR 根据纹理坐标,获取最近2个mip图层中采用二次线性获取的采用点,并取2个采用点之间的插值

自动生成Mip贴图

OpenGL ES 3.0 中提供了一个自动生成mip贴图的方法glGenerateMipmap;

纹理坐标的封装

纹理封装方式(Texture wrap modes)被用于指定超出纹理坐标限定范围[0.0,1.0]的行为。通过glTexParameter[i|f][v]可以设置纹理封装方式。这些mode可以独立设置s坐标轴,t坐标轴和r坐标轴。例如GL_TEXTURE_WRAP_Smode定义了s坐标超出[0.0,1.0]的行为。同样的GL_TEXTURE_WRAP_TGL_TEXTURE_WRAP_R分别定义了t坐标和r坐标的超出[0.0,1.0]的行为。

在OpenGL ES 3.0 中,有3中mode值可以设置。

GL_REPEAT      重复纹理
GL_CLAMP_TO_EDGE  限定读取纹理的边缘
GL_MIRRORED_REPEAT 重复纹理和镜像

纹理的调配

纹理调配控制输入的R,RG,RGB或RBGA纹理中的颜色分量在着色器中读取时如何映射到分量。通过调用glTexParameter[i|f][v]来设置纹理调配,key可以设置为GL_TEXTURE_SWIZZLE_R, GL_TEXTURE_SWIZZLE_G, GL_TEXTURE_ SWIZZLE_B, 或 GL_TEXTURE_SWIZZLE_A,而value可能分别从R,G,B,A分量读取的GL_RED, GL_GREEN, GL_BLUE, 或 GL_ALPHA。也可以通过GL_ZERO和GL_ONE将值设置为0或1

纹理细节级别

在一些程序中,在所有的纹理mip贴图都可以使用前就能够开始在屏幕上进行显示的功能是很有用的。比如GPS的程序,可以先显示低等级的mip贴图,等到所有的mip贴图都下载后,在显示高清的mip贴图。可以通过glTexParameter[i|f][v]中的GL_TEXTURE_BASE_LEVEL来设置可以被使用的最大mip贴图等级。默认是0。同样的,GL_TEXTURE_MAX_LEVEL设置了最小的mip贴图等级,默认是1000。

为了选择用于渲染的mip贴图级别,OpenGL ES自动计算一个细节级别(LOD)的值。这个浮点值决定了哪一mip贴图级别被筛选出来。一个程序能够控制LOD值的最大和最小值。通过设置GL_TEXTURE_MIN_LODGL_TEXTURE_MAX_LOD

在着色器中使用纹理

// Vertex shader
#version 300 es
layout(location = 0) in vec4 a_position;
layout(location = 1) in vec2 a_texCoord;
out vec2 v_texCoord;
void main()
{
   gl_Position = a_position;
   v_texCoord = a_texCoord;
}
// Fragment shader
#version 300 es
precision mediump float;
in vec2 v_texCoord;
layout(location = 0) out vec4 outColor;
uniform sampler2D s_texture;
void main() {
   outColor = texture( s_texture, v_texCoord );
}

碎片着色器中的texture函数,表示从指定的纹理单元中,根据输入的坐标,映射出纹理中相应的vec4颜色。

vec4 texture(sampler2D sampler, vec2 coord[, float bias])

sampler 采样器,指定的纹理单元的编号

coord  2D纹理的坐标
bias   可选参数,提供用于纹理读取的mip贴图偏值。这运行着色器明确偏置用于mip贴图选择的LOD计算值

在sampler参数需要传入的纹理单元编号前,需要先激活一个纹理单元,并将纹理绑定到该纹理单元上。使用glActiveTexture进行激活

void glActiveTexture(GLenum texture)
texture  激活纹理单元,GL_TEXTURE0, GL_TEXTURE1, ... , GL_TEXTURE31分别代表纹理单元0到31

使用glActiveTexture激活一个纹理单元后,便可使用glBindTexture将指定的纹理绑定到该纹理单元上。具体代码如下:

// Get the sampler locations
userData->samplerLoc = glGetUniformLocation(
                              userData->programObject,
                              “s_texture”);
// ...
// Bind the texture
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, userData->textureId);

// Set the sampler texture unit to 0
glUniformli(userData->samplerLoc, 0);

加载立体贴图,3D纹理和2D纹理数组,也是同样的操作,对应的texture分别为

vec4 texture(samplerCube sampler, vec3 coord[, float bias])
vec4 texture(sampler3D sampler, vec3 coord[, float bias])
vec4 texture(sampler2DArray sampler, vec3 coord[, float bias])

压缩纹理

OpenGL ES 3.0 支持2中压缩算法-EAC和ETC2。EAC版本用于压缩1到2频道的数据。ETC2版本用于压缩3到4频道的数据。使用glCompressedTexImage2D可以读取压缩的2D纹理和立体贴图纹理。使用glCompressedTexImage3D读取已压缩的2D纹理数组。注意:ETC2/EAC不支持3D纹理压缩,但是使用glCompressedTexImage3D可以加载指定供应商的3D纹理压缩格式

void glCompressedTexImage2D(GLenum target, GLint level, 
                                GLenum internalFormat,
                                GLsizei width, GLsizei height,
                                GLint border, GLsizei imageSize, 
                                const void *data)
void glCompressedTexImage3D(GLenum target, GLint level, 
                                GLenum internalFormat,
                                GLsizei width, GLsizei height,
                                GLsizei depth, GLint border, 
                                GLsizei imageSize,
                                const void *data)
                                
target  指定纹理目标
level     指定加载的mip级别,默认是0
internalFormat   纹理的内部存储格式
width           图片的像素宽度
height          图片的像素高度
depth           图片的像素深度
border          必须设置为0
imageSize       图片的字节大小
data            压缩后的图片数据

可以通过glGetIntegerv传入GL_COMPRESSED_TEXTURE_FORMATS进行查询支持的压缩格式,该函数会返回一个GLenum的数组。

纹理子图像规范

在使用glTexImage2D更新一张纹理图片后,可能需要更新图片的一部分。这时候可以使用glTexSubImage2D来来自2D纹理图像的一部分。

void glTexSubImage2D (GLenum target, GLint level,
                            GLInt xoffset, GLint yoffset
                            GLsizei width, GLsizei height,
                            GLenum format, Glenum type,
                            const void *pixels)
                            
target 纹理目标
level  mip贴图级别
xoffset 开始进行更新的x序列号
yoffset 开始进行更新的y序列号
width     进行更新的图像子区域的宽度
heigth   进行更新的图像子区域的高度
formate  输入纹理数据的格式
type    输入像素数据的类型
pixels  包含图像子区域的像素数据

这个函数将会更新区域(xoffset,yoffset)到(xoffset+width-1,yoffset+height-1)。注意:使用这个函数,纹理必须依据被指定,而且子图片的范围必须在指定的纹理图片之内,pixels的对其方式必须被指定为GL_UNPACK_ALIGNMENT

同样的原理,可以使用glCompressedTexSubImage2D更新压缩过的图片,使用它glTexSubImage3D更新3D纹理或2D纹理数组,使用glCompressedTexSubImage3D更新压缩过的2D纹理数组。

从颜色缓冲区复制纹理数据

glReadBuffer指定被复制的颜色缓存区。然后通过glCopyTexImage2D, glCopyTexSubImage2D,和 glCopyTexSubImage3D从指定的颜色缓冲区张读取纹理数据

采样器对象

为了减少大量纹理上使用相同的设置的开销。引入了采样器对象,将采样器状态与纹理状态分离。简而言之,所有可用glTexParameter[i|f][v]设置都可以对采样器对象进行设置。可以在一次函数调用中与纹理单元绑定使用。

glGenSamplers用于创建采用器,使用glDeleteSamplers删除采样器。使用glBindSampler将采样器与纹理单元进行绑定。使用glSamplerParameter[f|i][v]设置采样器参数。

不可变纹理

由于应用程序使用glTexImage2DglTexImage3D等函数独立指定纹理的每个mip贴图的级别。这导致了驱动程序无法在绘图之前确定纹理是否完全指定。也就是说,它必须检查每一个mip贴图级别或者子图像的格式是否相符、每一个级别的大小是否正确以及是否有足够的内存。这种绘图时检查可能代价很高,而使用不可变纹理可以避免这种情形。

不可变纹理的思路很简单:程序在加载数据之前指定纹理的格式和大小。OpenGL ES的驱动可以提前进行一致性和内存检查。一旦纹理不可变,它的格式和尺寸也就不能改变。然而程序仍然可以通过使用glTexSubImage2D, glTexSubImage3D,或 glGenerateMipMap来加载纹理。

为了创建不可变纹理,程序必须先使用glBindTexture绑定当前纹理,在调用glTexStorage2DglTexStorage3D创建不可变的存储空间。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容

  • 一、纹理基础 3D图形渲染中最基本的操作就是对一个表面应用纹理。纹理可以表现只从网格的几何形状无法得到的附加细节。...
    cain_huang阅读 8,671评论 0 7
  • http://blog.csdn.net/wangdingqiaoit/article/details/51457...
    jerryhigh阅读 5,298评论 0 8
  • 纹理只是一种能够应用到场景中的三角形上的图像数据,它通过经过过滤的纹理单元(texel,相当于纹理的像素)填充到实...
    Gaolex阅读 2,821评论 0 1
  • 纹理(Textures) 我们已经了解到,我们可以为每个顶点使用颜色来增加图形的细节,从而创建出有趣的图像。但是通...
    IceMJ阅读 5,621评论 2 13
  • 既然已经爱了 哪有什么如果 无论如何 即使一个人 也要唱完这支歌 未来 可以假设 过去 没有如果 r
    艾米读书写作阅读 179评论 5 2