当前位置: 首页 > 工具软件 > IBO > 使用案例 >

显示列表 VBO IBO Pbuffer 帧缓冲 获取屏幕数据

章安宜
2023-12-01

显示列表

打包所有状态到显存 不需要每次都调用那么多函数
创建显示列表

_cubeDisplay    =   1;
glNewList(_cubeDisplay,GL_COMPILE);
            renderCube();

结束指令

glEndList();

绘制

glCallList(_cubeDisplay);

一个指令完成之前的绘制命令

也可以将显示列表放在一个数组里面 unsigned char list[] = {_cubeDisplay,_maskDisplay};
绘制时候使用 glCallLists(2,GL_UNSIGNED_BYTE,list);

#include "OpenGLWindow.h"
#include <mmsystem.h>
#include "freeimage.h"
#include "CELLMath.hpp"

using namespace CELL;


struct Vertex
{
    float   x, y, z;
    float   u, v;
};

class   Sprite :public OpenGLWindow
{
public:
    GLuint      _texture1;
    GLuint      _texture2;
    GLuint      _texture3;
    GLuint      _cubeDisplay;
    GLuint      _maskDisplay;
public:
    unsigned    createTexture(int w, int h, const void* data, GLenum type)
    {
        unsigned    texId;
        glGenTextures(1, &texId);
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);


        return  texId;
    }
    /**
    *   ʹ��FreeImage����ͼƬ
    */
    unsigned    createTextureFromImage(const char* fileName)
    {
        //1 ��ȡͼƬ��ʽ
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 ����ͼƬ
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName, 0);

        FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);

        //! ��ȡ����ָ��
        FIBITMAP*   temp = dib;
        dib = FreeImage_ConvertTo32Bits(dib);
        FreeImage_Unload(temp);

        BYTE*   pixels = (BYTE*)FreeImage_GetBits(dib);
        int     width = FreeImage_GetWidth(dib);
        int     height = FreeImage_GetHeight(dib);

        for (int i = 0; i < width * height * 4; i += 4)
        {
            BYTE temp = pixels[i];
            pixels[i] = pixels[i + 2];
            pixels[i + 2] = temp;
        }

        unsigned    res = createTexture(width, height, pixels, GL_RGBA);
        FreeImage_Unload(dib);
        return      res;
    }
