码迷,mamicode.com
首页 > 其他好文 > 详细

outdated: 45.Vertex Buffer Objects

时间:2016-10-22 12:05:51      阅读:299      评论:0      收藏:0      [点我收藏+]

标签:bsd   names   rarp   img   ring   uml   icm   rda   hbox   

这一节主要说的是VBO,而我的机子不支持,只好抄个代码,可怕......这是截图。

技术分享

VBO初始化时的代码,

    // Check for VBOs supported
#ifndef NO_VBOS
    g_fVBOSupported = IsExtensionSupported("GL_ARB_vertex_buffer_object");
    if (g_fVBOSupported) {
        // Get pointer
        glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
        glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
        glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
        glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB");
        // Load vertex data into the graphics card memory
        g_pMesh->BuildVBOs();
    }
#else
    g_fVBOSupported = false;
#endif // !NO_VBOS

BuildVBOs()函数,

// VBO: Vertex Buffer Objects use high-performance graphics card memory 
// instead of your standard, ram-allocated memory
void CMesh::BuildVBOs()
{
    // Generate and bind the vertex buffer
    glGenBuffersARB(1, &m_nVBOVertices);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
    // Load data
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nVertexCount * 3 * sizeof(float), 
        m_pVertices, GL_STATIC_DRAW_ARB);
    // Generate and bind the texture coordinate buffer
    glGenBuffersARB(1, &m_nVBOTexCoords);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOTexCoords);
    // Load data
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nVertexCount * 2 * sizeof(float),
        m_pTexCoords, GL_STATIC_DRAW_ARB);

    delete[] m_pVertices;
    m_pVertices = NULL;
    delete[] m_pTexCoords;
    m_pTexCoords = NULL;
}

下面为代码,顺便改了下方向键,W/S/A/D/UP/DOWN/LEFT/RIGHT。

技术分享
#ifndef GL_FRAMEWORK_INCLUDED
#define GL_FRAMEWORK_INCLUDED

#include <windows.h>

typedef struct {                                   // Structure for keyboard stuff
    BOOL keyDown[256];
} Keys;

typedef struct {                                   // Contains information vital to applications 
    HMODULE hInstance;                             // Application Instance
    const char* className;
} Application;

typedef struct {                                   // Window creation info
    Application* application;
    char* title;
    int width;
    int height;
    int bitsPerPixel;
    BOOL isFullScreen;
} GL_WindowInit;

typedef struct {                                   // Contains information vital to a window
    Keys* keys;
    HWND hWnd;                                     // Windows handle
    HDC hDC;                                       // Device context
    HGLRC hRC;                                     // Rendering context
    GL_WindowInit init;
    BOOL isVisible;                                // Window visiable?
    DWORD lastTickCount;                           // Tick counter
} GL_Window;

void TerminateApplication(GL_Window* window);      // Terminate the application

void ToggleFullscreen(GL_Window* window);          // Toggle fullscreen / Windowed mode

BOOL Initialize(GL_Window* window, Keys* keys);

void Deinitialize(void);

void Update(DWORD milliseconds);

void Draw(void);

#endif
Previous.h
技术分享
#include <Windows.h>
#include <GL\glew.h>
#include <GL\glut.h>
#include "Previous.h"

#define WM_TOGGLEFULLSCREEN (WM_USER+1)                   // Application define message for toggling 
// between fulscreen / windowed mode
static BOOL g_isProgramLooping;                           // Window creation loop, for fullscreen / windowed mode
static BOOL g_createFullScreen;                           // If true, then create window

void TerminateApplication(GL_Window* window)              // Terminate the application
{
    PostMessage(window->hWnd, WM_QUIT, 0, 0);             // Send a WM_QUIT message
    g_isProgramLooping = FALSE;                           // Stop looping of the program
}

void ToggleFullscreen(GL_Window* window)                  // Toggle fullscreen /windowed mode
{
    PostMessage(window->hWnd, WM_TOGGLEFULLSCREEN, 0, 0); // Send a WM_TOGGLEFULLSCREEN message
}

