游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4808|回复: 0

opengl 怎样离屏(off-screen)渲染带有纹理的场景?

[复制链接]

1

主题

3

帖子

5

积分

新手上路

Rank: 1

积分
5
发表于 2006-11-17 19:23:00 | 显示全部楼层 |阅读模式
     我想把场景渲染到位图,然后保存成.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<<&quotixel 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可以直接运行.

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 22:13

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表