Aeon Engine c550894
AeonGames Open Source Game Engine
Loading...
Searching...
No Matches
OpenGLWindow.cpp
1/*
2Copyright (C) 2017-2022,2025,2026 Rodrigo Jose Hernandez Cordoba
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16#include "aeongames/Frustum.hpp"
17#include "aeongames/AABB.hpp"
18#include "aeongames/Pipeline.hpp"
19#include "aeongames/Material.hpp"
20#include "aeongames/Mesh.hpp"
22#include "aeongames/Node.hpp"
23#include "aeongames/Scene.hpp"
24#include "aeongames/Material.hpp"
25#include "aeongames/MemoryPool.hpp"
26#include "OpenGLWindow.hpp"
27#include "OpenGLRenderer.hpp"
28#include "OpenGLFunctions.hpp"
29#include <sstream>
30#include <iostream>
31#include <algorithm>
32#include <array>
33#include <utility>
34
35namespace AeonGames
36{
37 void OpenGLWindow::Initialize()
38 {
39 mMatrices.Initialize ( sizeof ( float ) * 16 * 3, GL_DYNAMIC_DRAW );
40 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
41 OPENGL_CHECK_ERROR_THROW;
42 glEnable ( GL_BLEND );
43 OPENGL_CHECK_ERROR_THROW;
44 glDepthFunc ( GL_LESS );
45 OPENGL_CHECK_ERROR_THROW;
46 glEnable ( GL_DEPTH_TEST );
47 OPENGL_CHECK_ERROR_THROW;
48 glCullFace ( GL_BACK );
49 OPENGL_CHECK_ERROR_THROW;
50 glEnable ( GL_CULL_FACE );
51 OPENGL_CHECK_ERROR_THROW;
53 glClearColor ( 0.5f, 0.5f, 0.5f, 1.0f );
54 OPENGL_CHECK_ERROR_THROW;
55 glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
56 OPENGL_CHECK_ERROR_THROW;
57 }
58
59
60 void OpenGLWindow::SetClearColor ( float R, float G, float B, float A )
61 {
62#if defined(_WIN32)
63 mOpenGLRenderer.MakeCurrent ( mDeviceContext );
64#elif defined(__unix__)
65 mOpenGLRenderer.MakeCurrent ( mWindowId );
66#endif
67 glClearColor ( R, G, B, A );
68 }
69
70 static GLenum GetIndexType ( const Mesh& aMesh )
71 {
72 switch ( aMesh.GetIndexSize() )
73 {
74 case 1:
75 return GL_UNSIGNED_BYTE;
76 case 2:
77 return GL_UNSIGNED_SHORT;
78 case 4:
79 return GL_UNSIGNED_INT;
80 };
81 std::cout << LogLevel::Error << "Invalid Index Size." << std::endl;
82 throw std::runtime_error ( "Invalid Index Size." );
83 }
84
85 static const std::unordered_map<Topology, GLenum> TopologyMap
86 {
87 {POINT_LIST, GL_POINTS},
88 {LINE_STRIP, GL_LINE_STRIP},
89 {LINE_LIST, GL_LINES},
90 {TRIANGLE_STRIP, GL_TRIANGLE_STRIP},
91 {TRIANGLE_FAN, GL_TRIANGLE_FAN},
92 {TRIANGLE_LIST, GL_TRIANGLES},
93 {LINE_LIST_WITH_ADJACENCY, GL_LINES_ADJACENCY},
94 {LINE_STRIP_WITH_ADJACENCY, GL_LINE_STRIP_ADJACENCY},
95 {TRIANGLE_LIST_WITH_ADJACENCY, GL_TRIANGLES_ADJACENCY},
96 {TRIANGLE_STRIP_WITH_ADJACENCY, GL_TRIANGLE_STRIP_ADJACENCY},
97 {PATCH_LIST, GL_PATCHES},
98 };
99
100#if defined(__unix__)
101 OpenGLWindow::OpenGLWindow ( OpenGLRenderer& aOpenGLRenderer, Display* aDisplay, ::Window aWindow ) :
102 mOpenGLRenderer{ aOpenGLRenderer },
103 mDisplay{aDisplay},
104 mWindowId{aWindow},
105 mFrameBuffer{},
106 mMemoryPoolBuffer{aOpenGLRenderer}
107 {
108 mOpenGLRenderer.MakeCurrent ( mWindowId );
109 mFrameBuffer.Initialize();
110 mMemoryPoolBuffer.Initialize ( static_cast<GLsizei> ( 8_mb ) );
111 XWindowAttributes xwa;
112 XGetWindowAttributes ( mDisplay, mWindowId, &xwa );
113 glViewport ( xwa.x, xwa.y, xwa.width, xwa.height );
114 Initialize();
115 }
116
117 OpenGLWindow::OpenGLWindow ( OpenGLWindow&& aOpenGLWindow ) :
118 mOpenGLRenderer { aOpenGLWindow.mOpenGLRenderer },
119 mFrameBuffer{std::move ( aOpenGLWindow.mFrameBuffer ) },
120 mMemoryPoolBuffer{std::move ( aOpenGLWindow.mMemoryPoolBuffer ) },
121 mMatrices{std::move ( aOpenGLWindow.mMatrices ) }
122 {
123 std::swap ( mDisplay, aOpenGLWindow.mDisplay );
124 std::swap ( mWindowId, aOpenGLWindow.mWindowId );
125 std::swap ( mFrustum, aOpenGLWindow.mFrustum );
126 std::swap ( mProjectionMatrix, aOpenGLWindow.mProjectionMatrix );
127 std::swap ( mViewMatrix, aOpenGLWindow.mViewMatrix );
128 }
129
130 OpenGLWindow::~OpenGLWindow()
131 {
132 if ( mWindowId != None )
133 {
134 mOpenGLRenderer.MakeCurrent();
135 mMemoryPoolBuffer.Finalize();
136 mMatrices.Finalize();
137 mFrameBuffer.Finalize();
138 mDisplay = nullptr;
139 mWindowId = None;
140 }
141 }
142
143 void OpenGLWindow::SwapBuffers()
144 {
145 glXSwapBuffers ( mDisplay, mWindowId );
146 }
147
148#elif defined(_WIN32)
149 OpenGLWindow::OpenGLWindow ( OpenGLRenderer& aOpenGLRenderer, HWND aWindow ) :
150 mOpenGLRenderer{ aOpenGLRenderer },
151 mWindowId{ aWindow },
152 mDeviceContext{GetDC ( mWindowId ) },
153 //mOverlay{Texture::Format::RGBA, Texture::Type::UNSIGNED_INT_8_8_8_8_REV},
154 mFrameBuffer{},
155 mMemoryPoolBuffer{aOpenGLRenderer}
156 {
157 RECT rect{};
158 GetWindowRect ( mWindowId, &rect );
159 PIXELFORMATDESCRIPTOR pfd{};
160 pfd.nSize = sizeof ( PIXELFORMATDESCRIPTOR );
161 pfd.nVersion = 1;
162 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
163 pfd.iPixelType = PFD_TYPE_RGBA;
164 pfd.cColorBits = 32;
165 pfd.cDepthBits = 32;
166 pfd.iLayerType = PFD_MAIN_PLANE;
167 int pf = ChoosePixelFormat ( mDeviceContext, &pfd );
168 SetPixelFormat ( mDeviceContext, pf, &pfd );
169 mOpenGLRenderer.MakeCurrent ( mDeviceContext );
170 mFrameBuffer.Initialize();
171 mMemoryPoolBuffer.Initialize ( static_cast<GLsizei> ( 8_mb ) );
172 glViewport ( rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top );
173 OPENGL_CHECK_ERROR_THROW;
174 Initialize();
175 }
176
177 OpenGLWindow::OpenGLWindow ( OpenGLWindow&& aOpenGLWindow ) :
178 mOpenGLRenderer { aOpenGLWindow.mOpenGLRenderer },
179 mFrameBuffer{std::move ( aOpenGLWindow.mFrameBuffer ) },
180 mMemoryPoolBuffer{std::move ( aOpenGLWindow.mMemoryPoolBuffer ) },
181 mMatrices{std::move ( aOpenGLWindow.mMatrices ) }
182 {
183 std::swap ( mWindowId, aOpenGLWindow.mWindowId );
184 std::swap ( mFrustum, aOpenGLWindow.mFrustum );
185 std::swap ( mDeviceContext, aOpenGLWindow.mDeviceContext );
186 std::swap ( mProjectionMatrix, aOpenGLWindow.mProjectionMatrix );
187 std::swap ( mViewMatrix, aOpenGLWindow.mViewMatrix );
188 }
189
190 OpenGLWindow::~OpenGLWindow()
191 {
192 if ( mWindowId != nullptr )
193 {
194 mOpenGLRenderer.MakeCurrent();
195 mMemoryPoolBuffer.Finalize();
196 mMatrices.Finalize();
197 mFrameBuffer.Finalize();
198 ReleaseDC ( mWindowId, mDeviceContext );
199 mWindowId = nullptr;
200 }
201 }
202
203 void OpenGLWindow::SwapBuffers()
204 {
205 ::SwapBuffers ( mDeviceContext );
206 }
207
208#endif
209
210 void OpenGLWindow::Render ( const Matrix4x4& aModelMatrix,
211 const Mesh& aMesh,
212 const Pipeline& aPipeline,
213 const Material* aMaterial,
214 const BufferAccessor* aSkeleton,
215 Topology aTopology,
216 uint32_t aVertexStart,
217 uint32_t aVertexCount,
218 uint32_t aInstanceCount,
219 uint32_t aFirstInstance ) const
220 {
221 mOpenGLRenderer.BindPipeline ( aPipeline );
222
223 mMatrices.WriteMemory ( 0, sizeof ( float ) * 16, aModelMatrix.GetMatrix4x4() );
224 mOpenGLRenderer.SetMatrices ( mMatrices );
225
226 if ( aMaterial )
227 {
228 mOpenGLRenderer.SetMaterial ( *aMaterial );
229 }
230
231 if ( aSkeleton )
232 {
233 mOpenGLRenderer.SetSkeleton ( *aSkeleton );
234 }
235
237 mOpenGLRenderer.BindMesh ( aMesh );
238 if ( aMesh.GetIndexCount() )
239 {
240 glDrawElementsInstanced ( TopologyMap.at ( aTopology ), ( aVertexCount != 0xffffffff ) ? aVertexCount : aMesh.GetIndexCount(),
241 GetIndexType ( aMesh ), reinterpret_cast<const uint8_t*> ( 0 ) + aMesh.GetIndexSize() *aVertexStart, aInstanceCount );
242 OPENGL_CHECK_ERROR_NO_THROW;
243 }
244 else
245 {
246 glDrawArraysInstanced ( TopologyMap.at ( aTopology ), aVertexStart, ( aVertexCount != 0xffffffff ) ? aVertexCount : aMesh.GetVertexCount(), aInstanceCount );
247 OPENGL_CHECK_ERROR_NO_THROW;
248 }
249 }
250
252 {
253 return mMemoryPoolBuffer.Allocate ( aSize );
254 }
255
257 {
258#if defined(_WIN32)
259 mOpenGLRenderer.MakeCurrent ( mDeviceContext );
260#elif defined(__unix__)
261 mOpenGLRenderer.MakeCurrent ( mWindowId );
262#endif
263 mFrameBuffer.Bind();
264 glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
265 glEnable ( GL_DEPTH_TEST );
266 }
267
269 {
270 mFrameBuffer.Unbind();
271 glClear ( GL_COLOR_BUFFER_BIT );
272 OPENGL_CHECK_ERROR_NO_THROW;
273 glDisable ( GL_DEPTH_TEST );
274 OPENGL_CHECK_ERROR_NO_THROW;
275 GLint dims[4] = {0};
276 glGetIntegerv ( GL_VIEWPORT, dims );
277 OPENGL_CHECK_ERROR_NO_THROW;
278 glBlitNamedFramebuffer (
279 mFrameBuffer.GetFBO(),
280 0,
281 dims[0],
282 dims[1],
283 dims[2],
284 dims[3],
285 dims[0],
286 dims[1],
287 dims[2],
288 dims[3],
289 GL_COLOR_BUFFER_BIT,
290 GL_LINEAR );
291 OPENGL_CHECK_ERROR_NO_THROW;
292#if 0
293 /* Bind and render overlay texture */
294 glUseProgram ( mOpenGLRenderer.GetOverlayProgram() );
295 OPENGL_CHECK_ERROR_NO_THROW;
296 glBindBuffer ( GL_ARRAY_BUFFER, mOpenGLRenderer.GetOverlayQuad() );
297 OPENGL_CHECK_ERROR_NO_THROW;
298 glBindTexture ( GL_TEXTURE_2D, mOverlay.GetTextureId() );
299 OPENGL_CHECK_ERROR_NO_THROW;
300 glEnableVertexAttribArray ( 0 );
301 OPENGL_CHECK_ERROR_NO_THROW;
302 glVertexAttribPointer ( 0, 2, GL_FLOAT, GL_FALSE, sizeof ( float ) * 4, 0 );
303 OPENGL_CHECK_ERROR_NO_THROW;
304 glEnableVertexAttribArray ( 1 );
305 OPENGL_CHECK_ERROR_NO_THROW;
306 glVertexAttribPointer ( 1, 2, GL_FLOAT, GL_FALSE, sizeof ( float ) * 4, reinterpret_cast<const void*> ( sizeof ( float ) * 2 ) );
307 OPENGL_CHECK_ERROR_NO_THROW;
308 glDrawArrays ( GL_TRIANGLE_FAN, 0, 4 );
309 OPENGL_CHECK_ERROR_NO_THROW;
310#endif
311 SwapBuffers();
312 mMemoryPoolBuffer.Reset();
313 }
314 void OpenGLWindow::WriteOverlayPixels ( int32_t aXOffset, int32_t aYOffset, uint32_t aWidth, uint32_t aHeight, Texture::Format aFormat, Texture::Type aType, const uint8_t* aPixels )
315 {
316 //mOverlay.WritePixels ( aXOffset, aYOffset, aWidth, aHeight, aFormat, aType, aPixels );
317 }
318
320 {
321 mProjectionMatrix = aMatrix * Matrix4x4
322 {
323 // Flip Matrix
324 1.0f, 0.0f, 0.0f, 0.0f,
325 0.0f, 1.0f, 0.0f, 0.0f,
326 0.0f, 0.0f, -1.0f, 0.0f,
327 0.0f, 0.0f, 0.0f, 1.0f
328 };
329 mFrustum = mProjectionMatrix * mViewMatrix;
330 mMatrices.WriteMemory ( sizeof ( float ) * 16, sizeof ( float ) * 16, mProjectionMatrix.GetMatrix4x4() );
331 }
332
334 {
335 mViewMatrix = aMatrix;
336 mFrustum = mProjectionMatrix * mViewMatrix;
337 mMatrices.WriteMemory ( sizeof ( float ) * 16 * 2, sizeof ( float ) * 16, mViewMatrix.GetMatrix4x4() );
338 }
339
341 {
342 return mProjectionMatrix;
343 }
345 {
346 return mViewMatrix;
347 }
348
350 {
351 return mFrustum;
352 }
353
354 void OpenGLWindow::ResizeViewport ( int32_t aX, int32_t aY, uint32_t aWidth, uint32_t aHeight )
355 {
356 if ( aWidth && aHeight )
357 {
358#if defined(_WIN32)
359 mOpenGLRenderer.MakeCurrent ( mDeviceContext );
360#elif defined(__unix__)
361 mOpenGLRenderer.MakeCurrent ( mWindowId );
362#endif
363 OPENGL_CHECK_ERROR_NO_THROW;
364 glViewport ( aX, aY, aWidth, aHeight );
365 OPENGL_CHECK_ERROR_THROW;
366 mFrameBuffer.Resize ( aWidth, aHeight );
367 //mOverlay.Resize ( aWidth, aHeight );
368 }
369 }
370}
Header for the axis aligned bounding box class.
Header for the frustum class.
Defines log severity levels and stream output for the AeonGames engine.
Header for the Scene class.
Provides access to a region within a memory pool buffer.
View frustum defined by six clipping planes, extracted from a projection (or view-projection) matrix.
Definition Frustum.hpp:35
Represents a surface material with uniform properties and texture samplers.
Definition Material.hpp:38
4 by 4 matrix in colum mayor order.
Definition Matrix4x4.hpp:35
DLL const float *const GetMatrix4x4() const
Get a pointer to the internal matrix data.
Definition Matrix4x4.cpp:53
Represents a polygon mesh with vertex attributes and index data.
Definition Mesh.hpp:31
DLL uint32_t GetIndexSize() const
Get the size in bytes of a single index.
Definition Mesh.cpp:43
DLL uint32_t GetIndexCount() const
Get the total number of indices.
Definition Mesh.cpp:48
DLL uint32_t GetVertexCount() const
Get the total number of vertices.
Definition Mesh.cpp:53
OpenGL rendering backend implementing the Renderer interface.
OpenGL per-window rendering context and state.
const Matrix4x4 & GetProjectionMatrix() const
Get the current projection matrix.
const Frustum & GetFrustum() const
Get the view frustum derived from the current matrices.
void SetClearColor(float R, float G, float B, float A)
Set the clear color for this window.
void SetProjectionMatrix(const Matrix4x4 &aMatrix)
Set the projection matrix for this window.
OpenGLWindow(OpenGLWindow &&aOpenGLWindow)
Move constructor.
void EndRender()
End the current frame and present.
void BeginRender()
Begin rendering a new frame.
void WriteOverlayPixels(int32_t aXOffset, int32_t aYOffset, uint32_t aWidth, uint32_t aHeight, Texture::Format aFormat, Texture::Type aType, const uint8_t *aPixels)
Write pixel data to the overlay texture.
const Matrix4x4 & GetViewMatrix() const
Get the current view matrix.
void Render(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
BufferAccessor AllocateSingleFrameUniformMemory(size_t aSize)
Allocate transient uniform memory for the current frame.
void SetViewMatrix(const Matrix4x4 &aMatrix)
Set the view matrix for this window.
void ResizeViewport(int32_t aX, int32_t aY, uint32_t aWidth, uint32_t aHeight)
Resize the rendering viewport.
Rendering pipeline resource.
Definition Pipeline.hpp:122
Type
Pixel component data type.
Definition Texture.hpp:51
Format
Pixel channel layout format.
Definition Texture.hpp:40
<- This is here just for the literals
Definition AABB.hpp:31
Topology
Primitive topology types for rendering.
Definition Pipeline.hpp:38
@ TRIANGLE_STRIP
Connected triangle strip.
Definition Pipeline.hpp:43
@ PATCH_LIST
Patch list for tessellation.
Definition Pipeline.hpp:50
@ LINE_LIST_WITH_ADJACENCY
Line list with adjacency information.
Definition Pipeline.hpp:46
@ TRIANGLE_LIST_WITH_ADJACENCY
Triangle list with adjacency information.
Definition Pipeline.hpp:48
@ POINT_LIST
List of individual points.
Definition Pipeline.hpp:40
@ LINE_STRIP
Connected line segments.
Definition Pipeline.hpp:41
@ LINE_LIST
Pairs of vertices forming individual lines.
Definition Pipeline.hpp:42
@ TRIANGLE_LIST
Independent triangles.
Definition Pipeline.hpp:45
@ TRIANGLE_STRIP_WITH_ADJACENCY
Triangle strip with adjacency information.
Definition Pipeline.hpp:49
@ TRIANGLE_FAN
Triangles sharing a common vertex.
Definition Pipeline.hpp:44
@ LINE_STRIP_WITH_ADJACENCY
Line strip with adjacency information.
Definition Pipeline.hpp:47
@ Error
Error conditions.
Definition LogLevel.hpp:33