Major Maintenance

- Major tidying
- Moved 'RendererProgram' classes out of the 'Renderer' class
- Moved 'RenderCommand' member variable out of 'GraphicsContext' and into
       the 'Renderer' class as a unique_ptr. results in 'Renderer' taking a
       windowHandle for construction
- Defined new macros for max quads in 'Renderer.h'
- Added the 'Stringifier' to 'Base.h'
- Added the 'ResourceManager' to the 'LightEngine.h'
- Application now logs the current file directory
- Fixed the forward declaration in GraphicsContext
- Fixed the debug break in Base.h
- Fixed 'dxShader' not logging compile errors
- 'glVertexLayout' now takes in a shared_ptr for 'VertexBuffer'
- 'glShader' now logs the shader compilation errors properly
- 'dxVertexLayout' now takes in a shared_ptr for 'Shader"
- Modified 'dxSharedContext' members to be private and made getters for them
- 'dxRenderCommand::SwapBuffers' now throws dxException for
       DXGI_ERROR_DEVICE_REMOD error
This commit is contained in:
Light 2021-07-01 19:25:46 +04:30
parent 7872e42c76
commit 2ab97d3863
70 changed files with 709 additions and 587 deletions

View file

@ -6,14 +6,16 @@ R"(
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Color;
out vec4 fragColor;
out vec4 vso_FragmentColor;
void main()
{
gl_Position = vec4(a_Position, 1.0);
fragColor = a_Color;
vso_FragmentColor = a_Color;
}
-GLSL
+HLSL
struct VertexOut
{
@ -26,6 +28,7 @@ VertexOut main(float3 InPosition : POSITION, float4 InColor : COLOR)
VertexOut vso;
vso.Position = float4(InPosition.x, InPosition.y, InPosition.z, 1.0);
vso.Color = InColor;
return vso;
}
-HLSL)"
@ -35,15 +38,17 @@ R"(
+GLSL
#version 440 core
in vec4 fragColor;
in vec4 vso_FragmentColor;
out vec4 FragmentColor;
out vec4 fso_FragmentColor;
void main()
{
FragmentColor = fragColor;
fso_FragmentColor = vso_FragmentColor;
}
-GLSL
+HLSL
float4 main(float4 Color : COLOR) : SV_Target
{

View file

@ -4,28 +4,30 @@ R"(
#version 440 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoords;
layout(location = 1) in vec2 a_TexCoord;
out vec2 texCoords;
out vec2 vso_TexCoord;
void main()
{
gl_Position = vec4(a_Position, 1.0);
texCoords = a_TexCoords;
vso_TexCoord = a_TexCoord;
}
-GLSL
+HLSL
struct VertexOut
{
float2 uv : UV;
float4 position : SV_Position;
float2 TexChoord : TEXCHOORD;
float4 Position : SV_Position;
};
VertexOut main(float3 InPosition : POSITION, float2 InUV : UV)
VertexOut main(float3 InPosition : POSITION, float2 InTexChoord : TEXCHOORD)
{
VertexOut vso;
vso.position = float4(InPosition, 1.0);
vso.uv = InUV;
vso.Position = float4(InPosition, 1.0);
vso.TexChoord = InTexChoord;
return vso;
}
@ -37,24 +39,26 @@ R"(
+GLSL
#version 440 core
in vec2 texCoords;
in vec2 vso_TexCoord;
uniform sampler2D u_Texture;
out vec4 FragmentColor;
out vec4 fso_FragmentColor;
void main()
{
FragmentColor = texture(u_Texture, texCoords);
fso_FragmentColor = texture(u_Texture, vso_TexCoord);
}
-GLSL
+HLSL
sampler samplerState : register(s0);
Texture2D<float4> myTexture : register(t0);
float4 main(float2 InUV : UV) : SV_Target
float4 main(float2 InTexChoord : TEXCHOORD) : SV_Target
{
return myTexture.Sample(samplerState, InUV);
return myTexture.Sample(samplerState, InTexChoord);
}
-HLSL

View file

@ -5,12 +5,16 @@
#endif
#include "Debug/Exceptions.h"
#include "Utility/Stringifier.h"
#include <memory>
#define LT_WIN(x) // Windows
#define LT_LIN(x) // Linux
#define LT_MAC(x) // Mac
#define LT_WIN(x) // windows
#define LT_LIN(x) // linux
#define LT_MAC(x) // mac
// #todo: figure out a proper way to give version numbers
#define LT_VERSION "0.5.1"
#if defined(LIGHT_PLATFORM_WINDOWS)
#define LT_BUILD_PLATFORM "Windows"
@ -29,5 +33,10 @@
#define BIT(x) 1 << x
// #todo: log to file in distribution builds
#define LT_ENGINE_ASSERT(x, ...) { if(!(x)) { LT_ENGINE_CRITICAL(__VA_ARGS__); /* __builtin_trap() */; throw ::Light::FailedAssertion(__FILE__, __LINE__); } }
#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); __builtin_trap(); } }
#if defined(LIGHT_PLATFORM_WINDOWS)
#define LT_ENGINE_ASSERT(x, ...) { if(!(x)) { LT_ENGINE_CRITICAL(__VA_ARGS__); __debugbreak(); throw ::Light::FailedAssertion(__FILE__, __LINE__); } }
#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); __debugbreak(); } }
#elif defined(LIGHT_PLATFORM_LINUX)
#define LT_ENGINE_ASSERT(x, ...) { if(!(x)) { LT_ENGINE_CRITICAL(__VA_ARGS__); /* #todo: implement break */ throw ::Light::FailedAssertion(__FILE__, __LINE__); } }
#define LT_CLIENT_ASSERT(x, ...) { if(!(x)) { LT_CLIENT_CRITICAL(__VA_ARGS__); /* #todo: implement break */ } }
#endif

View file

@ -11,6 +11,8 @@
#include "UserInterface/UserInterface.h"
#include <filesystem>
namespace Light {
Application::Application()
@ -38,10 +40,10 @@ namespace Light {
// reveal window
m_Window->SetVisibility(true);
//* [ GAMELOOP ] *//
//** GAMELOOP **//
while (!m_Window->IsClosed())
{
// update layyers
// update layers
m_LayerStack.OnUpdate(1000.0f / 60.0f); // #todo: implement time
// render layers
@ -53,10 +55,6 @@ namespace Light {
m_Window->GetGfxContext()->GetUserInterface()->Begin();
m_Window->GetGfxContext()->GetUserInterface()->End();
// swap buffers
m_Window->GetGfxContext()->GetRenderCommand()->SwapBuffers();
m_Window->GetGfxContext()->GetRenderCommand()->ClearBackBuffer();
// poll events
m_Window->PollEvents();
}
@ -85,6 +83,7 @@ namespace Light {
LT_ENGINE_INFO("________________________________________");
LT_ENGINE_INFO("Platform::");
LT_ENGINE_INFO(" OS: {}", LT_BUILD_PLATFORM);
LT_ENGINE_INFO(" DIR: {}", std::filesystem::current_path().generic_string());
LT_ENGINE_INFO("________________________________________");
}

View file

@ -34,18 +34,18 @@ namespace Light {
virtual void PollEvents() = 0;
virtual void OnEvent(const Event& event) = 0;
// Setters //
virtual void SetProperties(const WindowProperties& properties) = 0;
//* SETTERS *//
virtual void SetProperties(const WindowProperties& properties, bool affectVisibility = false) = 0;
virtual void SetTitle(const std::string& title) = 0;
virtual void SetSize(const glm::uvec2& size, bool add = false) = 0; // pass 0 for width or height for single dimension resizing
virtual void SetSize(const glm::uvec2& size, bool additive = false) = 0; // pass 0 for width or height for single dimension resizing
inline void Close() { b_Closed = true; }
virtual void SetVSync(bool vsync, bool toggle = false) = 0;
virtual void SetVisibility(bool visible, bool toggle = false) = 0;
// Getters //
//* GETTERS *//
inline GraphicsContext* GetGfxContext() const { return m_GraphicsContext.get(); }
inline const WindowProperties& GetProperties() const { return m_Properties; }

View file

@ -4,8 +4,6 @@
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include "Utility/Stringifier.h"
namespace Light {
std::shared_ptr<spdlog::logger> Logger::s_EngineLogger = nullptr;

View file

@ -43,7 +43,7 @@
namespace Light {
// #todo: add a FileLogger
// #todo: extend
class Logger
{
private:

View file

@ -4,7 +4,7 @@
#include <LightEngine.h>
// To be defined in client project
// to be defined in client project
extern Light::Application* Light::CreateApplication();
// #todo: use windows specific stuff
@ -22,17 +22,17 @@ int main(int argc, char** argv)
}
catch (Light::FailedAssertion)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled FailedAssertion");
LT_ENGINE_CRITICAL("main: exitting due to unhandled 'FailedAssertion'");
exitCode = -1;
}
catch(Light::glException)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled glException");
LT_ENGINE_CRITICAL("main: exitting due to unhandled 'glException'");
exitCode = -2;
}
catch (Light::dxException)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled dxException");
LT_ENGINE_CRITICAL("main: exitting due to unhandled 'dxException'");
exitCode = -3;
}
@ -44,7 +44,7 @@ int main(int argc, char** argv)
#include <LightEngine.h>
// To be defined in client project
// to be defined in client project
extern Light::Application* Light::CreateApplication();
// #todo: use linux specific stuff
@ -62,12 +62,12 @@ int main(int argc, char* argv[])
}
catch (Light::FailedAssertion)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled FailedAssertion");
LT_ENGINE_CRITICAL("main: exitting due to unhandled 'FailedAssertion'");
exitCode = -1;
}
catch(Light::glException)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled glException");
LT_ENGINE_CRITICAL("main: exitting due to unhandled 'glException'");
exitCode = -2;
}

View file

@ -20,10 +20,10 @@ namespace Light {
{
None = 0,
WindowEventCategory = BIT(0),
InputEventCategory = BIT(1),
WindowEventCategory = BIT(0),
InputEventCategory = BIT(1),
KeyboardEventCategory = BIT(2),
MouseEventCategory = BIT(3),
MouseEventCategory = BIT(3),
};
#define EVENT_TYPE(type) EventType GetEventType() const override { return ::Light::EventType:: type; }

View file

@ -13,7 +13,7 @@ namespace Light {
const int m_Key;
public:
KeyPressedEvent(int key): m_Key(key) {}
KeyPressedEvent(int key): m_Key(key) { }
inline int GetKey() const { return m_Key; }
@ -33,7 +33,7 @@ namespace Light {
const int m_Key;
public:
KeyReleasedEvent(int key): m_Key(key) {}
KeyReleasedEvent(int key): m_Key(key) { }
inline int GetKey() const { return m_Key; }

View file

@ -15,7 +15,7 @@ namespace Light {
const glm::vec2 m_Position;
public:
MouseMovedEvent(float x, float y) : m_Position(x, y) {}
MouseMovedEvent(float x, float y) : m_Position(x, y) { }
inline const glm::vec2& GetPosition() const { return m_Position; }
@ -38,7 +38,7 @@ namespace Light {
const float m_Offset;
public:
WheelScrolledEvent(float offset) : m_Offset(offset) {}
WheelScrolledEvent(float offset) : m_Offset(offset) { }
inline float GetOffset() const { return m_Offset; }
@ -58,7 +58,7 @@ namespace Light {
const int m_Button;
public:
ButtonPressedEvent(int button): m_Button(button) {}
ButtonPressedEvent(int button): m_Button(button) { }
inline int GetButton() const { return m_Button; }
@ -78,7 +78,7 @@ namespace Light {
const int m_Button;
public:
ButtonReleasedEvent(int button) : m_Button(button) {}
ButtonReleasedEvent(int button) : m_Button(button) { }
inline int GetButton() const { return m_Button; }

View file

@ -26,7 +26,7 @@ namespace Light {
const glm::ivec2 m_Position;
public:
WindowMovedEvent(int x, int y): m_Position(x, y) {}
WindowMovedEvent(int x, int y): m_Position(x, y) { }
const glm::ivec2& GetPosition() const{ return m_Position; }
@ -46,7 +46,7 @@ namespace Light {
const glm::uvec2 m_Size;
public:
WindowResizedEvent(unsigned int width, unsigned int height): m_Size(width, height) {}
WindowResizedEvent(unsigned int width, unsigned int height): m_Size(width, height) { }
const glm::uvec2& GetSize() const { return m_Size; }

View file

@ -11,10 +11,9 @@
#include "GraphicsContext.h"
namespace Light {
//* VERTEX BUFFER *//
//* VERTEX_BUFFER *//
VertexBuffer* VertexBuffer::Create(float* vertices, unsigned int stride, unsigned int count, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
@ -26,12 +25,12 @@ namespace Light {
return new dxVertexBuffer(vertices, stride, count, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "VertexBuffer::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "VertexBuffer::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}
//* INDEX BUFFER *//
//* INDEX_BUFFER *//
IndexBuffer* IndexBuffer::Create(unsigned int* indices, unsigned int count, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
@ -43,7 +42,7 @@ namespace Light {
return new dxIndexBuffer(indices, count, std::dynamic_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "IndexBuffer::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "IndexBuffer::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}

View file

@ -6,7 +6,7 @@ namespace Light {
class SharedContext;
//* VERTEX BUFFER *//
//* VERTEX_BUFFER *//
class VertexBuffer
{
public:
@ -22,7 +22,7 @@ namespace Light {
VertexBuffer() = default;
};
//* INDEX BUFFER *//
//* INDEX_BUFFER *//
class IndexBuffer
{
public:

View file

@ -4,16 +4,14 @@
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxGraphicsContext.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "Buffers.h"
#include "Renderer.h"
#include "RenderCommand.h"
#include "UserInterface/UserInterface.h"
// forward declaration
#include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h"
#include "UserInterface/UserInterface.h"
#include "Utility/ResourceManager.h"
#include "Utility/Stringifier.h"
namespace Light {
@ -23,23 +21,22 @@ namespace Light {
GraphicsContext* GraphicsContext::Create(GraphicsAPI api, GLFWwindow* windowHandle)
{
// terminate gfx context dependent classes
// terminate 'GraphicsContext' dependent classes
if (s_Context)
{
s_Context->m_Renderer.reset();
s_Context->m_RenderCommand.reset();
s_Context->m_UserInterface.reset();
delete s_Context;
}
// determine the default api
if (api == GraphicsAPI::Default)
{
#if defined(LIGHT_PLATFORM_WINDOWS)
api = GraphicsAPI::DirectX;
#elif defined(LIGHT_PLATFORM_LINUX)
// #todo:
api = GraphicsContext::OpenGL;
#elif defined(LIGHT_PLATFORM_MAC)
// #todo:
#endif
@ -57,20 +54,17 @@ namespace Light {
break;)
default:
LT_ENGINE_ASSERT(false, "GraphicsContext::Create: invalid/unsupported GraphicsAPI {}", Stringifier::GraphicsAPIToString(api));
LT_ENGINE_ASSERT(false, "GraphicsContext::Create: invalid/unsupported 'GraphicsAPI' {}", Stringifier::GraphicsAPIToString(api));
return nullptr;
}
// create gfx context dependent classes
// create 'GraphicsContext' dependent classes
s_Context->m_ResourceManager = std::unique_ptr<ResourceManager>(ResourceManager::Create(s_Context->m_SharedContext));
s_Context->m_RenderCommand = std::unique_ptr<RenderCommand>(RenderCommand::Create(windowHandle, s_Context->m_SharedContext));
s_Context->m_UserInterface = std::unique_ptr<UserInterface>(UserInterface::Create(windowHandle, s_Context->m_SharedContext));
s_Context->m_Renderer = std::unique_ptr<Renderer>(Renderer::Create(s_Context->m_RenderCommand, s_Context->m_SharedContext));
s_Context->m_Renderer = std::unique_ptr<Renderer>(Renderer::Create(windowHandle, s_Context->m_SharedContext));
// check
LT_ENGINE_ASSERT(s_Context->m_ResourceManager, "GraphicsContext::Create: failed to create ResourceManager");
LT_ENGINE_ASSERT(s_Context->m_RenderCommand, "GraphicsContext::Create: failed to create RenderCommand");
LT_ENGINE_ASSERT(s_Context->m_UserInterface, "GraphicsContext::Create: failed to create UserInterface");
LT_ENGINE_ASSERT(s_Context->m_Renderer, "GraphicsContext::Create: failed to create Renderer");

View file

@ -2,19 +2,15 @@
#include "Base.h"
#include "SharedContext.h"
struct GLFWwindow;
#include "Utility/ResourceManager.h"
namespace Light {
class ResourceManager;
class Renderer;
class RenderCommand;
class UserInterface;
class Renderer;
class SharedContext;
class WindowResizedEvent;
@ -23,8 +19,8 @@ namespace Light {
Default = 0,
OpenGL,
DirectX,
Vulkan,
Metal
Vulkan, // :#todo
Metal // :#todo
};
class GraphicsContext
@ -33,10 +29,8 @@ namespace Light {
static GraphicsContext* s_Context;
std::unique_ptr<ResourceManager> m_ResourceManager;
std::unique_ptr<Renderer> m_Renderer;
std::shared_ptr<RenderCommand> m_RenderCommand;
std::unique_ptr<UserInterface> m_UserInterface;
std::unique_ptr<Renderer> m_Renderer;
protected:
GraphicsAPI m_GraphicsAPI;
@ -57,7 +51,6 @@ namespace Light {
static inline GraphicsAPI GetGraphicsAPI() { return s_Context->m_GraphicsAPI; }
inline Renderer* GetRenderer() { return m_Renderer.get(); }
inline RenderCommand* GetRenderCommand() { return m_RenderCommand.get(); }
inline UserInterface* GetUserInterface() { return m_UserInterface.get(); }
protected:

View file

@ -2,11 +2,9 @@
#include "RenderCommand.h"
#include "OpenGL/glRenderCommand.h"
#include "SharedContext.h"
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxRenderCommand.h"
#include "Directx/dxSharedContext.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
@ -24,7 +22,7 @@ namespace Light {
return new dxRenderCommand((std::static_pointer_cast<dxSharedContext>)(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "RenderCommand::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "RenderCommand::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}

View file

@ -11,6 +11,8 @@ namespace Light {
class RenderCommand
{
public:
static RenderCommand* Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
RenderCommand(const RenderCommand&) = delete;
RenderCommand& operator=(const RenderCommand&) = delete;
@ -22,8 +24,6 @@ namespace Light {
virtual void Draw(unsigned int count) = 0;
virtual void DrawIndexed(unsigned int count) = 0;
static RenderCommand* Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
protected:
RenderCommand() = default;
};

View file

@ -1,47 +1,26 @@
#include "ltpch.h"
#include "Renderer.h"
#include "GraphicsContext.h"
#include "Utility/ResourceManager.h"
#include "../res/Shaders/QuadShader.h"
#include "../res/Shaders/TextureShader.h"
#include "RenderCommand.h"
#include "Texture.h"
namespace Light {
Renderer* Renderer::s_Context;
Renderer* Renderer::s_Context = nullptr;
Renderer::Renderer(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext)
: m_RenderCommand(renderCommand), m_SharedContext(sharedContext)
Renderer::Renderer(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext)
: m_QuadRenderer(LT_MAX_QUAD_RENDERER_VERTICES, sharedContext),
m_TextureRenderer(LT_MAX_TEXTURE_RENDERER_VERTICES, sharedContext)
{
LT_ENGINE_ASSERT(!s_Context, "Renderer::Renderer: an instance of 'Renderer' already exists, do not construct this class!");
s_Context = this;
ResourceManager::CreateShader("QuadShader", LT_ENGINE_RESOURCES_QUAD_SHADER_VS, LT_ENGINE_RESOURCES_QUAD_SHADER_PS);
ResourceManager::CreateShader("TextureShader", LT_ENGINE_RESOURCES_TEXTURE_SHADER_VS, LT_ENGINE_RESOURCES_TEXTURE_SHADER_PS);
//** quad renderer **//
m_QuadRenderer.shader = ResourceManager::GetShader("QuadShader");
m_QuadRenderer.vertexBuffer = std::unique_ptr<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(QuadRendererProgram::QuadVertexData), LT_MAX_QUAD * 4, m_SharedContext));
m_QuadRenderer.indexBuffer = std::unique_ptr<IndexBuffer>(IndexBuffer::Create(nullptr, LT_MAX_QUAD * 6, m_SharedContext));
m_QuadRenderer.vertexLayout = std::unique_ptr<VertexLayout>(VertexLayout::Create(m_QuadRenderer.vertexBuffer.get(), m_QuadRenderer.shader.get(), { { "POSITION", VertexElementType::Float3 },{ "COLOR", VertexElementType::Float4 } }, m_SharedContext));
//** quad renderer **//
//** texture rendererc **//
m_TextureRenderer.shader = ResourceManager::GetShader("TextureShader");
m_TextureRenderer.vertexBuffer = std::unique_ptr<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(TextureRendererProgram::TextureVertexData), LT_MAX_QUAD * 4, m_SharedContext));
m_TextureRenderer.indexBuffer = std::unique_ptr<IndexBuffer>(IndexBuffer::Create(nullptr, LT_MAX_QUAD * 6, m_SharedContext));
m_TextureRenderer.vertexLayout = std::unique_ptr<VertexLayout>(VertexLayout::Create(m_TextureRenderer.vertexBuffer.get(), m_TextureRenderer.shader.get(), { { "POSITION", VertexElementType::Float3 },{ "UV", VertexElementType::Float2 } }, m_SharedContext));
//** texture rendererc **//
m_RenderCommand = std::unique_ptr<RenderCommand>(RenderCommand::Create(windowHandle, sharedContext));
}
Renderer* Renderer::Create(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext)
Renderer* Renderer::Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext)
{
return new Renderer(renderCommand, sharedContext);
return new Renderer(windowHandle, sharedContext);
}
void Renderer::DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
@ -56,81 +35,73 @@ namespace Light {
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
{
// check
if (m_QuadRenderer.mapCurrent + 4 >= m_QuadRenderer.mapEnd)
{
LT_ENGINE_WARN("Render::DrawQuad: max calls per frame exceeded the limit: {}", LT_MAX_QUAD);
EndScene();
m_QuadRenderer.Map();
}
// locals
QuadRendererProgram::QuadVertexData* bufferMap = m_QuadRenderer.GetMapCurrent();
const float xMin = position.x;
const float yMin = position.y;
const float xMax = position.x + size.x;
const float yMax = position.y + size.y;
// TOP_LEFT
m_QuadRenderer.mapCurrent[0].position = { xMin, yMin, position.z };
m_QuadRenderer.mapCurrent[0].tint = tint;
//** TOP_LEFT **//
bufferMap[0].position = { xMin, yMin, position.z };
bufferMap[0].tint = tint;
// TOP_RIGHT
m_QuadRenderer.mapCurrent[1].position = { xMax, yMin, position.z };
m_QuadRenderer.mapCurrent[1].tint = tint;
//** TOP_RIGHT **//
bufferMap[1].position = { xMax, yMin, position.z };
bufferMap[1].tint = tint;
// BOTTOM_RIGHT
m_QuadRenderer.mapCurrent[2].position = { xMax, yMax, position.z };
m_QuadRenderer.mapCurrent[2].tint = tint;
//** BOTTOM_RIGHT **//
bufferMap[2].position = { xMax, yMax, position.z };
bufferMap[2].tint = tint;
// BOTTOM_LEFT
m_QuadRenderer.mapCurrent[3].position = { xMin, yMax, position.z };
m_QuadRenderer.mapCurrent[3].tint = tint;
//** BOTTOM_LEFT **//
bufferMap[3].position = { xMin, yMax, position.z };
bufferMap[3].tint = tint;
// advance
m_QuadRenderer.mapCurrent += 4;
m_QuadRenderer.quadCount++;
if (!m_QuadRenderer.Advance())
{
EndScene();
BeginScene();
}
}
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture)
{
// check
if (m_TextureRenderer.mapCurrent + 4 >= m_TextureRenderer.mapEnd)
{
LT_ENGINE_WARN("Render::DrawQuad(Texture): max calls per frame exceeded the limit: {}", LT_MAX_QUAD);
EndScene();
m_TextureRenderer.Map();
}
// #todo: implement a proper binding
texture->Bind();
// locals
TextureRendererProgram::TextureVertexData* bufferMap = m_TextureRenderer.GetMapCurrent();
const float xMin = position.x;
const float yMin = position.y;
const float xMax = position.x + size.x;
const float yMax = position.y + size.y;
// TOP_LEFT
m_TextureRenderer.mapCurrent[0].position = { xMin, yMin, position.z };
m_TextureRenderer.mapCurrent[0].uv = { 0, 0 };
//** TOP_LEFT **//
bufferMap[0].position = { xMin, yMin, position.z };
bufferMap[0].texcoord = { 0.0f, 0.0f };
// TOP_RIGHT
m_TextureRenderer.mapCurrent[1].position = { xMax, yMin, position.z };
m_TextureRenderer.mapCurrent[1].uv = { 1, 0 };
//** TOP_RIGHT **//
bufferMap[1].position = { xMax, yMin, position.z };
bufferMap[1].texcoord = { 1.0f, 0.0f };
// BOTTOM_RIGHT
m_TextureRenderer.mapCurrent[2].position = { xMax, yMax, position.z };
m_TextureRenderer.mapCurrent[2].uv = { 1, 1 };
//** BOTTOM_RIGHT **//
bufferMap[2].position = { xMax, yMax, position.z };
bufferMap[2].texcoord = { 1.0f, 1.0f };
// BOTTOM_LEFT
m_TextureRenderer.mapCurrent[3].position = { xMin, yMax, position.z };
m_TextureRenderer.mapCurrent[3].uv = { 0, 1 };
//** BOTTOM_LEFT **//
bufferMap[3].position = { xMin, yMax, position.z };
bufferMap[3].texcoord = { 0.0f, 1.0f };
// advance
m_TextureRenderer.mapCurrent += 4;
m_TextureRenderer.quadCount++;
if (!m_TextureRenderer.Advance())
{
EndScene();
BeginScene();
}
}
void Renderer::BeginScene()
@ -141,21 +112,22 @@ namespace Light {
void Renderer::EndScene()
{
if (m_QuadRenderer.quadCount)
//** QUAD_RENDERER **//
if (m_QuadRenderer.GetQuadCount())
{
m_QuadRenderer.Bind();
m_RenderCommand->DrawIndexed(m_QuadRenderer.quadCount * 6);
m_QuadRenderer.quadCount = 0;
m_RenderCommand->DrawIndexed(m_QuadRenderer.GetQuadCount() * 6u);
}
if (m_TextureRenderer.quadCount)
//** TEXT_RENDERER **//
if (m_TextureRenderer.GetQuadCount())
{
m_TextureRenderer.Bind();
m_RenderCommand->DrawIndexed(m_TextureRenderer.quadCount * 6);
m_TextureRenderer.quadCount = 0;
m_RenderCommand->DrawIndexed(m_TextureRenderer.GetQuadCount() * 6u);
}
m_RenderCommand->SwapBuffers();
m_RenderCommand->ClearBackBuffer();
}
}

View file

@ -2,116 +2,33 @@
#include "Base.h"
#include "Shader.h"
#include "Buffers.h"
#include "VertexLayout.h"
#include "RendererPrograms/QuadRendererProgram.h"
#include "RendererPrograms/TextureRendererProgram.h"
#include <glm/glm.hpp>
#define LT_MAX_QUAD_RENDERER_VERTICES 1028u * 4u
#define LT_MAX_TEXTURE_RENDERER_VERTICES 1028u * 4u
#include <memory>
#define LT_MAX_QUAD 124
struct GLFWwindow;
namespace Light {
class RenderCommand;
class SharedContext;
class Texture;
struct RendererProgram
{
virtual void Map() = 0;
virtual void Bind() = 0;
};
class SharedContext;
class Renderer
{
private:
struct QuadRendererProgram : RendererProgram
{
// graphics context
std::shared_ptr<Shader> shader;
std::shared_ptr<VertexBuffer> vertexBuffer;
std::shared_ptr<IndexBuffer> indexBuffer;
std::shared_ptr<VertexLayout> vertexLayout;
// buffer data
struct QuadVertexData
{
glm::vec3 position;
glm::vec4 tint;
};
QuadVertexData* mapCurrent = nullptr;
QuadVertexData* mapEnd = nullptr;
unsigned int quadCount = 0u;
// functions
void Map()
{
mapCurrent = (QuadVertexData*)vertexBuffer->Map();
mapEnd = mapCurrent + LT_MAX_QUAD * 4;
}
void Bind()
{
vertexBuffer->UnMap();
shader->Bind();
vertexLayout->Bind();
vertexBuffer->Bind();
indexBuffer->Bind();
}
};
struct TextureRendererProgram : public RendererProgram
{
// graphics context
std::shared_ptr<Shader> shader;
std::shared_ptr<VertexBuffer> vertexBuffer;
std::shared_ptr<IndexBuffer> indexBuffer;
std::shared_ptr<VertexLayout> vertexLayout;
// buffer data
struct TextureVertexData
{
glm::vec3 position;
glm::vec2 uv;
};
TextureVertexData* mapCurrent = nullptr;
TextureVertexData* mapEnd = nullptr;
unsigned int quadCount = 0u;
// functions
void Map()
{
mapCurrent = (TextureVertexData*)vertexBuffer->Map();
mapEnd = mapCurrent + LT_MAX_QUAD * 4;
}
void Bind()
{
vertexBuffer->UnMap();
shader->Bind();
vertexLayout->Bind();
vertexBuffer->Bind();
indexBuffer->Bind();
}
};
static Renderer* s_Context;
QuadRendererProgram m_QuadRenderer;
TextureRendererProgram m_TextureRenderer;
std::shared_ptr<RenderCommand> m_RenderCommand;
std::unique_ptr<RenderCommand> m_RenderCommand;
std::shared_ptr<SharedContext> m_SharedContext;
std::shared_ptr<Texture> m_TestTexture;
public:
static Renderer* Create(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext);
static Renderer* Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
static void DrawQuad(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture);
@ -120,7 +37,7 @@ namespace Light {
void EndScene();
private:
Renderer(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext);
Renderer(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture);

View file

@ -0,0 +1,54 @@
#include "ltpch.h"
#include "QuadRendererProgram.h"
#include "Graphics/Shader.h"
#include "Graphics/Buffers.h"
#include "Graphics/VertexLayout.h"
#include "../res/Shaders/QuadShader.h"
#include "Utility/ResourceManager.h"
namespace Light {
QuadRendererProgram::QuadRendererProgram(unsigned int maxVertices, std::shared_ptr<SharedContext> sharedContext)
: m_MaxVertices(maxVertices)
{
ResourceManager::CreateShader("LT_ENGINE_RESOURCES_QUAD_SHADER", LT_ENGINE_RESOURCES_QUAD_SHADER_VS, LT_ENGINE_RESOURCES_QUAD_SHADER_PS);
m_Shader = ResourceManager::GetShader("LT_ENGINE_RESOURCES_QUAD_SHADER");
m_VertexBuffer = std::shared_ptr<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(QuadVertexData), maxVertices, sharedContext));
m_IndexBuffer = std::shared_ptr<IndexBuffer>(IndexBuffer::Create(nullptr, (maxVertices / 4) * 6, sharedContext));
m_VertexLayout = std::shared_ptr<VertexLayout>(VertexLayout::Create(m_VertexBuffer, m_Shader, { { "POSITION", VertexElementType::Float3 },
{ "COLOR" , VertexElementType::Float4 }}, sharedContext));
}
bool QuadRendererProgram::Advance()
{
if (m_MapCurrent + 4 >= m_MapEnd)
{
LT_ENGINE_WARN("QuadRendererProgram::Advance: 'VertexBuffer' map went beyond 'MaxVertices': {}", m_MaxVertices);
return false;
}
m_MapCurrent += 4;
m_QuadCount++;
}
void QuadRendererProgram::Map()
{
m_QuadCount = 0u;
m_MapCurrent = (QuadRendererProgram::QuadVertexData*)m_VertexBuffer->Map();
m_MapEnd = m_MapCurrent + m_MaxVertices;
}
void QuadRendererProgram::Bind()
{
m_VertexBuffer->UnMap();
m_Shader->Bind();
m_VertexLayout->Bind();
m_VertexBuffer->Bind();
m_IndexBuffer->Bind();
}
}

View file

@ -0,0 +1,51 @@
#pragma once
#include "Base.h"
#include "RendererProgram.h"
#include <glm/glm.hpp>
namespace Light {
class Shader;
class VertexBuffer;
class IndexBuffer;
class VertexLayout;
class SharedContext;
class QuadRendererProgram : RendererProgram
{
private:
std::shared_ptr<Shader> m_Shader;
std::shared_ptr<VertexBuffer> m_VertexBuffer;
std::shared_ptr<IndexBuffer> m_IndexBuffer;
std::shared_ptr<VertexLayout> m_VertexLayout;
struct QuadVertexData; // <-- forward declaration
QuadVertexData* m_MapCurrent = nullptr;
QuadVertexData* m_MapEnd = nullptr;
unsigned int m_QuadCount = 0u;
unsigned int m_MaxVertices = 0u;
public:
struct QuadVertexData
{
glm::vec3 position;
glm::vec4 tint;
};
QuadRendererProgram(unsigned int maxVertices, std::shared_ptr<SharedContext> sharedContext);
bool Advance();
void Map() override;
void Bind() override;
inline QuadVertexData* GetMapCurrent() { return m_MapCurrent; }
inline unsigned int GetQuadCount() const { return m_QuadCount; }
inline constexpr unsigned int GetVertexSize() const { return sizeof(QuadVertexData); }
};
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "Base.h"
namespace Light {
class RendererProgram
{
virtual void Map() = 0;
virtual void Bind() = 0;
};
}

View file

@ -0,0 +1,54 @@
#include "ltpch.h"
#include "TextureRendererProgram.h"
#include "Graphics/Shader.h"
#include "Graphics/Buffers.h"
#include "Graphics/VertexLayout.h"
#include "../res/Shaders/TextureShader.h"
#include "Utility/ResourceManager.h"
namespace Light {
TextureRendererProgram::TextureRendererProgram(unsigned int maxVertices, std::shared_ptr<SharedContext> sharedContext)
: m_MaxVertices(maxVertices)
{
ResourceManager::CreateShader("LT_ENGINE_RESOURCES_TEXTURE_SHADER", LT_ENGINE_RESOURCES_TEXTURE_SHADER_VS, LT_ENGINE_RESOURCES_TEXTURE_SHADER_PS);
m_Shader = ResourceManager::GetShader("LT_ENGINE_RESOURCES_TEXTURE_SHADER");
m_VertexBuffer = std::shared_ptr<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(TextureVertexData), maxVertices, sharedContext));
m_IndexBuffer = std::shared_ptr<IndexBuffer>(IndexBuffer::Create(nullptr, (maxVertices / 4) * 6, sharedContext));
m_VertexLayout = std::shared_ptr<VertexLayout>(VertexLayout::Create(m_VertexBuffer, m_Shader, { { "POSITION", VertexElementType::Float3 },
{ "TEXCOORD", VertexElementType::Float2 }}, sharedContext));
}
bool TextureRendererProgram::Advance()
{
if (m_MapCurrent + 4 >= m_MapEnd)
{
LT_ENGINE_WARN("TextureRendererProgram::Advance: 'VertexBuffer' map went beyond 'MaxVertices': {}", m_MaxVertices);
return false;
}
m_MapCurrent += 4;
m_QuadCount++;
}
void TextureRendererProgram::Map()
{
m_QuadCount = 0u;
m_MapCurrent = (TextureRendererProgram::TextureVertexData*)m_VertexBuffer->Map();
m_MapEnd = m_MapCurrent + m_MaxVertices;
}
void TextureRendererProgram::Bind()
{
m_VertexBuffer->UnMap();
m_Shader->Bind();
m_VertexLayout->Bind();
m_VertexBuffer->Bind();
m_IndexBuffer->Bind();
}
}

View file

@ -0,0 +1,51 @@
#pragma once
#include "Base.h"
#include "RendererProgram.h"
#include <glm/glm.hpp>
namespace Light {
class Shader;
class VertexBuffer;
class IndexBuffer;
class VertexLayout;
class SharedContext;
class TextureRendererProgram : RendererProgram
{
private:
std::shared_ptr<Shader> m_Shader;
std::shared_ptr<VertexBuffer> m_VertexBuffer;
std::shared_ptr<IndexBuffer> m_IndexBuffer;
std::shared_ptr<VertexLayout> m_VertexLayout;
struct TextureVertexData; // <-- forward declaration
TextureVertexData* m_MapCurrent = nullptr;
TextureVertexData* m_MapEnd = nullptr;
unsigned int m_QuadCount = 0u;
unsigned int m_MaxVertices = 0u;
public:
struct TextureVertexData
{
glm::vec3 position;
glm::vec2 texcoord;
};
TextureRendererProgram(unsigned int maxVertices, std::shared_ptr<SharedContext> sharedContext);
bool Advance();
void Map() override;
void Bind() override;
inline TextureVertexData* GetMapCurrent() { return m_MapCurrent; }
inline unsigned int GetQuadCount() const { return m_QuadCount; }
inline constexpr unsigned int GetVertexSize() const { return sizeof(TextureVertexData); }
};
}

View file

@ -4,7 +4,7 @@
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxShader.h"
#include "DirectX/dxSharedContext.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
@ -23,7 +23,7 @@ namespace Light {
return new dxShader(vertexSource, pixelSource, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "Shader::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "Shader::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}

View file

@ -8,7 +8,6 @@ namespace Light {
{
public:
virtual ~SharedContext() = default;
void DummyFunc(const std::string& value) { LT_ENGINE_TRACE(value); }
};
}

View file

@ -1,14 +1,14 @@
#include "ltpch.h"
#include "Texture.h"
#include "GraphicsContext.h"
#include "OpenGL/glTexture.h"
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxTexture.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
namespace Light {
Texture* Texture::Create(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, std::shared_ptr<SharedContext> sharedContext)
@ -19,11 +19,10 @@ namespace Light {
return new glTexture(width, height, components, pixels);
case GraphicsAPI::DirectX: LT_WIN(
return new dxTexture(width, height, components, pixels, std::static_pointer_cast<dxSharedContext>(sharedContext));
)
return new dxTexture(width, height, components, pixels, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "Texture::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "Texture::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}

View file

@ -4,25 +4,25 @@
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxVertexLayout.h"
#include "DirectX/dxSharedContext.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
namespace Light {
VertexLayout* VertexLayout::Create(VertexBuffer* buffer, Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<SharedContext> sharedContext)
VertexLayout* VertexLayout::Create(std::shared_ptr<VertexBuffer> vertexBuffer, std::shared_ptr<Shader> shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
{
case GraphicsAPI::OpenGL:
return new glVertexLayout(buffer, elements);
return new glVertexLayout(vertexBuffer, elements);
case GraphicsAPI::DirectX: LT_WIN(
return new dxVertexLayout(shader, elements, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "VertexLayout::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "VertexLayout::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}

View file

@ -2,8 +2,6 @@
#include "Base.h"
#include <vector>
namespace Light {
class VertexBuffer;
@ -13,16 +11,16 @@ namespace Light {
enum class VertexElementType
{
Int1, Int2, Int3, Int4,
UInt1, UInt2, UInt3, UInt4,
Float1, Float2, Float3, Float4,
Int1 , Int2 , Int3 , Int4,
UInt1 , UInt2 , UInt3 , UInt4,
Float1 , Float2 , Float3 , Float4,
Double1, Double2, Double3, Double4
};
class VertexLayout
{
public:
static VertexLayout* Create(VertexBuffer* buffer, Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<SharedContext> sharedContext);
static VertexLayout* Create(std::shared_ptr<VertexBuffer> vertexBuffer, std::shared_ptr<Shader> shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<SharedContext> sharedContext);
virtual ~VertexLayout() = default;;

View file

@ -29,23 +29,23 @@ namespace Light {
inline const std::string& GetName() const { return m_Name; }
// Updates
//** UPDATES //
virtual void OnUpdate(float deltaTime) {}
virtual void OnUserInterfaceUpdate() {}
virtual void OnRender() {}
// Mouse events
//** MOUSE_EVENTS //
virtual bool OnMouseMoved(const MouseMovedEvent& event) { return false; }
virtual bool OnButtonPressed(const ButtonPressedEvent& event) { return false; }
virtual bool OnButtonReleased(const ButtonReleasedEvent& event) { return false; }
virtual bool OnWheelScrolled(const WheelScrolledEvent& event) { return false; }
// Keyboard events
//** KEYBOARD_EVENTS **//
virtual bool OnKeyPressed(const KeyPressedEvent& event) { return false; }
virtual bool OnKeyReleased(const KeyReleasedEvent& event) { return false; }
// Window Events
//** WINDOW_EVENTS **/
virtual bool OnWindowClosed(const WindowClosedEvent& event) { return false; }
virtual bool OnWindowResized(const WindowResizedEvent& event) { return false; }
virtual bool OnWindowMoved(const WindowMovedEvent& event) { return false; }

View file

@ -14,7 +14,7 @@ namespace Light {
LayerStack::LayerStack()
{
LT_ENGINE_ASSERT(!s_Context, "LayerStack::LayerStack: context re-initialization")
LT_ENGINE_ASSERT(!s_Context, "LayerStack::LayerStack: an instance of 'LayerStack' already exists, do not construct this class!")
s_Context = this;
}

View file

@ -28,7 +28,7 @@ namespace Light {
return new dxUserInterface(windowHandle, std::dynamic_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "UserInterface::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(false, "UserInterface::Create: invalid/unsupported 'GraphicsAPI' {}", GraphicsContext::GetGraphicsAPI());
return nullptr;
}
}
@ -38,7 +38,7 @@ namespace Light {
ImGuiIO& io = ImGui::GetIO();
switch (inputEvent.GetEventType())
{
// Mouse Events
//** MOUSE_EVENTS **//
case EventType::MouseMoved:
{
const MouseMovedEvent& event = (const MouseMovedEvent&)inputEvent;
@ -63,7 +63,7 @@ namespace Light {
ImGui::GetIO().MouseWheel = event.GetOffset();
return;
}
// Keyboard Events
//** MOUSE_EVENTS **//
case EventType::KeyPressed:
{
const KeyPressedEvent& event = (const KeyPressedEvent&)inputEvent;

View file

@ -2,12 +2,11 @@
#include "ResourceManager.h"
#include "Graphics/GraphicsContext.h"
#include "Graphics/Shader.h"
#include "Graphics/Texture.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>g
#include <stb_image.h>
namespace Light {
@ -21,12 +20,12 @@ namespace Light {
ResourceManager::ResourceManager(std::shared_ptr<SharedContext> sharedContext)
: m_SharedContext(sharedContext)
{
LT_ENGINE_ASSERT(!s_Context, "ResourceManager::ResourceManager: an instance of 'resource manager' already exists, do not construct this class");
LT_ENGINE_ASSERT(!s_Context, "ResourceManager::ResourceManager: an instance of 'ResourceManager' already exists, do not construct this class!");
s_Context = this;
stbi_set_flip_vertically_on_load(true);
}
void ResourceManager::CreateShaderImpl(const std::string& name, const std::string& vertexSource, const std::string& pixelSource)
{
// delim
@ -34,15 +33,15 @@ namespace Light {
GraphicsContext::GetGraphicsAPI() == GraphicsAPI::DirectX ? "HLSL" : NULL;
// check
LT_ENGINE_ASSERT(!vertexSource.empty(), "ResourceManager::CreateShader: vertex source is empty");
LT_ENGINE_ASSERT(!vertexSource.empty(), "ResourceManager::CreateShader: pixel source is empty");
LT_ENGINE_ASSERT(!delim.empty(), "ResourceManager::LoadShader: invalid/unsupported graphics api: {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(!vertexSource.empty(), "ResourceManager::CreateShader: 'vertexSource' is empty");
LT_ENGINE_ASSERT(!vertexSource.empty(), "ResourceManager::CreateShader: 'pixelSource' is empty");
LT_ENGINE_ASSERT(!delim.empty(), "ResourceManager::LoadShader: invalid/unsupported 'GraphicsAPI': {}", GraphicsContext::GetGraphicsAPI());
// save to string
std::string vsSource = vertexSource;
std::string psSource = pixelSource;
// extract source
// extract shader source
ResourceManager::ExtractShaderSource(vsSource, delim);
ResourceManager::ExtractShaderSource(psSource, delim);
@ -53,8 +52,8 @@ namespace Light {
void ResourceManager::LoadShaderImpl(const std::string& name, const std::string& vertexPath, const std::string& pixelPath)
{
// check
LT_ENGINE_ASSERT(!vertexPath.empty(), "ResourceManager::LoadShader: vertex path is empty");
LT_ENGINE_ASSERT(!pixelPath.empty(), "ResourceManager::LoadShader: pixel path is empty");
LT_ENGINE_ASSERT(!vertexPath.empty(), "ResourceManager::LoadShader: 'vertexPath' is empty");
LT_ENGINE_ASSERT(!pixelPath.empty(), "ResourceManager::LoadShader: 'pixelPath' is empty");
// initialize
std::ifstream vsStream(vertexPath), psStream(pixelPath);
@ -67,9 +66,9 @@ namespace Light {
GraphicsContext::GetGraphicsAPI() == GraphicsAPI::DirectX ? "HLSL" : NULL;
// check
LT_ENGINE_ASSERT(!delim.empty(), "ResourceManager::LoadShader: invalid/unsupported graphics api: {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(vsStream.is_open(), "ResourceManager::LoadShader: invalid vertex path: {}", vertexPath);
LT_ENGINE_ASSERT(psStream.is_open(), "ResourceManager::LoadShader: invalid pixel path: {}", pixelPath);
LT_ENGINE_ASSERT(!delim.empty(), "ResourceManager::LoadShader: invalid/unsupported 'GraphicsAPI': {}", GraphicsContext::GetGraphicsAPI());
LT_ENGINE_ASSERT(vsStream.is_open(), "ResourceManager::LoadShader: invalid 'vertexPath': {}", vertexPath);
LT_ENGINE_ASSERT(psStream.is_open(), "ResourceManager::LoadShader: invalid 'pixelPath': {}", pixelPath);
// read
while (std::getline(vsStream, line))
@ -90,18 +89,18 @@ namespace Light {
m_Shaders[name] = std::shared_ptr<Shader>(Shader::Create(vertexSource, pixelSource, m_SharedContext));
}
void ResourceManager::LoadTextureImpl(const std::string& name, const std::string& path, int desiredComponents)
void ResourceManager::LoadTextureImpl(const std::string& name, const std::string& path, unsigned int desiredComponents /* = 4u */)
{
// load image
int width, height, components;
unsigned char* pixels = stbi_load(path.c_str(), &width, &height, &components, desiredComponents);
// check
LT_ENGINE_ASSERT(pixels, "ResourceManager::LoadTexture: failed to load texture <{}>, path: {}", name, path);
LT_ENGINE_ASSERT(pixels, "ResourceManager::LoadTexture: failed to load texture <{}>, 'path': {}", name, path);
if (components != desiredComponents)
{
LT_ENGINE_WARN("ResourceManager::LoadTexture: image file compoenents != desired components ({} - {})", components, desiredComponents);
LT_ENGINE_WARN("ResourceManager::LoadTexture: <{}> path: {}", name, path);
LT_ENGINE_WARN("ResourceManager::LoadTexture: image file compoenents != 'desiredComponents' ({} - {})", components, desiredComponents);
LT_ENGINE_WARN("ResourceManager::LoadTexture: <{}> 'path': {}", name, path);
}
// create texture

View file

@ -2,8 +2,6 @@
#include "Base.h"
#include <glm/glm.hpp>
namespace Light {
class Shader;
@ -11,16 +9,17 @@ namespace Light {
class SharedContext;
// #todo: optimize
class ResourceManager
{
private:
static ResourceManager* s_Context;
std::unordered_map<std::string, std::shared_ptr<Shader>> m_Shaders;
std::unordered_map<std::string, std::shared_ptr<Texture>> m_Textures;
std::shared_ptr<SharedContext> m_SharedContext;
static ResourceManager* s_Context;
public:
static ResourceManager* Create(std::shared_ptr<SharedContext> sharedContext);
@ -28,7 +27,7 @@ namespace Light {
static inline void CreateShader(const std::string& name, const std::string& vertexSource, const std::string& pixelSource) { s_Context->CreateShaderImpl(name, vertexSource, pixelSource); }
static inline void LoadShader(const std::string& name, const std::string& vertexPath, const std::string& pixelPath) { s_Context->LoadShaderImpl(name, vertexPath, pixelPath); }
static inline void LoadTexture(const std::string& name, const std::string& path, int desiredComponents = 4) { s_Context->LoadTextureImpl(name, path, desiredComponents); }
static inline void LoadTexture(const std::string& name, const std::string& path, unsigned int desiredComponents = 4u) { s_Context->LoadTextureImpl(name, path, desiredComponents); }
static inline std::shared_ptr<Shader> GetShader(const std::string& name) { return s_Context->m_Shaders[name]; }
static inline std::shared_ptr<Texture> GetTexture(const std::string& name) { return s_Context->m_Textures[name]; }
@ -39,7 +38,7 @@ namespace Light {
void CreateShaderImpl(const std::string& name, const std::string& vertexSource, const std::string& pixelSource);
void LoadShaderImpl(const std::string& name, const std::string& vertexPath, const std::string& pixelPath);
void LoadTextureImpl(const std::string& name, const std::string& path, int desiredComponents);
void LoadTextureImpl(const std::string& name, const std::string& path, unsigned int desiredComponents = 4u);
private:
void ExtractShaderSource(std::string& src, const std::string& delim);
};

View file

@ -1,5 +1,6 @@
#pragma once
#include "Base.h"
namespace Light {

View file

@ -1,16 +1,17 @@
#pragma once
// Engine
// ENGINE //
#include "Base.h"
// Platform
// PLATFORM SPECIFIC //
// windows
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#undef NOMINMAX
#endif
// Containers
// CONTAINERS //
#include <array>
#include <vector>
#include <list>
@ -20,26 +21,26 @@
#include <unordered_map>
#include <unordered_set>
// Miscellaneous
// MISCELLANEOUS //
#include <algorithm>
#include <functional>
#include <memory>
#include <tuple>
#include <utility>
// IO
// INPUT_OUTPUT //
#include <iostream>
#include <fstream>
#include <sstream>
// Multi-threading
// MULTI_THREADING //
#include <thread>
#include <atomic>
// String
// STRING //
#include <string>
#include <string_view>
// C-Libraries
// C_LIBRARIES //
#include <time.h>
#include <math.h>

View file

@ -30,6 +30,10 @@
#include "UserInterface/UserInterface.h"
// -----------------------------
// Utility ---------------------
#include "Utility/ResourceManager.h"
// -----------------------------
// Base -----------------------
#include "Base.h"

View file

@ -5,10 +5,9 @@
namespace Light {
//* VERTEX BUFFER *//
//* VERTEX_BUFFER *//
dxVertexBuffer::dxVertexBuffer(float* vertices, unsigned int stride, unsigned int count, std::shared_ptr<dxSharedContext> sharedContext)
: m_Stride(stride), m_Context(sharedContext)
{
// buffer desc
D3D11_BUFFER_DESC bd = { 0 };
@ -22,7 +21,7 @@ namespace Light {
// create buffer
HRESULT hr;
DXC(m_Context->device->CreateBuffer(&bd, nullptr, &m_Buffer));
DXC(m_Context->GetDevice()->CreateBuffer(&bd, nullptr, &m_Buffer));
}
dxVertexBuffer::~dxVertexBuffer()
@ -32,19 +31,19 @@ namespace Light {
void* dxVertexBuffer::Map()
{
m_Context->deviceContext->Map(m_Buffer.Get(), NULL, D3D11_MAP_WRITE_DISCARD, NULL, &m_Map);
m_Context->GetDeviceContext()->Map(m_Buffer.Get(), NULL, D3D11_MAP_WRITE_DISCARD, NULL, &m_Map);
return m_Map.pData;
}
void dxVertexBuffer::UnMap()
{
m_Context->deviceContext->Unmap(m_Buffer.Get(), NULL);
m_Context->GetDeviceContext()->Unmap(m_Buffer.Get(), NULL);
}
void dxVertexBuffer::Bind()
{
static const unsigned int offset = 0u;
m_Context->deviceContext->IASetVertexBuffers(0u, 1u, m_Buffer.GetAddressOf(), &m_Stride, &offset);
m_Context->GetDeviceContext()->IASetVertexBuffers(0u, 1u, m_Buffer.GetAddressOf(), &m_Stride, &offset);
}
void dxVertexBuffer::UnBind()
@ -52,10 +51,10 @@ namespace Light {
static const unsigned int offset = 0u;
static ID3D11Buffer* buffer = nullptr;
m_Context->deviceContext->IASetVertexBuffers(0u, 1u, &buffer, &m_Stride, &offset);
m_Context->GetDeviceContext()->IASetVertexBuffers(0u, 1u, &buffer, &m_Stride, &offset);
}
//* INDEX BUFFER *//
//* INDEX_BUFFER *//
dxIndexBuffer::dxIndexBuffer(unsigned int* indices, unsigned int count, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
@ -66,8 +65,8 @@ namespace Light {
// check
if (count % 6 != 0)
{
LT_ENGINE_WARN("dxIndexBuffer::dxIndexBuffer: indices can only be null if count is multiple of 6");
LT_ENGINE_WARN("dxIndexBuffer::dxIndexBuffer: adding {} to count -> {}", (6 - (count % 6)), count + (6 - (count % 6)));
LT_ENGINE_WARN("dxIndexBuffer::dxIndexBuffer: 'indices' can only be null if count is multiple of 6");
LT_ENGINE_WARN("dxIndexBuffer::dxIndexBuffer: adding {} to 'count' -> {}", (6 - (count % 6)), count + (6 - (count % 6)));
count = count + (6 - (count % 6));
}
@ -102,14 +101,11 @@ namespace Light {
// create buffer
HRESULT hr;
DXC(m_Context->device->CreateBuffer(&bd, &sd, &m_Buffer));
DXC(m_Context->GetDevice()->CreateBuffer(&bd, &sd, &m_Buffer));
// delete indices
if (!hasIndices)
{
delete[] indices;
indices = nullptr;
}
}
dxIndexBuffer::~dxIndexBuffer()
@ -119,7 +115,7 @@ namespace Light {
void dxIndexBuffer::Bind()
{
m_Context->deviceContext->IASetIndexBuffer(m_Buffer.Get(), DXGI_FORMAT_R32_UINT, 0u);
m_Context->GetDeviceContext()->IASetIndexBuffer(m_Buffer.Get(), DXGI_FORMAT_R32_UINT, 0u);
}
void dxIndexBuffer::UnBind()
@ -127,7 +123,7 @@ namespace Light {
static const unsigned int offset = 0u;
static ID3D11Buffer* buffer = nullptr;
m_Context->deviceContext->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, offset);
m_Context->GetDeviceContext()->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, offset);
}
}

View file

@ -10,7 +10,7 @@ namespace Light {
class dxSharedContext;
//* VERTEX BUFFER *//
//* VERTEX_BUFFER *//
class dxVertexBuffer : public VertexBuffer
{
private:
@ -32,7 +32,7 @@ namespace Light {
void UnBind() override;
};
//* INDEX BUFFER *//
//* INDEX_BUFFER *//
class dxIndexBuffer : public IndexBuffer
{
private:

View file

@ -1,21 +1,17 @@
#include "ltpch.h"
#include "dxGraphicsContext.h"
#include "dxSharedContext.h"
// Required for forward declaration
#include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h"
#include "Graphics/Shader.h"
#include "Graphics/Buffers.h"
#include "Graphics/VertexLayout.h"
#include "UserInterface/UserInterface.h"
#include "Events/WindowEvents.h"
#include <glfw/glfw3.h>
// forward declaration
#include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h"
#include "UserInterface/UserInterface.h"
#include "Utility/ResourceManager.h"
#define GLFW_EXPOSE_NATIVE_WIN32
#include <glfw/glfw3.h>
#include <glfw/glfw3native.h>
namespace Light {
@ -23,26 +19,26 @@ namespace Light {
dxGraphicsContext::dxGraphicsContext(GLFWwindow* windowHandle)
: m_WindowHandle(windowHandle)
{
// DirectX API
// set 'GraphicsAPI';
m_GraphicsAPI = GraphicsAPI::DirectX;
// setup
// setup stuff
SetupDeviceAndSwapChain(windowHandle);
SetupRenderTargets();
SetupDebugInterface();
// create shared context
// create 'dxSharedContext'
m_SharedContext = std::make_shared<dxSharedContext>(m_Device, m_DeviceContext, m_SwapChain, m_RenderTargetView);
}
void dxGraphicsContext::OnWindowResize(const WindowResizedEvent& event)
{
SetResolution(event.GetSize());
SetResolution(event.GetSize().x, event.GetSize().y);
}
void dxGraphicsContext::SetupDeviceAndSwapChain(GLFWwindow* windowHandle)
{
//* swap chain desc *//
// swap chain desc
DXGI_SWAP_CHAIN_DESC sd = { 0 };
// buffer desc
@ -54,8 +50,7 @@ namespace Light {
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
// sample desc (for multi sampling)
// #todo: implement multi-sampling
// sample desc (for multi sampling) #todo: implement multi-samplingz
sd.SampleDesc.Count = 1u;
sd.SampleDesc.Quality = 0u;
@ -70,8 +65,8 @@ namespace Light {
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = NULL;
// determine device flags
UINT flags = NULL;
#ifdef LIGHT_DEBUG
flags = D3D11_CREATE_DEVICE_DEBUG;
@ -123,7 +118,7 @@ namespace Light {
{
D3D11_MESSAGE_ID_DEVICE_DRAW_SAMPLER_NOT_SET,
// #todo: add more message IDs here as needed
// #todo: add more message ids here as needed
};
D3D11_INFO_QUEUE_FILTER filter = { 0 };
@ -134,13 +129,13 @@ namespace Light {
#endif
}
void dxGraphicsContext::SetResolution(const glm::uvec2& resolution)
void dxGraphicsContext::SetResolution(unsigned int width, unsigned int height)
{
// viewport
D3D11_VIEWPORT viewport;
viewport.Width = 800.0f;
viewport.Height = 600.0f;
viewport.Width = width;
viewport.Height = height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;

View file

@ -3,8 +3,6 @@
#include "Base.h"
#include "Graphics/GraphicsContext.h"
#include <glm/glm.hpp>
#include <d3d11.h>
#include <wrl.h>
@ -37,7 +35,7 @@ namespace Light {
void SetupDebugInterface();
void SetResolution(const glm::uvec2& resolution);
void SetResolution(unsigned int width, unsigned int height);
};
}

View file

@ -1,47 +1,45 @@
#include "ltpch.h"
#include "dxRenderCommand.h"
#include "dxSharedContext.h"
namespace Light {
dxRenderCommand::dxRenderCommand(std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
}
{ }
void dxRenderCommand::SwapBuffers()
{
#ifdef LIGHT_DEBUG
HRESULT hr;
if (FAILED(hr = m_Context->swapChain->Present(0u, 0u)))
if (FAILED(hr = m_Context->GetSwapChain()->Present(0u, 0u)))
{
if (hr == DXGI_ERROR_DEVICE_REMOVED)
{
LT_ENGINE_CRITICAL("dxRenderCommand::SwapBuffers: DeviceRemoved:");
LT_ENGINE_CRITICAL(" {}", m_Context->device->GetDeviceRemovedReason());
LT_ENGINE_CRITICAL(" {}", m_Context->GetDevice()->GetDeviceRemovedReason());
throw dxException(hr, __FILE__, __LINE__);
}
}
#else
m_Context->swapChain->Present(0u, 0u);
m_Context->GetSwapChain()->Present(0u, 0u);
#endif
}
void dxRenderCommand::ClearBackBuffer()
{
float colors[] = { 1.2f, 0.4f, 0.9f, 1.0f };
m_Context->deviceContext->ClearRenderTargetView(m_Context->renderTargetView.Get(), colors);
float colors[] = { 1.2f, 0.4f, 0.9f, 1.0f }; // #todo: use a variable for this
m_Context->GetDeviceContext()->ClearRenderTargetView(m_Context->GetRenderTargetView().Get(), colors);
}
void dxRenderCommand::Draw(unsigned int count)
{
m_Context->deviceContext->Draw(count, 0u);
m_Context->GetDeviceContext()->Draw(count, 0u);
}
void dxRenderCommand::DrawIndexed(unsigned int count)
{
m_Context->deviceContext->DrawIndexed(count, 0u, 0u);
m_Context->GetDeviceContext()->DrawIndexed(count, 0u, 0u);
}
}

View file

@ -23,7 +23,6 @@ namespace Light {
virtual void Draw(unsigned int count) override;
virtual void DrawIndexed(unsigned int count) override;
};
}

View file

@ -1,13 +1,11 @@
#include "ltpch.h"
#include "dxShader.h"
#include "dxSharedContext.h"
#include <d3dcompiler.h>
namespace Light {
dxShader::dxShader(const std::string& vertexSource, const std::string& pixelSource, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
@ -15,16 +13,16 @@ namespace Light {
// compile shaders
HRESULT hr;
DXC(D3DCompile(vertexSource.c_str(), vertexSource.length(), NULL, nullptr, nullptr, "main", "vs_4_0", NULL, NULL, &m_VertexBlob, &vsErr));
DXC(D3DCompile(pixelSource.c_str(), pixelSource.length(), NULL, nullptr, nullptr, "main", "ps_4_0", NULL, NULL, &ps, &psErr));
D3DCompile(vertexSource.c_str(), vertexSource.length(), NULL, nullptr, nullptr, "main", "vs_4_0", NULL, NULL, &m_VertexBlob, &vsErr);
D3DCompile(pixelSource.c_str(), pixelSource.length(), NULL, nullptr, nullptr, "main", "ps_4_0", NULL, NULL, &ps, &psErr);
// check
LT_ENGINE_ASSERT(!vsErr.Get(), "dxShader::dxShader: vertex shader compile error: {}", (char*)vsErr->GetBufferPointer());
LT_ENGINE_ASSERT(!psErr.Get(), "dxShader::dxShader: vertex shader compile error: {}", (char*)psErr->GetBufferPointer());
LT_ENGINE_ASSERT(!psErr.Get(), "dxShader::dxShader: pixels shader compile error: {}", (char*)psErr->GetBufferPointer());
// create shaders
DXC(m_Context->device->CreateVertexShader(m_VertexBlob->GetBufferPointer(), m_VertexBlob->GetBufferSize(), NULL, &m_VertexShader));
DXC(m_Context->device->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), NULL, &m_PixelShader));
DXC(m_Context->GetDevice()->CreateVertexShader(m_VertexBlob->GetBufferPointer(), m_VertexBlob->GetBufferSize(), NULL, &m_VertexShader));
DXC(m_Context->GetDevice()->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), NULL, &m_PixelShader));
}
dxShader::~dxShader()
@ -34,14 +32,14 @@ namespace Light {
void dxShader::Bind()
{
m_Context->deviceContext->VSSetShader(m_VertexShader.Get(), nullptr, 0u);
m_Context->deviceContext->PSSetShader(m_PixelShader.Get(), nullptr, 0u);
m_Context->GetDeviceContext()->VSSetShader(m_VertexShader.Get(), nullptr, 0u);
m_Context->GetDeviceContext()->PSSetShader(m_PixelShader.Get(), nullptr, 0u);
}
void dxShader::UnBind()
{
m_Context->deviceContext->VSSetShader(nullptr, nullptr, 0u);
m_Context->deviceContext->PSSetShader(nullptr, nullptr, 0u);
m_Context->GetDeviceContext()->VSSetShader(nullptr, nullptr, 0u);
m_Context->GetDeviceContext()->PSSetShader(nullptr, nullptr, 0u);
}
}

View file

@ -19,6 +19,7 @@ namespace Light {
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_PixelShader;
Microsoft::WRL::ComPtr<ID3DBlob> m_VertexBlob;
public:
dxShader(const std::string& vertexSource, const std::string& pixelSource, std::shared_ptr<dxSharedContext> sharedContext);
~dxShader();
@ -29,5 +30,4 @@ namespace Light {
Microsoft::WRL::ComPtr<ID3DBlob> GetVertexBlob() { return m_VertexBlob; }
};
}

View file

@ -11,19 +11,25 @@ namespace Light {
// #todo:
class dxSharedContext : public SharedContext
{
private:
Microsoft::WRL::ComPtr<ID3D11Device > m_Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext > m_DeviceContext;
Microsoft::WRL::ComPtr<IDXGISwapChain > m_SwapChain;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_RenderTargetView;
public:
dxSharedContext(Microsoft::WRL::ComPtr<ID3D11Device> _device,
Microsoft::WRL::ComPtr<ID3D11DeviceContext> _deviceContext,
Microsoft::WRL::ComPtr<IDXGISwapChain> _swapChain,
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> _renderTargetView)
: device(_device), deviceContext(_deviceContext), swapChain(_swapChain), renderTargetView(_renderTargetView)
dxSharedContext(Microsoft::WRL::ComPtr<ID3D11Device > device,
Microsoft::WRL::ComPtr<ID3D11DeviceContext > deviceContext,
Microsoft::WRL::ComPtr<IDXGISwapChain > swapChain,
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView)
: m_Device(device), m_DeviceContext(deviceContext), m_SwapChain(swapChain), m_RenderTargetView(renderTargetView)
{
}
Microsoft::WRL::ComPtr<ID3D11Device> device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> deviceContext;
Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView;
inline Microsoft::WRL::ComPtr<ID3D11Device > GetDevice () { return m_Device; }
inline Microsoft::WRL::ComPtr<ID3D11DeviceContext > GetDeviceContext () { return m_DeviceContext; }
inline Microsoft::WRL::ComPtr<IDXGISwapChain > GetSwapChain () { return m_SwapChain; }
inline Microsoft::WRL::ComPtr<ID3D11RenderTargetView> GetRenderTargetView() { return m_RenderTargetView; }
};
}

View file

@ -1,6 +1,5 @@
#include "ltpch.h"
#include "dxTexture.h"
#include "dxSharedContext.h"
namespace Light {
@ -8,37 +7,42 @@ namespace Light {
dxTexture::dxTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
D3D11_TEXTURE2D_DESC textureDesc = { 0 };
// texture desc
D3D11_TEXTURE2D_DESC textureDesc = { };
textureDesc.Width = width;
textureDesc.Height = height;
textureDesc.MipLevels = 0;
textureDesc.ArraySize = 1;
textureDesc.Format = components == 4 ? DXGI_FORMAT_R8G8B8A8_UNORM :
components == 3 ? DXGI_FORMAT_R8G8B8A8_UNORM :
components == 2 ? DXGI_FORMAT_R8G8B8A8_UNORM :
components == 1 ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_UNKNOWN;
textureDesc.SampleDesc.Count = 1;
textureDesc.SampleDesc.Quality = 0;
textureDesc.MipLevels = 0u;
textureDesc.ArraySize = 1u;
textureDesc.Format = components == 4u ? DXGI_FORMAT_R8G8B8A8_UNORM :
components == 3u ? DXGI_FORMAT_R8G8B8A8_UNORM :
components == 2u ? DXGI_FORMAT_R8G8B8A8_UNORM :
components == 1u ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_UNKNOWN;
textureDesc.SampleDesc.Count = 1u;
textureDesc.SampleDesc.Quality = 0u;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
textureDesc.CPUAccessFlags = NULL;
textureDesc.MiscFlags = D3D11_RESOURCE_MISC_GENERATE_MIPS;
// create texture
HRESULT hr;
DXC(m_Context->device->CreateTexture2D(&textureDesc, nullptr, &m_Texture));
m_Context->deviceContext->UpdateSubresource(m_Texture.Get(), 0u, nullptr, pixels, width * 4, 0u);
DXC(m_Context->GetDevice()->CreateTexture2D(&textureDesc, nullptr, &m_Texture));
m_Context->GetDeviceContext()->UpdateSubresource(m_Texture.Get(), 0u, nullptr, pixels, width * 4u, 0u);
m_Texture->GetDesc(&textureDesc);
// shader resource view desc
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc = { };
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0u;
shaderResourceViewDesc.Texture2D.MipLevels = -1;
m_Context->device->CreateShaderResourceView(m_Texture.Get(), &shaderResourceViewDesc, &m_ResourceView);
m_Context->deviceContext->GenerateMips(m_ResourceView.Get());
// create shader resource view
m_Context->GetDevice()->CreateShaderResourceView(m_Texture.Get(), &shaderResourceViewDesc, &m_ResourceView);
m_Context->GetDeviceContext()->GenerateMips(m_ResourceView.Get());
// sampler desc
D3D11_SAMPLER_DESC samplerDesc = { };
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
@ -48,13 +52,14 @@ namespace Light {
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
m_Context->device->CreateSamplerState(&samplerDesc, &m_SamplerState);
// create sampler
m_Context->GetDevice()->CreateSamplerState(&samplerDesc, &m_SamplerState);
}
void dxTexture::Bind(unsigned int slot /* = 0 */)
void dxTexture::Bind(unsigned int slot /* = 0u */)
{
m_Context->deviceContext->PSSetSamplers(slot, 1u, m_SamplerState.GetAddressOf());
m_Context->deviceContext->PSSetShaderResources(slot, 1u, m_ResourceView.GetAddressOf());
m_Context->GetDeviceContext()->PSSetSamplers(slot, 1u, m_SamplerState.GetAddressOf());
m_Context->GetDeviceContext()->PSSetShaderResources(slot, 1u, m_ResourceView.GetAddressOf());
}
}

View file

@ -18,10 +18,11 @@ namespace Light {
Microsoft::WRL::ComPtr<ID3D11Texture2D> m_Texture;
Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_ResourceView;
Microsoft::WRL::ComPtr<ID3D11SamplerState> m_SamplerState;
public:
dxTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, std::shared_ptr<dxSharedContext> sharedContext);
void Bind(unsigned int slot /* = 0 */) override;
void Bind(unsigned int slot = 0u) override;
};
}

View file

@ -1,6 +1,5 @@
#include "ltpch.h"
#include "dxUserInterface.h"
#include "dxSharedContext.h"
#include <imgui.h>
@ -28,7 +27,7 @@ namespace Light {
// init
ImGui_ImplWin32_Init(glfwGetWin32Window(windowHandle));
ImGui_ImplDX11_Init(sharedContext->device.Get(), sharedContext->deviceContext.Get());
ImGui_ImplDX11_Init(sharedContext->GetDevice().Get(), sharedContext->GetDeviceContext().Get());
}
dxUserInterface::~dxUserInterface()
@ -44,7 +43,7 @@ namespace Light {
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
//* TEMP_ IMGUI DEBUG WINDOW _TEMP *//
//** #TEMP_IMGUI_DEMO_TEMP# **//
ImGui::ShowDemoWindow();
}
@ -61,7 +60,7 @@ namespace Light {
LT_ENGINE_INFO("UserInterface::");
LT_ENGINE_INFO(" API : ImGui");
LT_ENGINE_INFO(" Version: {}", ImGui::GetVersion());
LT_ENGINE_INFO(" GfxAPI : DirectX");
LT_ENGINE_INFO(" GraphicsAPI : DirectX");
LT_ENGINE_INFO("________________________________________");
}

View file

@ -3,11 +3,11 @@
#include "Base.h"
#include "UserInterface/UserInterface.h"
struct GLFWwindow;
#include <d3d11.h>
#include <wrl.h>
struct GLFWwindow;
namespace Light {
class dxSharedContext;

View file

@ -1,15 +1,15 @@
#include "ltpch.h"
#include "dxVertexLayout.h"
#include "dxSharedContext.h"
#include "dxShader.h"
#include "dxSharedContext.h"
namespace Light {
dxVertexLayout::dxVertexLayout(Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<dxSharedContext> sharedContext)
dxVertexLayout::dxVertexLayout(std::shared_ptr<Shader> shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
// local
// occupy space for input elements
std::vector<D3D11_INPUT_ELEMENT_DESC> inputElementsDesc;
inputElementsDesc.reserve(elements.size());
@ -26,13 +26,12 @@ namespace Light {
0u });
}
// #todo: take in shared_ptr
dxShader* dxpShader = static_cast<dxShader*>(shader);
LT_ENGINE_ASSERT(dxpShader, "dxVertexLayout::dxVertexLayout: failed to cast Shader to dxShader");
std::shared_ptr<dxShader> dxpShader = std::dynamic_pointer_cast<dxShader>(shader);
LT_ENGINE_ASSERT(dxpShader, "dxVertexLayout::dxVertexLayout: failed to cast 'Shader' to 'dxShader'");
// create input layout (vertex layout)
HRESULT hr;
DXC(m_Context->device->CreateInputLayout(&inputElementsDesc[0], inputElementsDesc.size(), dxpShader->GetVertexBlob().Get()->GetBufferPointer(), dxpShader->GetVertexBlob().Get()->GetBufferSize(), &m_InputLayout));
DXC(m_Context->GetDevice()->CreateInputLayout(&inputElementsDesc[0], inputElementsDesc.size(), dxpShader->GetVertexBlob().Get()->GetBufferPointer(), dxpShader->GetVertexBlob().Get()->GetBufferSize(), &m_InputLayout));
}
dxVertexLayout::~dxVertexLayout()
@ -42,18 +41,19 @@ namespace Light {
void dxVertexLayout::Bind()
{
m_Context->deviceContext->IASetInputLayout(m_InputLayout.Get());
m_Context->GetDeviceContext()->IASetInputLayout(m_InputLayout.Get());
}
void dxVertexLayout::UnBind()
{
m_Context->deviceContext->IASetInputLayout(nullptr);
m_Context->GetDeviceContext()->IASetInputLayout(nullptr);
}
DXGI_FORMAT dxVertexLayout::GetDxgiFormat(VertexElementType type)
{
switch (type)
{
// #todo: add char
// int
case Light::VertexElementType::Int1: return DXGI_FORMAT_R32_SINT;
case Light::VertexElementType::Int2: return DXGI_FORMAT_R32G32_SINT;
@ -78,7 +78,7 @@ namespace Light {
case Light::VertexElementType::Double3:
case Light::VertexElementType::Double4:
default: LT_ENGINE_ASSERT(false, "dxVertexLayout::GetDxgiFormat: invalid type");
default: LT_ENGINE_ASSERT(false, "dxVertexLayout::GetDxgiFormat: invalid 'VertexElementType'");
}
}

View file

@ -19,7 +19,7 @@ namespace Light {
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_InputLayout;
public:
dxVertexLayout(Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<dxSharedContext> sharedContext);
dxVertexLayout(std::shared_ptr<Shader> shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<dxSharedContext> sharedContext);
~dxVertexLayout();
void Bind() override;

View file

@ -5,6 +5,7 @@
namespace Light {
//** VERTEX_BUFFER **//
glVertexBuffer::glVertexBuffer(float* vertices, unsigned int count)
{
glCreateBuffers(1, &m_BufferID);
@ -36,6 +37,7 @@ namespace Light {
glBindBuffer(GL_ARRAY_BUFFER, NULL);
}
//** INDEX_BUFFER **//
glIndexBuffer::glIndexBuffer(unsigned int* indices, unsigned int count)
{
// generate indices if not provided
@ -45,8 +47,8 @@ namespace Light {
// check
if (count % 6 != 0)
{
LT_ENGINE_WARN("glIndexBuffer::glIndexBuffer: count should be divisible by 6 when no indices is provided");
LT_ENGINE_WARN("glIndexBuffer::glIndexBuffer: adding {} to count -> {}", (6 - (count % 6)), count + (6 - (count % 6)));
LT_ENGINE_WARN("glIndexBuffer::dxIndexBuffer: 'indices' can only be null if count is multiple of 6");
LT_ENGINE_WARN("glIndexBuffer::glIndexBuffer: adding {} to 'count' -> {}", (6 - (count % 6)), count + (6 - (count % 6)));
count = count + (6 - (count % 6));
}

View file

@ -5,6 +5,7 @@
namespace Light {
//** VERTEX_BUFFER **//
class glVertexBuffer : public VertexBuffer
{
private:
@ -21,6 +22,7 @@ namespace Light {
void UnBind() override;
};
//** INDEX_BUFFER **//
class glIndexBuffer : public IndexBuffer
{
private:

View file

@ -1,17 +1,13 @@
#include "ltpch.h"
#include "glGraphicsContext.h"
// Required for forward declaration
#include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h"
#include "Graphics/Shader.h"
#include "Graphics/Buffers.h"
#include "Graphics/VertexLayout.h"
#include "UserInterface/UserInterface.h"
#include "Events/WindowEvents.h"
#include "Utility/Stringifier.h"
// forward declaration
#include "Graphics/Renderer.h"
#include "Graphics/RenderCommand.h"
#include "UserInterface/UserInterface.h"
#include "Utility/ResourceManager.h"
#include <glad/glad.h>
#include <GLFW/glfw3.h>
@ -21,10 +17,13 @@ namespace Light {
glGraphicsContext::glGraphicsContext(GLFWwindow* windowHandle)
: m_WindowHandle(windowHandle)
{
// set 'GraphicsAPI'
m_GraphicsAPI = GraphicsAPI::OpenGL;
// make context current
glfwMakeContextCurrent(windowHandle);
// load opengl (glad)
LT_ENGINE_ASSERT(gladLoadGLLoader((GLADloadproc)glfwGetProcAddress), "glGraphicsContext::glGraphicsContext: failed to initialize opengl (glad)");
// #todo: add blender
@ -36,7 +35,7 @@ namespace Light {
{
if (event.GetSize().x < 0 || event.GetSize().y < 0)
{
LT_ENGINE_ERROR("glGraphicsContext::OnWindowResize: width/height cannot be negative: [{}x{}]", event.GetSize().x, event.GetSize().y);
LT_ENGINE_ERROR("glGraphicsContext::OnWindowResize: 'width'/'height' cannot be negative: [{}x{}]", event.GetSize().x, event.GetSize().y);
return;
}
@ -56,6 +55,7 @@ namespace Light {
void glGraphicsContext::SetDebugMessageCallback()
{
// determine log level
#if defined(LIGHT_DEBUG)
glEnable(GL_DEBUG_OUTPUT);
glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE);
@ -67,6 +67,7 @@ namespace Light {
return;
#endif
// setup message callback
glDebugMessageCallback([](unsigned int source, unsigned int type,
unsigned int id, unsigned int severity,
int length, const char* message,

View file

@ -8,8 +8,7 @@ namespace Light {
glRenderCommand::glRenderCommand(GLFWwindow* windowHandle)
: m_WindowHandle(windowHandle)
{
}
{ }
void glRenderCommand::SwapBuffers()
{
@ -19,7 +18,7 @@ namespace Light {
void glRenderCommand::ClearBackBuffer()
{
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.25f, 0.45f, 0.91f, 1.0f);
glClearColor(0.25f, 0.45f, 0.91f, 1.0f); // #todo: use a variable for this
}
void glRenderCommand::Draw(unsigned int count)

View file

@ -11,58 +11,67 @@ namespace Light {
// create shaders
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
unsigned int pixelShader = glCreateShader(GL_FRAGMENT_SHADER);
unsigned int fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
// & (address of) needs an lvalue
// &(address of) needs an lvalue
const char* lVertexSource = vertexSource.c_str();
const char* lFragmentSource = fragmentSource.c_str();
// set shaders' sorce code
// set shaders' source code
glShaderSource(vertexShader, 1, &lVertexSource, NULL);
glShaderSource(pixelShader, 1, &lFragmentSource, NULL);
glShaderSource(fragmentShader, 1, &lFragmentSource, NULL);
// compile shaders
glCompileShader(vertexShader);
glCompileShader(pixelShader);
glCompileShader(fragmentShader);
//* TEMP__ HANDLE SHADER COMPILE FAILURE __TEMP **//
//** #TEMP_HANDLE_SHADER_COMPILE_FAILURE# **//
int isCompiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &maxLength);
int logLength = 0;
glGetShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> errorLog(maxLength);
glGetShaderInfoLog(vertexShader, maxLength, &maxLength, &errorLog[0]);
for(int i = 0; i < errorLog.size() -1; i++)
std::cout << errorLog[i];
char* errorLog = (char*)alloca(logLength);
glGetShaderInfoLog(vertexShader, logLength, &logLength, &errorLog[0]);
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
LT_ENGINE_ASSERT(false, "glShader::glShader: failed to compile vertex shader:\n {}", errorLog);
return;
}
glGetShaderiv(pixelShader, GL_COMPILE_STATUS, &isCompiled);
glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
{
GLint maxLength = 0;
glGetShaderiv(pixelShader, GL_INFO_LOG_LENGTH, &maxLength);
int logLength = 0;
glGetShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &logLength);
std::vector<char> errorLog(maxLength);
glGetShaderInfoLog(pixelShader, maxLength, &maxLength, &errorLog[0]);
char* errorLog = (char*)alloca(logLength);
glGetShaderInfoLog(fragmentShader, logLength, &logLength, &errorLog[0]);
glDeleteShader(pixelShader);
glDeleteShader(fragmentShader);
glDeleteShader(vertexShader);
LT_ENGINE_ASSERT(false, "glShader::glShader: failed to compile fragment shader:\n {}", errorLog);
return;
}
//* TEMP__ HANDLE SHADER COMPILE FAILURE __TEMP **//
//** #TEMP_HANDLE_SHADER_COMPILE_FAILURE# **//
// attach and link shaders to the shader program
// attach shaders
glAttachShader(m_ShaderID, vertexShader);
glAttachShader(m_ShaderID, pixelShader);
glAttachShader(m_ShaderID, fragmentShader);
// link shader program
glLinkProgram(m_ShaderID);
// delete shaders (free memory)
glDeleteShader(vertexShader);
glDeleteShader(pixelShader);
glDeleteShader(fragmentShader);
// #todo: validate program
}

View file

@ -4,9 +4,6 @@
namespace Light {
struct glSharedContext
{
};
struct glSharedContext { };
}

View file

@ -10,13 +10,13 @@ namespace Light {
// create texture
glCreateTextures(GL_TEXTURE_2D, 1, &m_TextureID);
// texture parameters
// set texture parameters
glTextureParameteri(m_TextureID, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTextureParameteri(m_TextureID, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTextureParameteri(m_TextureID, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTextureParameteri(m_TextureID, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// vocab = 0
// determine formats
unsigned int format = components == 4u ? GL_RGBA :
components == 3u ? GL_RGB :
components == 2u ? GL_RG :
@ -30,6 +30,10 @@ namespace Light {
// check
LT_ENGINE_ASSERT(format, "glTexture::glTexture: invalid number of components: {}", components);
// #todo: isn't there something like glTextureImage2D ???
// create texture and mipsmaps
Bind();
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
@ -40,7 +44,7 @@ namespace Light {
glDeleteTextures(1, &m_TextureID);
}
void glTexture::Bind(unsigned int slot/*= 0*/)
void glTexture::Bind(unsigned int slot /* = 0u */)
{
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, m_TextureID);

View file

@ -9,13 +9,12 @@ namespace Light {
{
private:
unsigned int m_TextureID;
unsigned int m_ActiveTexture;
public:
glTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels);
~glTexture();
void Bind(unsigned int slot = 0) override;
void Bind(unsigned int slot = 0u) override;
};
}

View file

@ -38,7 +38,7 @@ namespace Light {
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
//* TEMP_ IMGUI DEBUG WINDOW _TEMP *//
//** #TEMP_IMGUI_DEMO_TEMP# **//
ImGui::ShowDemoWindow();
}
@ -55,7 +55,7 @@ namespace Light {
LT_ENGINE_INFO("UserInterface::");
LT_ENGINE_INFO(" API : ImGui");
LT_ENGINE_INFO(" Version: {}", ImGui::GetVersion());
LT_ENGINE_INFO(" GfxAPI : OpenGL");
LT_ENGINE_INFO(" GraphicsAPI : OpenGL");
LT_ENGINE_INFO("________________________________________");
}

View file

@ -7,11 +7,11 @@
namespace Light {
glVertexLayout::glVertexLayout(VertexBuffer* buffer, const std::vector<std::pair<std::string, VertexElementType>>& elements)
glVertexLayout::glVertexLayout(std::shared_ptr<VertexBuffer> buffer, const std::vector<std::pair<std::string, VertexElementType>>& elements)
{
// check
LT_ENGINE_ASSERT(dynamic_cast<glVertexBuffer*>(buffer), "glVertexLayout::glVertexLayout: failed to cast VertexBuffer to glVertexBuffer");
LT_ENGINE_ASSERT(!elements.empty(), "glVertexLayout::glVertexLayout: elements is empty");
LT_ENGINE_ASSERT(std::dynamic_pointer_cast<glVertexBuffer>(buffer), "glVertexLayout::glVertexLayout: failed to cast 'VertexBuffer' to 'glVertexBuffer'");
LT_ENGINE_ASSERT(!elements.empty(), "glVertexLayout::glVertexLayout: 'elements' is empty");
// local
std::vector<glVertexElementDesc> elementsDesc;
@ -60,23 +60,24 @@ namespace Light {
{
switch (type)
{
// #todo: add char
// int
case VertexElementType::Int1: return { GL_INT, 1, sizeof(int), offset };
case VertexElementType::Int2: return { GL_INT, 2, sizeof(int), offset };
case VertexElementType::Int3: return { GL_INT, 3, sizeof(int), offset };
case VertexElementType::Int4: return { GL_INT, 4, sizeof(int), offset };
case VertexElementType::Int1: return { GL_INT, 1u, sizeof(int), offset };
case VertexElementType::Int2: return { GL_INT, 2u, sizeof(int), offset };
case VertexElementType::Int3: return { GL_INT, 3u, sizeof(int), offset };
case VertexElementType::Int4: return { GL_INT, 4u, sizeof(int), offset };
// uint
case VertexElementType::UInt1: return { GL_UNSIGNED_INT, 1, sizeof(unsigned int), offset };
case VertexElementType::UInt2: return { GL_UNSIGNED_INT, 2, sizeof(unsigned int), offset };
case VertexElementType::UInt3: return { GL_UNSIGNED_INT, 3, sizeof(unsigned int), offset };
case VertexElementType::UInt4: return { GL_UNSIGNED_INT, 4, sizeof(unsigned int), offset };
case VertexElementType::UInt1: return { GL_UNSIGNED_INT, 1u, sizeof(unsigned int), offset };
case VertexElementType::UInt2: return { GL_UNSIGNED_INT, 2u, sizeof(unsigned int), offset };
case VertexElementType::UInt3: return { GL_UNSIGNED_INT, 3u, sizeof(unsigned int), offset };
case VertexElementType::UInt4: return { GL_UNSIGNED_INT, 4u, sizeof(unsigned int), offset };
// float
case VertexElementType::Float1: return { GL_FLOAT, 1, sizeof(float), offset };
case VertexElementType::Float2: return { GL_FLOAT, 2, sizeof(float), offset };
case VertexElementType::Float3: return { GL_FLOAT, 3, sizeof(float), offset };
case VertexElementType::Float4: return { GL_FLOAT, 4, sizeof(float), offset };
case VertexElementType::Float1: return { GL_FLOAT, 1u, sizeof(float), offset };
case VertexElementType::Float2: return { GL_FLOAT, 2u, sizeof(float), offset };
case VertexElementType::Float3: return { GL_FLOAT, 3u, sizeof(float), offset };
case VertexElementType::Float4: return { GL_FLOAT, 4u, sizeof(float), offset };
// double
case VertexElementType::Double1: return { GL_DOUBLE, 1, sizeof(float), offset };
@ -85,7 +86,7 @@ namespace Light {
case VertexElementType::Double4: return { GL_DOUBLE, 4, sizeof(float), offset };
default:
LT_ENGINE_ASSERT(false, "glVertexLayout::GetElementDesc: invalid vertex element type");
LT_ENGINE_ASSERT(false, "glVertexLayout::GetElementDesc: invalid 'VertexElementType'");
return {};
}
}

View file

@ -19,7 +19,7 @@ namespace Light {
unsigned int m_ArrayID;
public:
glVertexLayout(VertexBuffer* buffer, const std::vector<std::pair<std::string, VertexElementType>>& elements);
glVertexLayout(std::shared_ptr<VertexBuffer> buffer, const std::vector<std::pair<std::string, VertexElementType>>& elements);
~glVertexLayout();
void Bind() override;

View file

@ -21,7 +21,7 @@ namespace Light {
: m_EventCallback(callback)
{
// init glfw
LT_ENGINE_ASSERT(glfwInit(), "lWindow::lWindow: failed to initialize glfw");
LT_ENGINE_ASSERT(glfwInit(), "lWindow::lWindow: failed to initialize 'glfw'");
// create window
glfwWindowHint(GLFW_VERSION_MAJOR, 4);
@ -30,7 +30,7 @@ namespace Light {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
m_Handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr);
LT_ENGINE_ASSERT(m_Handle, "lWindow::lWindow: failed to create glfw window");
LT_ENGINE_ASSERT(m_Handle, "lWindow::lWindow: failed to create 'GLFWwindow'");
// manage events
glfwSetWindowUserPointer(m_Handle, &m_EventCallback);
@ -38,7 +38,7 @@ namespace Light {
// create graphics context
m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::OpenGL, m_Handle));
LT_ENGINE_ASSERT(m_GraphicsContext, "lWindow::lWindow: failed to create graphics context");
LT_ENGINE_ASSERT(m_GraphicsContext, "lWindow::lWindow: failed to create 'GraphicsContext'");
}
lWindow::~lWindow()
@ -46,13 +46,18 @@ namespace Light {
glfwDestroyWindow(m_Handle);
}
void lWindow::SetProperties(const WindowProperties& properties)
void lWindow::SetProperties(const WindowProperties& properties, bool affectsVisiblity /* = false */)
{
// save the visibility status and re-assign if 'affectVisibility' is false
bool visible = affectsVisiblity ? properties.visible : m_Properties.visible;
m_Properties = properties;
glfwSetWindowSize(m_Handle, properties.size.x, properties.size.y);
glfwSetWindowTitle(m_Handle, properties.title.c_str());
glfwSwapInterval(static_cast<int>(properties.vsync));
m_Properties.visible = visible;
// set properties
SetTitle(properties.title);
SetSize(properties.size);
SetVSync(properties.vsync);
SetVisibility(visible);
}
void lWindow::SetTitle(const std::string& title)
@ -62,16 +67,16 @@ namespace Light {
glfwSetWindowTitle(m_Handle, title.c_str());
}
void lWindow::SetSize(const glm::uvec2& size, bool add/*= false*/)
void lWindow::SetSize(const glm::uvec2& size, bool additive /* = false */)
{
m_Properties.size.x = size.x == 0u ? m_Properties.size.x : add ? m_Properties.size.x + size.x : size.x;
m_Properties.size.y = size.y == 0u ? m_Properties.size.y : add ? m_Properties.size.y + size.y : size.y;
m_Properties.size.x = size.x == 0u ? m_Properties.size.x : additive ? m_Properties.size.x + size.x : size.x;
m_Properties.size.y = size.y == 0u ? m_Properties.size.y : additive ? m_Properties.size.y + size.y : size.y;
glfwSetWindowSize(m_Handle, size.x, size.y);
}
void lWindow::SetVSync(bool vsync, bool toggle/*= false*/)
void lWindow::SetVSync(bool vsync, bool toggle /* = false */)
{
m_Properties.vsync = toggle ? !m_Properties.vsync : vsync;
@ -90,7 +95,8 @@ namespace Light {
void lWindow::BindGlfwEvents()
{
//** mouse events **//
//** MOUSE_EVENTS **//
// cursor position
glfwSetCursorPosCallback(m_Handle, [](GLFWwindow* window, double xpos, double ypos)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -99,6 +105,7 @@ namespace Light {
callback(event);
});
// button
glfwSetMouseButtonCallback(m_Handle, [](GLFWwindow* window, int button, int action, int mods)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -115,6 +122,7 @@ namespace Light {
}
});
// scroll
glfwSetScrollCallback(m_Handle, [](GLFWwindow* window, double xoffset, double yoffset)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -123,7 +131,8 @@ namespace Light {
callback(event);
});
//** keyboard events **//
//** KEYBOARD_EVENTS **//
// key
glfwSetKeyCallback(m_Handle, [](GLFWwindow* window, int key, int scancode, int action, int mods)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -140,7 +149,8 @@ namespace Light {
}
});
//** window events **//
//** WINDOW_EVENTS **//
// position
glfwSetWindowPosCallback(m_Handle, [](GLFWwindow* window, int xpos, int ypos)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -149,6 +159,7 @@ namespace Light {
callback(event);
});
// size
glfwSetWindowSizeCallback(m_Handle, [](GLFWwindow* window, int width, int height)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -157,6 +168,7 @@ namespace Light {
callback(event);
});
// close
glfwSetWindowCloseCallback(m_Handle, [](GLFWwindow* window)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
@ -165,6 +177,7 @@ namespace Light {
callback(event);
});
// focus
glfwSetWindowFocusCallback(m_Handle, [](GLFWwindow* window, int focus)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);

View file

@ -15,6 +15,7 @@ namespace Light {
GLFWwindow* m_Handle = nullptr;
std::function<void(Event&)> m_EventCallback;
public:
lWindow(std::function<void(Event&)> callback);
@ -23,11 +24,11 @@ namespace Light {
void PollEvents() override;
void OnEvent(const Event& event) override;
void SetProperties(const WindowProperties& properties) override;
void SetProperties(const WindowProperties& properties, bool affectsVisiblity = false) override;
void SetTitle(const std::string& title) override;
void SetSize(const glm::uvec2& size, bool add = false) override;
void SetSize(const glm::uvec2& size, bool additive = false) override;
void SetVSync(bool vsync, bool toggle = false) override;
void SetVisibility(bool visible, bool toggle = false);

View file

@ -21,7 +21,7 @@ namespace Light {
: m_EventCallback(callback)
{
// init glfw
LT_ENGINE_ASSERT(glfwInit(), "wWindow::wWindow: failed to initialize glfw");
LT_ENGINE_ASSERT(glfwInit(), "wWindow::wWindow: failed to initialize 'glfw'");
// create window
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
@ -30,15 +30,15 @@ namespace Light {
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
m_Handle = glfwCreateWindow(1u, 1u, "", nullptr, nullptr);
LT_ENGINE_ASSERT(m_Handle, "wWindow::wWindow: glfwCreateWindow: failed to create glfw window");
LT_ENGINE_ASSERT(m_Handle, "wWindow::wWindow: glfwCreateWindow: failed to create 'GLFWwindow'");
// manage events
// bind event stuff
glfwSetWindowUserPointer(m_Handle, &m_EventCallback);
BindGlfwEvents();
// create graphics context
m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::DirectX, m_Handle));
LT_ENGINE_ASSERT(m_GraphicsContext, "wWindow::wWindow: failed to create graphics context");
m_GraphicsContext = std::unique_ptr<GraphicsContext>(GraphicsContext::Create(GraphicsAPI::OpenGL, m_Handle));
LT_ENGINE_ASSERT(m_GraphicsContext, "wWindow::wWindow: failed to create 'GraphicsContext'");
}
wWindow::~wWindow()
@ -46,13 +46,18 @@ namespace Light {
glfwDestroyWindow(m_Handle);
}
void wWindow::SetProperties(const WindowProperties& properties)
void wWindow::SetProperties(const WindowProperties& properties, bool affectVisibility /* = false */)
{
// save the visibility status and re-assign if 'affectVisibility' is false
bool visible = affectVisibility ? properties.visible : m_Properties.visible;
m_Properties = properties;
m_Properties.visible = visible;
glfwSetWindowSize(m_Handle, properties.size.x, properties.size.y); // #todo: check if this triggers an event
glfwSetWindowTitle(m_Handle, properties.title.c_str());
glfwSwapInterval((int)properties.vsync);
// set properties
SetTitle(properties.title);
SetSize(properties.size);
SetVSync(properties.vsync);
SetVisibility(visible);
}
void wWindow::SetVisibility(bool visible, bool toggle)
@ -74,10 +79,12 @@ namespace Light {
{
switch (event.GetEventType())
{
// closed
case EventType::WindowClosed:
b_Closed = true;
break;
// resized
case EventType::WindowResized:
m_GraphicsContext->OnWindowResize((const WindowResizedEvent&)event);
break;
@ -91,114 +98,92 @@ namespace Light {
glfwSetWindowTitle(m_Handle, m_Properties.title.c_str());
}
void wWindow::SetVSync(bool vsync, bool toggle /*= false*/)
void wWindow::SetVSync(bool vsync, bool toggle /* = false */)
{
m_Properties.vsync = toggle ? !m_Properties.vsync : vsync;
glfwSwapInterval(m_Properties.vsync);
}
void wWindow::SetSize(const glm::uvec2& size, bool add /*= false*/)
void wWindow::SetSize(const glm::uvec2& size, bool additive /* = false */)
{
m_Properties.size.x = size.x == 0u ? m_Properties.size.x : add ? m_Properties.size.x + size.x : size.x;
m_Properties.size.y = size.y == 0u ? m_Properties.size.y : add ? m_Properties.size.y + size.y : size.y;
m_Properties.size.x = size.x == 0u ? m_Properties.size.x : additive ? m_Properties.size.x + size.x : size.x;
m_Properties.size.y = size.y == 0u ? m_Properties.size.y : additive ? m_Properties.size.y + size.y : size.y;
glfwSetWindowSize(m_Handle, m_Properties.size.x, m_Properties.size.y);
}
void wWindow::BindGlfwEvents()
{
// Mouse Events //
//** MOUSE_EVENTS **//
// cursor position
glfwSetCursorPosCallback(m_Handle, [](GLFWwindow* window, double xpos, double ypos)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
MouseMovedEvent event(xpos, ypos);
callback(event);
callback(MouseMovedEvent(xpos, ypos));
});
// button
glfwSetMouseButtonCallback(m_Handle, [](GLFWwindow* window, int button, int action, int mods)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
ButtonPressedEvent event(button);
callback(event);
}
callback(ButtonPressedEvent(button));
else
{
ButtonReleasedEvent event(button);
callback(event);
}
callback(ButtonReleasedEvent (button));
});
// scroll
glfwSetScrollCallback(m_Handle, [](GLFWwindow* window, double xoffset, double yoffset)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
WheelScrolledEvent event(yoffset);
callback(event);
callback(WheelScrolledEvent (yoffset));
});
// Keyboard Events //
//** KEYBOARD_EVENTS **//
// key
glfwSetKeyCallback(m_Handle, [](GLFWwindow* window, int key, int scancode, int action, int mods)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
if (action == GLFW_PRESS)
{
KeyPressedEvent event(key);
callback(event);
}
callback(KeyPressedEvent(key));
else
{
KeyReleasedEvent event(key);
callback(event);
}
callback(KeyReleasedEvent(key));
});
// Window Events //
// position
glfwSetWindowPosCallback(m_Handle, [](GLFWwindow* window, int xpos, int ypos)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
WindowMovedEvent event(xpos, ypos);
callback(event);
callback(WindowMovedEvent(xpos, ypos));
});
// size
glfwSetWindowSizeCallback(m_Handle, [](GLFWwindow* window, int width, int height)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
WindowResizedEvent event(width, height);
callback(event);
callback(WindowResizedEvent(width, height));
});
// close
glfwSetWindowCloseCallback(m_Handle, [](GLFWwindow* window)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
WindowClosedEvent event;
callback(event);
callback(WindowClosedEvent());
});
// focus
glfwSetWindowFocusCallback(m_Handle, [](GLFWwindow* window, int focus)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
if(focus == GLFW_TRUE)
{
WindowGainFocusEvent event;
callback(event);
}
callback(WindowGainFocusEvent());
else
{
WindowLostFocusEvent event;
callback(event);
}
callback(WindowLostFocusEvent());
});
}
}

View file

@ -25,12 +25,12 @@ namespace Light {
void PollEvents() override;
void OnEvent(const Event& event) override;
// Setters //
void SetProperties(const WindowProperties& properties) override;
//** SETTERS **//
void SetProperties(const WindowProperties& properties, bool affectVisibility = false) override;
void SetTitle(const std::string& title) override;
void SetSize(const glm::uvec2& size, bool add = false) override;
void SetSize(const glm::uvec2& size, bool additive = false) override;
void SetVSync(bool vsync, bool toggle = false) override;
void SetVisibility(bool visible, bool toggle = false) override;

View file

@ -22,7 +22,7 @@ public:
// Attach the sandbox layer
Light::LayerStack::AttachLayer(new SandboxLayer("SandboxLayer"));
}
~Sandbox()
{
LT_CLIENT_TRACE("Sandbox::~Sandbox");

View file

@ -18,7 +18,10 @@ public:
Light::Renderer::DrawQuad(glm::vec3(0.2f, 0.5f, 0.0f), glm::vec2(0.6f, 0.6f), glm::vec4(.2f, 1.f, .2f, 1.0f));
Light::Renderer::DrawQuad(glm::vec3(-0.3f, 0.2f, 0.0f), glm::vec2(.4f, .4f), glm::vec4(.2f, 2.f, 1.f, 1.0f));
Light::Renderer::DrawQuad(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec2(1.0f, 1.0f), m_AwesomefaceTexture);
Light::Renderer::DrawQuad(glm::vec3(-0.3f, -0.5f, 0.0f), glm::vec2(0.1f, 0.1f), m_AwesomefaceTexture);
Light::Renderer::DrawQuad(glm::vec3(-0.5f, +0.5f, 0.0f), glm::vec2(0.1f, 0.1f), m_AwesomefaceTexture);
Light::Renderer::DrawQuad(glm::vec3(-0.1f, -0.5f, 0.0f), glm::vec2(0.1f, 0.1f), m_AwesomefaceTexture);
Light::Renderer::DrawQuad(glm::vec3(+0.5f, -0.5f, 0.0f), glm::vec2(0.1f, 0.1f), m_AwesomefaceTexture);
}
};