|
|
我想把场景渲染到位图,然后保存成.bmp或.tga的文件
由于要2048*2048大小,故而只能采用离屏渲染
下面是我参照别人的代码(没有邦定纹理),结果ok(不绑定纹理可以正常存成一幅位图)。
但是,在渲染时绑定纹理(bmp或tga格式),
纹理映射不能起作用,保存的图像和没有纹理是一样的,请问这是为什么?
应该怎么做才能把一个带有纹理映射的场景保存到位图?
请高手指点。
#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <commctrl.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <glut.h>
#include <string>
#include <gl/glaux.h>
#include <windows.h> // Header File For Windows
#include <stdio.h> // Header File For Standard Input/Output
#define BITMAP_ID 0x4D42 // the universal bitmap ID
using namespace std;
BOOL LoadBMP(TCHAR* szFileName)
{
HANDLE hFileHandle;
BITMAPINFO *pBitmapInfo = NULL;
unsigned long lInfoSize = 0;
unsigned long lBitSize = 0;
int nTextureWidth;
int nTextureHeight;
BYTE *pBitmapData;
// Open the Bitmap file
hFileHandle = CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,
NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
// Check for open failure (most likely file does not exist).
if(hFileHandle == INVALID_HANDLE_VALUE)
return FALSE;
// File is Open. Read in bitmap header information
BITMAPFILEHEADER bitmapHeader;
DWORD dwBytes;
ReadFile(hFileHandle,&bitmapHeader,sizeof(BITMAPFILEHEADER),
&dwBytes,NULL);
if(dwBytes != sizeof(BITMAPFILEHEADER))
return FALSE;
// Check format of bitmap file
if(bitmapHeader.bfType != 'MB')
return FALSE;
// Read in bitmap information structure
lInfoSize = bitmapHeader.bfOffBits - sizeof(BITMAPFILEHEADER);
pBitmapInfo = (BITMAPINFO *) new BYTE[lInfoSize];
ReadFile(hFileHandle,pBitmapInfo,lInfoSize,&dwBytes,NULL);
if(dwBytes != lInfoSize)
return FALSE;
nTextureWidth = pBitmapInfo->bmiHeader.biWidth;
nTextureHeight = pBitmapInfo->bmiHeader.biHeight;
lBitSize = pBitmapInfo->bmiHeader.biSizeImage;
if(lBitSize == 0)
lBitSize = (nTextureWidth *
pBitmapInfo->bmiHeader.biBitCount + 7) / 8 *
abs(nTextureHeight);
// Allocate space for the actual bitmap
pBitmapData = new BYTE[lBitSize];
// Read in the bitmap bits
ReadFile(hFileHandle,pBitmapData,lBitSize,&dwBytes,NULL);
if(lBitSize != dwBytes)
{
if(pBitmapData)
delete [] (BYTE *) pBitmapData;
pBitmapData = NULL;
return FALSE;
}
CloseHandle(hFileHandle);
if(pBitmapInfo != NULL)
delete [] (BYTE *)pBitmapInfo;
// This is specific to the binary format of the data read in.
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D(GL_TEXTURE_2D, 0, 3, nTextureWidth, nTextureHeight, 0,
GL_BGR_EXT, GL_UNSIGNED_BYTE, pBitmapData);
if(pBitmapData)
delete [] (BYTE *) pBitmapData;
return TRUE;
}
/*
BITMAPINFOHEADER bitmapInfoHeader; // bitmap info header
unsigned char* bitmapData; // the bitmap data
unsigned char *LoadBitmapFile(char *filename, BITMAPINFOHEADER *bitmapInfoHeader)
{
FILE *filePtr; // the file pointer
BITMAPFILEHEADER bitmapFileHeader; // bitmap file header
unsigned char *bitmapImage; // bitmap image data
int imageIdx = 0; // image index counter
unsigned char tempRGB; // swap variable
// open filename in "read binary" mode
filePtr = fopen(filename, "rb");
if (filePtr == NULL)
return NULL;
// read the bitmap file header
fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER), 1, filePtr);
// verify that this is a bitmap by checking for the universal bitmap id
if (bitmapFileHeader.bfType != BITMAP_ID)
{
fclose(filePtr);
return NULL;
}
// read the bitmap information header
fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER), 1, filePtr);
// move file pointer to beginning of bitmap data
fseek(filePtr, bitmapFileHeader.bfOffBits, SEEK_SET);
// allocate enough memory for the bitmap image data
bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
// verify memory allocation
if (!bitmapImage)
{
free(bitmapImage);
fclose(filePtr);
return NULL;
}
// read in the bitmap image data
fread(bitmapImage, 1, bitmapInfoHeader->biSizeImage, filePtr);
// make sure bitmap image data was read
if (bitmapImage == NULL)
{
fclose(filePtr);
return NULL;
}
// swap the R and B values to get RGB since the bitmap color format is in BGR
for (imageIdx = 0; imageIdx < bitmapInfoHeader->biSizeImage; imageIdx+=3)
{
tempRGB = bitmapImage[imageIdx];
bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
bitmapImage[imageIdx + 2] = tempRGB;
}
// close the file and return the bitmap image data
fclose(filePtr);
return bitmapImage;
}
*/
/*
#define EXIT {fclose(fichier); return -1;}
#define CTOI(C) (*(int*)&C)
GLuint TexNum[1];
//------------------------------------------------------------------------------
// Charge une image BMP 24 bits
//------------------------------------------------------------------------------
int LoadBMP(char *filename, int nb)
{
GLubyte *image;
GLubyte Header[0x36];
GLuint DataPos, imageSize;
GLsizei Width,Height;
int i;
// Lit le fichier et son header
FILE * fichier = fopen(filename,"rb");
if (!fichier)
return -1;
if (fread(Header,1,0x36,fichier)!=0x36)
EXIT;
if (Header[0]!='B' || Header[1]!='M')
EXIT;
if (CTOI(Header[0x1E])!=0)
EXIT;
if (CTOI(Header[0x1C])!=24)
EXIT;
// Récupère les infos de l'image
Width = CTOI(Header[0x12]);
Height = CTOI(Header[0x16]);
( CTOI(Header[0x0A]) == 0 ) ? ( DataPos=0x36 ) : ( DataPos = CTOI(Header[0x0A]) );
( CTOI(Header[0x22]) == 0 ) ? ( imageSize=Width*Height*3 ) : ( DataPos = CTOI(Header[0x22]) );
// Charge l'image
image = (GLubyte *) malloc ( imageSize );
if (fread(image,1,imageSize,fichier)!=imageSize)
{
free (image);
EXIT;
}
// Inverse R et B
for ( i = 0; i < imageSize; i += 3 )
{
int t = image;
image = image[i+2];
image[i+2] = t;
}
// Traitements de la texture par OpenGL
glPixelStorei(GL_UNPACK_ALIGNMENT,1); // Construit la texture sous forme de données
glGenTextures(nb, &TexNum[nb]); // Génère une ID pour la texture OpenGL
glBindTexture(GL_TEXTURE_2D, TexNum[nb]); // Pointe la texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_REPEAT);
// Génère la texture OpenGL en mémoire
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
fclose (fichier);
free (image);
return TexNum[nb];
}
*/
BOOL SaveBmp(HBITMAP hBitmap, string FileName)
{
HDC hDC;
//当前分辨率下每象素所占字节数
int iBits;
//位图中每象素所占字节数
WORD wBitCount;
//定义调色板大小, 位图中像素字节大小 ,位图文件大小 , 写入文件字节数
DWORD dwPaletteSize=0, dwBmBitsSize=0, dwDIBSize=0, dwWritten=0;
//位图属性结构
BITMAP Bitmap;
//位图文件头结构
BITMAPFILEHEADER bmfHdr;
//位图信息头结构
BITMAPINFOHEADER bi;
//指向位图信息头结构
LPBITMAPINFOHEADER lpbi;
//定义文件,分配内存句柄,调色板句柄
HANDLE fh, hDib, hPal,hOldPal=NULL;
//计算位图文件每个像素所占字节数
hDC = CreateDC("DISPLAY", NULL, NULL, NULL);
iBits = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);
DeleteDC(hDC);
if (iBits <= 1) wBitCount = 1;
else if (iBits <= 4) wBitCount = 4;
else if (iBits <= 8) wBitCount = 8;
else wBitCount = 24;
GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
bi.biSize = sizeof(BITMAPINFOHEADER);
bi.biWidth = Bitmap.bmWidth;
bi.biHeight = Bitmap.bmHeight;
bi.biPlanes = 1;
bi.biBitCount = wBitCount;
bi.biCompression = BI_RGB;
bi.biSizeImage = 0;
bi.biXPelsPerMeter = 0;
bi.biYPelsPerMeter = 0;
bi.biClrImportant = 0;
bi.biClrUsed = 0;
dwBmBitsSize = ((Bitmap.bmWidth * wBitCount + 31) / 32) * 4 * Bitmap.bmHeight;
//为位图内容分配内存
hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize + sizeof(BITMAPINFOHEADER));
lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
*lpbi = bi;
// 处理调色板
hPal = GetStockObject(DEFAULT_PALETTE);
if (hPal)
{
hDC = ::GetDC(NULL);
hOldPal = ::SelectPalette(hDC, (HPALETTE)hPal, FALSE);
RealizePalette(hDC);
}
// 获取该调色板下新的像素值
GetDIBits(hDC, hBitmap, 0, (UINT) Bitmap.bmHeight, (LPSTR)lpbi + sizeof(BITMAPINFOHEADER)
+dwPaletteSize, (BITMAPINFO *)lpbi, DIB_RGB_COLORS);
//恢复调色板
if (hOldPal)
{
::SelectPalette(hDC, (HPALETTE)hOldPal, TRUE);
RealizePalette(hDC);
::ReleaseDC(NULL, hDC);
}
//创建位图文件
fh = CreateFile(FileName.c_str(), GENERIC_WRITE,0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (fh == INVALID_HANDLE_VALUE) return FALSE;
// 设置位图文件头
bmfHdr.bfType = 0x4D42; // "BM"
dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize;
bmfHdr.bfSize = dwDIBSize;
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)sizeof(BITMAPINFOHEADER) + dwPaletteSize;
// 写入位图文件头
WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);
// 写入位图文件其余内容
WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);
//清除
GlobalUnlock(hDib);
GlobalFree(hDib);
CloseHandle(fh);
return TRUE;
}
void mGLRender()
{
//unsigned char* bitmapData; // the bitmap data
// bitmapData = LoadBitmapFile("test.bmp", &bitmapInfoHeader);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
glColor3f(1,0,0);
glLoadIdentity(); // Reset The View
glTranslatef(0.0f,0.0f,-5.0f);
//glRotatef(xrot,1.0f,0.0f,0.0f);
//glRotatef(yrot,0.0f,1.0f,0.0f);
//glRotatef(zrot,0.0f,0.0f,1.0f);
//glBindTexture(GL_TEXTURE_2D, texture[0]);
glClearColor(0.9f,0.9f,0.3f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
gluPerspective(30.0, 1.0, 1.0, 10.0);
glMatrixMode(GL_MODELVIEW);
gluLookAt(0, 0, -5, 0, 0, 0, 0, 1, 0);
glBegin(GL_TRIANGLES);
glColor3d(1, 0, 0);
glVertex3d(0, 1, 0);
glColor3d(0, 1, 0);
glVertex3d(-1, -1, 0);
glColor3d(0, 0, 1);
glVertex3d(1, -1, 0);
glEnd();
glFlush(); // remember to flush GL output!
}
int _tmain(int argc, _TCHAR* argv[])
{
const int WIDTH = 2048;
const int HEIGHT = 2048;
// Create a memory DC compatible with the screen
HDC hdc = CreateCompatibleDC(0);
if (hdc == 0) cout<<"Could not create memory device context";
// Create a bitmap compatible with the DC
// must use CreateDIBSection(), and this means all pixel ops must be synchronised
// using calls to GdiFlush() (see CreateDIBSection() docs)
BITMAPINFO bmi = {
{ sizeof(BITMAPINFOHEADER), WIDTH, HEIGHT, 1, 24, BI_RGB, 0, 0, 0, 0, 0 },
{ 0 }
};
DWORD *pbits; // pointer to bitmap bits
HBITMAP hbm = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, (void **) &pbits,
0, 0);
if (hbm == 0)
cout<<"Could not create bitmap";
// Select the bitmap into the DC
HGDIOBJ r = SelectObject(hdc, hbm);
if (r == 0)
cout<<"Could not select bitmap into DC";
// Choose the pixel format
PIXELFORMATDESCRIPTOR pfd = {
sizeof (PIXELFORMATDESCRIPTOR), // struct size
1, // Version number
PFD_DRAW_TO_BITMAP|
PFD_DOUBLEBUFFER|
PFD_SUPPORT_GDI|
PFD_SUPPORT_OPENGL, // use OpenGL drawing to BM
PFD_TYPE_RGBA, // RGBA pixel values
24, // color bits
0, 0, 0, // RGB bits shift sizes...
0, 0, 0, // Don't care about them
0, 0, // No alpha buffer info
0, 0, 0, 0, 0, // No accumulation buffer
16, // depth buffer bits
0, // No stencil buffer
0, // No auxiliary buffers
PFD_MAIN_PLANE, // Layer type
0, // Reserved (must be 0)
0, // No layer mask
0, // No visible mask
0 // No damage mask
};
int pfid = ChoosePixelFormat(hdc, &pfd);
if (pfid == 0)
cout<<" ixel format selection failed";
// Set the pixel format
// - must be done *after* the bitmap is selected into DC
BOOL b = SetPixelFormat(hdc, pfid, &pfd);
if (!b)
cout<<"Pixel format set failed";
// Create the OpenGL resource context (RC) and make it current to the thread
HGLRC hglrc = wglCreateContext(hdc);
if (hglrc == 0) cout<<"OpenGL resource context creation failed";
wglMakeCurrent(hdc, hglrc);
//if(LoadBitmap(NULL,"out.bmp") == NULL)
// {
// cout << "failed";
// }
// glEnable(GL_TEXTURE_2D);
if(!LoadBMP("out.bmp"))
{
cout<<"failed";
}
GLuint texture[1];
glEnable(GL_TEXTURE_2D); // Storage For One Texture ( NEW )
glGenTextures(1, &texture[0]); // Create The Texture
// Typical Texture Generation Using Data From The Bitmap
glBindTexture(GL_TEXTURE_2D, texture[0]);
//glTexImage2D(GL_TEXTURE_2D, 0, 3, WIDTH, HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, );
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
// Draw using GL - remember to sync with GdiFlush()
GdiFlush();
mGLRender();
SaveBmp(hbm,"output2.bmp");
//SwapBuffers(wglGetCurrentDC());
//::Sleep(3000);
/*
Examining the bitmap bits (pbits) at this point with a debugger will reveal
that the colored triangle has been drawn.
*/
// Clean up
wglDeleteContext(hglrc); // Delete RC
SelectObject(hdc, r); // Remove bitmap from DC
DeleteObject(hbm); // Delete bitmap
DeleteDC(hdc); // Delete DC
return 0;
}
此代码在vs2003可以直接运行.
|
|