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