void ReshapeGL(int width, int height)                     // Reshape the window  when it‘s moved or resized
{
    glViewport(0, 0, (GLsizei)(width), (GLsizei)(height)); // Reset the current viewport
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // Calcutate the aspect ratio of the window
    gluPerspective(45.0f, (GLfloat)(width) / (GLfloat)(height), 1.0, 1000.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}

BOOL ChangeScreenResolution(int width, int height, int bitsPerPixel)     // Change the screen resolution
{
    DEVMODE dmScreenSettings;                              // Device mode
    ZeroMemory(&dmScreenSettings, sizeof(DEVMODE));        // Make sure memory is cleared
    dmScreenSettings.dmSize = sizeof(DEVMODE);             // Size of the devmode structure
    dmScreenSettings.dmPelsWidth = width;
    dmScreenSettings.dmPelsHeight = height;
    dmScreenSettings.dmBitsPerPel = bitsPerPixel;
    dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
    if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
        return FALSE;                                      // Display change failed
    }
    return TRUE;
}

BOOL CreateWindowGL(GL_Window* window)
{
    DWORD windowStyle = WS_OVERLAPPEDWINDOW;                // Define window style
    DWORD windowExtendedStyle = WS_EX_APPWINDOW;            // Define the window‘s extended style

    PIXELFORMATDESCRIPTOR pdf = {
        sizeof(PIXELFORMATDESCRIPTOR),                      // Size of this pixel format descriptor
        1,                                                  // Version Number
        PFD_DRAW_TO_WINDOW |                                // Format must support window
        PFD_SUPPORT_OPENGL |                                // Format must support openGL
        PFD_DOUBLEBUFFER,                                   // Must support double buffering
        PFD_TYPE_RGBA,                                      // Request an RGBA format
        window->init.bitsPerPixel,                          // Select color depth
        0, 0, 0, 0, 0, 0,                                   // Color bits ignored
        0,                                                  // No alpha buffer
        0,                                                  // Shift bit ignored
        0,                                                  // No accumulation buffer
        0, 0, 0, 0,                                         // Accumulation bits ignored
        16,                                                 // 16bits Z-buffer (depth buffer)
        0,                                                  // No stencil buffer
        0,                                                  // No auxiliary buffer
        PFD_MAIN_PLANE,                                     // Main drawing layer
        0,                                                  // Reserved
        0, 0, 0                                             // Layer masks ignored
    };
    RECT windowRect = { 0, 0, window->init.width, window->init.height };   // Window coordiantes

    GLuint PixelFormat;

    if (window->init.isFullScreen == TRUE) {
        if (ChangeScreenResolution(window->init.width, window->init.height, window->init.bitsPerPixel) == FALSE)
        {
            // Fullscreen mode failed, run in windowed mode instead
            MessageBox(HWND_DESKTOP, "Mode Switch Failed.\nRuning In Windowed Mode.",
                "Error", MB_OK | MB_ICONEXCLAMATION);
            window->init.isFullScreen = FALSE;
        }
        else {
            ShowCursor(FALSE);
            windowStyle = WS_POPUP;                         // Popup window
            windowExtendedStyle |= WS_EX_TOPMOST;
        }
    }
    else {
        // Adjust window, account for window borders
        AdjustWindowRectEx(&windowRect, windowStyle, 0, windowExtendedStyle);
    }
    // Create Opengl window
    window->hWnd = CreateWindowEx(windowExtendedStyle,      // Extended style
        window->init.application->className,                // Class name
        window->init.title,                                 // Window title
        windowStyle,                                        // Window style
        0, 0,                                               // Window X,Y position
        windowRect.right - windowRect.left,                 // Window width
        windowRect.bottom - windowRect.top,                 // Window height
        HWND_DESKTOP,                                       // Desktop is window‘s parent
        0,                                                  // No menu
        window->init.application->hInstance,                // Pass the window instance
        window);

    if (window->hWnd == 0) {                                // Was window creation a success?
        return FALSE;
    }
    window->hDC = GetDC(window->hWnd);
    if (window->hDC == 0) {
        DestroyWindow(window->hWnd);
        window->hWnd = 0;
        return FALSE;
    }
    PixelFormat = ChoosePixelFormat(window->hDC, &pdf);     // Find a compatible pixel format
    if (PixelFormat == 0) {
        ReleaseDC(window->hWnd, window->hDC);               // Release device context
        window->hDC = 0;
        DestroyWindow(window->hWnd);
        window->hWnd = 0;
        return FALSE;
    }
    if (SetPixelFormat(window->hDC, PixelFormat, &pdf) == FALSE) {   // Try to set the pixel format
        ReleaseDC(window->hWnd, window->hDC);
        window->hDC = 0;
        DestroyWindow(window->hWnd);
        window->hWnd = 0;
        return FALSE;
    }
    window->hRC = wglCreateContext(window->hDC);            // Try to get a rendering context
    if (window->hRC == 0) {
        ReleaseDC(window->hWnd, window->hDC);
        window->hDC = 0;
        DestroyWindow(window->hWnd);
        window->hWnd = 0;
        return FALSE;
    }
    // Make the rendering context our current rendering context
    if (wglMakeCurrent(window->hDC, window->hRC) == FALSE) {
        wglDeleteContext(window->hRC);                      //  Delete the rendering context
        window->hRC = 0;
        ReleaseDC(window->hWnd, window->hDC);
        window->hDC = 0;
        DestroyWindow(window->hWnd);
        window->hWnd = 0;
        return FALSE;
    }
    ShowWindow(window->hWnd, SW_NORMAL);                    // Make the window visiable
    window->isVisible = TRUE;
    ReshapeGL(window->init.width, window->init.height);     // Reshape our GL window
    ZeroMemory(window->keys, sizeof(Keys));                 // Clear all keys
    window->lastTickCount = GetTickCount();
    return TRUE;
}

