OpenGL技术之摆脱GLUT的束缚

作者:i_dovelemon

日期:2017-03-12

来源:CSDN

主题:OpenGL, Render Context

引言

才开始学习OpenGL的同学,大部分都是通过使用GLUT来进行学习的。确实,GLUT为我们简化了很多的工作,使得我们能够专心的学习OpenGL相关的知识,而忽略和操作系统相关的操作。但是,当我们需要自己管理操作系统的相关操作的时候,GLUT的限制就出现了,所以今天,我们就来讲讲如何在不使用GLUT的情况下,在Windows上自行管理窗口,使用OpenGL进行绘制。

渲染上下文(Render Context)

OpenGL的所有调用命令都是在一个渲染上下文中进行的,而创建渲染上下文的API并不是由OpenGL标准来定义,而是由具体的操作系统平台来定义的。如果你想要使用OpenGL进行绘图的操作,你就必须要创建一个绘图上下文,然后通过对应操作系统的API将上下文中绘制的东西显示到屏幕上。

像素格式(Pixel Format)

当我们用OpenGL渲染上下文进行渲染的时候,我们需要为显示的像素指定格式,然后询问操作系统,此种格式是否被支持,如果支持就使用该格式,反之则使用与之相近的格式进行设置。

在windows平台,这个描述像素格式的结果为:PIXELFORMATDESCRIPTOR

设置像素格式

在Window平台上,绘制图像一般是通过GDI接口中的设备上下文(Device Context, DC)来进行的。所以,如果寻求像素,设置像素格式自然需要通过它来进行。

当我们创建了窗口之后,我们就能够通过GetDC(HWND)函数来获取相对应的设备上下文。后面我们只要通过如下的函数调用来询问,设置像素格式即可:

    g_DC = GetDC(g_Hwnd);

    // Set surface pixel format
    PIXELFORMATDESCRIPTOR pixel_desc;
    pixel_desc.nSize = sizeof(pixel_desc); //WORD  nSize;
    pixel_desc.nVersion = 1; //WORD  nVersion;
    pixel_desc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;//DWORD dwFlags;
    pixel_desc.iPixelType = PFD_TYPE_RGBA; //BYTE  iPixelType;
    pixel_desc.cColorBits = 32; //BYTE  cColorBits;
    pixel_desc.cRedBits = 0;//BYTE  cRedBits;
    pixel_desc.cRedShift = 0;//BYTE  cRedShift;
    pixel_desc.cGreenBits = 0;//BYTE  cGreenBits;
    pixel_desc.cGreenShift = 0;//BYTE  cGreenShift;
    pixel_desc.cBlueBits = 0;//BYTE  cBlueBits;
    pixel_desc.cBlueShift = 0;//BYTE  cBlueShift;
    pixel_desc.cAlphaBits = 0;//BYTE  cAlphaBits;
    pixel_desc.cAlphaShift = 0;//BYTE  cAlphaShift;
    pixel_desc.cAccumBits = 0;//BYTE  cAccumBits;
    pixel_desc.cAccumRedBits = 0;//BYTE  cAccumRedBits;
    pixel_desc.cAccumGreenBits = 0;//BYTE  cAccumGreenBits;
    pixel_desc.cAccumBlueBits = 0;//BYTE  cAccumBlueBits;
    pixel_desc.cAccumAlphaBits = 0;//BYTE  cAccumAlphaBits;
    pixel_desc.cDepthBits = 24;//BYTE  cDepthBits;
    pixel_desc.cStencilBits = 8;//BYTE  cStencilBits;
    pixel_desc.cAuxBuffers = 0;//BYTE  cAuxBuffers;
    pixel_desc.iLayerType = PFD_MAIN_PLANE;//BYTE  iLayerType;
    pixel_desc.bReserved = 0;//BYTE  bReserved;
    pixel_desc.dwLayerMask = 0;//DWORD dwLayerMask;
    pixel_desc.dwVisibleMask = 0;//DWORD dwVisibleMask;
    pixel_desc.dwDamageMask = 0;//DWORD dwDamageMask;

    int pixel_fmt = ChoosePixelFormat(g_DC, &pixel_desc);
    if (pixel_fmt == 0) {
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return;
    }

    if (SetPixelFormat(g_DC, pixel_fmt, &pixel_desc) == FALSE) {
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return;
    }

    int n = GetPixelFormat(g_DC);
	DescribePixelFormat(g_DC, n, sizeof(pixel_desc), &pixel_desc);