public:
    virtual void    onInitGL()
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glEnable(GL_TEXTURE_2D);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        _texture1 = createTextureFromImage("floor.bmp");
        _texture2 = createTextureFromImage("CrossHair.bmp");
        _texture3 = createTextureFromImage("CrossHairMask.bmp");

        _cubeDisplay    =   1;
        glNewList(_cubeDisplay,GL_COMPILE);
            renderCube();
        glEndList();

        _maskDisplay    =   2;
        glNewList(_maskDisplay,GL_COMPILE);
            renderOrth();
        glEndList();
    }
    virtual void    onShutdownGL()
    {
        glDeleteTextures(1, &_texture1);
        glDeleteTextures(1, &_texture2);
        glDeleteTextures(1, &_texture3);

        glDeleteLists(_cubeDisplay,1);
        glDeleteLists(_maskDisplay, 1);
    }

    void    renderCube()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, 0.0f, -5);

        glDisableClientState(GL_VERTEX_ARRAY);

        glDisableClientState(GL_TEXTURE_COORD_ARRAY);

        // Bind the wall texture to the wall quads
        glBindTexture(GL_TEXTURE_2D, _texture1);

        // Display a 4 long quads to represent walls
        glBegin(GL_QUADS);

        // BACK WALL ///

        glTexCoord2f(0.0f, 2.0f);	glVertex3f(-15, 1, -15);

        glTexCoord2f(0.0f, 0.0f);	glVertex3f(-15, -1, -15);

        glTexCoord2f(12.0f, 0.0f);	glVertex3f(15, -1, -15);

        glTexCoord2f(12.0f, 2.0f);	glVertex3f(15, 1, -15);

        // FRONT WALL ///

        glTexCoord2f(0.0f, 2.0f);	glVertex3f(-15, 1, 15);

        glTexCoord2f(0.0f, 0.0f);	glVertex3f(-15, -1, 15);

        glTexCoord2f(12.0f, 0.0f);	glVertex3f(15, -1, 15);

        glTexCoord2f(12.0f, 2.0f);	glVertex3f(15, 1, 15);

        // LEFT WALL ///

        glTexCoord2f(0.0f, 2.0f);	glVertex3f(-15, 1, -15);

        glTexCoord2f(0.0f, 0.0f);	glVertex3f(-15, -1, -15);

        glTexCoord2f(12.0f, 0.0f);	glVertex3f(-15, -1, 15);

        glTexCoord2f(12.0f, 2.0f);	glVertex3f(-15, 1, 15);


        // RIGHT WALL ///

        glTexCoord2f(0.0f, 2.0f);	glVertex3f(15, 1, -15);

        glTexCoord2f(0.0f, 0.0f);	glVertex3f(15, -1, -15);

        glTexCoord2f(12.0f, 0.0f);	glVertex3f(15, -1, 15);

        glTexCoord2f(12.0f, 2.0f);	glVertex3f(15, 1, 15);

        // Stop drawing the walls
        glEnd();

        // Bind this texture to the floor quad
        glBindTexture(GL_TEXTURE_2D, _texture1);

        // Display a huge quad to represent a floor
        glBegin(GL_QUADS);

        glTexCoord2f(0.0f, 16.0f);	glVertex3f(-15, -1, -15);

        glTexCoord2f(0.0f, 0.0f);	glVertex3f(-15, -1, 15);

        glTexCoord2f(16.0f, 0.0f);	glVertex3f(15, -1, 15);

        glTexCoord2f(16.0f, 16.0f);	glVertex3f(15, -1, -15);

        // Stop drawing the floor
        glEnd();

    }
    void    renderOrth()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, _width, _height, 0, -100, 100);
        Vertex  vert[] =
        {
            { 0, 0 ,            0,  0.0f, 1.0f },
            { 0, _height ,      0,  0.0f, 0.0f },
            { _width, _height , 0,  1.0f, 0.0f },
            { _width, 0 ,       0,  1.0f, 1.0f },
        };
       
        glDisable(GL_DEPTH_TEST);
        glBlendFunc(GL_DST_COLOR, GL_ZERO);
        glEnable(GL_BLEND);
        glBindTexture(GL_TEXTURE_2D, _texture3);

        glEnableClientState(GL_VERTEX_ARRAY);
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), &vert[0].x);

        glEnableClientState(GL_TEXTURE_COORD_ARRAY);
        glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), &vert[0].u);

        glDrawArrays(GL_QUADS, 0, 4);

        glBlendFunc(GL_ONE, GL_ONE);

        glBindTexture(GL_TEXTURE_2D, _texture2);
        glDrawArrays(GL_QUADS, 0, 4);

        glDisable(GL_BLEND);
        glEnable(GL_DEPTH_TEST);
    }

    virtual void render(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //renderCube();

        unsigned char list[] =   {_cubeDisplay,_maskDisplay};
    
        glCallLists(2,GL_UNSIGNED_BYTE,list);
        //glCallList(_cubeDisplay);
        //renderOrth();

        //glCallList(_maskDisplay);
    }
};



int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow)
{
    Sprite   context;

    context.main(640, 480);
    return 0;
}

VBO 顶点缓存对象

应用程序客户端 opengl是服务端
每一次都要从传递数据给显卡
直接将数据放在显卡 减少了数据从内存到显存的传递 提升了效率

创建

 glGenBuffers(1,&_vbo);  //生成vbo句柄
  glBindBuffer(GL_ARRAY_BUFFER,_vbo);  //绑定 告诉buffer是用来做什么的

传送

glBufferData(GL_ARRAY_BUFFER,sizeof(g_cubeVertices),g_cubeVertices,GL_STATIC_DRAW); //传送到显存 参数 顶点缓存类型 数据大小 数据 数据的用途
glBindBuffer(GL_ARRAY_BUFFER,0); //防止对后续的绘制影响 重置缓存

使用
绘制之前开始

 glBindBuffer(GL_ARRAY_BUFFER,_vbo);

告诉使用VBO绘制

opengl根据元素之间的内存偏移来计算下一个元素的位置 1个float 4个字节

 float* addrVertex = (float*)0;
 float* uvAddress = (float*)12;

 float* colorAddress = (float*)20;

  glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);
  glColorPointer(3, GL_FLOAT, sizeof(Vertex), colorAddress);
  glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), uvAddress);

glBufferSubData 可以用来更新数据 显示列表没这个功能

#include "OpenGLWindow.h"
#include <mmsystem.h>
#include "freeimage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")