BOOL DestroyWindowGL(GL_Window* window)
{
    if (window->hWnd != 0) {
        if (window->hDC != 0) {
            wglMakeCurrent(window->hDC, 0);                 // Setting current active rendering context to zero
            if (window->hRC != 0) {
                wglDeleteContext(window->hRC);
                window->hRC = 0;
            }
            ReleaseDC(window->hWnd, window->hDC);
            window->hDC = 0;
        }
        DestroyWindow(window->hWnd);
        window->hWnd = 0;
    }
    if (window->init.isFullScreen) {
        ChangeDisplaySettings(NULL, 0);                     // Switch back to desktop resolution
        ShowCursor(TRUE);
    }
    return TRUE;
}

// Process window message callback
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    // Get the window context
    GL_Window* window = (GL_Window*)(GetWindowLong(hWnd, GWL_USERDATA));
    switch (uMsg) {                                         // Evaluate window message
    case WM_SYSCOMMAND:                                     // Intercept system commands
    {
        switch (wParam) {                                   // Check system calls
        case SC_SCREENSAVE:                                 // Screensaver trying to start?
        case SC_MONITORPOWER:                               // Mointer trying to enter powersave?
            return 0;                                           // Prevent form happening
        }
        break;
    }
    return 0;
    case WM_CREATE:
    {
        CREATESTRUCT* creation = (CREATESTRUCT*)(lParam);   // Store window structure pointer
        window = (GL_Window*)(creation->lpCreateParams);
        SetWindowLong(hWnd, GWL_USERDATA, (LONG)(window));
    }
    return 0;

    case WM_CLOSE:
        TerminateApplication(window);
        return 0;

    case WM_SIZE:
        switch (wParam) {
        case SIZE_MINIMIZED:                                 // Was window minimized?
            window->isVisible = FALSE;
            return 0;
        case SIZE_MAXIMIZED:
            window->isVisible = TRUE;
            ReshapeGL(LOWORD(lParam), HIWORD(lParam));
            return 0;
        case SIZE_RESTORED:
            window->isVisible = TRUE;
            ReshapeGL(LOWORD(lParam), HIWORD(lParam));
            return 0;
        }
        break;

    case WM_KEYDOWN:
        if ((wParam >= 0) && (wParam <= 255)) {
            window->keys->keyDown[wParam] = TRUE;            // Set the selected key(wParam) to true
            return 0;
        }
        break;

    case WM_KEYUP:
        if ((wParam >= 0) && (wParam <= 255)) {
            window->keys->keyDown[wParam] = FALSE;
            return 0;
        }
        break;

    case WM_TOGGLEFULLSCREEN:
        g_createFullScreen = (g_createFullScreen == TRUE) ? FALSE : TRUE;
        PostMessage(hWnd, WM_QUIT, 0, 0);
        break;
    }
    return DefWindowProc(hWnd, uMsg, wParam, lParam);        // Pass unhandle message to DefWindowProc
}

