在使用纹理的时候,有时候会出现超过纹理边界的问题,GL_TEXTURE_WRAP系列参数用来设置当这些超出边界时应该怎样处理。下面结合代码和代码产生的结果进行说明每个参数的作用。代码基于红宝书——《opengl编程指南》7th上的代码,自己再稍微改改,用来产生各种效果。
#include "stdafx.h"
#include
#include
#define checkImageWidth 64
#define checkImageHeight 64
static GLubyte checkImage[checkImageHeight][checkImageWidth][4];
static GLuint texName;
//产生纹理的函数
void makeCheckImage(void)
{
int i, j, c;
for ( i = 0; i < checkImageHeight; ++i )
for( j = 0; j < checkImageWidth; ++j )
{
c = ((( i & 0x8) == 0 )^ (( j & 0x8)) == 0) * 255;
checkImage[i][j][0] = ( GLubyte )c;
checkImage[i][j][1] = ( GLubyte )c;
checkImage[i][j][2] = ( GLubyte )c;
checkImage[i][j][3] = ( GLubyte )255;
}
}
void init( void )
{
glClearColor(0.0,0.0,0.0,0.0);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
makeCheckImage();
glPixelStorei( GL_UNPACK_ALIGNMENT,1);
glGenTextures(1,&texName);
glBindTexture(GL_TEXTURE_2D,texName);
// glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP); //GL_CLAMP GL_CLAMP_TO_BORDER
// glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP); //GL_REPEAT GL_CLAMP_TO_EDGE
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float color[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
glTexParameterfv( GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,checkImageWidth,checkImageHeight,
0,GL_RGBA,GL_UNSIGNED_BYTE,checkImage);
}
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_TEXTURE_2D);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE);
glBindTexture(GL_TEXTURE_2D,texName);
glBegin( GL_QUADS );
glTexCoord2f( 0.0, 0.0);
glVertex2f( -1.0, -1.0);
glTexCoord2f( 0.0, 1.8 );
glVertex2f( -1.0, 1.0 );
glTexCoord2f( 1.8, 1.8 );
glVertex2f( 1.0, 1.0 );
glTexCoord2f( 1.8, 0.0 );
glVertex2f ( 1.0, -1.0 );
glEnd( );
glFlush();
}
int main(int argc, char* argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode( GLUT_SINGLE|GLUT_RGBA);
glutInitWindowSize(512, 512);
glutInitWindowPosition(0, 0);
glutCreateWindow("棋盘纹理");
glutDisplayFunc(display);
glutIdleFunc(display);
init();
glutMainLoop();
return 0;
}
1. 首先是GL_REPEAT,这个比较简单,就是重复边界的纹理。产生的效果如下:
2. GL_CLAMP采用这种模式是,opengl就在一个2X2的加权纹理单元数组中使用取自边框的纹理单元。这时候的边框如果没有设置的话,应该就是原纹理的边界的像素值。
3. GL_CLAMP_TO_EDGE,在这种模式下,边框始终被忽略。位于纹理边缘或者靠近纹理边缘的纹理单元将用于纹理计算,但不使用纹理边框上的纹理单元。在实验中,不管有没有设置边框,都与与上面的GL_CLAMP结果相同。在下面的参考文献中给了一个解释:因为很多硬件并不支持边界处理,所以实现GL_CLAMP_TP_EDGE和GL_CLAMP的效果好象是一样的。
4. GL_CLAMP_TO_BORDER如果纹理坐标位于范围[0,1]之外,那么只用边框纹理单元(如果没有边框,则使用常量边框颜色,我想常量边框颜色就是黑色)用于纹理。在靠近纹理坐标边缘的地方,无论是边框还是纹理内部都可能根据一个2X2的数组进行采样。
5. 在GL_CLAMP_TO_BORDER的基础上使用上面的代码设置GL_TEXTURE_BORDER_COLOR(设置边框颜色为红色),可以得到下面的结果:
参考文献:
1.http://blog.csdn.net/superkris/article/details/5567593
2.http://blog.163.com/ray_jun/blog/static/167053642201162493648552/
3.《opengl编程指南》第七版9.6.2节——重复和截取纹理