outdated: 32.Picking, Alpha Blending, Alpha Testing, Sorting

一个射击类的小demo。分为三个文件,Previous.h、Previous.cpp和Main.cpp。

在Previous.cpp的CreateWindowGL中新增了AdjustWindowRectEx()函数,可以根据客户端的期望大小计算窗口大小,矩形通过函数创建一个理想大小的窗口。

ChoosePixelFormat()函数试图匹配一个最接近的像素格式通过上下文给的像素格式规格。

在Mian.cpp文件的Selection()函数中,glGetIntegerv()函数返回一个选定后的参数的值。glSelectBuffer()函数建立了选择缓存模式值的缓冲区。glRenderMode()函数设置光栅化模型。gluPickMatrix()函数创建一个矩阵放大在鼠标处的部分。

下面为代码,

#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);

void Selection(void);

extern int mouse_x;
extern int mouse_y;

#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

int mouse_x, mouse_y;                                     // The current position of the mouse

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, 100.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

    ShowCursor(FALSE);
    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 {
            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 DestoryWindowGL(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;

    case WM_LBUTTONDOWN:
    {
        mouse_x = LOWORD(lParam);
        mouse_y = HIWORD(lParam);
        Selection();
    }
    break;

    case WM_MOUSEMOVE:
    {
        mouse_x = LOWORD(lParam);
        mouse_y = HIWORD(lParam);
    }
    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 = "Picking";                           // 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();
            DestoryWindowGL(&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 <math.h>
#include <stdio.h>
#include <stdarg.h>
#include <gl/glew.h>
#include <GL\glut.h>
#include <time.h>
#include "Previous.h"

#pragma comment( lib, "winmm.lib" )                                // Search for winMM library while linking
#pragma comment(lib, "legacy_stdio_definitions.lib")

#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 4
#endif

void DrawTargets();

GL_Window* g_window;
Keys* g_keys;

GLuint base;                                                 // Front display list
GLuint roll;                                                 // Rolling clouds
GLint level = 1;                                             // Current level
GLint miss;                                                  // Missed Targets
GLint kills;                                                 // Level kill counter
GLint score;                                                 // Current score
bool game;                                                   // Game over?

typedef int(*compfn)(const void*, const void*);              // Typedef for compare function

struct objects {
    GLuint rot;                                              // Rotation
    bool hit;                                                // Object hit
    GLuint frame;                                             // Current explosion fram
    GLuint dir;                                              // Object Direction
    GLuint texid;                                            // Texture ID
    GLfloat x;                                               // Object X position
    GLfloat y;                                               // Object Y position
    GLfloat spin;                                            // Object spin
    GLfloat distance;                                        // Object distance
};

typedef struct {
    GLubyte* imageData;
    GLuint bpp;                                              // Image color depth in bits per pixel
    GLuint width;
    GLuint height;
    GLuint texID;
} TextureImage;

TextureImage textures[10];

objects object[30];

struct dimension {
    GLfloat w;                                                  // Width
    GLfloat h;                                                  // Height
};

// Size of each object : Blueface,      Bucket,       Targets,       Coke,          Vase
dimension size[5] = { {1.0f, 1.0f},{ 1.0f, 1.0f },{ 1.0f, 1.0f },{0.5f, 1.0f}, {0.75f, 1.5f} };

bool LoadTGA(TextureImage* texture, char* filename)
{
    GLubyte TGAheader[12] = { 0,0,2,0,0,0,0,0,0,0,0,0 };// Uncompressed TGA header
    GLubyte TGAcompare[12];                             // Used to compare TGA header
    GLubyte header[6];                                  // First 6 useful bytes from the header
    GLuint bytesPerPixel;                               // Holds number of bytes per pixel used in the TGA file
    GLuint imageSize;                                    // Used to store the image size when setting aside ram
    GLuint temp;                                        // Temporary variable
    GLuint type = GL_RGBA;                              // Set the default GL mode to RGBA (32 bpp)

    FILE* file = fopen(filename, "rb");
    if (file == NULL || fread(TGAcompare, 1, sizeof(TGAcompare), file) != sizeof(TGAcompare) ||
        memcmp(TGAheader, TGAcompare, sizeof(TGAheader)) != 0 ||
        fread(header, 1, sizeof(header), file) != sizeof(header))
    {
        if (file == NULL) {
            return FALSE;
        }
        else {
            fclose(file);
            return FALSE;
        }
    }

    texture->width = header[1] * 256 + header[0];
    texture->height = header[3] * 256 + header[2];

    if (texture->width <= 0 || texture->height <= 0 || (header[4] != 24 && header[4] != 32)) {
        fclose(file);
        return FALSE;
    }
    texture->bpp = header[4];
    bytesPerPixel = texture->bpp / 8;
    imageSize = texture->width * texture->height * bytesPerPixel;
    texture->imageData = (GLubyte*)malloc(imageSize);

    if (texture->imageData == NULL || fread(texture->imageData, 1, imageSize, file) != imageSize) {
        if (texture->imageData != NULL) {
            free(texture->imageData);
        }
        fclose(file);
        return  FALSE;
    }
    for (GLuint i = 0; i < int(imageSize); i += bytesPerPixel) {
        temp = texture->imageData[i];
        texture->imageData[i] = texture->imageData[i + 2];
        texture->imageData[i + 2] = temp;
    }
    fclose(file);
    glGenTextures(1, &texture[0].texID);

    glBindTexture(GL_TEXTURE_2D, texture[0].texID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    if (texture[0].bpp == 24) {
        type = GL_RGB;
    }
    glTexImage2D(GL_TEXTURE_2D, 0, type, texture[0].width, texture[0].height, 0, type,
        GL_UNSIGNED_BYTE, texture[0].imageData);
    return true;
}

GLvoid BuildFont(GLvoid)
{
    base = glGenLists(95);
    glBindTexture(GL_TEXTURE_2D, textures[9].texID);
    for (int loop = 0; loop < 95; ++loop) {
        float cx = float(loop % 16) / 16.0f;
        float cy = float(loop / 16) / 8.0f;

        glNewList(base + loop, GL_COMPILE);
            glBegin(GL_QUADS);
                glTexCoord2f(cx, 1.0f - cy - 0.120f);
                glVertex2i(0, 0);
                glTexCoord2f(cx + 0.0625f, 1.0f - cy - 0.120f);
                glVertex2i(16, 0);
                glTexCoord2f(cx + 0.0625f, 1.0f - cy);
                glVertex2i(16, 16);
                glTexCoord2f(cx, 1.0f - cy); glVertex2i(0, 16);
            glEnd();
            glTranslated(10, 0, 0);
        glEndList();
    }
}

GLvoid glPrint(GLint x, GLint y, const char *string, ...)
{
    char text[256];
    va_list    ap;                                              // Pointer to list of arguments

    if (string == NULL) {
        return;
    }

    va_start(ap, string);                                    // Parses the string for variables
    vsprintf(text, string, ap);                              // And converts symbols to actual numbers
    va_end(ap);                                              // Results are stored in text

    glBindTexture(GL_TEXTURE_2D, textures[9].texID);
    glPushMatrix();
    glLoadIdentity();
    glTranslated(x, y, 0);
    glListBase(base - 32);
    glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);       // Draws the display list text
    glPopMatrix();
}

int Compare(struct objects* elem1, struct objects* elem2)
{
    if (elem1->distance < elem2->distance) {
        return -1;
    }
    else if (elem1->distance > elem2->distance) {
        return 1;
    }
    else {
        return 0;
    }
}

GLvoid InitObject(int num)
{
    object[num].rot = 1;                                     // Clockwise rotation
    object[num].frame = 0;                                    // Reset the explosion fram
    object[num].hit = FALSE;                                 // Reset object hit status
    object[num].texid = rand() % 5;
    object[num].distance = -(float(rand() % 4001) / 100.0f);
    object[num].y = -1.5f + (float(rand() % 451) / 100.0f);
    object[num].x = ((object[num].distance - 15.0f) / 2.0f) - (5 * level) - float(rand() % (5 * level));
    object[num].dir = (rand() % 2);

    if (object[num].dir == 0) {
        object[num].rot = 2;
        object[num].x = -object[num].x;
    }
    if (object[num].texid == 0) {                            // Blue face
        object[num].y = -2.0f;
    }
    if (object[num].texid == 1) {                            // Bucket
        object[num].dir = 3;
        object[num].x = float(rand() % int(object[num].distance - 10.0f)) +
            ((object[num].distance - 10.0f) / 2.0f);
        object[num].y = 4.5f;
    }
    if (object[num].texid == 2) {                            // Target
        object[num].dir = 2;
        object[num].x = float(rand() % int(object[num].distance - 10.0f)) +
            ((object[num].distance - 10.0f) / 2.0f);
        object[num].y = -3.0f - float(rand() % (5 * level));
    }
    qsort((void*)&object, level, sizeof(struct objects), (compfn)Compare);
}

BOOL Initialize(GL_Window* window, Keys* keys)
{
    g_window = window;
    g_keys = keys;
    srand((unsigned)time(NULL));
    if ((!LoadTGA(&textures[0], "Data/BlueFace.tga")) ||     // Load the blueface texture
        (!LoadTGA(&textures[1], "Data/Bucket.tga")) ||       // Load the bucket texture
        (!LoadTGA(&textures[2], "Data/Target.tga")) ||       // Load the target Texture
        (!LoadTGA(&textures[3], "Data/Coke.tga")) ||         // Load the coke texture
        (!LoadTGA(&textures[4], "Data/Vase.tga")) ||         // Load the vase texture
        (!LoadTGA(&textures[5], "Data/Explode.tga")) ||      // Load the explosion texture
        (!LoadTGA(&textures[6], "Data/Ground.tga")) ||       // Load the ground texture
        (!LoadTGA(&textures[7], "Data/Sky.tga")) ||          // Load the sky texture
        (!LoadTGA(&textures[8], "Data/Crosshair.tga")) ||    // Load the crosshair texture
        (!LoadTGA(&textures[9], "Data/Font.tga")))           // Load the crosshair texture
    {
        return FALSE;
    }
    BuildFont();
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClearDepth(1.0f);
    glDepthFunc(GL_LEQUAL);
    glEnable(GL_DEPTH_TEST);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);       // Enable alpha blending
    glEnable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_CULL_FACE);

    for (int loop = 0; loop < 30; ++loop) {
        InitObject(loop);
    }
    return TRUE;
}

void Deinitialize(void)
{
    glDeleteLists(base, 95);
}

void Selection(void)
{
    GLuint buffer[512];                                      // Set up a selection buffer
    GLint hits;                                              // The number of objects that we selected

    if (game) {
        return;
    }
    PlaySound("data/shot.wav", NULL, SND_ASYNC);
    GLint viewport[4];                                       // x, y, length, width

    // This sets the array <viewport> to the size and location of the screen relative to the window
    glGetIntegerv(GL_VIEWPORT, viewport);
    glSelectBuffer(512, buffer);                             // Tell opengl to use our array for selection

    // Puts opengl in selection mode. Nothing will be draw. Object ID‘s and extents are stored in the buffer
    (void)glRenderMode(GL_SELECT);
    glInitNames();                                           // Name stack
    glPushName(0);

    glMatrixMode(GL_PROJECTION);                             // Selects the projection matrix
    glPushMatrix();
    glLoadIdentity();

    // This create a matrix that will zoom up to a small portion of the screen, where the mouse is.
    gluPickMatrix((GLdouble)mouse_x, (GLdouble)(viewport[3] - mouse_y), 1.0f, 1.0f, viewport);

    // Apply the perspective matrix
    gluPerspective(45.0f, (GLfloat)(viewport[2] - viewport[0]) / (GLfloat)(viewport[3] - viewport[1]),
        0.1f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    DrawTargets();                                           // Render the targets to the selection buffer
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    hits = glRenderMode(GL_RENDER);

    if (hits > 0) {
        int choose = buffer[3];
        int depth = buffer[1];
        for (int loop = 1; loop < hits; ++loop) {
            if (buffer[loop * 4 + 1] < GLuint(depth)) {
                choose = buffer[loop * 4 + 3];
                depth = buffer[loop * 4 + 1];
            }
        }
        if (!object[choose].hit) {
            object[choose].hit = TRUE;
            score += 1;
            kills += 1;
            if (kills > level * 5) {
                miss = 0;
                kills = 0;
                level += 1;
                if (level > 30) {
                    level = 30;
                }
            }
        }
    }
}

void Update(DWORD milliseconds)
{
    if (g_keys->keyDown[VK_ESCAPE]) {
        TerminateApplication(g_window);
    }
    if (g_keys->keyDown[‘ ‘] && game) {
        for (int loop = 0; loop < 30; ++loop) {
            InitObject(loop);
        }
        game = FALSE;
        score = 0;
        level = 1;
        kills = 0;
        miss = 0;
    }
    if (g_keys->keyDown[VK_F1]) {
        ToggleFullscreen(g_window);
    }
    roll -= milliseconds * 0.00005f;                         // Roll the clouds
    for (int loop = 0; loop < level; ++loop)
    {
        if (object[loop].rot == 1)                           // If Rotation is clockwise
            object[loop].spin -= 0.2f * (float(loop + milliseconds));    // Spin clockwise

        if (object[loop].rot == 2)                           // If rotation is counter clockwise
            object[loop].spin += 0.2f * (float(loop + milliseconds));    // Spin counter clockwise

        if (object[loop].dir == 1)                           // If direction is right
            object[loop].x += 0.012f * float(milliseconds);    // Move right

        if (object[loop].dir == 0)                           // If direction is left
            object[loop].x -= 0.012f * float(milliseconds);    // Move left

        if (object[loop].dir == 2)                           // If direction is up
            object[loop].y += 0.012f * float(milliseconds);    // Move up

        if (object[loop].dir == 3)                           // If direction isdown
            object[loop].y -= 0.0025f * float(milliseconds);   // Move down
        // If we are to far left, direction is left and the object was not hit
        if ((object[loop].x < (object[loop].distance - 15.0f) / 2.0f) && (object[loop].dir == 0) &&
            !object[loop].hit)
        {
            miss += 1;                                       // Increase miss
            object[loop].hit = TRUE;
        }

        if ((object[loop].x > -(object[loop].distance - 15.0f) / 2.0f) && (object[loop].dir == 1) &&
            !object[loop].hit)
        {
            miss += 1;
            object[loop].hit = TRUE;
        }

        if ((object[loop].y < -2.0f) && (object[loop].dir == 3) && !object[loop].hit) {
            miss += 1;
            object[loop].hit = TRUE;
        }

        if ((object[loop].y > 4.5f) && (object[loop].dir == 2)) {
            object[loop].dir = 3;
        }
    }
}

void Object(float width, float height, GLuint texid)
{
    glBindTexture(GL_TEXTURE_2D, textures[texid].texID);
    glBegin(GL_QUADS);
        glTexCoord2f(0.0f, 0.0f); glVertex3f(-width, -height, 0.0f);
        glTexCoord2f(1.0f, 0.0f); glVertex3f(width, -height, 0.0f);
        glTexCoord2f(1.0f, 1.0f); glVertex3f(width, height, 0.0f);
        glTexCoord2f(0.0f, 1.0f); glVertex3f(-width, height, 0.0f);
    glEnd();
}

void Explosion(int num)
{
    float ex = (float)((object[num].frame / 4) % 4) / 4.0f;
    float ey = (float)((object[num].frame / 4) / 4) / 4.0f;

    glBindTexture(GL_TEXTURE_2D, textures[5].texID);
    glBegin(GL_QUADS);
        glTexCoord2f(ex, 1.0f - (ey));
        glVertex3f(-1.0f, -1.0f, 0.0f);
        glTexCoord2f(ex + 0.25f, 1.0f - (ey));
        glVertex3f(1.0f, -1.0f, 0.0f);
        glTexCoord2f(ex + 0.25f, 1.0f - (ey + 0.25f));
        glVertex3f(1.0f, 1.0f, 0.0f);
        glTexCoord2f(ex, 1.0f - (ey + 0.25f));
        glVertex3f(-1.0f, 1.0f, 0.0f);
    glEnd();

    object[num].frame += 1;
    if (object[num].frame > 63)
    {
        InitObject(num);
    }
}

void DrawTargets(void)
{
    glLoadIdentity();
    glTranslatef(0.0f, 0.0f, -10.0f);
    for (int loop = 0; loop < level; ++loop) {
        glLoadName(loop);                                    // Assign object a name (ID)
        glPushMatrix();
        glTranslatef(object[loop].x, object[loop].y, object[loop].distance);
        if (object[loop].hit) {
            Explosion(loop);
        }
        else {
            glRotatef(object[loop].spin, 0.0f, 0.0f, 1.0f);
            Object(size[object[loop].texid].w, size[object[loop].texid].h, object[loop].texid);
        }
        glPopMatrix();
    }
}

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

    glPushMatrix();
    glBindTexture(GL_TEXTURE_2D, textures[7].texID);
    glBegin(GL_QUADS);
    glTexCoord2f(1.0f, roll / 1.5f + 1.0f); glVertex3f(28.0f, +7.0f, -50.0f);
    glTexCoord2f(0.0f, roll / 1.5f + 1.0f); glVertex3f(-28.0f, +7.0f, -50.0f);
    glTexCoord2f(0.0f, roll / 1.5f + 0.0f); glVertex3f(-28.0f, -3.0f, -50.0f);
    glTexCoord2f(1.0f, roll / 1.5f + 0.0f); glVertex3f(28.0f, -3.0f, -50.0f);

    glTexCoord2f(1.5f, roll + 1.0f); glVertex3f(28.0f, +7.0f, -50.0f);
    glTexCoord2f(0.5f, roll + 1.0f); glVertex3f(-28.0f, +7.0f, -50.0f);
    glTexCoord2f(0.5f, roll + 0.0f); glVertex3f(-28.0f, -3.0f, -50.0f);
    glTexCoord2f(1.5f, roll + 0.0f); glVertex3f(28.0f, -3.0f, -50.0f);

    glTexCoord2f(1.0f, roll / 1.5f + 1.0f); glVertex3f(28.0f, +7.0f, 0.0f);
    glTexCoord2f(0.0f, roll / 1.5f + 1.0f); glVertex3f(-28.0f, +7.0f, 0.0f);
    glTexCoord2f(0.0f, roll / 1.5f + 0.0f); glVertex3f(-28.0f, +7.0f, -50.0f);
    glTexCoord2f(1.0f, roll / 1.5f + 0.0f); glVertex3f(28.0f, +7.0f, -50.0f);

    glTexCoord2f(1.5f, roll + 1.0f); glVertex3f(28.0f, +7.0f, 0.0f);
    glTexCoord2f(0.5f, roll + 1.0f); glVertex3f(-28.0f, +7.0f, 0.0f);
    glTexCoord2f(0.5f, roll + 0.0f); glVertex3f(-28.0f, +7.0f, -50.0f);
    glTexCoord2f(1.5f, roll + 0.0f); glVertex3f(28.0f, +7.0f, -50.0f);
    glEnd();

    glBindTexture(GL_TEXTURE_2D, textures[6].texID);
    glBegin(GL_QUADS);
    glTexCoord2f(7.0f, 4.0f - roll); glVertex3f(27.0f, -3.0f, -50.0f);
    glTexCoord2f(0.0f, 4.0f - roll); glVertex3f(-27.0f, -3.0f, -50.0f);
    glTexCoord2f(0.0f, 0.0f - roll); glVertex3f(-27.0f, -3.0f, 0.0f);
    glTexCoord2f(7.0f, 0.0f - roll); glVertex3f(27.0f, -3.0f, 0.0f);
    glEnd();

    DrawTargets();
    glPopMatrix();

    // Crosshair (In Ortho View)
    RECT window;                                             // Storage For Window Dimensions
    GetClientRect(g_window->hWnd, &window);                  // Get Window Dimensions
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glOrtho(0, window.right, 0, window.bottom, -1, 1);
    glMatrixMode(GL_MODELVIEW);
    glTranslated(mouse_x, window.bottom - mouse_y, 0.0f);
    Object(16, 16, 8);                                       // Crosshair

    glPrint(240, 450, "Productions");
    glPrint(10, 10, "Level: %i", level);
    glPrint(250, 10, "Score: %i", score);

    if (miss > 9) {
        miss = 9;
        game = TRUE;
    }

    if (game) {
        glPrint(490, 10, "GAME OVER");
    }
    else {
        glPrint(490, 10, "Morale: %i/10", 10 - miss);
    }

    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);

    glFlush();                                               // Flush the GL rendering pipeline
}