BOOL RegisterWindowClass(Application* application)
{
    WNDCLASSEX windowClass;
    ZeroMemory(&windowClass, sizeof(WNDCLASSEX));            // Make sure memory is cleared
    windowClass.cbSize = sizeof(WNDCLASSEX);                 // Size of the windowClass structure
    windowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;  // Redraws the window for any movement / resizing
    windowClass.lpfnWndProc = (WNDPROC)(WindowProc);         // WindowProc handles message
    windowClass.hInstance = application->hInstance;          // Set the instance
    windowClass.hbrBackground = (HBRUSH)(COLOR_APPWORKSPACE);// Class background brush color
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);       // Load the arrow pointer
    windowClass.lpszClassName = application->className;      // Sets the application className
    if (RegisterClassEx(&windowClass) == 0) {
        MessageBox(HWND_DESKTOP, "RegisterClassEx Failed!", "Error", MB_OK | MB_ICONEXCLAMATION);
        return FALSE;
    }
    return TRUE;
}

int WINAPI WinMain(HINSTANCE hIstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    Application application;
    GL_Window window;
    Keys keys;
    BOOL isMessagePumpActive;
    MSG msg;
    DWORD tickCount;

    application.className = "OpenGL";
    application.hInstance = hIstance;

    ZeroMemory(&window, sizeof(GL_Window));
    window.keys = &keys;                                     // Window key structure
    window.init.application = &application;                  // Window application
    window.init.title = "Resource File";                       // Window title
    window.init.width = 640;                                 // Window width
    window.init.height = 480;                                // Window height
    window.init.bitsPerPixel = 16;                           // Bits per pixel
    window.init.isFullScreen = TRUE;                         // Fullscreen? (set to TRUE)

    ZeroMemory(&keys, sizeof(Keys));
    if (MessageBox(HWND_DESKTOP, "Would You Like To Run In Fullscreen Mode?", "Start FullScreen?",
        MB_YESNO | MB_ICONQUESTION) == IDNO)
    {
        window.init.isFullScreen = FALSE;
    }
    if (RegisterWindowClass(&application) == FALSE)
    {
        MessageBox(HWND_DESKTOP, "Error Registering Window Class!", "Error", MB_OK | MB_ICONEXCLAMATION);
        return -1;
    }
    g_isProgramLooping = TRUE;
    g_createFullScreen = window.init.isFullScreen;
    while (g_isProgramLooping) {                             // Loop until WM_QUIT is received
        window.init.isFullScreen = g_createFullScreen;       // Set init param of window creation to fullscreen?
        if (CreateWindowGL(&window) == TRUE) {               // Was window creation successful?
                                                             // At this point we should have a window that is setup to render OpenGL
            if (Initialize(&window, &keys) == FALSE) {
                TerminateApplication(&window);               // Close window, this will handle the shutdown
            }
            else {
                isMessagePumpActive = TRUE;
                while (isMessagePumpActive == TRUE) {
                    // Success creating window. Check for window messages
                    if (PeekMessage(&msg, window.hWnd, 0, 0, PM_REMOVE) != 0) {
                        if (msg.message != WM_QUIT) {
                            DispatchMessage(&msg);
                        }
                        else {
                            isMessagePumpActive = FALSE;     // Terminate the message pump
                        }
                    }
                    else {
                        if (window.isVisible == FALSE) {
                            WaitMessage();                   // Application is minimized wait for a message
                        }
                        else {
                            // Process application loop
                            tickCount = GetTickCount();      // Get the tick count
                            Update(tickCount - window.lastTickCount); // Update the counter
                            window.lastTickCount = tickCount;// Set last count to current count
                            Draw();                          // Draw screen
                            SwapBuffers(window.hDC);
                        }
                    }
                }
            }
            // Application is finished
            Deinitialize();
            DestroyWindowGL(&window);
        }
        else {
            MessageBox(HWND_DESKTOP, "Error Creating OpenGL Window", "Error", MB_OK | MB_ICONEXCLAMATION);
            g_isProgramLooping = FALSE;
        }
    }
    UnregisterClass(application.className, application.hInstance);    // UnRegister window class
    return 0;
}
Previous.cpp
技术分享
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <gl/glew.h>
#include <gl/glut.h>
#include <GL/GLUAX.H>
#include <mmsystem.h>
#include "Previous.h"

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

#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 4
#endif