创建渲染上下文

当我们为DC指定了我们想要的像素格式之后,我们就需要通过操作系统提供的函数来创建OpenGL的渲染上下文。在Windows操作系统中,和OpenGL渲染上下文相关的函数都是以wgl开头的,这里我们需要使用的是如下三个函数:wglCreateContext, wglMakeCurrent, wglDeleteContext。

以下是如何使用这些函数的相关代码。

首先,我们需要根据DC创建渲染上下文,并将它设置为当前使用的渲染上下文,如下调用所示:

    // Create opengl render context
    g_GLRC = wglCreateContext(g_DC);
    if (g_GLRC == NULL) {
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return;
    }
    wglMakeCurrent(g_DC, g_GLRC);

当我们使用完毕渲染上下文的时候,我们就可以删除它,如下代码:

    wglMakeCurrent(g_DC, NULL);
    wglDeleteContext(g_GLRC);

渲染

当我们创建好渲染上下文,并且将它设置为当前启用的渲染上下文之后,我们就可以通过OpenGL的API调用来渲染我们需要的场景。当我们将OpenGL的渲染命令Flush了之后,我们就可以通过操作系统提供的SwapBuffers函数来将绘制的图像显示在屏幕上。

相关设置

为了能够使用wglCreateContext, wglDeleteContext, wglMakeCurrent这几个函数,我们需要链接Opengl32.lib到我们的项目中去,同时为了使用OpenGL的相关扩展,我们可以手动获取相关的函数,也可以通过GLEW库来实现。我这里通过GLEW来实现。

完整代码

以下是完整的使用该方法进行OpenGL渲染的代码:

#include <Windows.h>

#include <GL\glew.h>

//--------------------------------------------------------------------------------------
// Variables
//--------------------------------------------------------------------------------------
HWND g_Hwnd;
HDC g_DC;
HGLRC g_GLRC;

//--------------------------------------------------------------------------------------
// Function Declaration
//--------------------------------------------------------------------------------------
void opengl_init();
void opengl_run();
void opengl_destroy();

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

//--------------------------------------------------------------------------------------
// Function Definition
//--------------------------------------------------------------------------------------
int _stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPSTR cmdLine, int nShowCmd) {
    // Register window class
    WNDCLASSEX wnd;
    wnd.cbClsExtra = 0;
    wnd.cbSize = sizeof(wnd);
    wnd.cbWndExtra = NULL;
    wnd.hbrBackground = HBRUSH(COLOR_WINDOW + 1);
    wnd.hCursor = LoadCursor(NULL, IDC_ARROW);
    wnd.hIcon = NULL;
    wnd.hIconSm = NULL;
    wnd.hInstance = hInstance;
    wnd.lpfnWndProc = WndProc;
    wnd.lpszClassName = L"OpenGLRC";
    wnd.lpszMenuName = NULL;
    wnd.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClassEx(&wnd)) {
        MessageBox(NULL, NULL, L"Fuck you", MB_OK);
        return -1;
    }

    // Create window
    RECT client_rect = {0, 0, 800, 600};
    AdjustWindowRect(&client_rect, WS_OVERLAPPEDWINDOW, FALSE);
    g_Hwnd = CreateWindowEx(0, L"OpenGLRC", L"OpenGL", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT
        , client_rect.right - client_rect.left, client_rect.bottom - client_rect.top, NULL, NULL, hInstance, NULL);
    if (g_Hwnd == NULL) {
        int err = GetLastError();
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return -1;
    }

    ShowWindow(g_Hwnd, nShowCmd);

    opengl_init();

    // Message loop
    MSG msg = {0};
    while (msg.message != WM_QUIT) {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        } else {
            opengl_run();
        }
    }

    opengl_destroy();

    return 0;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_DESTROY:
        PostQuitMessage(0);
        break;

    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }

    return 0;
}