Main.cpp

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

时间: 2024-08-11 03:38:31

outdated: 32.Picking, Alpha Blending, Alpha Testing, Sorting的相关文章

【Unity Shaders】Alpha Test和Alpha Blending

写在前面 关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到半透明问题的时候,总是不知道为什么A就遮挡了B,而B明明在A前面.这篇文章就总结一下我现在的认识~ Alpha Test和Alpha Blending是两种处理透明的方法. Alpha Test采用一种很霸道极端的机制,只要一个像素的alpha不满足条件,那么它就会被fragment shader舍弃,"我才不要你类!":否则,就会按正常方式写入到缓存中,并进行正常的深度检验等等,也就是说,Alpha Test

(转)【Unity Shaders】Alpha Test和Alpha Blending

转自:http://blog.csdn.net/candycat1992/article/details/41599167 写在前面 关于alpha的问题一直是个比较容易摸不清头脑的事情,尤其是涉及到半透明问题的时候,总是不知道为什么A就遮挡了B,而B明明在A前面.这篇文章就总结一下我现在的认识~ Alpha Test和Alpha Blending是两种处理透明的方法. Alpha Test采用一种很霸道极端的机制,只要一个像素的alpha不满足条件,那么它就会被fragment shader舍

【Unity Shader】---Alpha Blending的意义