struct Vertex
{
    float x, y, z;
    float u, v;
    float r, g, b;
}


Vertex g_cubeVertices[] =
{
    { -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
    { 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
    { 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
    { -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

    { -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
    { -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
    { 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
    { 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

    { -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
    { -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
    { 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
    { 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

    { -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
    { 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
    { 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
    { -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

    { 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
    { 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
    { 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
    { 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

    { -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
    { -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
    { -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
    { -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
};



class   VertexBufferObject :public OpenGLWindow
{
public:
    GLuint  _texture;
    GLuint  _vbo;
public:
    unsigned    createTexture(int w, int h, const void* data, GLenum type)
    {
        unsigned    texId;
        glGenTextures(1, &texId);
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);


        return  texId;
    }
    /**
    *   ʹ��FreeImage����ͼƬ
    */
    unsigned    createTextureFromImage(const char* fileName)
    {
        //1 ��ȡͼƬ��ʽ
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 ����ͼƬ
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName, 0);

        FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);

        //! ��ȡ����ָ��
        FIBITMAP*   temp = dib;
        dib = FreeImage_ConvertTo32Bits(dib);
        FreeImage_Unload(temp);

        BYTE*   pixels = (BYTE*)FreeImage_GetBits(dib);
        int     width = FreeImage_GetWidth(dib);
        int     height = FreeImage_GetHeight(dib);

        for (int i = 0; i < width * height * 4; i += 4)
        {
            BYTE temp = pixels[i];
            pixels[i] = pixels[i + 2];
            pixels[i + 2] = temp;
        }

        unsigned    res = createTexture(width, height, pixels, GL_RGBA);
        FreeImage_Unload(dib);
        return      res;
    }
public:
    virtual void    onInitGL()
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        glEnable(GL_TEXTURE_2D);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        _texture    =   createTextureFromImage("floor.bmp");


        glGenBuffers(1,&_vbo);
        glBindBuffer(GL_ARRAY_BUFFER,_vbo);
        glBufferData(GL_ARRAY_BUFFER,sizeof(g_cubeVertices),g_cubeVertices,GL_STATIC_DRAW);

        glBindBuffer(GL_ARRAY_BUFFER,0);

      
    }
    virtual void    onShutdownGL()
    {
        glDeleteBuffers(1,&_vbo);
    }

    void    renderCube()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, 0.0f, -5);
        glBindTexture(GL_TEXTURE_2D, _texture);

        
        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);

        glBindBuffer(GL_ARRAY_BUFFER,_vbo);

        //glEnable(GL_DEPTH_TEST);
        /**
        * �����ҿ����������
        */
        float* addrVertex = (float*)0;
        float* uvAddress = (float*)12;

        float* colorAddress = (float*)20;

        //--------------Ԫ�ظ���---Ԫ������---Ԫ��֮����ڴ�ƫ��---���ݵ�ַ
        //OpenGL����Ԫ��֮����ڴ�ƫ����������һ��Ԫ�ص�λ�á�
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);
        glColorPointer(3, GL_FLOAT, sizeof(Vertex), colorAddress);
        glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), uvAddress);

        glDrawArrays(GL_QUADS, 0, 24);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    }
    virtual void render(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //! ������
       renderCube();       
    }
};



int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow)
{
    VertexBufferObject   context;

    context.main(640, 480);
    return 0;
}

索引缓冲 减少重复顶点

1.创建顶点缓冲区 索引缓冲区

  glGenBuffers(1,&_vbo);
        glBindBuffer(GL_ARRAY_BUFFER,_vbo);
        glBufferData(GL_ARRAY_BUFFER,sizeof(g_cubeVertices),g_cubeVertices,GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER,0);


        glGenBuffers(1,&_ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(g_cubeIndices),g_cubeIndices,GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);

绘制之前绑定缓冲区

 glBindBuffer(GL_ARRAY_BUFFER,_vbo);
 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibo);

绘制方法修改

 float* addrVertex = (float*)12;

  float* colorAddress = (float*)0;

  glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);
   glColorPointer(3, GL_FLOAT, sizeof(Vertex), colorAddress);

    glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0);
#include "OpenGLWindow.h"
#include <mmsystem.h>
#include "freeimage.h"
#include "CELLMath.hpp"

using namespace CELL;

#pragma comment(lib,"winmm.lib")


struct Vertex
{
    float r, g, b;
    float x, y, z;
};

Vertex g_cubeVertices[] =
{
    { 1.0f,0.0f,0.0f, -1.0f,-1.0f, 1.0f }, // 0
    { 0.0f,1.0f,0.0f, 1.0f,-1.0f, 1.0f }, // 1
    { 0.0f,0.0f,1.0f, 1.0f, 1.0f, 1.0f }, // 2
    { 1.0f,1.0f,0.0f, -1.0f, 1.0f, 1.0f }, // 3
    { 1.0f,0.0f,1.0f, -1.0f,-1.0f,-1.0f }, // 4
    { 0.0f,1.0f,1.0f, -1.0f, 1.0f,-1.0f }, // 5
    { 1.0f,1.0f,1.0f, 1.0f, 1.0f,-1.0f }, // 6
    { 1.0f,0.0f,0.0f, 1.0f,-1.0f,-1.0f }, // 7
};


GLubyte g_cubeIndices[] =
{
    0, 1, 2, 3, // Quad 0
    4, 5, 6, 7, // Quad 1
    5, 3, 2, 6, // Quad 2
    4, 7, 1, 0, // Quad 3
    7, 6, 2, 1, // Quad 4
    4, 0, 3, 5 // Quad 5
};


class   IndexBufferObject :public OpenGLWindow
{
public:
    GLuint  _texture;
    GLuint  _vbo;
    GLuint  _ibo;
public:
    unsigned    createTexture(int w, int h, const void* data, GLenum type)
    {
        unsigned    texId;
        glGenTextures(1, &texId);
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);


        return  texId;
    }
    /**
    *   ʹ��FreeImage����ͼƬ
    */
    unsigned    createTextureFromImage(const char* fileName)
    {
        //1 ��ȡͼƬ��ʽ
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 ����ͼƬ
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName, 0);

        FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);

        //! ��ȡ����ָ��
        FIBITMAP*   temp = dib;
        dib = FreeImage_ConvertTo32Bits(dib);
        FreeImage_Unload(temp);

        BYTE*   pixels = (BYTE*)FreeImage_GetBits(dib);
        int     width = FreeImage_GetWidth(dib);
        int     height = FreeImage_GetHeight(dib);

        for (int i = 0; i < width * height * 4; i += 4)
        {
            BYTE temp = pixels[i];
            pixels[i] = pixels[i + 2];
            pixels[i + 2] = temp;
        }

        unsigned    res = createTexture(width, height, pixels, GL_RGBA);
        FreeImage_Unload(dib);
        return      res;
    }
public:
    virtual void    onInitGL()
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        glGenBuffers(1,&_vbo);
        glBindBuffer(GL_ARRAY_BUFFER,_vbo);
        glBufferData(GL_ARRAY_BUFFER,sizeof(g_cubeVertices),g_cubeVertices,GL_STATIC_DRAW);
        glBindBuffer(GL_ARRAY_BUFFER,0);


        glGenBuffers(1,&_ibo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibo);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER,sizeof(g_cubeIndices),g_cubeIndices,GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,0);
      
    }
    virtual void    onShutdownGL()
    {
    }

    void    renderCube()
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, 0.0f, -5);


        glBindBuffer(GL_ARRAY_BUFFER,_vbo);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,_ibo);

        glEnableClientState(GL_VERTEX_ARRAY);

        glEnableClientState(GL_COLOR_ARRAY);


        float* addrVertex = (float*)12;

        float* colorAddress = (float*)0;

        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);
        glColorPointer(3, GL_FLOAT, sizeof(Vertex), colorAddress);

        glDrawElements(GL_QUADS, 24, GL_UNSIGNED_BYTE, 0);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
    }
    virtual void render(void)
    {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        //! ������
       renderCube();       
    }
};



int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow)
{
    IndexBufferObject   context;

    context.main(640, 480);
    return 0;
}