#define MESH_RESOLUTION 4.0f            // Pixels per vertex
#define MESH_HEIGHTSCALE 1.0f           // Mesh height scale
#define GL_ARRAY_BUFFER_ARB 0x8892      // VBO extension definitions
#define GL_STATIC_DRAW_ARB 0x88E4

typedef void (APIENTRY * PFNGLBINDBUFFERARBPROC) (GLenum target, GLuint buffer);
typedef void (APIENTRY * PFNGLDELETEBUFFERSARBPROC) (GLsizei n, const GLuint *buffers);
typedef void (APIENTRY * PFNGLGENBUFFERSARBPROC) (GLsizei n, GLuint *buffers);
typedef void (APIENTRY * PFNGLBUFFERDATAARBPROC) (GLenum target, int size, const GLvoid *data, GLenum usage);

// VBO extension function pointers
PFNGLGENBUFFERSARBPROC glGenBuffersARB = NULL;                  // VBO name generation procedure
PFNGLBINDBUFFERARBPROC glBindBufferARB = NULL;                  // VBO bind procedure
PFNGLBUFFERDATAARBPROC glBufferDataARB = NULL;                  // VBO data loading procedure
PFNGLDELETEBUFFERSARBPROC glDeleteBuffersARB = NULL;                // VBO deletion procedure

class CVert {       // Vertex
public:
    float x;
    float y;
    float z;
};

class CTexCoord {     // Texture coordinate
public:
    float u;
    float v;
};

class CMesh {
public:
    // Mesh data
    int m_nVertexCount;                // Vertex count
    CVert* m_pVertices;                // Vertex data
    CTexCoord* m_pTexCoords;           // Texture coordinate
    unsigned int m_nTextureId;         // Texture ID
    // Vertex buffer object name 
    unsigned int m_nVBOVertices;       // Vertex VBO name
    unsigned int m_nVBOTexCoords;      // Texture coordinate VBO name
    // Temporary data
    AUX_RGBImageRec* m_pTextureImage;  // Heightmap data

public:
    CMesh();
    ~CMesh();
    bool LoadHeightmap(char* szPath, float flHeightScale, float flResolution);
    float PtHeight(int nX, int nY);   // Single point height
    void BuildVBOs();     // Build function
};

bool g_fVBOSupported = false;
CMesh* g_pMesh = NULL;         // Mesh data
float g_flYRot = 0.0f;         // Rotation
float g_flXRot = 0.0f;
float DisX = 0.0f;
float DisZ = 0.0f;
int g_nFPS = 0, g_nFrames = 0;     // FPS and FPS counter
DWORD g_dwLastFPS = 0;            // Last FPS check time

GL_Window*    g_window;
Keys*        g_keys;

CMesh::CMesh()
{
    m_pTextureImage = NULL;
    m_pVertices = NULL;
    m_pTexCoords = NULL;
    m_nVertexCount = 0;
    m_nVBOVertices = m_nVBOTexCoords = m_nTextureId = 0;
}

CMesh :: ~CMesh()
{
    // Delete VBOs
    if (g_fVBOSupported) {
        unsigned int nBuffers[2] = { m_nVBOVertices, m_nVBOTexCoords };
        glDeleteBuffersARB(2, nBuffers);
    }

    if (m_pVertices) {
        delete[] m_pVertices;
    }
    m_pVertices = NULL;

    if (m_pTexCoords) {
        delete[] m_pTexCoords;
    }
    m_pTexCoords = NULL;
}