void opengl_init() {
    g_DC = GetDC(g_Hwnd);

    // Set surface pixel format
    PIXELFORMATDESCRIPTOR pixel_desc;
    pixel_desc.nSize = sizeof(pixel_desc); //WORD  nSize;
    pixel_desc.nVersion = 1; //WORD  nVersion;
    pixel_desc.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;//DWORD dwFlags;
    pixel_desc.iPixelType = PFD_TYPE_RGBA; //BYTE  iPixelType;
    pixel_desc.cColorBits = 32; //BYTE  cColorBits;
    pixel_desc.cRedBits = 0;//BYTE  cRedBits;
    pixel_desc.cRedShift = 0;//BYTE  cRedShift;
    pixel_desc.cGreenBits = 0;//BYTE  cGreenBits;
    pixel_desc.cGreenShift = 0;//BYTE  cGreenShift;
    pixel_desc.cBlueBits = 0;//BYTE  cBlueBits;
    pixel_desc.cBlueShift = 0;//BYTE  cBlueShift;
    pixel_desc.cAlphaBits = 0;//BYTE  cAlphaBits;
    pixel_desc.cAlphaShift = 0;//BYTE  cAlphaShift;
    pixel_desc.cAccumBits = 0;//BYTE  cAccumBits;
    pixel_desc.cAccumRedBits = 0;//BYTE  cAccumRedBits;
    pixel_desc.cAccumGreenBits = 0;//BYTE  cAccumGreenBits;
    pixel_desc.cAccumBlueBits = 0;//BYTE  cAccumBlueBits;
    pixel_desc.cAccumAlphaBits = 0;//BYTE  cAccumAlphaBits;
    pixel_desc.cDepthBits = 24;//BYTE  cDepthBits;
    pixel_desc.cStencilBits = 8;//BYTE  cStencilBits;
    pixel_desc.cAuxBuffers = 0;//BYTE  cAuxBuffers;
    pixel_desc.iLayerType = PFD_MAIN_PLANE;//BYTE  iLayerType;
    pixel_desc.bReserved = 0;//BYTE  bReserved;
    pixel_desc.dwLayerMask = 0;//DWORD dwLayerMask;
    pixel_desc.dwVisibleMask = 0;//DWORD dwVisibleMask;
    pixel_desc.dwDamageMask = 0;//DWORD dwDamageMask;

    int pixel_fmt = ChoosePixelFormat(g_DC, &pixel_desc);
    if (pixel_fmt == 0) {
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return;
    }

    if (SetPixelFormat(g_DC, pixel_fmt, &pixel_desc) == FALSE) {
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return;
    }

    int n = GetPixelFormat(g_DC);
	DescribePixelFormat(g_DC, n, sizeof(pixel_desc), &pixel_desc);

    // Create opengl render context
    g_GLRC = wglCreateContext(g_DC);
    if (g_GLRC == NULL) {
        MessageBox(NULL, NULL, L"Error", MB_OK);
        return;
    }
    wglMakeCurrent(g_DC, g_GLRC);

    // Init glew
    glewInit();
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
}

void opengl_run() {
    GLfloat clear_c[4] = {rand() % 100 / 100.0f, rand() % 100 / 100.0f
    ,rand() % 100 / 100.0f, 1.0f};
    glClearColor(clear_c[0], clear_c[1], clear_c[2], 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    glFlush();
    SwapBuffers(g_DC);
}

void opengl_destroy() {
    wglMakeCurrent(g_DC, NULL);
    wglDeleteContext(g_GLRC);
    ReleaseDC(g_Hwnd, g_DC);
}

总结

有了这个方法,我们就能够自行的管理窗口相关的操作,接下来我将根据这个方法来修改GLB代码库,以便于后面对DX11进行支持。

时间: 2024-10-16 18:40:13

OpenGL技术之摆脱GLUT的束缚的相关文章

Vin码识别(车架号识别)技术,摆脱手动录入提高工作效率

本文主题:Vin码识别(车架号识别)技术,摆脱手动录入提高工作效率 本文关键词:Vin码识别,汽车Vin码识别,车架号识别,汽车车架号识别,车代码识别,车代号识别 本文主旨:一.Vin码(车架号)在什么位置 二.什么是Vin码识别(车架号识别) 三.Vin码识别(车架号识别)产品特点 四.Vin码识别(车架号识别)技术参数 五.Vin码识别(车架号识别)应用领域 文章正文: 一.Vin码(车架号)在什么位置 1)除挂车和摩托车外,在门铰链柱.门锁柱或与门锁柱接合的门边之一的柱子上,接近于驾驶员座

