Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在没有库的情况下初始化OpenGL_C++_Opengl_Game Engine - Fatal编程技术网

C++ 在没有库的情况下初始化OpenGL

C++ 在没有库的情况下初始化OpenGL,c++,opengl,game-engine,C++,Opengl,Game Engine,我在网上找到的每一个教程都使用SDL或GLADE或其他库来初始化OpenGL。有没有一种不用额外库(如DirectX)初始化OpenGL的方法 原因是,我正在构建一个游戏引擎,我希望尽可能减少外部库,并能够处理更多错误消息。初始化OpenGL因操作系统而异,这就是为什么人们制作这些库来简化其他开发人员的工作 一些教程将帮助您 适用于Windows(WGL) 适用于Linux(GLX) 关于这样做,没有多少高质量的信息。我发现用户在github上有一段很棒的代码,名为windows\u

我在网上找到的每一个教程都使用SDL或GLADE或其他库来初始化OpenGL。有没有一种不用额外库(如DirectX)初始化OpenGL的方法


原因是,我正在构建一个游戏引擎,我希望尽可能减少外部库,并能够处理更多错误消息。

初始化OpenGL因操作系统而异,这就是为什么人们制作这些库来简化其他开发人员的工作

一些教程将帮助您

适用于Windows(WGL)

适用于Linux(GLX)


关于这样做,没有多少高质量的信息。我发现用户在github上有一段很棒的代码,名为
windows\u modern\u opengl\u context.c
。我想我会在这里分享,让别人更容易找到。如果您链接
-lopengl32
,并确保有
-mwindows
标记,它应该可以用现代c编译器编译。我使用的是
gcc-std=c11
。如果您想使用C++,则在初始化结构时,可能需要编辑代码以不使用指定的初始化器。我不确定

编辑:

此代码使用带有现代opengl上下文(版本3.3)的win32 api创建一个空窗口。您仍然需要加载适当的gl扩展以调用函数,例如
glCreateShader(…)我建议使用来执行此操作。如果像我说的那样使用glad,那么应该使用
gladLoadGL()
而不是
gladloadgloader()
来加载扩展

// Sample code showing how to create a modern OpenGL window and rendering context on Win32.

#include <windows.h>
#include <gl/gl.h>
#include <stdbool.h>

typedef HGLRC WINAPI wglCreateContextAttribsARB_type(HDC hdc, HGLRC hShareContext, const int *attribList);

wglCreateContextAttribsARB_type *wglCreateContextAttribsARB;

// See https://www.opengl.org/registry/specs/ARB/wgl_create_context.txt for all values
#define WGL_CONTEXT_MAJOR_VERSION_ARB             0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB             0x2092
#define WGL_CONTEXT_PROFILE_MASK_ARB              0x9126

#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB          0x00000001

typedef BOOL WINAPI wglChoosePixelFormatARB_type(HDC hdc, const int *piAttribIList, const FLOAT *pfAttribFList, UINT nMaxFormats, int *piFormats, UINT *nNumFormats);

wglChoosePixelFormatARB_type *wglChoosePixelFormatARB;

// See https://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt for all values
#define WGL_DRAW_TO_WINDOW_ARB                    0x2001
#define WGL_ACCELERATION_ARB                      0x2003
#define WGL_SUPPORT_OPENGL_ARB                    0x2010
#define WGL_DOUBLE_BUFFER_ARB                     0x2011
#define WGL_PIXEL_TYPE_ARB                        0x2013
#define WGL_COLOR_BITS_ARB                        0x2014
#define WGL_DEPTH_BITS_ARB                        0x2022
#define WGL_STENCIL_BITS_ARB                      0x2023

#define WGL_FULL_ACCELERATION_ARB                 0x2027
#define WGL_TYPE_RGBA_ARB                         0x202B

static void
fatal_error(char *msg)
{
    MessageBoxA(NULL, msg, "Error", MB_OK | MB_ICONEXCLAMATION);
    exit(EXIT_FAILURE);
}