bool CMesh::LoadHeightmap(char* szPath, float flHeightScale, float flResolution)
{
    FILE* fTest = fopen(szPath, "r");
    if (!fTest) {
        return false;
    }
    fclose(fTest);
    m_pTextureImage = auxDIBImageLoad(szPath);

    // (( Terrain Width / Resolution ) * ( Terrain Length / Resolution ) * 
    // 3 Vertices in a Triangle * 2 Triangles in a Square )
    m_nVertexCount = 
        (int)(m_pTextureImage->sizeX * m_pTextureImage->sizeY * 6 / (flResolution * flResolution));
    
    m_pVertices = new CVert[m_nVertexCount];          // Vertex data
    m_pTexCoords = new CTexCoord[m_nVertexCount];     // Tex coord data

    int nX, nZ, nTri, nIndex = 0;
    float flX, flZ;

    for (nZ = 0; nZ < m_pTextureImage->sizeY; nZ += (int)flResolution) {
        for (nX = 0; nX < m_pTextureImage->sizeX; nX += (int)flResolution) {
            for (nTri = 0; nTri < 6; ++nTri) {
                flX = (float)nX + ((nTri == 1 || nTri == 2 || nTri == 5) ? flResolution : 0.0f);
                flZ = (float)nZ + ((nTri == 2 || nTri == 4 || nTri == 5) ? flResolution : 0.0f);

                // Using PtHeight to obtain the Y value
                m_pVertices[nIndex].x = flX - (m_pTextureImage->sizeX / 2);
                m_pVertices[nIndex].y = PtHeight((int)flX, (int)flZ) * flHeightScale;
                m_pVertices[nIndex].z = flZ - (m_pTextureImage->sizeY / 2);

                // Texture coordinate
                m_pTexCoords[nIndex].u = flX / m_pTextureImage->sizeX;
                m_pTexCoords[nIndex].v = flZ / m_pTextureImage->sizeY;

                nIndex++;
            }
        }
    }
    glGenTextures(1, &m_nTextureId);
    glBindTexture(GL_TEXTURE_2D, m_nTextureId);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, m_pTextureImage->sizeX, m_pTextureImage->sizeY, 0, 
        GL_RGB, GL_UNSIGNED_BYTE, m_pTextureImage->data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    if (m_pTextureImage) {
        if (m_pTextureImage->data) {
            delete[] m_pTextureImage->data;
        }
        delete[] m_pTextureImage;
    }
    return true;
}

float CMesh::PtHeight(int nX, int nY)
{
    // Calculate the position in the texture
    int nPos = ((nX % m_pTextureImage->sizeX) + 
        ((nY % m_pTextureImage->sizeY) * m_pTextureImage->sizeX)) * 3;
    float flR = (float)m_pTextureImage->data[nPos];
    float flG = (float)m_pTextureImage->data[nPos + 1];
    float flB = (float)m_pTextureImage->data[nPos + 2];
    // Calculate the height using the luminance algorithm
    return (0.229f * flR + 0.587f * flG + 0.114f * flB);
}

// VBO: Vertex Buffer Objects use high-performance graphics card memory 
// instead of your standard, ram-allocated memory
void CMesh::BuildVBOs()
{
    // Generate and bind the vertex buffer
    glGenBuffersARB(1, &m_nVBOVertices);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOVertices);
    // Load data
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nVertexCount * 3 * sizeof(float), 
        m_pVertices, GL_STATIC_DRAW_ARB);
    // Generate and bind the texture coordinate buffer
    glGenBuffersARB(1, &m_nVBOTexCoords);
    glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_nVBOTexCoords);
    // Load data
    glBufferDataARB(GL_ARRAY_BUFFER_ARB, m_nVertexCount * 2 * sizeof(float),
        m_pTexCoords, GL_STATIC_DRAW_ARB);

    delete[] m_pVertices;
    m_pVertices = NULL;
    delete[] m_pTexCoords;
    m_pTexCoords = NULL;
}

bool IsExtensionSupported(char* szTargetExtension)
{
    const unsigned char* pszExtensions = NULL;
    const unsigned char* pszStart;
    unsigned char* pszWhere;
    unsigned char* pszTerminator;
    // Extension names should not have spaces
    pszWhere = (unsigned char*)strchr(szTargetExtension,  );
    if (!pszWhere || *szTargetExtension == \0) {
        return false;
    }
    // Get extension string
    pszExtensions = glGetString(GL_EXTENSIONS);
    // Search the extensions string for an exact copy
    pszStart = pszExtensions;
    for (;;) {
        pszWhere = (unsigned char*)strstr((const char*)pszStart, szTargetExtension);
        if (!pszWhere) {
            break;
        }
        pszTerminator = pszWhere + strlen(szTargetExtension);
        if (pszWhere == pszStart || *(pszWhere - 1) ==  ) {
            if (*pszTerminator ==   || *pszTerminator == \0) {
                return true;
            }
        }
        pszStart = pszTerminator;
    }
    return false;
}