OpenGL初使用,glut库安装(vs2013)

最近要开始做三维重建,需要使用opencv 和 openGL,第一次使用OpenGL,当然要从装glut库来开始. glut 库文件下载地址如下:http://download.csdn.net/detail/hyqsong/8618163 安装步奏如下: 1.将glut.h,放在vs2013安装目录的include下,新建一个GL目录(没有的话):例如我的路径是: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\GL

OpenGL常见错误之——glut.h文件的函数无法正常连接

glut.h文件的函数无法正常连接,典型的错误如下:------ 已启动生成: 项目: gears, 配置: Debug Win32 ------1>正在链接...1>GEARS.obj : error LNK2019: 无法解析的外部符号 [email protected],该符号在函数 [email protected] 中被引用1>GEARS.obj : error LNK2019: 无法解析的外部符号 [email protected],该符号在函数 [email protect

教你摆脱光盘的束缚

有时候.我们将光盘里的程序拷到U盘里或者硬盘里,由于实在是不想走到哪都带着一张光盘,或者是笔记本电脑压根儿就没有光驱. 然而,在安装光盘里程序或者安装完之后执行的时候,会提示"请放入光盘,再执行一次",假设不插入光盘,就没办法继续执行了: 遇到这样的情况,我们须要两步就能解决: 1.制作ISO镜像 插入光盘.打开软件"UltraISOPortable".选择"工具"-"制作光盘映像文件": 选择你刚刚插入的光盘.点击"

全景智慧城市VR全景行业佼佼者,VR全景

全景智慧城市VR全景行业佼佼者,VR全景,又被称为3D实景,是一种新兴的富媒体技术,其与视频,声音,图片等传统的流媒体大的区别是"可操作,可交互". 一. 360度全景市场需要随着计算机技术的飞速发展,多媒体所包含的种类也越来越多,所能表现的效果也越来越多, 而一些比较传统的表现方式也越来越无法满足大部分客户对于展示方式的要求. 在传统的表现方式中,展示的手段无非是静态的平面图片和动态的视频,也有进行三维全景进行展示的. 静态图片只能提供场景的某一角度图像,即使是广角镜头,也不能有效全

VR全景智慧城市:360全景市场需要背景及其优势~

VR元年已过,VR项目.VR创业潮转为理性,VR行业分为两个方向:硬件和内容. VR全景,又被称为3D实景,是一种新兴的富媒体技术,其与视频,声音,图片等传统的流媒体大的区别是"可操作,可交互". 一. 360度全景市场需要随着计算机技术的飞速发展,多媒体所包含的种类也越来越多,所能表现的效果也越来越多, 而一些比较传统的表现方式也越来越无法满足大部分客户对于展示方式的要求. 在传统的表现方式中,展示的手段无非是静态的平面图片和动态的视频,也有进行三维全景进行展示的. 静态图片只能提供

eclipse openGL glut运行环境配置

eclipse_opengl_glut_setting opengl一般使用vs来开发,我个人还是偏向使用eclipse,这里是eclipse使用glut的配置 首先下载glut包,包含下面5个文件: glut.dll glut.h glut.lib glut32.dll glut32.lib 这里有个下载链接:http://www.opengl.org/resources/libraries/glut/glutdlls37beta.zip 将glut.dll glut32.dll放到C:\Wi

转:openGL入门(1)

                    OpenGL入门教程 第一课: 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640*480分辨率.16色来做吗?显然是不行的. 本帖的目的是让大家放弃TC的老旧图形接口,让大家接触一些新事物. OpenGL作为当前主流的图形API之一,它在一些场合具有比DirectX更优越的特性. 1.与C语言紧密结合. OpenGL命令最初就是用C语言函

VC 6中配置OpenGL开发环境

2010,2012中配置类似 http://hi.baidu.com/yanzi52351/item/f9a600dffa4caa4ddcf9be1d VC 6中配置OpenGL开发环境 这里,我习惯使用VC 6,就使用它作为开发OpenGL应用的IDE吧. 要在Windows下学习OpenGL,首先就是要配置开发环境,我在这里详细的说明整个配置过程,希望对初学的朋友有所帮助. 第一步:下载OpenGL库 Windows环境下的GLUT下载地址:(大小约为150k) http://downloa