static void
init_opengl_extensions(void)
{
    // Before we can load extensions, we need a dummy OpenGL context, created using a dummy window.
    // We use a dummy window because you can only set the pixel format for a window once. For the
    // real window, we want to use wglChoosePixelFormatARB (so we can potentially specify options
    // that aren't available in PIXELFORMATDESCRIPTOR), but we can't load and use that before we
// have a context.
    WNDCLASSA window_class = {
        .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
        .lpfnWndProc = DefWindowProcA,
        .hInstance = GetModuleHandle(0),
        .lpszClassName = "Dummy_WGL_djuasiodwa",
    };

    if (!RegisterClassA(&window_class)) {
        fatal_error("Failed to register dummy OpenGL window.");
    }

    HWND dummy_window = CreateWindowExA(
        0,
        window_class.lpszClassName,
        "Dummy OpenGL Window",
        0,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        0,
        0,
        window_class.hInstance,
        0);

    if (!dummy_window) {
        fatal_error("Failed to create dummy OpenGL window.");
    }

    HDC dummy_dc = GetDC(dummy_window);

    PIXELFORMATDESCRIPTOR pfd = {
        .nSize = sizeof(pfd),
        .nVersion = 1,
        .iPixelType = PFD_TYPE_RGBA,
        .dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
        .cColorBits = 32,
        .cAlphaBits = 8,
        .iLayerType = PFD_MAIN_PLANE,
        .cDepthBits = 24,
        .cStencilBits = 8,
    };

    int pixel_format = ChoosePixelFormat(dummy_dc, &pfd);
    if (!pixel_format) {
        fatal_error("Failed to find a suitable pixel format.");
    }
    if (!SetPixelFormat(dummy_dc, pixel_format, &pfd)) {
        fatal_error("Failed to set the pixel format.");
    }

    HGLRC dummy_context = wglCreateContext(dummy_dc);
    if (!dummy_context) {
        fatal_error("Failed to create a dummy OpenGL rendering context.");
    }

    if (!wglMakeCurrent(dummy_dc, dummy_context)) {
        fatal_error("Failed to activate dummy OpenGL rendering context.");
    }

    wglCreateContextAttribsARB = (wglCreateContextAttribsARB_type*)wglGetProcAddress("wglCreateContextAttribsARB");
    wglChoosePixelFormatARB = (wglChoosePixelFormatARB_type*)wglGetProcAddress("wglChoosePixelFormatARB");

    wglMakeCurrent(dummy_dc, 0);
    wglDeleteContext(dummy_context);
    ReleaseDC(dummy_window, dummy_dc);
    DestroyWindow(dummy_window);
}

static HGLRC
init_opengl(HDC real_dc)
{
    init_opengl_extensions();

    // Now we can choose a pixel format the modern way, using wglChoosePixelFormatARB.
    int pixel_format_attribs[] = {
        WGL_DRAW_TO_WINDOW_ARB,     GL_TRUE,
        WGL_SUPPORT_OPENGL_ARB,     GL_TRUE,
        WGL_DOUBLE_BUFFER_ARB,      GL_TRUE,
        WGL_ACCELERATION_ARB,       WGL_FULL_ACCELERATION_ARB,
        WGL_PIXEL_TYPE_ARB,         WGL_TYPE_RGBA_ARB,
        WGL_COLOR_BITS_ARB,         32,
        WGL_DEPTH_BITS_ARB,         24,
        WGL_STENCIL_BITS_ARB,       8,
        0
    };

    int pixel_format;
    UINT num_formats;
    wglChoosePixelFormatARB(real_dc, pixel_format_attribs, 0, 1, &pixel_format, &num_formats);
    if (!num_formats) {
        fatal_error("Failed to set the OpenGL 3.3 pixel format.");
    }

    PIXELFORMATDESCRIPTOR pfd;
    DescribePixelFormat(real_dc, pixel_format, sizeof(pfd), &pfd);
    if (!SetPixelFormat(real_dc, pixel_format, &pfd)) {
        fatal_error("Failed to set the OpenGL 3.3 pixel format.");
    }

    // Specify that we want to create an OpenGL 3.3 core profile context
    int gl33_attribs[] = {
        WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
        WGL_CONTEXT_MINOR_VERSION_ARB, 3,
        WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
        0,
    };

    HGLRC gl33_context = wglCreateContextAttribsARB(real_dc, 0, gl33_attribs);
    if (!gl33_context) {
        fatal_error("Failed to create OpenGL 3.3 context.");
    }

    if (!wglMakeCurrent(real_dc, gl33_context)) {
        fatal_error("Failed to activate OpenGL 3.3 rendering context.");
    }

    return gl33_context;
}

