OpenGL离屏渲染保存为Bmp图片

#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "freeglut.lib")

#include "windows.h"
#include <stdio.h>
#include <gl/glew.h>
#include <gl/glut.h>


int windowWidth = 0;
int windowHeight = 0;

const int TexWidth = 500;
const int TexHeight = 500;

int colorBitLen = 32;

bool leftMouseDown = false;
float mouseX, mouseY;
float cameraAngleX, cameraAngleY;
float xRot, yRot;
GLubyte buff[TexWidth * TexHeight * 4] = {0};

GLuint textureID;
GLuint frameBufferID;
GLuint renderBufferID;

void drawCube()
{

	glBindTexture(GL_TEXTURE_2D, textureID);
	glColor4f(1, 1, 1, 1);

	glBegin(GL_QUADS);
	//Front
	glNormal3d(0, 0, 1);

	glVertex3d(-1, -1, 1);   	glTexCoord2d(0, 0);
	glVertex3d(1, -1, 1);   	glTexCoord2d(1, 0);
	glVertex3d(1, 1, 1);   	glTexCoord2d(1, 1);
	glVertex3d(-1, 1, 1);   	glTexCoord2d(0, 1);

	Back
	//glNormal3d(0, 0, -1);
	//glVertex3d(1, -1, -1); glTexCoord2d(0, 0);
	//glVertex3d(-1, -1, -1); glTexCoord2d(1, 0);
	//glVertex3d(-1, 1, -1);  glTexCoord2d(1, 1);
	//glVertex3d(1, 1, -1);   glTexCoord2d(0, 1);

	Left
	//glNormal3d(-1, 0, 0);
	//glVertex3d(-1, -1, -1); glTexCoord2d(0, 0);
	//glVertex3d(-1, -1, 1);  glTexCoord2d(1, 0);
	//glVertex3d(-1, 1, 1);   glTexCoord2d(1, 1);
	//glVertex3d(-1, 1, -1);  glTexCoord2d(0, 1);

	Right
	//glNormal3d(1, 0, 0);
	//glVertex3d(1, -1, 1);   glTexCoord2d(0, 0);
	//glVertex3d(1, -1, -1);  glTexCoord2d(1, 0);
	//glVertex3d(1, 1, -1);   glTexCoord2d(1, 1);
	//glVertex3d(1, 1, 1);    glTexCoord2d(0, 1);

	Top
	//glNormal3d(0, 1, 0);
	//glVertex3d(-1, 1, 1);   glTexCoord2d(0, 0);
	//glVertex3d(1, 1, 1);    glTexCoord2d(1, 0);
	//glVertex3d(1, 1, -1);   glTexCoord2d(1, 1);
	//glVertex3d(-1, 1, -1);  glTexCoord2d(0, 1);

	Bottom
	//glNormal3d(0, -1, 0);
	//glVertex3d(1, -1, 1);   glTexCoord2d(0, 0);
	//glVertex3d(-1, -1, 1);  glTexCoord2d(1, 0);
	//glVertex3d(-1, -1, -1); glTexCoord2d(1, 1);
	//glVertex3d(1, -1, -1);  glTexCoord2d(0, 1);

	glEnd();
	glBindTexture(GL_TEXTURE_2D, 0);
}


void ChangeSize(int w, int h)
{
	windowWidth = w;
	windowHeight = h;

	if (h == 0)
		h = 1;
}

void savePixelData(GLubyte *data, int size) {
	FILE* pFile;
	fopen_s(&pFile, "C:\\Users\\bluda\\Desktop\\test.bmp", "wt");
	if (!pFile) { fprintf(stderr, "error \n"); exit(-1); }

	BITMAPFILEHEADER hdr;
	BITMAPINFOHEADER infoHdr;

	infoHdr.biSize = sizeof(BITMAPINFOHEADER);
	infoHdr.biWidth = TexWidth;
	infoHdr.biHeight = TexHeight;
	infoHdr.biPlanes = 1;
	infoHdr.biBitCount = colorBitLen;
	infoHdr.biCompression = 0;
	infoHdr.biSizeImage = size;
	infoHdr.biXPelsPerMeter = 0;
	infoHdr.biYPelsPerMeter = 0;
	infoHdr.biClrUsed = 0;
	infoHdr.biClrImportant = 0;

	hdr.bfType = 0x4D42;
	hdr.bfReserved1 = 0;
	hdr.bfReserved2 = 0;
	hdr.bfOffBits = 54;
	hdr.bfSize = (DWORD)(sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + size);

	fwrite(&hdr, 1, sizeof(BITMAPFILEHEADER), pFile);
	fwrite(&infoHdr, 1, sizeof(BITMAPINFOHEADER), pFile);
	fwrite(data, 1, size, pFile);

	fclose(pFile);
	printf("color data saved! \n");
}