Alpha Blending 即Alpha混合 Blending 就是处理透明度的,处理光栅化最后阶段,显示在屏幕上的颜色 1 Blend Off 关闭alpha混合 2 混合公式:Blend SrcFactor DstFactor SrcFactor 混合源系数 Shader当前计算点的颜色的混合系数 DstFactor 混合目标系数 当前点之前累积的颜色的混合系数 最终颜色 = (Shader计算出的点颜色值 * 源系数)+(点累积颜色 * 目标系数) 3 常用的混合系数 one 1(仅显示

adjacent shapes抗锯齿情况下的alpha blending问题

问题描述: Unfortunately I stumbled across the issue with adjacent shapes. On a transparent background (in the plain color space) I draw mutiple  polygons, some are connected others are not and each polygon has a  different color. The polygons do never ov

Unity3D Shader官方教程翻译(十一)----Shader语法:Pass的Blending(混合)

ShaderLab syntax: Blending 混合 Blending is used to make transparent objects. 混合是用来制作透明物体的. When graphics are rendered, after all shaders have executed and all textures have been applied, the pixels are written to the screen. How they are combined with

GDI+概述

Windows GDI+是 Windows XP 或者 Windows Server 2003操作系统的 负责显示屏幕信息和打印操作的子系统. GDI+是一组采用C++类封装的 API. GDI+可分为三部分: <1> 2-D vector graphics (2D矢量图形), 这部分主要涉及画一些基本图形,如线,曲线,图表等. 基本图形是通过在屏幕坐标中通过一系列点组成的. <2> Imaging(图片),有些图片使用矢量绘图会很困难, 因此GDI+的一些类用于绘制这些图片,这些

UnityShader快速上手指南(三)

简介 这一篇还是一些基本的shader操作:裁剪.透明和法向量的应用 (纠结了很久写不写这些,因为代码很简单,主要是些概念上的东西) 先来看下大概的效果图:(从左到右依次是裁剪,透明,加了法向量的透明) 裁剪 代码 Shader "LT/Lesson3_Cull" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) } SubShader { Pass { Cull Off CGPROGRAM #pragma

【浅墨Unity3D Shader编程】之四 热带雨林篇: 剔除、深度测试、Alpha测试以及基本雾效合辑

本系列文章由@浅墨_毛星云 出品,转载请注明出处.   文章链接:http://hpw123.net/a/C__/kongzhitaichengxu/2014/1222/163.html 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] QQ交流群:330595914 更多文章尽在:http://www.hpw123.net 本文介绍了Unity中Shader书写中会用到的剔除.深度测试.Alpha测试以及基

深度排序与alpha混合 【转】

  翻译:李现民 最后修改:2012-07-03 原文:Depth sorting alpha blended objects 先说个题外话,本来我想回答在 Creators Club论坛上的一个常见问题,但(意外的是)我竟然没能从网上找到一个令人满意的答案. 问题本身很简单,但答案却有些复杂: “为什么我的透明物体的绘制顺序是错误的,或者为什么它们的一部分不见了?” 当绘制一个3D场景的时候,将图形按深度排序非常重要,只有这样靠近摄像机的物体才能被绘制在(离摄像机)更远的物体的上面.我们不会希