static LRESULT CALLBACK
window_callback(HWND window, UINT msg, WPARAM wparam, LPARAM lparam)
{
    LRESULT result = 0;

    switch (msg) {
        case WM_CLOSE:
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
        default:
            result = DefWindowProcA(window, msg, wparam, lparam);
            break;
    }

    return result;
}

static HWND
create_window(HINSTANCE inst)
{
    WNDCLASSA window_class = {
        .style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC,
        .lpfnWndProc = window_callback,
        .hInstance = inst,
        .hCursor = LoadCursor(0, IDC_ARROW),
        .hbrBackground = 0,
        .lpszClassName = "WGL_fdjhsklf",
    };

    if (!RegisterClassA(&window_class)) {
        fatal_error("Failed to register window.");
    }

    // Specify a desired width and height, then adjust the rect so the window's client area will be
    // that size.
    RECT rect = {
        .right = 1024,
        .bottom = 576,
    };
    DWORD window_style = WS_OVERLAPPEDWINDOW;
    AdjustWindowRect(&rect, window_style, false);

    HWND window = CreateWindowExA(
        0,
        window_class.lpszClassName,
        "OpenGL",
        window_style,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        rect.right - rect.left,
        rect.bottom - rect.top,
        0,
        0,
        inst,
        0);

    if (!window) {
        fatal_error("Failed to create window.");
    }

    return window;
}

