纹理
纹理是一个用来保存图像的颜色元素值的OpenGL ES 缓存。它可以控制一个渲染的三角形中每个像素的颜色。纹理可以使用任何图像,包括树木、云彩、机器、人物。当把纹理应用到几何图形中后,会使渲染的场景更显自然,会使三角形的复杂组合像是真实的物体而不是只有颜色的面。在纹理的缓存中保存的颜色值可能要耗费很多的内存,所以,应该尽量使用最小的图像来产生可以接受的渲染结果。
纹素
当用一个图片初始化一个纹理缓存后,在这个图像中的每个像素变成了纹理中的一个纹素。与像素类似。纹素保存颜色数据。要说区别。就是像素有具体的尺寸大小,而纹素没有,纹素存在于一个没有尺寸的数学坐标系中。
纹理坐标系
图1-1(纹理坐标系)
纹理坐标系中有一个命为 S 和 T 的2D轴(上面画错了,x当成是S,y当成是T)。在一个纹理中无论有多少纹素,纹理的尺寸永远在S轴上是从 0 - 1.0 ,在T 轴上 是从 0 - 1.0.比如:一张图片宽是100像素,高是100像素。那S轴的1.0就表示截取图片的宽是100像素,如果S轴是0.5,则只会截取到图片的宽是50像素,图片只会显示一半。
片元
每个顶点坐标的X、Y、Z坐标被转换成视口坐标后,GPU会设置转换生成的三角形内的每个像素的颜色。转换几何形状数据为帧缓存中的颜色像素的渲染步骤叫做点阵化(rasterizing),每个颜色像素叫做片元(franment)。
映射
程序需要指定怎么对齐纹理和顶点,以便让GPU知道每个片元的颜色由哪些纹素来决定。这个对齐又叫做映射(mapping)。
其实每个顶点除了给定的X、Y、Z坐标,每个顶点还给出了U和V的坐标值。U坐标会映射纹理中的S轴,V坐标会映射到T轴。
取样
GPU会根据每个片元的U、V位置从绑定的纹理中选择纹素。这个过程叫做取样。取样会把纹理的S和T坐标系中与每个渲染的三角形的顶点的U、V坐标匹配起来。例如:一个U、V坐标为{0.5,0.5}的片元会被当前绑定的纹理中最接近中间位置的纹素着色。
取样模式
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
GL_TEXTURE_MIN_FILTER 多个纹素对应一个片元时
GL_TEXTURE_MAG_FILTER 没有足够多的纹素来唯一性地映射一个片元,会有放大纹理的效果
GL_LINEAR 当使用指定参数 GL_TEXTURE_MIN_FILTER,会使用线性插法来混合这些颜色以得到片元最终的颜色,
GL_LINEAR当使用指定参数GL_TEXTURE_MAG_FILTER,会混合附近纹素的颜色来计算片元的颜色,会有一个放大纹理的效果,并会让它模糊地出现在渲染的三角形上
GL_NEAREST 与片元U、V坐标最接近的纹素的颜色会被取样,当指定参数是 GL_TEXTURE_MAG_FILTER,会有一个放大纹理的效果
除了上面这放大和缩小的过滤选项之外,当U、V坐标的值小于0或者大于1的时候,有以下两种选择,要么尽可能多的重复纹理以填满映射到几何图形的整个U、V区域,要么每当片元的U、V坐标超出纹理的S、T坐标系范围的时候,取样纹理边缘的纹素。
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
GL_TEXTURE_WRAP_S 和 GL_TEXTURE_WRAP_T 分别代表纹理坐标系的S 和T轴
GL_REPEAT :代表重复纹理
GL_CLAMP_TO_EDGE:代表取边缘纹理
代码实现
1.定义一个结构体
三角形顶点数据结构体2.设置上下文,创建绑定顶点缓存区域,分配内存
创建绑定顶点缓存区域,分配内存3.创建绑定顶点索引缓存区域,分配内存
创建绑定顶点索引缓存区域,分配内存4.设置属性
5.添加纹理
6.绘制
7.最后进行销毁
8.运行结果
在这个demo第二个例子中我们还用到了一个新的函数,这里说一下。
glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
// 用来更新一个已有缓冲区对象中的一部分数据
@param target 用来指定需要更新的缓冲区对象的类型,如 GL_ARRAY_BUFFER
@param GLintptr 要从什么地方开始更新原来的数据(以字节为单位)
@param size 需要更新的数据量的大小
@param data 个指向新数据源的指针,将新的数据源拷贝到缓冲区对象中完成更新
网友评论