BOOL Initialize(GL_Window* window, Keys* keys)
{
    g_window = window;
    g_keys = keys;

    g_pMesh = new CMesh();
    if (!g_pMesh->LoadHeightmap("Data/terrain.bmp",
        MESH_HEIGHTSCALE, MESH_RESOLUTION))
    {
        MessageBox(NULL, "Error Loading Heightmap", "Error", MB_OK);
        return FALSE;
    }

    // Check for VBOs supported
#ifndef NO_VBOS
    g_fVBOSupported = IsExtensionSupported("GL_ARB_vertex_buffer_object");
    if (g_fVBOSupported) {
        // Get pointer
        glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
        glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
        glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
        glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB");
        // Load vertex data into the graphics card memory
        g_pMesh->BuildVBOs();
    }
#else
    g_fVBOSupported = false;
#endif // !NO_VBOS

    glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glShadeModel(GL_SMOOTH);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glEnable(GL_TEXTURE_2D);
    glColor4f(1.0f, 1.0f, 1.0f, 1.0f);

    return TRUE;
}

void Deinitialize(void)
{
    if (g_pMesh) {
        delete g_pMesh;
    }
    g_pMesh = NULL;
}

void Update(DWORD milliseconds)
{
//    g_flYRot += (float)(milliseconds) / 1000.0f * 25.0f;    // Consistantly rotate
    if (g_keys->keyDown[VK_ESCAPE] == TRUE) {
        TerminateApplication(g_window);
    }
    if (g_keys->keyDown[VK_F1] == TRUE) {
        ToggleFullscreen(g_window);
    }
    if (g_keys->keyDown[VK_UP]) {
        g_flXRot -= 0.1f;
        if (g_flXRot <= -20.0f) {
            g_flXRot = -20.0f;
        }
    }
    if (g_keys->keyDown[VK_DOWN]) {
        g_flXRot += 0.1f;
        if (g_flXRot >= 20.0f) {
            g_flXRot = 20.0f;
        }
    }

    if (g_keys->keyDown[VK_LEFT]) {
        g_flYRot -= 0.1f;
    }
    if (g_keys->keyDown[VK_RIGHT]) {
        g_flYRot += 0.1f;
    }
    if (g_keys->keyDown[W]) {
        DisZ += 0.1f;
    }
    if (g_keys->keyDown[S]) {
        DisZ -= 0.1f;
    }
    if (g_keys->keyDown[A]) {
        DisX += 0.1f;
    }
    if (g_keys->keyDown[D]) {
        DisX -= 0.1f;
    }
}

void Draw(void)
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();

    if (GetTickCount() - g_dwLastFPS >= 1000) {
        g_dwLastFPS = GetTickCount();             // Update time virable
        g_nFPS = g_nFrames;                       // Save the FPS
        g_nFrames = 0;                            // Reset the FPS counter

        char szTitle[256] = { 0 };
        sprintf(szTitle, "VBO - %d Triangles, %d FPS", 
            g_pMesh->m_nVertexCount / 3, g_nFPS);
        if (g_fVBOSupported) {
            strcat(szTitle, ", Using VBOs");
        }
        else {
            strcat(szTitle, ", Not Using VBOs");
        }
        SetWindowText(g_window->hWnd, szTitle);
    }
    g_nFrames++;

    glTranslatef(DisX, 0, DisZ);
    glTranslatef(0.0f, -220.0f, 0.0f);
    glRotatef(g_flXRot, 1.0f, 0.0f, 0.0f);
    glRotatef(g_flYRot, 0.0f, 1.0f, 0.0f);

    // Enable pointer
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Set pointer to data
    if (g_fVBOSupported) {
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_pMesh->m_nVBOVertices);
        glVertexPointer(3, GL_FLOAT, 0, (char*)NULL);
        glBindBufferARB(GL_ARRAY_BUFFER_ARB, g_pMesh->m_nVBOTexCoords);
        glTexCoordPointer(2, GL_FLOAT, 0, (char*)NULL);
    }
    else {
        glVertexPointer(3, GL_FLOAT, 0, g_pMesh->m_pVertices);
        glTexCoordPointer(2, GL_FLOAT, 0, g_pMesh->m_pTexCoords);
    }

    glDrawArrays(GL_TRIANGLES, 0, g_pMesh->m_nVertexCount);    // Render

    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
}
Main.cpp

Thanks for Nehe‘s tutorials, this is his home.

outdated: 45.Vertex Buffer Objects

标签:bsd   names   rarp   img   ring   uml   icm   rda   hbox   

原文地址:http://www.cnblogs.com/clairvoyant/p/5987031.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!