离屏渲染

pbuffer opengl扩展 一个应用程序建立多个opengl对象
建立一个opengl对象在后台绘制

封装pbuffer类
存储数据用于后台绘制

两个opengl对象 一个主窗口 一个后台的pbuffer

wglsharelists 两个对象共享资源

窗口不显示也可以渲染 叫做离屏渲染

1.创建pbuffer
2.改变上下问 将pbuffer设置为当前对象 将主窗口渲染结果 输出到贴图
3.使用pbuffer后台的渲染结果 再对主窗口进行渲染

#include "OpenGLWindow.h"
#include <mmsystem.h>
#include "freeimage.h"
#include "CELLMath.hpp"
#include "PixelBuffer.h"

using namespace CELL;

#pragma comment(lib,"winmm.lib")


struct Vertex
{
    float x, y, z;
    float u, v;
    float r, g, b;
};

class   PBOWindow :public OpenGLWindow
{
public:
    GLuint              _texture;
    PixelBuffer         _pbuffer;
    GLuint              _dynamic;
public:
    unsigned    createTexture(int w, int h, const void* data, GLenum type)
    {
        unsigned    texId;
        glGenTextures(1, &texId);
        glBindTexture(GL_TEXTURE_2D, texId);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

        glTexImage2D(GL_TEXTURE_2D, 0, type, w, h, 0, type, GL_UNSIGNED_BYTE, data);


        return  texId;
    }
    /**
    *   ʹ��FreeImage����ͼƬ
    */
    unsigned    createTextureFromImage(const char* fileName)
    {
        //1 ��ȡͼƬ��ʽ
        FREE_IMAGE_FORMAT fifmt = FreeImage_GetFileType(fileName, 0);
        if (fifmt == FIF_UNKNOWN)
        {
            return  0;
        }
        //2 ����ͼƬ
        FIBITMAP    *dib = FreeImage_Load(fifmt, fileName, 0);

        FREE_IMAGE_COLOR_TYPE type = FreeImage_GetColorType(dib);

        //! ��ȡ����ָ��
        FIBITMAP*   temp = dib;
        dib = FreeImage_ConvertTo32Bits(dib);
        FreeImage_Unload(temp);

        BYTE*   pixels = (BYTE*)FreeImage_GetBits(dib);
        int     width = FreeImage_GetWidth(dib);
        int     height = FreeImage_GetHeight(dib);

        for (int i = 0; i < width * height * 4; i += 4)
        {
            BYTE temp = pixels[i];
            pixels[i] = pixels[i + 2];
            pixels[i + 2] = temp;
        }

        unsigned    res = createTexture(width, height, pixels, GL_RGBA);
        FreeImage_Unload(dib);
        return      res;
    }
public:
    virtual void    onInitGL()
    {
        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

        glEnable(GL_TEXTURE_2D);
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);
        _texture    =   createTextureFromImage("floor.bmp");
        _pbuffer.setup(_hWnd,_hDC,_hRC,640,480);
        glEnable(GL_TEXTURE_2D);
        _dynamic  = createTexture(_pbuffer._width, _pbuffer._height,0,GL_RGBA);

      
    }
    virtual void    onShutdownGL()
    {
    }

    void    renderCube(GLuint tex,bool rot)
    {
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluPerspective(45.0f, double(_width) / double(_height), 0.1f, 100.0f);

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
        glTranslatef(0.0f, 0.0f, -5);

        static  float   angle = 0;
        if (rot)
        {
            glRotated(angle,1,1,1);
            ++angle;
        }
        glBindTexture(GL_TEXTURE_2D, tex);

        Vertex g_cubeVertices[] =
        {
            { -1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 0.0f },
            { 1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 0.0f, 0.0f },
            { 1.0f, 1.0f, 1.0f,1.0f, 1.0f,1.0f, 0.0f, 0.0f },
            { -1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 0.0f },

            { -1.0f,-1.0f,-1.0f,1.0f, 0.0f,0.0f, 1.0f, 0.0f },
            { -1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 1.0f, 0.0f },
            { 1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 0.0f },
            { 1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 0.0f },

            { -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 0.0f, 1.0f },
            { -1.0f, 1.0f, 1.0f,0.0f, 0.0f,0.0f, 0.0f, 1.0f },
            { 1.0f, 1.0f, 1.0f,1.0f, 0.0f,0.0f, 0.0f, 1.0f },
            { 1.0f, 1.0f,-1.0f,1.0f, 1.0f,0.0f, 0.0f, 1.0f },

            { -1.0f,-1.0f,-1.0f,1.0f, 1.0f,1.0f, 1.0f, 0.0f },
            { 1.0f,-1.0f,-1.0f,0.0f, 1.0f,1.0f, 1.0f, 0.0f },
            { 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 1.0f, 0.0f },
            { -1.0f,-1.0f, 1.0f,1.0f, 0.0f,1.0f, 1.0f, 0.0f },

            { 1.0f,-1.0f,-1.0f,1.0f, 0.0f,1.0f, 0.0f, 1.0f },
            { 1.0f, 1.0f,-1.0f,1.0f, 1.0f,1.0f, 0.0f, 1.0f },
            { 1.0f, 1.0f, 1.0f,0.0f, 1.0f,1.0f, 0.0f, 1.0f },
            { 1.0f,-1.0f, 1.0f,0.0f, 0.0f,1.0f, 0.0f, 1.0f },

            { -1.0f,-1.0f,-1.0f,0.0f, 0.0f,0.0f, 1.0f, 1.0f },
            { -1.0f,-1.0f, 1.0f,1.0f, 0.0f,0.0f, 1.0f, 1.0f },
            { -1.0f, 1.0f, 1.0f,1.0f, 1.0f,0.0f, 1.0f, 1.0f },
            { -1.0f, 1.0f,-1.0f,0.0f, 1.0f,0.0f, 1.0f, 1.0f }
        };

        glEnableClientState(GL_VERTEX_ARRAY);
        glEnableClientState(GL_COLOR_ARRAY);
        glEnableClientState(GL_TEXTURE_COORD_ARRAY);


        /**
        * �����ҿ����������
        */
        float* addrVertex = (float*)g_cubeVertices;
        float* uvAddress = (float*)&g_cubeVertices[0].u;

        float* colorAddress = (float*)&g_cubeVertices[0].r;

        //--------------Ԫ�ظ���---Ԫ������---Ԫ��֮����ڴ�ƫ��---���ݵ�ַ
        //OpenGL����Ԫ��֮����ڴ�ƫ����������һ��Ԫ�ص�λ�á�
        glVertexPointer(3, GL_FLOAT, sizeof(Vertex), addrVertex);
        glColorPointer(3, GL_FLOAT, sizeof(Vertex), colorAddress);
        glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), uvAddress);

        glDrawArrays(GL_QUADS, 0, 24);

        glDisableClientState(GL_VERTEX_ARRAY);
        glDisableClientState(GL_COLOR_ARRAY);
    }
    virtual void render(void)
    {
        _pbuffer.makeCurrent();
       
        
        //glEnable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glEnable(GL_DEPTH_TEST);
        renderCube(_texture,true);
        glBindTexture(GL_TEXTURE_2D, _dynamic);
        glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, _pbuffer._width, _pbuffer._height);
       
        makeCurrent();
        //glEnable(GL_DEPTH_TEST);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//         //! ������
        renderCube(_dynamic,false);
    }
};