void renderToImg() {

	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
	glReadPixels(0, 0, TexWidth, TexHeight, GL_RGBA, GL_UNSIGNED_BYTE, buff);
	savePixelData(buff, TexWidth * TexHeight * 4);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

#define BMP_Header_Length 54



void SetupRC()
{
	glGenTextures(1, &textureID);
	glBindTexture(GL_TEXTURE_2D, textureID);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TexWidth, TexHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
	glBindTexture(GL_TEXTURE_2D, 0);

	glGenRenderbuffers(1, &renderBufferID);
	glBindRenderbuffer(GL_RENDERBUFFER, renderBufferID);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TexWidth, TexHeight);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	glGenFramebuffers(1, &frameBufferID);
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderBufferID);


	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
	if (status != GL_FRAMEBUFFER_COMPLETE)
	{
		fprintf(stderr, "GLEW Error: %s\n", "FRAME BUFFER STATUS Error!");
		return;
	}

	glEnable(GL_DEPTH_TEST);
	glEnable(GL_TEXTURE_2D);
}

void RenderScene(void)
{
	//设置渲染到纹理的视口和投影矩阵
	glViewport(0, 0, TexWidth, TexHeight);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0f, (float)(TexWidth) / TexHeight, 1.0f, 100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	//渲染到纹理
	glBindFramebuffer(GL_FRAMEBUFFER, frameBufferID);
	glClearColor(1, 1, 1, 1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glColor3f(1, 0, 1);
	glPushMatrix();
	glTranslated(0, 0.0, -10);
	glRotated(xRot, 1, 0, 0);
	glRotated(yRot, 0, 1, 0);
	glutSolidTeapot(1.0);

	// 加载图片
	glPopMatrix();

	//切换到窗口系统的帧缓冲区
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glBindTexture(GL_TEXTURE_2D, 0);
	glViewport(0, 0, windowWidth, windowHeight);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(60.0f, (float)(windowWidth) / windowHeight, 1.0f, 100.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glClearColor(0.2, 0.3, 0.4, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glTranslated(0, 0, -5);
	glRotated(cameraAngleY*0.5, 1, 0, 0);
	glRotated(cameraAngleX*0.5, 0, 1, 0);
	glColor3d(1.0, 1.0, 1.0);
	drawCube();
	glutSwapBuffers();
}


void MouseFuncCB(int button, int state, int x, int y)
{
	mouseX = x;
	mouseY = y;

	if (button == GLUT_LEFT_BUTTON)
	{
		if (state == GLUT_DOWN)
		{
			leftMouseDown = true;
		}
		else if (state == GLUT_UP)
		{
			leftMouseDown = false;
		}
	}

	if (button == GLUT_RIGHT_BUTTON)
	{
		if (state == GLUT_DOWN)
		{
		}
		else if (state == GLUT_UP)
		{
			renderToImg();
		}
	}

}


void MouseMotionFuncCB(int x, int y)
{
	if (leftMouseDown)
	{
		cameraAngleX += (x - mouseX);
		cameraAngleY += (y - mouseY);

		mouseX = x;
		mouseY = y;
	}

	glutPostRedisplay();
}


void TimerFuncCB(int value)
{
	xRot += 2;
	yRot += 3;
	glutPostRedisplay();
	glutTimerFunc(33, TimerFuncCB, 1);
}


int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
	glutInitWindowSize(TexWidth, TexHeight);
	glutCreateWindow("OpenGL");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);
	glutMouseFunc(MouseFuncCB);
	glutMotionFunc(MouseMotionFuncCB);
	glutTimerFunc(33, TimerFuncCB, 1);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
	}

	SetupRC();

	glutMainLoop();
	return 0;
}

 

 

这个是离屏渲染的图片

 

这个是窗口种

按鼠标右键 保存图片。

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值