int WINAPI
WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmd_line, int show)
{
    HWND window = create_window(inst);
    HDC gldc = GetDC(window);
    HGLRC glrc = init_opengl(gldc);

    ShowWindow(window, show);
    UpdateWindow(window);

    bool running = true;
    while (running) {
        MSG msg;
        while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) {
            if (msg.message == WM_QUIT) {
                running = false;
            } else {
                TranslateMessage(&msg);
                DispatchMessageA(&msg);
            }
        }

        glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        // Do OpenGL rendering here

        SwapBuffers(gldc);
    }

    return 0;
}
//演示如何在Win32上创建现代OpenGL窗口和渲染上下文的示例代码。
#包括
#包括
#包括
typedef HGLRC WINAPI wglCreateContextAttribsARB_类型(HDC HDC、HGLRC hShareContext、const int*attribList);
wglCreateContextAttribsARB_type*wglCreateContextAttribsARB;
//看https://www.opengl.org/registry/specs/ARB/wgl_create_context.txt 所有价值观
#定义工作组上下文主要版本ARB 0x2091
#定义WGL_上下文_次要_版本_ARB 0x2092
#定义WGL\U上下文\U配置文件\U掩码\U ARB 0x9126
#定义WGL\U上下文\U核心\U配置文件\U位\U ARB 0x00000001
typedef BOOL WINAPI wglChoosePixelFormatARB_类型(HDC HDC、const int*piAttribIList、const FLOAT*pfAttribFList、UINT nMaxFormats、int*piFormats、UINT*nNumFormats);
wglChoosePixelFormatARB_type*wglChoosePixelFormatARB;
//看https://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt 所有价值观
#定义WGL\U绘图到\U窗口\U ARB 0x2001
#定义WGL\U加速度\U ARB 0x2003
#定义WGL\u支持\u OPENGL\u ARB 0x2010
#定义WGL双缓冲区ARB 0x2011
#定义WGL_像素_类型_ARB 0x2013
#定义WGL\U颜色\U位\U ARB 0x2014
#定义WGL\U深度\U位\U ARB 0x2022
#定义工作组模板位ARB 0x2023
#定义WGL\u全加速度\u ARB 0x2027
#定义WGL_类型_RGBA_ARB 0x202B
静态空隙
致命错误(字符*消息)
{
MessageBoxA(空,消息,“错误”,MB|U OK | MB|U图标连接);
退出(退出失败);
}
静态空隙
init_opengl_扩展(无效)
{
//在加载扩展之前,我们需要一个使用虚拟窗口创建的虚拟OpenGL上下文。
//我们使用虚拟窗口,因为您只能为一个窗口设置一次像素格式
//在实际窗口中,我们希望使用wglChoosePixelFormatARB(因此我们可以潜在地指定选项)
//这在PIXELFORMATDESCRIPTOR中不可用),但我们无法在启动之前加载并使用它
//有一个上下文。
WNDCLASSA窗口\u类={
.style=CS|HREDRAW | CS|VREDRAW | CS|OWNDC,
.lpfnWndProc=DefWindowProcA,
.hInstance=GetModuleHandle(0),
.lpszClassName=“Dummy_WGL_djuasiodwa”,
};
if(!RegisterClassA(&window_类)){
致命错误(“未能注册虚拟OpenGL窗口”);
}
HWND dummy_window=CreateWindowExA(
0,
window_class.lpszClassName,
“虚拟OpenGL窗口”,
0,
CW_使用默认值,
CW_使用默认值,
CW_使用默认值,
CW_使用默认值,
0,
0,
窗口_class.hInstance,
0);
如果(!虚拟窗口){
致命错误(“未能创建虚拟OpenGL窗口”);
}
HDC dummy_dc=GetDC(dummy_窗口);
像素格式描述符pfd={
.nSize=sizeof(pfd),
.nVersion=1,
.iPixelType=PFD\U TYPE\U RGBA,
.dwFlags=PFD_DRAW_TO_WINDOW | PFD_SUPPORT | OPENGL | PFD_DOUBLEBUFFER,
.cColorBits=32,
.cAlphaBits=8,
.iLayerType=PFD_主平面,
.cDepthBits=24,
.cStencilBits=8,
};
int-pixel\u-format=选择像素格式(虚拟像素、dc和pfd);
如果(!像素_格式){
致命的_错误(“未能找到合适的像素格式”);
}
if(!SetPixelFormat(虚拟\u dc、像素\u格式和pfd)){
致命的_错误(“设置像素格式失败”);
}
HGLRC dummy_context=wglCreateContext(dummy_dc);
if(!dummy_context){
致命错误(“未能创建虚拟OpenGL渲染上下文”);
}
如果(!wglMakeCurrent(虚拟\u dc,虚拟\u上下文)){
致命错误(“未能激活虚拟OpenGL渲染上下文”);
}
wglCreateContextAttribsARB=(wglCreateContextAttribsARB_type*)wglGetProcAddress(“wglCreateContextAttribsARB”);
wglChoosePixelFormatARB=(wglChoosePixelFormatARB_type*)wglGetProcAddress(“wglChoosePixelFormatARB”);
WglMake电流(虚拟直流,0);
wglDeleteContext(虚拟上下文);
释放dc(虚拟窗口,虚拟dc);
破坏窗口(虚拟窗口);
}
静态HGLRC
init_opengl(HDC real_dc)
{
init_opengl_扩展();
//现在,我们可以使用wglchoospexelformatarb以现代方式选择像素格式。
整数像素格式属性[]={
WGL\u DRAW\u\u TO\u WINDOW\u ARB,GL\u TRUE,
工作组支持