6#include "LkEngine/Core/LObject/ObjectPtr.h"
7#include "LkEngine/Core/Memory/MemoryUtils.h"
9#include "LkEngine/Renderer/TextureEnum.h"
10#include "LkEngine/Renderer/Image.h"
11#include "LkEngine/Renderer/Framebuffer.h"
12#include "LkEngine/Renderer/Shader.h"
13#include "LkEngine/Renderer/VertexBuffer.h"
14#include "LkEngine/Renderer/BlendingSpecification.h"
15#include "LkEngine/Renderer/ArrayTextureSpecification.h"
16#include "LkEngine/Renderer/GeometryPool.h"
24#define LK_OpenGL_Verify(OpenGLFunction) \
25 LOpenGL_Internal::CheckForErrors(); \
27 LK_CORE_VERIFY(LOpenGL_Internal::VerifyFunctionResult(#OpenGLFunction, __FILE__, __LINE__))
34#define LK_OpenGL_Verify_Func(Func, ...) { LK_OpenGL_Verify(Func(__VA_ARGS__)); }
41#define glTexImage2D(...) LK_OpenGL_Verify_Func(glTexImage2D, __VA_ARGS__)
42#define glTexSubImage2D(...) LK_OpenGL_Verify_Func(glTexSubImage2D, __VA_ARGS__)
55 namespace LOpenGL_Internal
57 FORCEINLINE
static void CheckForErrors()
59 while (glGetError() != GL_NO_ERROR)
64 FORCEINLINE
static bool VerifyFunctionResult(
const char* InFunction,
const char* InFile,
int InLine)
66 while (GLenum Error = glGetError())
68 LK_CORE_ERROR_TAG(
"OpenGL",
"Error {}\n Function: {}\n File: {}\n Line: {}",
69 static_cast<int>(Error), InFunction, InFile, InLine);
77 static_assert(std::conjunction_v<std::is_same<int, GLint>, std::is_same<int32_t, GLint>>);
78 static_assert(std::conjunction_v<std::is_same<uint32_t, GLuint>, std::is_same<unsigned int, GLuint>>);
79 static_assert(std::is_same_v<byte, GLubyte>);
93 LK_OpenGL_Verify(glGetIntegerv(GL_MAJOR_VERSION, &Major));
94 LK_OpenGL_Verify(glGetIntegerv(GL_MINOR_VERSION, &Minor));
95 Version.Major = Major;
96 Version.Minor = Minor;
99 glGetIntegerv(GL_NUM_EXTENSIONS, &Extensions);
100 SupportedExtensions.reserve(Extensions);
101 for (
int i = 0; i < Extensions; i++)
103 SupportedExtensions.push_back(std::string(
reinterpret_cast<const char*
>(glGetStringi(GL_EXTENSIONS, i))));
107 static std::string GetVersion()
110 std::sprintf(CharBuf,
"%s", glGetString(GL_VERSION));
112 return std::string(CharBuf);
115 static bool IsExtensionSupported(
const char* Extension)
118 LK_OpenGL_Verify(glGetIntegerv(GL_NUM_EXTENSIONS, &Extensions));
119 for (GLint i = 0; i < Extensions; i++)
121 const char* Ext =
reinterpret_cast<const char*
>(glGetStringi(GL_EXTENSIONS, i));
122 if (strcmp(Ext, Extension) == 0)
131 static const std::vector<std::string>& GetSupportedExtensions()
133 return SupportedExtensions;
136 static int GetMajorVersion() {
return Version.Major; }
137 static int GetMinorVersion() {
return Version.Minor; }
147 static std::vector<std::string> SupportedExtensions;
171 switch (InBlendFunction)
173 case ESourceBlendFunction::Zero:
return GL_ZERO;
174 case ESourceBlendFunction::One:
return GL_ONE;
175 case ESourceBlendFunction::Alpha:
return GL_SRC_ALPHA;
176 case ESourceBlendFunction::Color:
return GL_SRC_COLOR;
177 case ESourceBlendFunction::One_Minus_DestinationAlpha:
return GL_ONE_MINUS_DST_ALPHA;
180 LK_CORE_ASSERT(
false,
"Invalid source blend function");
189 switch (InBlendFunction)
191 case EDestinationBlendFunction::Zero:
return GL_ZERO;
192 case EDestinationBlendFunction::One:
return GL_ONE;
193 case EDestinationBlendFunction::Alpha:
return GL_DST_ALPHA;
194 case EDestinationBlendFunction::Color:
return GL_DST_COLOR;
195 case EDestinationBlendFunction::One_Minus_SourceAlpha:
return GL_ONE_MINUS_SRC_ALPHA;
198 LK_CORE_ASSERT(
false,
"Invalid destination blend function");
202 FORCEINLINE
static const GLubyte* GetExtensions()
204 return glGetString(GL_EXTENSIONS);
207 FORCEINLINE
static void PrintExtensions()
210 LK_OpenGL_Verify(glGetIntegerv(GL_NUM_EXTENSIONS, &Extensions));
211 for (
int Index = 0; Index < Extensions; Index++)
213 const byte* Extension = glGetStringi(GL_EXTENSIONS, Index);
214 LK_CORE_INFO(
"OpenGL Extension: {}", std::string(
reinterpret_cast<const char*
>(Extension)));
218 FORCEINLINE
static GLenum GetFormatDataType(EImageFormat ImageFormat)
222 case EImageFormat::RGB:
223 case EImageFormat::RGBA:
224 case EImageFormat::RGBA8:
return GL_UNSIGNED_BYTE;
225 case EImageFormat::RGBA16F:
226 case EImageFormat::RGBA32F:
return GL_FLOAT;
229 LK_CORE_ASSERT(
false,
"Unknown OpenGLFormatDataType: {}",
static_cast<int>(ImageFormat));
230 return GL_INVALID_VALUE;
233 FORCEINLINE
static GLenum GetImageFormat(
const EImageFormat ImageFormat)
237 case EImageFormat::RGB:
return GL_RGB;
240 case EImageFormat::RGBA:
241 case EImageFormat::RGBA8:
242 case EImageFormat::RGBA16F:
243 case EImageFormat::RGBA32F:
return GL_RGBA;
246 case EImageFormat::SRGB:
return GL_SRGB;
247 case EImageFormat::SRGBA:
return GL_SRGB_ALPHA;
250 LK_CORE_ASSERT(
false,
"Unknown OpenGLImageFormat {}",
static_cast<int>(ImageFormat));
251 return GL_INVALID_ENUM;
254 FORCEINLINE
static GLenum GetImageInternalFormat(
const EImageFormat Format)
258 case EImageFormat::RGB:
return GL_RGB8;
259 case EImageFormat::RGBA:
return GL_RGBA8;
260 case EImageFormat::RGBA8:
return GL_RGBA8;
261 case EImageFormat::RGBA16F:
return GL_RGBA16F;
262 case EImageFormat::RGBA32F:
return GL_RGBA32F;
263 case EImageFormat::DEPTH24STENCIL8:
return GL_DEPTH24_STENCIL8;
264 case EImageFormat::DEPTH32F:
return GL_DEPTH_COMPONENT32F;
267 LK_CORE_ASSERT(
false,
"Invalid image format");
268 return GL_INVALID_ENUM;
271 FORCEINLINE
static GLenum GetSamplerWrap(
const ETextureWrap TextureWrap)
275 case ETextureWrap::Clamp:
return GL_CLAMP_TO_EDGE;
276 case ETextureWrap::Repeat:
return GL_REPEAT;
279 LK_CORE_ASSERT(
false,
"Unknown OpenGLSamplerWrap: {}",
static_cast<int>(TextureWrap));
280 return GL_INVALID_VALUE;
283 FORCEINLINE
static GLenum GetSamplerFilter(
const ETextureFilter TextureFilter,
const bool bUseMipmap)
285 switch (TextureFilter)
287 case ETextureFilter::Linear:
return bUseMipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR;
288 case ETextureFilter::Nearest:
return bUseMipmap ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST;
291 LK_CORE_ASSERT(
false,
"Unknown OpenGLSamplerFilter: {}, mipmap: {}",
static_cast<int>(TextureFilter), bUseMipmap);
292 return GL_INVALID_VALUE;
295 FORCEINLINE
static GLenum ImageFormatToDataFormat(EImageFormat ImageFormat)
299 case EImageFormat::RGBA:
300 case EImageFormat::RGBA8:
301 case EImageFormat::RGBA16F:
302 case EImageFormat::RGBA32F:
return GL_RGBA;
304 case EImageFormat::RG8:
305 case EImageFormat::RG16F:
306 case EImageFormat::RG32F:
return GL_RG;
308 case EImageFormat::RGB:
309 case EImageFormat::RGB8:
return GL_RGB;
311 case EImageFormat::RED8UI:
312 case EImageFormat::RED16UI:
313 case EImageFormat::RED32UI:
return GL_RED_INTEGER;
314 case EImageFormat::RED32F:
return GL_RED_INTEGER;
317 LK_CORE_ASSERT(
false,
"Invalid ImageFormat: {}",
static_cast<int>(ImageFormat));
318 return GL_INVALID_VALUE;
321 FORCEINLINE
static constexpr GLenum ImageFormatToInternalFormat(EImageFormat ImageFormat)
325 case EImageFormat::RGB:
return GL_RGB32F;
326 case EImageFormat::RGB8:
return GL_RGB8;
328 case EImageFormat::RGBA:
return GL_RGBA32F;
329 case EImageFormat::RGBA8:
return GL_RGBA8;
330 case EImageFormat::RGBA16F:
return GL_RGBA16F;
331 case EImageFormat::RGBA32F:
return GL_RGBA32F;
333 case EImageFormat::RG16F:
return GL_RG16F;
334 case EImageFormat::RG32F:
return GL_RG32F;
336 case EImageFormat::RED8UI:
return GL_R8UI;
337 case EImageFormat::RED16UI:
return GL_R16UI;
338 case EImageFormat::RED32UI:
return GL_R32UI;
339 case EImageFormat::RED32F:
return GL_R32F;
342 LK_CORE_ASSERT(
false,
"Invalid internal ImageFormat: {}",
static_cast<int>(ImageFormat));
343 return GL_INVALID_VALUE;
346 FORCEINLINE
static constexpr GLenum ShaderDataTypeToOpenGLBaseType(
EShaderDataType type)
350 case EShaderDataType::Float:
return GL_FLOAT;
351 case EShaderDataType::Float2:
return GL_FLOAT;
352 case EShaderDataType::Float3:
return GL_FLOAT;
353 case EShaderDataType::Float4:
return GL_FLOAT;
354 case EShaderDataType::Mat3:
return GL_FLOAT;
355 case EShaderDataType::Mat4:
return GL_FLOAT;
356 case EShaderDataType::Int:
357 case EShaderDataType::Int2:
358 case EShaderDataType::Int3:
359 case EShaderDataType::Int4:
return GL_INT;
360 case EShaderDataType::Bool:
return GL_BOOL;
363 return GL_INVALID_ENUM;
366 FORCEINLINE
static GLenum TextureTarget(
const bool IsMultisampled)
368 return (IsMultisampled ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
371 FORCEINLINE
static void CreateTextures(
const bool bMultisampled, uint32_t* OutTextureID,
const uint32_t Count)
374 glCreateTextures(TextureTarget(bMultisampled), Count, OutTextureID)
378 FORCEINLINE
static void BindTexture(
const bool bMultisampled,
const uint32_t ID)
381 glBindTexture(TextureTarget(bMultisampled), ID)
385 FORCEINLINE
static void AttachColorTexture(
const uint32_t ID,
const int Samples,
const GLenum InternalFormat,
386 const GLenum Format,
const uint32_t Width,
const uint32_t Height,
389 const bool bMultisampled = (Samples > 1);
393 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, InternalFormat, Width, Height, GL_FALSE)
398 LK_OpenGL_Verify(glTexImage2D(GL_TEXTURE_2D, 0, InternalFormat, Width, Height, 0, Format, GL_UNSIGNED_BYTE,
nullptr));
399 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
400 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
401 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
402 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
403 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
407 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + Index, TextureTarget(bMultisampled), ID, 0)
411 FORCEINLINE
static void AttachDepthTexture(
const uint32_t ID,
const int Samples,
const GLenum Format,
412 const GLenum AttachmentType,
const uint32_t Width,
const uint32_t Height)
414 const bool bMultisampled = (Samples > 1);
418 glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, Samples, Format, Width, Height, GL_FALSE)
423 LK_OpenGL_Verify(glTexStorage2D(GL_TEXTURE_2D, 1, Format, Width, Height));
424 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
425 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
426 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
427 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
428 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
431 LK_OpenGL_Verify(glFramebufferTexture2D(GL_FRAMEBUFFER, AttachmentType, TextureTarget(bMultisampled), ID, 0));
434 FORCEINLINE
static GLenum GetFramebufferTextureFormat(
const EImageFormat ImageFormat)
438 case EImageFormat::RGBA8:
return GL_RGBA8;
439 case EImageFormat::RGBA16F:
return GL_RGBA16F;
440 case EImageFormat::RGBA32F:
return GL_RGBA32F;
441 case EImageFormat::RED8UI:
442 case EImageFormat::RED8UN:
443 case EImageFormat::RED16UI:
444 case EImageFormat::RED32UI:
return GL_RED_INTEGER;
445 case EImageFormat::DEPTH24STENCIL8:
return GL_DEPTH24_STENCIL8;
448 LK_CORE_ASSERT(
false,
"Invalid ImageFormat");
449 return GL_INVALID_VALUE;
452 FORCEINLINE
static void ApplyTextureFilter(ETextureFilter TextureFilter,
bool bGenerateMipmap)
454 if (TextureFilter == ETextureFilter::Linear)
458 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
462 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
465 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
467 else if (TextureFilter == ETextureFilter::Nearest)
471 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST));
475 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
478 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
480 else if (TextureFilter == ETextureFilter::None)
482 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));
483 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
487 static void ApplyTextureWrap(ETextureWrap TextureWrap)
489 if (TextureWrap == ETextureWrap::Clamp)
492 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
493 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
495 else if (TextureWrap == ETextureWrap::Repeat)
498 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
499 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
503 static void ApplyTextureFilter(
const LRendererID& RendererID,
const ETextureFilter TextureFilter,
504 bool bGenerateMipmap =
true)
506 switch (TextureFilter)
508 case ETextureFilter::Linear:
511 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_MIN_FILTER,
512 (bGenerateMipmap ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)));
515 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
520 case ETextureFilter::Nearest:
523 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_MIN_FILTER,
524 (bGenerateMipmap ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
526 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
531 case ETextureFilter::None:
534 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_MIN_FILTER,
535 (bGenerateMipmap ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST)));
538 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
545 FORCEINLINE
static void ApplyTextureWrap(
const LRendererID RendererID,
const ETextureWrap TextureWrap)
549 case ETextureWrap::None:
551 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT));
552 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT));
556 case ETextureWrap::Clamp:
558 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT));
559 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT));
563 case ETextureWrap::Repeat:
565 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_WRAP_S, GL_REPEAT));
566 LK_OpenGL_Verify(glTextureParameteri(RendererID, GL_TEXTURE_WRAP_T, GL_REPEAT));
570 default: LK_CORE_ASSERT(
false,
"Unknown texture wrap: {}",
static_cast<int>(TextureWrap));
577 FORCEINLINE
static float GetSampleDepth(
int x,
int y,
int WindowWidth,
int WindowHeight)
580 LK_OpenGL_Verify(glGetIntegerv(GL_VIEWPORT, Viewport));
583 y = WindowHeight - y;
586 LK_OpenGL_Verify(glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &Depth));
591 FORCEINLINE
static std::pair<int, int> ConvertDimensionsToWidthAndHeight(
const EArrayTextureDimension TexDim)
595 case EArrayTextureDimension::Dim_200x200:
return { 200, 200 };
596 case EArrayTextureDimension::Dim_512x512:
return { 512, 512 };
597 case EArrayTextureDimension::Dim_1024x1024:
return { 1024, 1024 };
598 case EArrayTextureDimension::Dim_2048x2048:
return { 2048, 2048 };
599 case EArrayTextureDimension::Dim_4096x4096:
return { 4096, 4096 };
602 LK_CORE_ASSERT(
false,
"Unknown OpenGLTextureArrayDimension");
606 FORCEINLINE
static EArrayTextureDimension DetermineDimension(
const int InWidth,
const int InHeight)
608 LK_VERIFY(InWidth == InHeight,
"Passed dimension size is not equal");
611 case 200:
return EArrayTextureDimension::Dim_200x200;
612 case 512:
return EArrayTextureDimension::Dim_512x512;
613 case 1024:
return EArrayTextureDimension::Dim_1024x1024;
614 case 2048:
return EArrayTextureDimension::Dim_2048x2048;
615 case 4096:
return EArrayTextureDimension::Dim_4096x4096;
618 LK_CORE_ASSERT(
false,
"Failed to determine dimension");
622 FORCEINLINE
static void GenerateTextureArrayImage(
const LRendererID ID,
const FArrayTextureSpecification& Specification)
624 auto [Width, Height] = ConvertDimensionsToWidthAndHeight(Specification.Dimension);
625 LK_OpenGL_Verify(glTextureStorage3D(ID,
626 Specification.Layers,
627 ImageFormatToDataFormat(Specification.ImageFormat),
633 FORCEINLINE
static int GetPrimitiveTopology(
const EPrimitiveTopology Topology)
637 case EPrimitiveTopology::Points:
return GL_POINTS;
638 case EPrimitiveTopology::Lines:
return GL_LINES;
639 case EPrimitiveTopology::Triangles:
return GL_TRIANGLES;
642 LK_CORE_ASSERT(
false,
"Unknown topology, cannot convert to OpenGL format");
643 return GL_INVALID_ENUM;
647 #if defined(LK_OPENGL4)
648 using LOpenGL = LOpenGL4;
649 #elif defined(LK_OPENGL3)
650 using LOpenGL = LOpenGL3;
652 using LOpenGL = LOpenGL4;
658 namespace LOpenGL_Debug
660 extern uint32_t CubeTexture_;
661 extern uint32_t FloorTexture_;
663 extern uint32_t CubeVAO;
664 extern uint32_t CubeVBO;
665 extern uint32_t QuadVAO;
666 extern uint32_t QuadVBO;
668 extern uint32_t SkyboxVBO;
670 extern TObjectPtr<LVertexBuffer> CubeVertexBuffer;
671 extern TObjectPtr<LVertexBuffer> PlaneVertexBuffer;
672 extern TObjectPtr<LTexture2D> CubeTexture;
673 extern TObjectPtr<LTexture2D> PlaneTexture;
675 extern TObjectPtr<LShader> ScreenShader;
676 extern TObjectPtr<LShader> DebugShader;
677 extern TObjectPtr<LShader> CubeDebugShader;
680 extern TObjectPtr<LVertexBuffer> SkyboxVertexBuffer;
681 extern TObjectPtr<LTextureCube> SkyboxTexture;
682 extern TObjectPtr<LShader> SkyboxShader;
683 extern uint32_t CubemapTexture;
685 extern glm::mat4 ModelMVP;
686 extern glm::mat4 View;
687 extern glm::mat4 Projection;
690 static float Cube_Vertices[] = {
692 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
693 0.5f, -0.5f, -0.5f, 1.0f, 0.0f,
694 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
695 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
696 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
697 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f,
699 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
700 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
701 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
702 0.5f, 0.5f, 0.5f, 1.0f, 1.0f,
703 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f,
704 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
706 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
707 -0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
708 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
709 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
710 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
711 -0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
713 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
714 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
715 0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
716 0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
717 0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
718 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
720 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
721 0.5f, -0.5f, -0.5f, 1.0f, 1.0f,
722 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
723 0.5f, -0.5f, 0.5f, 1.0f, 0.0f,
724 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f,
725 -0.5f, -0.5f, -0.5f, 0.0f, 1.0f,
727 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f,
728 0.5f, 0.5f, -0.5f, 1.0f, 1.0f,
729 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
730 0.5f, 0.5f, 0.5f, 1.0f, 0.0f,
731 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f,
732 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f
735 static float Cube_TextureCoords[] = {
780 static float Plane_Vertices[] = {
782 5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
783 -5.0f, -0.5f, 5.0f, 0.0f, 0.0f,
784 -5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
786 5.0f, -0.5f, 5.0f, 2.0f, 0.0f,
787 -5.0f, -0.5f, -5.0f, 0.0f, 2.0f,
788 5.0f, -0.5f, -5.0f, 2.0f, 2.0f
792 static float Quad_Vertices[] = {
794 -0.3f, 1.0f, 0.0f, 1.0f,
795 -0.3f, 0.7f, 0.0f, 0.0f,
796 0.3f, 0.7f, 1.0f, 0.0f,
798 -0.3f, 1.0f, 0.0f, 1.0f,
799 0.3f, 0.7f, 1.0f, 0.0f,
800 0.3f, 1.0f, 1.0f, 1.0f
804 static float Skybox_Vertices[] = {
852 static float Cube_Vertices_NT[] = {
854 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
855 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
856 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
857 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
858 -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
859 -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
861 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
862 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
863 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
864 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
865 -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
866 -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
868 -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
869 -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
870 -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
871 -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
872 -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
873 -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
875 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
876 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
877 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
878 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
879 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
880 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
882 -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
883 0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
884 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
885 0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
886 -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
887 -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
889 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
890 0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
891 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
892 0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
893 -0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
894 -0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
899 FORCEINLINE
static uint32_t LoadTexture(
const char* path)
902 LK_OpenGL_Verify(glGenTextures(1, &TextureID));
907 unsigned char* data = stbi_load(path, &Width, &Height, &Channels, 0);
915 else if (Channels == 3)
919 else if (Channels == 4)
925 LK_CORE_ASSERT(
false,
"Invalid GLFormat");
926 Format = GL_INVALID_ENUM;
929 LK_OpenGL_Verify(glBindTexture(GL_TEXTURE_2D, TextureID));
930 LK_OpenGL_Verify(glTexImage2D(GL_TEXTURE_2D, 0, Format, Width, Height, 0, Format, GL_UNSIGNED_BYTE, data));
931 LK_OpenGL_Verify(glGenerateMipmap(GL_TEXTURE_2D));
933 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
934 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
935 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
936 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
938 stbi_image_free(data);
942 LK_CORE_ERROR_TAG(
"OpenGLRenderer2D",
"Texture failed to load at path {}", path);
943 stbi_image_free(data);
954 void SetupDebugCube();
955 void GeneratePlaneVaoAndVbo();
956 void GenerateScreenQuadVaoAndVbo(uint32_t& vao, uint32_t& vbo);
957 void SetupTexturesAndShaders();
960 void RenderMirrorTexture(
const glm::mat4& view = glm::mat4(1.0f),
const glm::mat4& proj = glm::mat4(1.0f));
961 void RenderScreenTexture(
const glm::mat4& view = glm::mat4(1.0f),
const glm::mat4& proj = glm::mat4(1.0f));
962 void RenderCubes(
const glm::mat4& view = glm::mat4(1.0f),
const glm::mat4& proj = glm::mat4(1.0f));
963 void RenderFloor(
const glm::mat4& view = glm::mat4(1.0f),
const glm::mat4& proj = glm::mat4(1.0f));
964 void RenderSkybox(
const TObjectPtr<LSceneCamera> Camera);
965 void RenderSkybox(
const glm::mat4& ViewMatrix,
const glm::mat4& ProjectionMatrix);
967 TObjectPtr<LShader> GetDebugShader();
968 TObjectPtr<LShader> GetScreenShader();
970 static uint32_t LoadCubemap(std::vector<std::string> faces)
972 LK_MARK_FUNC_FOR_REMOVAL();
975 glGenTextures(1, &TextureID);
976 glBindTexture(GL_TEXTURE_CUBE_MAP, TextureID);
978 int Width, Height, Channels;
979 for (uint32_t i = 0; i < faces.size(); i++)
981 unsigned char* Data = stbi_load(faces[i].c_str(), &Width, &Height, &Channels, 0);
985 glTexImage2D((GL_TEXTURE_CUBE_MAP_POSITIVE_X + i), 0, GL_RGB, Width, Height, 0, GL_RGB, GL_UNSIGNED_BYTE, Data)
987 stbi_image_free(Data);
991 LK_CORE_ASSERT(
false,
"Failed to load texture {}", faces[i]);
992 stbi_image_free(Data);
996 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
997 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
998 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
999 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
1000 LK_OpenGL_Verify(glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE));
1007 LK_MARK_FUNC_FOR_REMOVAL();
1009 LK_CORE_DEBUG_TAG(
"LOpenGL",
"Generating skybox");
1010 LK_OpenGL_Verify(glGenVertexArrays(1, &InSkyboxVao));
1011 LK_OpenGL_Verify(glGenBuffers(1, &InSkyboxVbo));
1012 LK_OpenGL_Verify(glBindVertexArray(InSkyboxVao));
1013 LK_OpenGL_Verify(glBindBuffer(GL_ARRAY_BUFFER, InSkyboxVbo));
1014 LK_OpenGL_Verify(glBufferData(GL_ARRAY_BUFFER,
sizeof(Geometry::Vertices::Skybox), &Geometry::Vertices::Skybox, GL_STATIC_DRAW));
1015 LK_OpenGL_Verify(glEnableVertexAttribArray(0));
1016 LK_OpenGL_Verify(glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 *
sizeof(
float), (
void*)0));
1018 SkyboxShader = LShader::Create(
"Assets/Shaders/OpenGL/Skybox.shader");
1019 SkyboxShader->Bind();
1020 SkyboxShader->Set(
"skybox", 0);
1023 static void RenderSkybox(
const LRendererID texture,
const glm::mat4& view,
const glm::mat4& projection)
1025 LK_MARK_FUNC_FOR_REMOVAL();
1028 LK_OpenGL_Verify(glDepthFunc(GL_LEQUAL));
1029 SkyboxShader->Bind();
1030 SkyboxShader->Set(
"view", view);
1031 SkyboxShader->Set(
"projection", projection);
1034 LK_OpenGL_Verify(glBindVertexArray(SkyboxVAO));
1035 LK_OpenGL_Verify(glActiveTexture(GL_TEXTURE0));
1036 LK_OpenGL_Verify(glBindTexture(GL_TEXTURE_CUBE_MAP, texture));
1037 LK_OpenGL_Verify(glDrawArrays(GL_TRIANGLES, 0, 36));
1038 LK_OpenGL_Verify(glBindVertexArray(0));
1039 LK_OpenGL_Verify(glDepthFunc(GL_LESS));
1048 FORCEINLINE
static constexpr const char* ToString(
const EArrayTextureDimension TextureArrayDimension)
1050 switch (TextureArrayDimension)
1052 case EArrayTextureDimension::Dim_512x512:
return "512x512";
1053 case EArrayTextureDimension::Dim_1024x1024:
return "1024x1024";
1054 case EArrayTextureDimension::Dim_2048x2048:
return "2048x2048";
1055 case EArrayTextureDimension::Dim_4096x4096:
return "4096x4096";
1058 LK_CORE_ASSERT(
false,
"Unknown ETextureArrayDimension value: {}",
static_cast<int>(TextureArrayDimension));
uint32_t LRendererID
Definition CoreTypes.h:30
void InitializeEnvironment()
Setup debug environment with a plane and two cubes.
Definition LkOpenGL.cpp:268
EShaderDataType
Definition VertexBufferLayout.h:12
Definition LkOpenGL.h:156
Definition LkOpenGL.h:165
static FORCEINLINE int GetSourceBlendFunction(const ESourceBlendFunction InBlendFunction)
Convert ESourceBlendFunction to OpenGL source blend function.
Definition LkOpenGL.h:169
static FORCEINLINE int GetDestinationBlendFunction(const EDestinationBlendFunction InBlendFunction)
Convert EDestinationBlendFunction to OpenGL destination blend function.
Definition LkOpenGL.h:187
static FORCEINLINE float GetSampleDepth(int x, int y, int WindowWidth, int WindowHeight)
Definition LkOpenGL.h:577
Definition LkOpenGL.h:141
static void LoadInfo()
Load info about the GL backend. Load major/minor version, populate vector with supported extensions.
Definition LkOpenGL.h:90