opengl 的贴图功能是很基本的,不过也难住了我这个新手,所以特意写了一个示例程序,以便以后查阅。
程序很简单,只是在在 x, y 平面画一个框,然后贴上一张图。并且可以保存opengl窗口到图片。
程序:
//本程序的目的是展示贴图和保存图片
#include <Windows.h>
#include <gl/glut.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;
// Rotation amounts
static GLfloat xRot = 0.0f;
static GLfloat yRot = 0.0f;
const int height = 600;
const int width = 800;
static GLbyte TextData[1000*1000*4];
static GLuint TexName;
static int picrows = 0;
static int piccols = 0;
void savepic()
{
GLint viewPort[4] = {0};
glGetIntegerv(GL_VIEWPORT, viewPort);
int winrows = viewPort[3];
int wincols = viewPort[2];
GLbyte *colorArr = new GLbyte[winrows*wincols*3];
glReadPixels(viewPort[0], viewPort[1], viewPort[2], viewPort[3], GL_RGB, GL_UNSIGNED_BYTE, colorArr);
for(int i=0; i<winrows * wincols * 3; i ++) {
if(colorArr[i] == -1) { colorArr[i] = 255; }
}
Mat show = Mat(winrows, wincols, CV_8UC3, Scalar::all(0));
for (int i = 0; i< winrows; i++)
{
for (int j = 0; j< wincols; j++)
{
show.at<Vec3b>(winrows-i-1, j) = Vec3b(colorArr[(i*wincols+j)*3+2], colorArr[(i*wincols+j)*3+1], colorArr[(i*wincols+j)*3]);
}
}
delete colorArr;
imshow("show", show);
waitKey(33);
}
// Called to draw scene
void RenderScene(void)
{
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Save the matrix state and do the rotations
glPushMatrix();
glRotatef(xRot, 1.0f, 0.0f, 0.0f);
glRotatef(yRot, 0.0f, 1.0f, 0.0f);
//模型
glBegin(GL_QUADS);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0, 1.0);
glVertex3f(-1.0, 1.0, 0);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0, 0.0);
glVertex3f(-1.0, -1.0, 0);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0, 0.0);
glVertex3f(1.0, -1.0, 0);
glNormal3f(0.0f, 0.0f, 1.0f);
glTexCoord2f(1.0, 1.0);
glVertex3f(1.0, 1.0, 0);
glEnd();
// Restore the matrix state
glPopMatrix();
// Display the results
glutSwapBuffers();
//savepic();
}
// This function does any needed initialization on the rendering
// context.
void SetupRC()
{
// Black background
glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
////////////set pixel storage modes
glPixelStoref( GL_UNPACK_ALIGNMENT, 1 );
glGenTextures( 1, &TexName );
glBindTexture( GL_TEXTURE_2D, TexName );
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, piccols,
picrows, 0, GL_RGBA, GL_UNSIGNED_BYTE,
TextData );
//设置s方向纹理重复,为重复设置。
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
//t方向的纹理重复
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
//设置滤波方式为线性滤波
// when texture area is large, bilinear filter the first mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
// when texture area is small, bilinear filter the closest mipmap
glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
//GL_DECAL表示只用纹理颜色,不关心物体表面颜色
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glEnable(GL_TEXTURE_2D);
}
/////////////////////////////////////////////////////
// Handle arrow keys
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
{
xRot-= 5.0f;
}
if(key == GLUT_KEY_DOWN)
{
xRot += 5.0f;
}
if(key == GLUT_KEY_LEFT)
yRot -= 5.0f;
if(key == GLUT_KEY_RIGHT)
yRot += 5.0f;
if(key > 356.0f)
xRot = 0.0f;
if(key < -1.0f)
xRot = 355.0f;
if(key > 356.0f)
yRot = 0.0f;
if(key < -1.0f)
yRot = 355.0f;
// Refresh the Window
glutPostRedisplay();
}
//////////////////////////////////////////////////////////
// Reset projection
void ChangeSize(int w, int h)
{
// Prevent a divide by zero
if(h == 0)
h = 1;
// Set Viewport to window dimensions
glViewport(0, 0, w, h);
// Reset coordinate system
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//GLfloat fAspect = (GLfloat) w / (GLfloat) h;
//gluPerspective(45.0f, fAspect, 1.0f, 225.0f);
glOrtho(-1.3, 1.3, -1.3, 1.3, -10, 10);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
//载入图片
void gettex(string name)
{
Mat t = imread(name);
piccols = t.cols;
picrows = t.rows;
assert(picrows<=1000
&&piccols<=1000);
for (int i = picrows-1; i>= 0; i--)
{
for (int j = 0; j< piccols; j++)
{
TextData[((picrows-1-i)*piccols+j)*4+0] = (GLubyte)t.at<Vec3b>(i, j)[2];
TextData[((picrows-1-i)*piccols+j)*4+1] = (GLubyte)t.at<Vec3b>(i, j)[1];
TextData[((picrows-1-i)*piccols+j)*4+2] = (GLubyte)t.at<Vec3b>(i, j)[0];
TextData[((picrows-1-i)*piccols+j)*4+3] = 255;
}
}
}
int main(int argc, char* argv[])
{
//读取tex
gettex("test.jpg");
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800,600);
glutCreateWindow("pic");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
SetupRC();
glutMainLoop();
return 0;
}
需要注意的是,当打开savepic开关,并且缩小窗口的时候,会提示错误,目前不太清楚是什么原因。
原因在于保存的时候长宽必须是4的倍数才行。不然会出错。所以,改变窗口大小的话,可以在reshape函数里强制要求长宽被4整除即可。
另外放上一个obj读取的代码,写的很好。不过只能读取点,没有显示。http://download.csdn.net/detail/lcbwlx/6923111