int WINAPI WinMain(HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR     lpCmdLine,
    int       nCmdShow)
{
    PBOWindow   context;

    context.main(640, 480);
    return 0;
}

FBO 帧缓冲对象 另外一种离屏渲染方式 比pbuffer要好 pbuffer需要两个opengl对象 交替当前对象
FBO 缓存一帧的对象

建立 FrameBuffer

 glGenFramebuffers(1, &_FBOID);  //产生一个对象 不分配空间
 glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);   

 glGenRenderbuffers(1, &_RBOID);
 glBindRenderbuffer(GL_RENDERBUFFER, _RBOID);
 glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);

 glBindRenderbuffer(GL_RENDERBUFFER, 0);
 //关联 只有深度没有颜色 
 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _RBOID);

//颜色使用纹理

  void    begin(GLuint textureId)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, _FBOID);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
        glFramebufferRenderbuffer( GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, _RBOID );

    }

virtual void render(void)
{
_fbo.begin(_textureId);

glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderCube(_texture);
_fbo.end();

}

上面操作都是在fbo进行 看不到渲染的结果
结果缓存在纹理
切换渲染到主窗口

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glEnable(GL_DEPTH_TEST);
 renderCube(_textureId,false);

跟pbuffer相比 占用内存更小 不保存状态 不需要创建另一个对象

读取屏幕数据 pbuffer或者fbo

glReadPixels

 RECT    rect;
 GetClientRect(_hWnd,&rect);
 int     w   =   rect.right - rect.left;
 int     h   =   rect.bottom - rect.top;
 unsigned char*   data=   new unsigned char[w * h * 4];
 memset(data,0,w * h * 4);
  glReadPixels(0,0,w,h,GL_RGBA,GL_UNSIGNED_BYTE,data);
 类似资料: