sculpto
gl.cpp
Go to the documentation of this file.
1/*!****************************************************************//*!*
2 * \file gl.cpp
3 * \brief OpenGL context implementation module.
4 *
5 * \author Sabitov Kirill
6 * \date 26 June 2022
7 *********************************************************************/
8
9#include "sclpch.h"
12#include "gl.h"
13
14#ifdef SCL_PLATFORM_WINDOWS
15
16#include <wglew.h>
17#include <wglext.h>
18
19HGLRC glInitialiseContext(HDC hDC)
20{
21 // Choose pixel format
22 int pixel_format_attribs[] = {
23 WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
24 WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
25 WGL_DOUBLE_BUFFER_ARB, GL_TRUE,
26 WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
27 WGL_PIXEL_TYPE_ARB, WGL_TYPE_RGBA_ARB,
28 WGL_COLOR_BITS_ARB, 32,
29 WGL_DEPTH_BITS_ARB, 32,
30 WGL_STENCIL_BITS_ARB, 8,
31 0
32 };
33
34 // Pixel format setup
35 PIXELFORMATDESCRIPTOR pfd = { 0 };
36 pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
37 pfd.nVersion = 1;
38 pfd.dwFlags = PFD_DOUBLEBUFFER | PFD_SUPPORT_OPENGL;
39 pfd.cColorBits = 32;
40 pfd.cDepthBits = 32;
41
42 INT pixel_format = ChoosePixelFormat(hDC, &pfd);
43 SCL_CORE_ASSERT(pixel_format, "Failed to find a suitable pixel format.");
44 DescribePixelFormat(hDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
45 SCL_CORE_ASSERT(SetPixelFormat(hDC, pixel_format, &pfd), "Failed to set the pixel format.");
46
47 // Setup temporary rendering context
48 HGLRC hTmpGLRC = wglCreateContext(hDC);
49 SCL_CORE_ASSERT(hTmpGLRC, "Failed to create temporery OpenGL rendering context.");
50 SCL_CORE_ASSERT(wglMakeCurrent(hDC, hTmpGLRC), "Failed to activate temporery OpenGL rendering context.");
51
52 // Initializing GLEW library
53 glewExperimental = true;
54 GLenum glew_init_status = glewInit();
55 SCL_CORE_ASSERT(glew_init_status == GLEW_OK, "Failed to initialize OpenGL glew.\nError log:\n{}", (const char *)glewGetErrorString(glew_init_status));
56 SCL_CORE_ASSERT(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader, "Your hardware not supported. No shaders support.");
57
58 // Enable a new OpenGL profile support
59 UINT num_formats;
60 wglChoosePixelFormatARB(hDC, pixel_format_attribs, nullptr, 1, &pixel_format, &num_formats);
61
62 // Setup rendering context
63 int context_attribs[] = {
64 WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
65 WGL_CONTEXT_MINOR_VERSION_ARB, 6,
66 WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB,
67 0
68 };
69
70 SCL_CORE_ASSERT(wglMakeCurrent(nullptr, nullptr), "Falied to deactivate temporery rendering context.");
71 SCL_CORE_ASSERT(wglDeleteContext(hTmpGLRC), "Failed to delete temporary rendering context.");
72
73 HGLRC hGLRC = wglCreateContextAttribsARB(hDC, nullptr, context_attribs);
74 SCL_CORE_ASSERT(hGLRC, "Failed to create rendering context.");
75 SCL_CORE_ASSERT(wglMakeCurrent(hDC, hGLRC), "Failed to set rendering context to main window.");
76
77 return hGLRC;
78}
79
80#endif
83{
84 return ClearColor;
85}
86
88{
89 return IsWireframe;
90}
91
93{
94 return CullingMode;
95}
96
98{
99 return IsVSync;
100}
101
102void scl::gl::SetClearColor(const vec4 &ClearColor)
103{
104 this->ClearColor = ClearColor;
105 glClearColor(SCL_VEC_XYZW(ClearColor));
106}
107
108void scl::gl::SetWireframeMode(bool IsWireframe)
109{
110 this->IsWireframe = IsWireframe;
111 glPolygonMode(GL_FRONT_AND_BACK, IsWireframe ? GL_LINE : GL_FILL);
112}
113
115{
116 this->CullingMode = CullingMode;
117 switch (CullingMode)
118 {
119 case scl::render_cull_face_mode::OFF: glDisable(GL_CULL_FACE); return;
120 case scl::render_cull_face_mode::BACK: glEnable(GL_CULL_FACE); glCullFace(GL_BACK); return;
121 case scl::render_cull_face_mode::FRONT: glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); return;
122 }
123
124 SCL_CORE_ASSERT(0, "Unknown culling mode!");
125}
126
127void scl::gl::SetVSync(bool IsVSync)
128{
129 this->IsVSync = IsVSync;
130#ifdef SCL_PLATFORM_WINDOWS
131 wglSwapIntervalEXT(IsVSync);
132#endif
133}
134
136{
137 switch (MeshType)
138 {
139 case scl::mesh_type::LINES: return GL_LINES;
140 case scl::mesh_type::POINTS: return GL_POINTS;
141 case scl::mesh_type::PATCHES: return GL_PATCHES;
142 case scl::mesh_type::TRIANGLES: return GL_TRIANGLES;
143 case scl::mesh_type::TRISTRIP: return GL_TRIANGLE_STRIP;
144 }
145
146 SCL_CORE_ASSERT(0, "Unknown mesh type!");
147 return GLenum();
148}
149
151{
152 switch (Type)
153 {
155 return GL_BOOL;
156
161 return GL_INT;
162
168 return GL_FLOAT;
169 }
170
171 SCL_CORE_ASSERT(0, "Unknown shader veriable type.");
172 return GLenum();
173}
174
175static void APIENTRY glDebugOutput(UINT Source, UINT Type, UINT Id, UINT Severity,
176 INT Length, const CHAR *Message, const VOID *UserParam);
177
178void scl::gl::CreateContext(const HWND &hAppWnd, int W, int H, bool VSync)
179{
180#ifdef SCL_PLATFORM_WINDOWS
181 hWnd = &hAppWnd;
182 hDC = GetDC(hAppWnd);
183 hGLRC = glInitialiseContext(hDC);
184#endif
186 SetVSync(VSync);
187
188 // Set default OpenGL parameters
189 glClearColor(0, 0, 0, 0);
190 glEnable(GL_DEPTH_TEST);
191 glEnable(GL_BLEND);
192
193 glEnable(GL_PRIMITIVE_RESTART);
194 glPrimitiveRestartIndex(render_context::MESH_RESTART_INDEX);
195
196 // Enable debug callback
197#ifndef SCL_DIST
198 glEnable(GL_DEBUG_OUTPUT);
199 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
200 glDebugMessageCallback(glDebugOutput, nullptr);
201 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
202#endif
203}
204
206{
207 SCL_CORE_SUCCES("OpenGL render context initialisation started.");
208
209#ifdef SCL_PLATFORM_WINDOWS
210 application &app = application::Get();
211 const window &win = app.GetWindow();
212 const window::data win_data = win.GetWindowData();
213
214 this->CreateContext(win.GetHandle(), win_data.Width, win_data.Height, true);
215 SCL_CORE_SUCCES("Windows OpenGL render context initialised successfully.");
216#endif
217}
218
220{
221 wglMakeCurrent(nullptr, nullptr);
222 wglDeleteContext(hGLRC);
223 ReleaseDC(*hWnd, hDC);
224}
225
227{
231 ::SwapBuffers(hDC);
232}
233
235{
236 VertexArray->Bind();
237 glDrawElements(
238 GetGLPrimitiveType(VertexArray->GetType()),
239 VertexArray->GetIndexBuffer()->GetCount(),
240 GL_UNSIGNED_INT,
241 nullptr
242 );
243 VertexArray->Unbind();
244}
245
246void scl::gl::DrawIndicesInstanced(const shared<vertex_array> &VertexArray, int InstanceCount)
247{
248 VertexArray->Bind();
249 glDrawElementsInstanced(
250 GetGLPrimitiveType(VertexArray->GetType()),
251 VertexArray->GetIndexBuffer()->GetCount(),
252 GL_UNSIGNED_INT,
253 nullptr,
254 InstanceCount
255 );
256 VertexArray->Unbind();
257}
258
259/*!*
260 * OpenGl Debug output function.
261 *
262 * \param Source - source APi or device.
263 * \param Type - error type.
264 * \param Id - error message id.
265 * \param Severity - message severity.
266 * \param Length - message text length.
267 * \param Message - message text.
268 * \param UserParam - user addon parameters pointer.
269 * \return None.
270 */
271static void APIENTRY glDebugOutput(UINT Source, UINT Type, UINT Id, UINT Severity,
272 INT Length, const CHAR *Message, const VOID *UserParam)
273{
274 INT len = 0;
275 static CHAR Buf[10000] {};
276
278 if (Id == 131169 || Id == 131185 || Id == 131218 || Id == 131204)
279 return;
280
281 len += sprintf_s(Buf + len, 10000, "OpenGL debug message (Id - %i):\n%s.\n", Id, Message);
282 switch (Source)
283 {
284 case GL_DEBUG_SOURCE_API: len += sprintf_s(Buf + len, 10000, "Source: API\n"); break;
285 case GL_DEBUG_SOURCE_WINDOW_SYSTEM: len += sprintf_s(Buf + len, 10000, "Source: Window System\n"); break;
286 case GL_DEBUG_SOURCE_SHADER_COMPILER: len += sprintf_s(Buf + len, 10000, "Source: Shader Compiler\n"); break;
287 case GL_DEBUG_SOURCE_THIRD_PARTY: len += sprintf_s(Buf + len, 10000, "Source: Third Party\n"); break;
288 case GL_DEBUG_SOURCE_APPLICATION: len += sprintf_s(Buf + len, 10000, "Source: Application\n"); break;
289 case GL_DEBUG_SOURCE_OTHER: len += sprintf_s(Buf + len, 10000, "Source: Other\n"); break;
290 }
291 len += sprintf_s(Buf + len, 10000, "\n");
292
293 switch (Type)
294 {
295 case GL_DEBUG_TYPE_ERROR: len += sprintf_s(Buf + len, 10000, "Type: Error"); break;
296 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: len += sprintf_s(Buf + len, 10000, "Type: Deprecated Behaviour"); break;
297 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: len += sprintf_s(Buf + len, 10000, "Type: Undefined Behaviour"); break;
298 case GL_DEBUG_TYPE_PORTABILITY: len += sprintf_s(Buf + len, 10000, "Type: Portability"); break;
299 case GL_DEBUG_TYPE_PERFORMANCE: len += sprintf_s(Buf + len, 10000, "Type: Performance"); break;
300 case GL_DEBUG_TYPE_MARKER: len += sprintf_s(Buf + len, 10000, "Type: Marker"); break;
301 case GL_DEBUG_TYPE_PUSH_GROUP: len += sprintf_s(Buf + len, 10000, "Type: Push Group"); break;
302 case GL_DEBUG_TYPE_POP_GROUP: len += sprintf_s(Buf + len, 10000, "Type: Pop Group"); break;
303 case GL_DEBUG_TYPE_OTHER: len += sprintf_s(Buf + len, 10000, "Type: Other"); break;
304 }
305
306 switch (Severity)
307 {
308 case GL_DEBUG_SEVERITY_HIGH:
309 SCL_CORE_ERROR(Buf);
310 break;
311 case GL_DEBUG_SEVERITY_MEDIUM:
312 case GL_DEBUG_SEVERITY_LOW:
313 SCL_CORE_WARN(Buf);
314 break;
315 case GL_DEBUG_SEVERITY_NOTIFICATION:
316 SCL_CORE_INFO(Buf);
317 break;
318 }
319}
#define SCL_CORE_ASSERT(expr,...)
Definition: assert.h:69
void DrawIndices(const shared< vertex_array > &VertexArray) override
Definition: gl.cpp:234
static GLenum GetGLShaderVariableType(shader_variable_type Type)
Definition: gl.cpp:150
const vec4 & GetClearColor() const override
Definition: gl.cpp:82
void DrawIndicesInstanced(const shared< vertex_array > &VertexArray, int InstanceCount) override
Definition: gl.cpp:246
void SetClearColor(const vec4 &ClearColor) override
Definition: gl.cpp:102
void SetCullingMode(render_cull_face_mode CullingMode) override
Definition: gl.cpp:114
void Init() override
Definition: gl.cpp:205
void SetWireframeMode(bool IsWireframe) override
Definition: gl.cpp:108
render_cull_face_mode GetCullingMode() const override
Definition: gl.cpp:92
bool GetWireframeMode() const override
Definition: gl.cpp:87
bool GetVSync() const override
Definition: gl.cpp:97
void SwapBuffers() override
Definition: gl.cpp:226
static GLenum GetGLPrimitiveType(mesh_type MeshType)
Definition: gl.cpp:135
void CreateContext(const HWND &hAppWnd, int W, int H, bool VSync)
Definition: gl.cpp:178
void Close() override
Definition: gl.cpp:219
void SetVSync(bool VSync)
Definition: gl.cpp:127
static const int MESH_RESTART_INDEX
const data & GetWindowData() const
Definition: window.h:48
const window_handle & GetHandle() const
Definition: window.h:50
#define SCL_CORE_SUCCES(...)
Definition: log.h:42
#define SCL_CORE_WARN(...)
Definition: log.h:43
#define SCL_CORE_INFO(...)
Definition: log.h:41
#define SCL_CORE_ERROR(...)
Definition: log.h:44
std::shared_ptr< T > shared
Definition: smart_ptr.h:15
shader_variable_type
mesh_type
Definition: vertex_array.h:18
render_cull_face_mode
Sculpto library prehompiled header. Defines common definitions, includes commonly used modules.
#define SCL_VEC_XYZW(v)
Definition: vec4.h:19
Vertex array interfaces implementation module.