纹理坐标包装
(Texture Coordinate Wrapping) 当纹理坐标超过了范围 [0.0, 1.0] 时纹理包装被使用。纹理包装模式使用glTexParameter[i|f][v]
设定。纹理包装模式能被独立的设定为s坐标和t坐标。GL_TEXTURE_WRAP_S定义s坐标超出范围 [0.0, 1.0] 的情况。GL_TEXTURE_WRAP_T设定t坐标。
包装模式有:GL_REPEAT重复,GL_CLAMP_TO_EDGE采样纹理边缘,GL_MIRRORED_REPEAT镜像重复纹理。
示例代码如下,完整代码见github的tag:lesson8-1。
// Draw quad with repeat wrap mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glUniform1f(offsetLoc, -0.7f);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
// Draw quad with clamp to edge wrap mode
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glUniform1f(offsetLoc, 0.0f);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
// Draw quad with mirrored repeat
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
glUniform1f(offsetLoc, 0.7f);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
效果如图:
Mipmap贴图
纹理过滤中讲到最邻近过滤和双线性插值过滤。尽管双线性过滤很适合处理放大,但是对于缩小到超过一定的大小时,它就不好用了。一个纹理在渲染表面所占大小减少得越多,就会有越多的纹理元素拥挤到每一个片段上。因为OpenGL的双线性过滤只给每个片段使用四个纹理元素,我们将会丢失很多细节。因为每一帧都要选择不同的纹理元素,这还会引起噪音以及移动中的物体闪烁。为了克服这些缺陷,可以使用Mipmap贴图技术,它可以用来生成一组优化过的不同大小的纹理。当生成这组纹理的时候,OpenGL会使用所有的纹理元素生成每个级别的纹理,当过滤纹理时,还要确保所有的纹理元素都能被使用。在渲染时,OpenGL会根据每个片段的纹理元素数量为每个片段选择最合适的级别。
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
GLES2支持自动产生多级纹理。
void glGenerateMipmap(GLenum target)
target产生多级纹理的目标可以是GL_TEXTURE_2D或GL_TEXTURE_CUBE_MAP。这个函数会产生从原始图像到级别为0的全部的多级纹理链。
示例代码:完整代码见github的tag:lesson8-2。
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, wid, hei,
0, GL_RGB, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
//...
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
效果如图:
读取tga纹理
前面的纹理数据都不是真正的图片,这里展示一个例子来贴一张最简单的tga图片。
将准备好的放入android设备中去
adb push ~/Desktop/1.tga /sdcard/
如果app要访问设备内的位置,AndroidManifest.xml需要添加权限:
<uses-permission android:name="android.permission.INTERNET"/>
读取图片的数据,然后其他的就没什么不同的了。完整代码见github的tag:lesson8-3。
const char* fileName = "/sdcard/1.tga";
int wid, hei;
char *buffer = this->loadTGA(fileName, &wid, &hei);
if (buffer == NULL)
{
LOGE("Error loading (%s) image.\n", fileName);
return;
}
glGenTextures(1, &textureId);
glBindTexture(GL_TEXTURE_2D, textureId);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, wid, hei, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
效果图:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。