19#include "OpenGLRenderer.hpp"
20#include "OpenGLBuffer.hpp"
21#include "OpenGLWindow.hpp"
22#include "OpenGLFunctions.hpp"
24#include "aeongames/Mesh.hpp"
25#include "aeongames/Pipeline.hpp"
26#include "aeongames/Material.hpp"
27#include "aeongames/Texture.hpp"
32 std::atomic<size_t> OpenGLRenderer::mRendererCount{0};
34 Display* OpenGLRenderer::mDisplay {};
39layout (location = 0) in vec2 aPos;
40layout (location = 1) in vec2 aTexCoords;
47 gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
49 TexCoords = aTexCoords;
65layout (location = 0) uniform sampler2D OverlayTexture;
69 FragColor = texture(OverlayTexture, TexCoords);
81 -1.0f, 1.0f, 0.0f, 1.0f,
82 -1.0f, -1.0f, 0.0f, 0.0f,
83 1.0f, -1.0f, 1.0f, 0.0f,
84 1.0f, 1.0f, 1.0f, 1.0f
90 static PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsString =
nullptr;
91 static PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs =
nullptr;
92 const int ContextAttribs[] =
94 WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
95 WGL_CONTEXT_MINOR_VERSION_ARB, 5,
96 WGL_CONTEXT_PROFILE_MASK_ARB,
97 WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
101 static ATOM gRendererWindowClass{0};
102 static std::atomic<size_t> mRendererCount{0};
104 static HWND CreateRendererWindow()
106 RECT rect = { 0, 0, 10, 10 };
107 if(gRendererWindowClass == 0)
110 wcex.cbSize =
sizeof ( WNDCLASSEX );
111 wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
112 wcex.lpfnWndProc = ( WNDPROC ) DefWindowProc;
115 wcex.hInstance = GetModuleHandle (
nullptr );
116 wcex.hIcon = LoadIcon (
nullptr, IDI_WINLOGO );
117 wcex.hCursor = LoadCursor (
nullptr, IDC_ARROW );
118 wcex.hbrBackground =
nullptr;
119 wcex.lpszMenuName =
nullptr;
120 wcex.lpszClassName =
"AeonEngineOpenGLInternalWindow";
121 wcex.hIconSm =
nullptr;
122 gRendererWindowClass = RegisterClassEx ( &wcex );
125 return CreateWindowEx ( WS_EX_APPWINDOW | WS_EX_WINDOWEDGE,
126 MAKEINTATOM ( gRendererWindowClass ),
"AeonEngine OpenGL Internal Window",
127 WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
129 rect.right - rect.left, rect.bottom - rect.top,
132 GetModuleHandle (
nullptr ),
135 static void DestroyRendererWindow(HWND hWnd)
137 assert(mRendererCount);
138 DestroyWindow ( hWnd );
139 if(--mRendererCount == 0)
141 UnregisterClass (
reinterpret_cast<LPCSTR
> (
142#
if defined(_M_X64) || defined(__amd64__)
145 MAKELONG ( gRendererWindowClass, 0 ) ),
nullptr );
146 gRendererWindowClass = 0;
150 mWindowId{CreateRendererWindow()},
151 mDeviceContext{GetDC(mWindowId)}
153 PIXELFORMATDESCRIPTOR pfd{};
154 pfd.nSize =
sizeof ( PIXELFORMATDESCRIPTOR );
156 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
157 pfd.iPixelType = PFD_TYPE_RGBA;
160 pfd.iLayerType = PFD_MAIN_PLANE;
161 int pf = ChoosePixelFormat ( mDeviceContext, &pfd );
162 SetPixelFormat ( mDeviceContext, pf, &pfd );
165 mOpenGLContext = wglCreateContext ( mDeviceContext );
169 if ( !wglGetExtensionsString )
171 if ( ! ( wglGetExtensionsString = ( PFNWGLGETEXTENSIONSSTRINGARBPROC ) wglGetProcAddress (
"wglGetExtensionsStringARB" ) ) )
173 wglDeleteContext (
static_cast<HGLRC
> ( mOpenGLContext ) );
174 mOpenGLContext =
nullptr;
175 ReleaseDC ( mWindowId, mDeviceContext );
176 DestroyRendererWindow ( mWindowId );
177 std::cout <<
LogLevel::Error <<
"Failed retrieving a pointer to wglGetExtensionsString" << std::endl;
178 throw std::runtime_error (
"Failed retrieving a pointer to wglGetExtensionsString" );
181 if ( !wglCreateContextAttribs )
183 if ( ! ( wglCreateContextAttribs = ( PFNWGLCREATECONTEXTATTRIBSARBPROC ) wglGetProcAddress (
"wglCreateContextAttribsARB" ) ) )
185 wglDeleteContext (
static_cast<HGLRC
> ( mOpenGLContext ) );
186 mOpenGLContext =
nullptr;
187 ReleaseDC ( mWindowId, mDeviceContext );
188 DestroyRendererWindow ( mWindowId );
189 std::cout <<
LogLevel::Error <<
"Failed retrieving a pointer to wglCreateContextAttribsARB" << std::endl;
190 throw std::runtime_error (
"Failed retrieving a pointer to wglCreateContextAttribsARB" );
193 if ( strstr ( wglGetExtensionsString ( mDeviceContext ),
"WGL_ARB_create_context" ) !=
nullptr )
195 wglDeleteContext (
static_cast<HGLRC
> ( mOpenGLContext ) );
196 if ( ! ( mOpenGLContext = wglCreateContextAttribs ( mDeviceContext,
nullptr, ContextAttribs ) ) )
198 ReleaseDC ( mWindowId, mDeviceContext );
199 DestroyRendererWindow ( mWindowId );
200 std::cout <<
LogLevel::Error <<
"wglCreateContextAttribs Failed" << std::endl;
201 throw std::runtime_error (
"wglCreateContextAttribs Failed" );
206 wglDeleteContext (
static_cast<HGLRC
> ( mOpenGLContext ) );
207 mOpenGLContext =
nullptr;
208 ReleaseDC ( mWindowId, mDeviceContext );
209 DestroyRendererWindow ( mWindowId );
210 std::cout <<
LogLevel::Error <<
"WGL_ARB_create_context is not available" << std::endl;
211 throw std::runtime_error (
"WGL_ARB_create_context is not available" );
217 std::cout <<
LogLevel::Error <<
"Unable to Load OpenGL functions." << std::endl;
218 throw std::runtime_error (
"Unable to Load OpenGL functions." );
220 glGenVertexArrays ( 1, &mVertexArrayObject );
221 glBindVertexArray ( mVertexArrayObject );
222 AttachWindow (
static_cast<HWND
> ( aWindow ) );
225 bool OpenGLRenderer::MakeCurrent(HDC aDeviceContext)
227 if ( !wglMakeCurrent ( (aDeviceContext==
nullptr) ? mDeviceContext : aDeviceContext, mOpenGLContext ) )
229 LPSTR pBuffer = NULL;
230 FormatMessage ( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS,
231 nullptr, GetLastError(), MAKELANGID ( LANG_NEUTRAL, SUBLANG_DEFAULT ), ( LPSTR ) &pBuffer, 0,
nullptr );
232 if ( pBuffer !=
nullptr )
234 std::cout << pBuffer << std::endl;
235 LocalFree ( pBuffer );
242 OpenGLRenderer::~OpenGLRenderer()
244 mWindowStore.clear();
246 mTextureStore.clear();
248 mMaterialStore.clear();
249 mPipelineStore.clear();
250 wglMakeCurrent (
nullptr,
nullptr);
251 if ( wglDeleteContext (
static_cast<HGLRC
> ( mOpenGLContext ) ) != TRUE )
253 std::cout << LogLevel::Error <<
"wglDeleteContext failed." << std::endl;
255 mOpenGLContext =
nullptr;
256 ReleaseDC ( mWindowId, mDeviceContext );
257 DestroyRendererWindow ( mWindowId );
258 mDeviceContext =
nullptr;
261#elif defined(__unix__)
262 static int context_attribs[] =
264 GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
265 GLX_CONTEXT_MINOR_VERSION_ARB, 5,
266 GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
270 static GLXFBConfig GetGLXConfig ( Display* display, ::Window window)
272 XWindowAttributes xwa{};
273 XGetWindowAttributes(display, window, &xwa);
274 VisualID xwvid = XVisualIDFromVisual(xwa.visual);
276 int frame_buffer_config_count{};
277 GLXFBConfig *frame_buffer_configs =
278 glXGetFBConfigs ( display,
279 DefaultScreen ( display ),
280 &frame_buffer_config_count );
281 if ( !frame_buffer_configs )
283 std::cout << LogLevel::Error <<
"Failed to retrieve a framebuffer config" << std::endl;
284 throw std::runtime_error (
"Failed to retrieve a framebuffer config" );
287 (void) std::remove_if(frame_buffer_configs, frame_buffer_configs + frame_buffer_config_count,
288 [display,xwvid] (
const GLXFBConfig & x ) ->
bool
290 XVisualInfo *xvi = glXGetVisualFromFBConfig(display, x);
291 if(xvi && xvi->visualid == xwvid)
300 GLXFBConfig result = frame_buffer_configs[ 0 ];
301 XFree ( frame_buffer_configs );
305 OpenGLRenderer::OpenGLRenderer(
void* aWindow)
307 if(mRendererCount == 0)
309 XSetErrorHandler ( [] ( Display * mDisplay, XErrorEvent * error_event ) ->
int
311 char error_string[1024];
312 XGetErrorText ( mDisplay, error_event->error_code, error_string, 1024 );
323 if(mDisplay){XCloseDisplay(mDisplay);}
324 mDisplay = XOpenDisplay (
nullptr );
328 if ( !glXCreateContextAttribsARB )
330 if ( ! ( glXCreateContextAttribsARB =
331 ( PFNGLXCREATECONTEXTATTRIBSARBPROC )
332 glXGetProcAddressARB ( (
const GLubyte * )
"glXCreateContextAttribsARB" ) ) )
334 std::cout << LogLevel::Error <<
"Failed retrieving glXCreateContextAttribsARB." << std::endl;
335 throw std::runtime_error (
"Failed retrieving glXCreateContextAttribsARB." );
339 GLXFBConfig glxconfig = GetGLXConfig(mDisplay,
reinterpret_cast<::Window
>(aWindow));
341 if (
nullptr == ( mOpenGLContext = glXCreateContextAttribsARB ( mDisplay, glxconfig,
nullptr,
342 True, context_attribs ) ) )
344 std::cout << LogLevel::Error <<
"glXCreateContextAttribsARB Failed." << std::endl;
345 throw std::runtime_error (
"glXCreateContextAttribsARB Failed." );
349 if ( ! glXIsDirect ( mDisplay,
static_cast<GLXContext
> ( mOpenGLContext ) ) )
351 std::cout <<
LogLevel ( LogLevel::Info ) <<
352 "Indirect GLX rendering context obtained" << std::endl;
356 std::cout <<
LogLevel ( LogLevel::Info ) <<
357 "Direct GLX rendering context obtained" << std::endl;
360 if ( !MakeCurrent(
reinterpret_cast<::Window
>(
reinterpret_cast<::Window
>(aWindow))) )
362 std::cout << LogLevel::Error <<
"glXMakeCurrent failed." << std::endl;
363 throw std::runtime_error (
"glXMakeCurrent failed." );
368 std::cout << LogLevel::Error <<
"Unable to Load OpenGL functions." << std::endl;
369 throw std::runtime_error (
"Unable to Load OpenGL functions." );
372 glGenVertexArrays ( 1, &mVertexArrayObject );
373 glBindVertexArray ( mVertexArrayObject );
375 AttachWindow(aWindow);
380 bool OpenGLRenderer::MakeCurrent(::Window aWindowId)
382 return glXMakeCurrent (mDisplay, (aWindowId) ? aWindowId : None , (aWindowId) ? mOpenGLContext :
nullptr );
385 OpenGLRenderer::~OpenGLRenderer()
387 mWindowStore.clear();
389 mTextureStore.clear();
391 mMaterialStore.clear();
392 mPipelineStore.clear();
393 if ( mOpenGLContext != None )
395 glXDestroyContext ( mDisplay, mOpenGLContext );
396 mOpenGLContext = None;
398 if(--mRendererCount == 0)
400 XCloseDisplay(mDisplay);
409 GLint compile_status{};
411 OPENGL_CHECK_ERROR_THROW;
412 GLuint vertex_shader = glCreateShader ( GL_VERTEX_SHADER );
413 OPENGL_CHECK_ERROR_THROW;
415 OPENGL_CHECK_ERROR_THROW;
416 glCompileShader ( vertex_shader );
417 OPENGL_CHECK_ERROR_THROW;
418 glGetShaderiv ( vertex_shader, GL_COMPILE_STATUS, &compile_status );
419 OPENGL_CHECK_ERROR_THROW;
420 if ( compile_status != GL_TRUE )
423 glGetShaderiv ( vertex_shader, GL_INFO_LOG_LENGTH, &info_log_len );
424 OPENGL_CHECK_ERROR_THROW;
425 std::string log_string;
426 log_string.resize ( info_log_len );
427 if ( info_log_len > 1 )
429 glGetShaderInfoLog ( vertex_shader, info_log_len,
nullptr,
const_cast<GLchar*
> ( log_string.data() ) );
430 OPENGL_CHECK_ERROR_THROW;
432 std::cout << log_string << std::endl;
436 OPENGL_CHECK_ERROR_THROW;
438 uint32_t fragment_shader = glCreateShader ( GL_FRAGMENT_SHADER );
439 OPENGL_CHECK_ERROR_THROW;
441 OPENGL_CHECK_ERROR_THROW;
442 glCompileShader ( fragment_shader );
443 OPENGL_CHECK_ERROR_THROW;
444 glGetShaderiv ( fragment_shader, GL_COMPILE_STATUS, &compile_status );
445 OPENGL_CHECK_ERROR_THROW;
446 if ( compile_status != GL_TRUE )
449 glGetShaderiv ( fragment_shader, GL_INFO_LOG_LENGTH, &info_log_len );
450 OPENGL_CHECK_ERROR_THROW;
451 std::string log_string;
452 log_string.resize ( info_log_len );
453 if ( info_log_len > 1 )
455 glGetShaderInfoLog ( fragment_shader, info_log_len,
nullptr,
const_cast<GLchar*
> ( log_string.data() ) );
456 OPENGL_CHECK_ERROR_THROW;
458 std::cout << log_string << std::endl;
462 OPENGL_CHECK_ERROR_THROW;
465 OPENGL_CHECK_ERROR_THROW;
467 OPENGL_CHECK_ERROR_THROW;
469 OPENGL_CHECK_ERROR_THROW;
470 glDeleteShader ( vertex_shader );
471 OPENGL_CHECK_ERROR_THROW;
472 glDeleteShader ( fragment_shader );
473 OPENGL_CHECK_ERROR_THROW;
475 OPENGL_CHECK_ERROR_THROW;
476 glUniform1i ( 0, 0 );
477 OPENGL_CHECK_ERROR_THROW;
484 OPENGL_CHECK_ERROR_NO_THROW;
488 OPENGL_CHECK_ERROR_NO_THROW;
490 OPENGL_CHECK_ERROR_NO_THROW;
492 OPENGL_CHECK_ERROR_NO_THROW;
497 OPENGL_CHECK_ERROR_NO_THROW;
499 OPENGL_CHECK_ERROR_NO_THROW;
544 std::cout <<
LogLevel::Error <<
"OpenGL object already loaded." << std::endl;
545 throw std::runtime_error (
"OpenGL object already loaded." );
567 OPENGL_CHECK_ERROR_NO_THROW;
586 if ( uniform_block ==
nullptr ){
return;}
590 assert(
static_cast<const size_t>(uniform_block->
size) >= aSkeletonBuffer.
GetSize());
591 glBindBufferRange ( GL_UNIFORM_BUFFER, uniform_block->
binding, buffer_id, aSkeletonBuffer.
GetOffset(), aSkeletonBuffer.
GetSize() );
592 OPENGL_CHECK_ERROR_THROW;
600 if ( uniform_block ==
nullptr ){
return;}
602 assert(
static_cast<const size_t>(uniform_block->
size) == aMatricesBuffer.
GetSize());
603 glBindBufferRange ( GL_UNIFORM_BUFFER, uniform_block->
binding, aMatricesBuffer.
GetBufferId(), 0, aMatricesBuffer.
GetSize() );
604 OPENGL_CHECK_ERROR_THROW;
651 return it->second.GetTextureId();
674 std::cout <<
LogLevel::Warning <<
" Window " << aWindowId <<
" Already Loaded at: " << __FUNCTION__ << std::endl;
700 it->second.SetProjectionMatrix ( aMatrix );
710 it->second.SetViewMatrix ( aMatrix );
720 it->second.SetClearColor ( R, G, B, A );
729 it->second.ResizeViewport ( aX, aY, aWidth, aHeight );
739 it->second.BeginRender();
748 it->second.EndRender();
757 uint32_t aVertexStart,
758 uint32_t aVertexCount,
759 uint32_t aInstanceCount,
760 uint32_t aFirstInstance )
const
767 it->second.Render ( aModelMatrix, aMesh, aPipeline, aMaterial, aSkeleton, aTopology, aVertexStart, aVertexCount, aInstanceCount, aFirstInstance );
776 throw std::runtime_error (
"Unknown Window Id." );
778 return it->second.GetFrustum();
786 throw std::runtime_error (
"Unknown Window Id." );
788 return it->second.AllocateSingleFrameUniformMemory ( aSize );
793 return mOpenGLContext;
Defines log severity levels and stream output for the AeonGames engine.
Provides access to a region within a memory pool buffer.
DLL const MemoryPoolBuffer * GetMemoryPoolBuffer() const
Get the underlying memory pool buffer.
DLL size_t GetOffset() const
Get the byte offset of this accessor within the memory pool buffer.
DLL size_t GetSize() const
Get the size of the accessible region.
View frustum defined by six clipping planes, extracted from a projection (or view-projection) matrix.
Represents a surface material with uniform properties and texture samplers.
4 by 4 matrix in colum mayor order.
Represents a polygon mesh with vertex attributes and index data.
@ MATRICES
Matrices binding.
@ SKELETON
Skeleton binding.
OpenGL GPU buffer wrapper implementing the Buffer interface.
GLuint GetBufferId() const
Get the OpenGL buffer object identifier.
size_t GetSize() const final
Get the total size of the buffer in bytes.
OpenGL material binding handler for shader uniforms and textures.
OpenGL memory pool buffer for transient per-frame uniform allocations.
const Buffer & GetBuffer() const final
Get a reference to the underlying Buffer.
OpenGL mesh wrapper managing vertex and index buffers.
OpenGL shader program pipeline with attribute and uniform reflection.
void LoadPipeline(const Pipeline &aPipeline) final
Loads a rendering pipeline (shaders and state) into the renderer.
void FinalizeOverlay()
Release overlay shader program and quad buffer.
void UnloadTexture(const Texture &aTexture) final
Unloads a texture from GPU memory.
void LoadMaterial(const Material &aMaterial) final
Loads material data into the renderer.
void BindMesh(const Mesh &aMesh)
Bind a mesh for subsequent draw calls.
void SetViewMatrix(void *aWindowId, const Matrix4x4 &aMatrix) final
Sets the view matrix for a specific window surface.
void InitializeOverlay()
Initialize overlay shader program and quad buffer.
BufferAccessor AllocateSingleFrameUniformMemory(void *aWindowId, size_t aSize) final
Allocates uniform buffer memory that is valid for a single frame.
GLuint GetOverlayQuad() const
Get the overlay screen-quad buffer.
std::unordered_map< size_t, OpenGLMaterial > mMaterialStore
Loaded material cache.
void UnloadMesh(const Mesh &aMesh) final
Unloads mesh data from GPU memory.
void SetProjectionMatrix(void *aWindowId, const Matrix4x4 &aMatrix) final
Sets the projection matrix for a specific window surface.
void BeginRender(void *aWindowId) final
Begins a render pass for the given window surface.
void EndRender(void *aWindowId) final
Ends the current render pass for the given window surface.
std::unordered_map< void *, OpenGLWindow > mWindowStore
Attached window map.
void SetMatrices(const OpenGLBuffer &aMatricesBuffer) const
Bind the matrices uniform buffer for the current draw.
const Frustum & GetFrustum(void *aWindowId) const final
Returns the view frustum for the given window surface.
void SetSkeleton(const BufferAccessor &aSkeletonBuffer) const
Upload skeleton joint matrices for skinned rendering.
void LoadMesh(const Mesh &aMesh) final
Loads mesh data into GPU memory.
std::unordered_map< size_t, OpenGLPipeline > mPipelineStore
Loaded pipeline cache.
OpenGLRenderer(void *aWindow)
Construct from a native window handle.
GLuint mVertexArrayObject
General VAO.
std::unordered_map< size_t, OpenGLTexture > mTextureStore
Loaded texture cache.
void BindPipeline(const Pipeline &aPipeline)
Bind a pipeline (shader program) for rendering.
void Render(void *aWindowId, const Matrix4x4 &aModelMatrix, const Mesh &aMesh, const Pipeline &aPipeline, const Material *aMaterial=nullptr, const BufferAccessor *aSkeleton=nullptr, Topology aTopology=Topology::TRIANGLE_LIST, uint32_t aVertexStart=0, uint32_t aVertexCount=0xffffffff, uint32_t aInstanceCount=1, uint32_t aFirstInstance=0) const final
Issues a draw call for a mesh with the given pipeline and optional material.
void UnloadPipeline(const Pipeline &aPipeline) final
Unloads a rendering pipeline from the renderer.
OpenGLPipeline * mCurrentPipeline
Currently bound pipeline.
void SetMaterial(const Material &aMaterial)
Set the active material for rendering.
void LoadTexture(const Texture &aTexture) final
Loads a texture into GPU memory.
void UnloadMaterial(const Material &aMaterial) final
Unloads material data from the renderer.
std::unordered_map< size_t, OpenGLMesh > mMeshStore
Loaded mesh cache.
void SetClearColor(void *aWindowId, float R, float G, float B, float A) final
Sets the color to be used to clear the window background.
void ResizeViewport(void *aWindowId, int32_t aX, int32_t aY, uint32_t aWidth, uint32_t aHeight) final
Resizes the specific window surface's viewport.
void AttachWindow(void *aWindowId) final
Attach a Window as a rendering surface.
void DetachWindow(void *aWindowId) final
Detach a Window as a rendering surface.
GLuint GetOverlayProgram() const
Get the overlay shader program identifier.
GLuint GetVertexArrayObject() const
Get the shared vertex array object.
GLuint GetTextureId(const Texture &aTexture)
Get the OpenGL texture identifier for a loaded texture.
void * GetContext() const
Get the platform-specific OpenGL rendering context.
OpenGL texture resource wrapper.
OpenGL per-window rendering context and state.
Rendering pipeline resource.
DLL size_t GetConsecutiveId() const
Get the Consecutive Id for the resource object.
Represents a 2D texture image resource.
OpenGLBuffer mOverlayQuad
Overlay quadrilateral.
GLuint mOverlayProgram
Raw overlay shader program.
<- This is here just for the literals
const GLchar vertex_shader_code[]
Overlay vertex shader GLSL source code.
const GLint fragment_shader_len
Length of the overlay fragment shader source.
bool LoadOpenGLAPI()
Load all OpenGL function pointers and log driver information.
const GLchar *const fragment_shader_code_ptr
Pointer to the overlay fragment shader source.
const float vertices[]
Overlay screen-quad vertex data (positions and texture coordinates).
const GLchar *const vertex_shader_code_ptr
Pointer to the overlay vertex shader source.
const GLint vertex_shader_len
Length of the overlay vertex shader source.
const GLchar fragment_shader_code[]
Overlay fragment shader GLSL source code.
Topology
Primitive topology types for rendering.
LogLevel
Severity levels for engine log messages.
@ Warning
Potential issues that may need attention.
constexpr GLuint vertex_size
Total byte size of the overlay vertex data.