opengl 显示图片以及保存图片

时间:2022-09-10 17:08:28

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