Major changes

- Major tidying
- Some fixes
-
This commit is contained in:
Light 2021-06-19 15:12:42 +04:30
parent 21e4432c60
commit fcfe73923d
54 changed files with 432 additions and 254 deletions

2
Dependencies/imgui vendored

@ -1 +1 @@
Subproject commit 6fb2e276cbee262fed50d9c9acf98fa314f624f8
Subproject commit e401b8f2c0e89ddd783245a88549f5c5e23a2c21

View file

@ -28,5 +28,5 @@
#define BIT(x) 1 << x
// #todo: log to file in distribution builds
#define LT_ENGINE_ASSERT(x, ...) { if(!(x)) { LT_ENGINE_CRITICAL(__VA_ARGS__); __debugbreak(); } }
#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(); } }

View file

@ -27,60 +27,61 @@ namespace Light {
void Application::GameLoop()
{
// check
LT_ENGINE_ASSERT(!m_LayerStack.IsEmpty(), "Application::GameLoop: Layerstack is empty");
LT_ENGINE_ASSERT(!m_LayerStack.IsEmpty(), "Application::GameLoop(pre): LayerStack is empty");
// Log window data
Logger::LogDebugData();
// log debug data
LogDebugData();
Logger::LogDebugData();
m_Window->GetGfxContext()->LogDebugData();
m_Window->GetGfxContext()->GetUserInterface()->LogDebugData();
// Show window
// reveal window
m_Window->SetVisibility(true);
// GAMELOOP //
//* [ GAMELOOP ] *//
while (!m_Window->IsClosed())
{
// Events
m_Window->PollEvents();
// update layyers
m_LayerStack.OnUpdate(1000.0f / 60.0f); // #todo: implement time
// Rendering
// render layers
m_Window->GetGfxContext()->GetRenderer()->BeginScene();
m_LayerStack.OnRender();
m_Window->GetGfxContext()->GetRenderer()->EndScene();
// Buffer updates
// render user interface
m_Window->GetGfxContext()->GetUserInterface()->Begin();
m_Window->GetGfxContext()->GetUserInterface()->End();
// swap buffers
m_Window->GetGfxContext()->GetRenderCommand()->SwapBuffers();
m_Window->GetGfxContext()->GetRenderCommand()->ClearBackBuffer();
// Update
// ...
// UserInterface
m_Window->GetGfxContext()->GetUserInterface()->Begin();
m_Window->GetGfxContext()->GetUserInterface()->End();
// poll events
m_Window->PollEvents();
}
}
void Application::OnEvent(const Event& event)
{
// Window
// window
if (event.HasCategory(WindowEventCategory))
m_Window->OnEvent(event);
// UserInterface
// user interface
if (event.HasCategory(InputEventCategory))
m_Window->GetGfxContext()->GetUserInterface()->OnInput(event);
// Input
// #todo: add input manager
// ...
// Layers
// layers
m_LayerStack.OnEvent(event);
}
void Application::LogDebugData()
{
// #todo: log more information
LT_ENGINE_INFO("________________________________________");
LT_ENGINE_INFO("Platform::");
LT_ENGINE_INFO(" OS: {}", LT_BUILD_PLATFORM);

View file

@ -39,13 +39,12 @@ namespace Light {
virtual void SetTitle(const std::string& title) = 0;
virtual void SetSize(const glm::uvec2& size) = 0; // pass 0 for width or height for single dimension resizing
virtual void SetSize(const glm::uvec2& size, bool add = false) = 0; // pass 0 for width or height for single dimension resizing
inline void Close() { b_Closed = true; }
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 //
inline GraphicsContext* GetGfxContext() const { return m_GraphicsContext.get(); }

View file

@ -11,8 +11,14 @@
namespace Light {
FailedAssertion::FailedAssertion(const char* file, int line)
{
LT_ENGINE_CRITICAL("FailedAssertion::FailedAssertion: assertion failed in: {} (line {})", file, line);
}
glException::glException(unsigned int source, unsigned int type, unsigned int id, const char* msg)
{
// #todo: improve
LT_ENGINE_CRITICAL("________________________________________");
LT_ENGINE_CRITICAL("glException::glException::");
LT_ENGINE_CRITICAL(" Severity: {}", Stringifier::glDebugMsgSeverity(GL_DEBUG_SEVERITY_HIGH));
@ -28,7 +34,7 @@ namespace Light {
LT_ENGINE_CRITICAL("________________________________________");
}
LT_WIN(
#ifdef LIGHT_PLATFORM_WINDOWS
dxException::dxException(long hr, const char* file, int line)
{
char* message;
@ -37,7 +43,7 @@ namespace Light {
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)(&message), NULL, nullptr);
// #todo: format better
// #todo: improve
LT_ENGINE_CRITICAL("________________________________________");
LT_ENGINE_CRITICAL("dxException::dxException::");
LT_ENGINE_CRITICAL(" File: {}, Line: {}", file, line);
@ -45,6 +51,7 @@ namespace Light {
LT_ENGINE_CRITICAL("________________________________________");
LocalFree(message);
})
}
#endif
}

View file

@ -3,6 +3,11 @@
#define DXC(x) hr = x; if(FAILED(x)) throw dxException(hr, __FILE__, __LINE__)
namespace Light {
struct FailedAssertion : std::exception
{
FailedAssertion(const char* file, int line);
};
// OpenGL
struct glException : std::exception

View file

@ -2,6 +2,7 @@
#include "Logger.h"
#include <spdlog/sinks/stdout_color_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include "Utility/Stringifier.h"
@ -9,6 +10,9 @@ namespace Light {
std::shared_ptr<spdlog::logger> Logger::s_EngineLogger = nullptr;
std::shared_ptr<spdlog::logger> Logger::s_ClientLogger = nullptr;
std::shared_ptr<spdlog::logger> Logger::s_FileLogger = nullptr;
std::string Logger::s_LogFilePath = LT_LOG_FILE_LOCATION;
void Light::Logger::Initialize()
{
@ -16,8 +20,12 @@ namespace Light {
spdlog::set_pattern("%^[%M:%S:%e] <%n>: %v%$");
// create loggers
#ifndef LIGHT_DIST
s_EngineLogger = spdlog::stdout_color_mt("Engine");
s_ClientLogger = spdlog::stdout_color_mt("Client");
#endif
s_FileLogger = spdlog::basic_logger_mt("File", s_LogFilePath);
s_FileLogger->set_pattern("%^[%M:%S:%e] <%l>: %v%$");
// set level
#if defined(LIGHT_DEBUG)
@ -26,20 +34,17 @@ namespace Light {
#elif defined (LIGHT_RELEASE)
s_EngineLogger->set_level(spdlog::level::info);
s_ClientLogger->set_level(spdlog::level::info);
#else
s_EngineLogger->set_level(spdlog::level::off);
s_ClientLogger->set_level(spdlog::level::off);
#endif
}
void Logger::LogDebugData()
{
// #todo: improve
LT_ENGINE_INFO("________________________________________");
LT_ENGINE_INFO("Logger::");
LT_ENGINE_INFO(" ClientLevel: {}", Stringifier::spdlogLevel(s_ClientLogger->level()));
LT_ENGINE_INFO(" EngineLevel: {}", Stringifier::spdlogLevel(s_EngineLogger->level()));
LT_ENGINE_INFO(" ClientLevel : {}", Stringifier::spdlogLevel(s_ClientLogger->level()));
LT_ENGINE_INFO(" EngineLevel : {}", Stringifier::spdlogLevel(s_EngineLogger->level()));
LT_ENGINE_INFO(" FileLevel : {}", Stringifier::spdlogLevel(s_FileLogger->level()));
LT_ENGINE_INFO(" DefaultLevel: {}", Stringifier::spdlogLevel(spdlog::get_level()));
LT_ENGINE_INFO("________________________________________");
}

View file

@ -5,6 +5,15 @@
#include <spdlog/spdlog.h>
// LOGGER MACROS //
#define LT_LOG_FILE_LOCATION "Log.txt";
// File
#define LT_FILE_INFO(...) ::Light::Logger::GetFileLogger()->log(spdlog::level::info , __VA_ARGS__)
#define LT_FILE_WARN(...) ::Light::Logger::GetFileLogger()->log(spdlog::level::warn , __VA_ARGS__)
#define LT_FILE_ERROR(...) ::Light::Logger::GetFileLogger()->log(spdlog::level::err , __VA_ARGS__)
#define LT_FILE_CRITICAL(...) ::Light::Logger::GetFileLogger()->log(spdlog::level::critical, __VA_ARGS__)
#ifndef LIGHT_DIST
// Engine
#define LT_ENGINE_TRACE(...) ::Light::Logger::GetEngineLogger()->log(spdlog::level::trace , __VA_ARGS__)
@ -38,7 +47,8 @@ namespace Light {
class Logger
{
private:
static std::shared_ptr<spdlog::logger> s_EngineLogger, s_ClientLogger;
static std::shared_ptr<spdlog::logger> s_EngineLogger, s_ClientLogger, s_FileLogger;
static std::string s_LogFilePath;
public:
Logger() = delete;
@ -47,6 +57,7 @@ namespace Light {
static inline std::shared_ptr<spdlog::logger> GetEngineLogger() { return s_EngineLogger; }
static inline std::shared_ptr<spdlog::logger> GetClientLogger() { return s_ClientLogger; }
static inline std::shared_ptr<spdlog::logger> GetFileLogger() { return s_FileLogger; }
static void LogDebugData();
};

View file

@ -19,6 +19,11 @@ int main(int argc, char** argv)
application->GameLoop();
}
catch (Light::FailedAssertion)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled FailedAssertion");
exitCode = -1;
}
catch(Light::glException)
{
LT_ENGINE_CRITICAL("main: exitting due to unhandled glException");

View file

@ -43,12 +43,12 @@ namespace Light {
class WindowResizedEvent : public Event
{
private:
const glm::ivec2 m_Size;
const glm::uvec2 m_Size;
public:
WindowResizedEvent(int width, int height): m_Size(width, height) {}
WindowResizedEvent(unsigned int width, unsigned int height): m_Size(width, height) {}
const glm::ivec2& GetSize() const { return m_Size; }
const glm::uvec2& GetSize() const { return m_Size; }
virtual std::string GetInfoLog() const override
{

View file

@ -2,24 +2,28 @@
#include "Buffers.h"
#include "OpenGL/glBuffers.h"
#include "SharedContext.h"
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxBuffers.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
namespace Light {
VertexBuffer* VertexBuffer::Create(float* vertices, unsigned int stride, unsigned int count, void* sharedContext)
//* VERTEX BUFFER *//
VertexBuffer* VertexBuffer::Create(float* vertices, unsigned int stride, unsigned int count, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
{
case GraphicsAPI::OpenGL:
return new glVertexBuffer(vertices, count);
case GraphicsAPI::DirectX: LT_WIN(
return new dxVertexBuffer(vertices, stride, count, sharedContext);)
case GraphicsAPI::DirectX:
return new dxVertexBuffer(vertices, stride, count, std::static_pointer_cast<dxSharedContext>(sharedContext));
default:
LT_ENGINE_ASSERT(false, "VertexBuffer::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
@ -27,7 +31,8 @@ namespace Light {
}
}
IndexBuffer* IndexBuffer::Create(unsigned int* indices, unsigned int count, void* sharedContext)
//* INDEX BUFFER *//
IndexBuffer* IndexBuffer::Create(unsigned int* indices, unsigned int count, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
{
@ -35,7 +40,7 @@ namespace Light {
return new glIndexBuffer(indices, count);
case GraphicsAPI::DirectX: LT_WIN(
return new dxIndexBuffer(indices, count, sharedContext);)
return new dxIndexBuffer(indices, count, std::dynamic_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "IndexBuffer::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());

View file

@ -4,10 +4,13 @@
namespace Light {
class SharedContext;
//* VERTEX BUFFER *//
class VertexBuffer
{
public:
static VertexBuffer* Create(float* vertices, unsigned int stride, unsigned int count, void* sharedContext);
static VertexBuffer* Create(float* vertices, unsigned int stride, unsigned int count, std::shared_ptr<SharedContext> sharedContext);
virtual void* Map() = 0;
virtual void UnMap() = 0;
@ -19,10 +22,11 @@ namespace Light {
VertexBuffer() = default;
};
//* INDEX BUFFER *//
class IndexBuffer
{
public:
static IndexBuffer* Create(unsigned int* indices, unsigned int count, void* sharedContext);
static IndexBuffer* Create(unsigned int* indices, unsigned int count, std::shared_ptr<SharedContext> sharedContext);
virtual void Bind() = 0;
virtual void UnBind() = 0;

View file

@ -12,6 +12,8 @@
#include "RenderCommand.h"
#include "UserInterface/UserInterface.h"
#include "Utility/Stringifier.h"
namespace Light {
GraphicsContext* GraphicsContext::s_Context = nullptr;
@ -31,8 +33,12 @@ namespace Light {
// determine the default api
if (api == GraphicsAPI::Default)
{
#ifdef LIGHT_PLATFORM_WINDOWS
api = GraphicsAPI::OpenGL; // TODO: Change to DirectX
#if defined(LIGHT_PLATFORM_WINDOWS)
api = GraphicsAPI::DirectX;
#elif defined(LIGHT_PLATFORM_LINUX)
// #todo:
#elif defined(LIGHT_PLATFORM_MAC)
// #todo:
#endif
}
@ -42,11 +48,13 @@ namespace Light {
case GraphicsAPI::OpenGL:
s_Context = new glGraphicsContext(windowHandle);
break;
case GraphicsAPI::DirectX: LT_WIN(
s_Context = new dxGraphicsContext(windowHandle);
break;)
default:
LT_ENGINE_ASSERT(false, "GraphicsContext::Create: invalid/unsupported GraphicsAPI {}", api);
LT_ENGINE_ASSERT(false, "GraphicsContext::Create: invalid/unsupported GraphicsAPI {}", Stringifier::GraphicsAPIToString(api));
return nullptr;
}
@ -56,8 +64,9 @@ namespace Light {
s_Context->m_Renderer = std::unique_ptr<Renderer>(Renderer::Create(s_Context->m_RenderCommand, s_Context->m_SharedContext));
// sanity check
LT_ENGINE_ASSERT(s_Context->m_RenderCommand, "GraphicsContext::Create: RenderCommand creation failed");
LT_ENGINE_ASSERT(s_Context->m_UserInterface, "GraphicsContext::Create: UserInterface creation failed");
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");
return s_Context;
}

View file

@ -2,6 +2,8 @@
#include "Base.h"
#include "SharedContext.h"
struct GLFWwindow;
namespace Light {
@ -32,7 +34,7 @@ namespace Light {
protected:
GraphicsAPI m_GraphicsAPI;
void* m_SharedContext = nullptr;
std::shared_ptr<SharedContext> m_SharedContext = nullptr;
public:
static GraphicsContext* Create(GraphicsAPI api, GLFWwindow* windowHandle);

View file

@ -2,15 +2,18 @@
#include "RenderCommand.h"
#include "OpenGL/glRenderCommand.h"
#include "SharedContext.h"
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxRenderCommand.h"
#include "Directx/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
namespace Light {
RenderCommand* RenderCommand::Create(GLFWwindow* windowHandle, void* sharedContext)
RenderCommand* RenderCommand::Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
{
@ -18,7 +21,7 @@ namespace Light {
return new glRenderCommand(windowHandle);
case GraphicsAPI::DirectX: LT_WIN(
return new dxRenderCommand(sharedContext);)
return new dxRenderCommand((std::static_pointer_cast<dxSharedContext>)(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "RenderCommand::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());

View file

@ -6,6 +6,8 @@ struct GLFWwindow;
namespace Light {
class SharedContext;
class RenderCommand
{
public:
@ -20,7 +22,7 @@ namespace Light {
virtual void Draw(unsigned int count) = 0;
virtual void DrawIndexed(unsigned int count) = 0;
static RenderCommand* Create(GLFWwindow* windowHandle, void* sharedContext);
static RenderCommand* Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
protected:
RenderCommand() = default;

View file

@ -9,7 +9,7 @@ namespace Light {
Renderer* Renderer::s_Context;
Renderer::Renderer(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext)
Renderer::Renderer(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext)
: m_RenderCommand(renderCommand), m_SharedContext(sharedContext)
{
s_Context = this;
@ -17,12 +17,12 @@ namespace Light {
// QUADRENDERER //
m_QuadRenderer.shader = std::unique_ptr<Shader>(Shader::Create("res/vertex.vertex", "res/fragment.fragment", m_SharedContext));
m_QuadRenderer.vertexBuffer = std::unique_ptr<VertexBuffer>(VertexBuffer::Create(nullptr, sizeof(QuadRendererProgram::QuadVertexData), LT_MAX_QUAD * 4, 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));
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));
// QUADRENDERER //
}
Renderer* Renderer::Create(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext)
Renderer* Renderer::Create(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext)
{
return new Renderer(renderCommand, sharedContext);
}

View file

@ -15,6 +15,7 @@
namespace Light {
class RenderCommand;
class SharedContext;
struct RendererProgram
{
@ -29,9 +30,9 @@ namespace Light {
{
// graphics context
std::shared_ptr<Shader> shader;
std::shared_ptr<VertexLayout> vertexLayout;
std::shared_ptr<VertexBuffer> vertexBuffer;
std::shared_ptr<IndexBuffer> indexBuffer;
std::shared_ptr<VertexLayout> vertexLayout;
// buffer data
struct QuadVertexData
@ -67,9 +68,9 @@ namespace Light {
std::shared_ptr<RenderCommand> m_RenderCommand;
void* m_SharedContext;
std::shared_ptr<SharedContext> m_SharedContext;
public:
static Renderer* Create(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext);
static Renderer* Create(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext);
static void DrawQuad(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
@ -77,7 +78,7 @@ namespace Light {
void EndScene();
private:
Renderer(std::shared_ptr<RenderCommand> renderCommand, void* sharedContext);
Renderer(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext);
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint);
};

View file

@ -4,6 +4,7 @@
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxShader.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "GraphicsContext.h"
@ -12,7 +13,7 @@
namespace Light {
Shader* Shader::Create(const std::string& vertexPath, const std::string& pixelPath, void* sharedContext)
Shader* Shader::Create(const std::string& vertexPath, const std::string& pixelPath, std::shared_ptr<SharedContext> sharedContext)
{
// load shader source
std::string vertexSource = FileManager::ReadTXTFile(vertexPath);
@ -30,7 +31,7 @@ namespace Light {
ExtractShaderSource(vertexSource, "HLSL");
ExtractShaderSource(pixelSource, "HLSL");
return new dxShader(vertexSource, pixelSource, sharedContext);)
return new dxShader(vertexSource, pixelSource, std::static_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "Shader::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
@ -42,18 +43,21 @@ namespace Light {
{
size_t begDelimPos, endDelimPos;
// find begin and end delimiter (eg. +GLSL ... -GLSL )
begDelimPos = src.find('+' + delim) + 5;
endDelimPos = src.find('-' + delim);
// check
LT_ENGINE_ASSERT(begDelimPos != std::string::npos + 5,
"Shader::ExtractShaderSource: failed to find the start delimeter in shader source, delim: {}, shader:\n{}",
delim, src);
LT_ENGINE_ASSERT(endDelimPos != std::string::npos,
"Shader::ExtractShaderSource: failed to find the end delimeter in shader source, delim: {}, shader:\n{}",
delim, src);
"Shader::ExtractShaderSource: failed to find the end delimeter in shader source, delim: {}, shader:\n{}",
delim, src);
// extract the shader
src = src.substr(begDelimPos, endDelimPos - begDelimPos);
}

View file

@ -4,10 +4,12 @@
namespace Light {
class SharedContext;
class Shader
{
public:
static Shader* Create(const std::string& vertexPath, const std::string& pixelPath, void* sharedContext);
static Shader* Create(const std::string& vertexPath, const std::string& pixelPath, std::shared_ptr<SharedContext> sharedContext);
virtual ~Shader() = default;

View file

@ -0,0 +1,14 @@
#pragma once
#include "Base.h"
namespace Light {
class SharedContext
{
public:
virtual ~SharedContext() = default;
void DummyFunc(const std::string& value) { LT_ENGINE_TRACE(value); }
};
}

View file

@ -4,21 +4,22 @@
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxVertexLayout.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, void* sharedContext)
VertexLayout* VertexLayout::Create(VertexBuffer* buffer, 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);
case GraphicsAPI::DirectX:
return new dxVertexLayout(shader, elements, sharedContext);
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());

View file

@ -8,6 +8,8 @@ namespace Light {
class VertexBuffer;
class Shader;
class SharedContext;
enum class VertexElementType
{
@ -20,7 +22,7 @@ namespace Light {
class VertexLayout
{
public:
static VertexLayout* Create(VertexBuffer* buffer, Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, void* sharedContext);
static VertexLayout* Create(VertexBuffer* buffer, Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<SharedContext> sharedContext);
virtual ~VertexLayout() = default;;

View file

@ -100,6 +100,7 @@ namespace Light {
void LayerStack::AttachLayerImpl(Layer* layer)
{
// #todo: handle attaching layer on for loop
m_Layers.push_back(layer);
m_Begin = m_Layers.begin();
m_End = m_Layers.end();
@ -107,13 +108,14 @@ namespace Light {
LT_ENGINE_TRACE("LayerStack::PushLayer: Attached [{}]", layer->GetName());
}
void LayerStack::DetatchLayerImpl(Layer* layer)
void LayerStack::DetachLayerImpl(Layer* layer)
{
// #todo: handle detaching layer on for loop
m_Layers.erase(std::find(m_Layers.begin(), m_Layers.end(), layer));
m_Begin = m_Layers.begin();
m_End = m_Layers.end();
LT_ENGINE_TRACE("LayerStack::PushLayer: Detatched[{}]", layer->GetName());
LT_ENGINE_TRACE("LayerStack::PushLayer: Detached[{}]", layer->GetName());
}
}

View file

@ -22,7 +22,7 @@ namespace Light {
~LayerStack();
static inline void AttachLayer(Layer* layer) { s_Context->AttachLayerImpl(layer); }
static inline void DetatchLayer(Layer* layer) { s_Context->DetatchLayerImpl(layer); }
static inline void DetachLayer(Layer* layer) { s_Context->DetachLayerImpl(layer); }
void OnUpdate(float deltaTime);
void OnUserInterfaceUpdate();
@ -38,7 +38,7 @@ namespace Light {
private:
void AttachLayerImpl(Layer* layer);
void DetatchLayerImpl(Layer* layer);
void DetachLayerImpl(Layer* layer);
};
}

View file

@ -4,6 +4,7 @@
#ifdef LIGHT_PLATFORM_WINDOWS
#include "DirectX/dxUserInterface.h"
#include "DirectX/dxSharedContext.h"
#endif
#include "Graphics/GraphicsContext.h"
@ -16,7 +17,7 @@
namespace Light {
UserInterface* UserInterface::Create(GLFWwindow* windowHandle, void* sharedContext)
UserInterface* UserInterface::Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext)
{
switch (GraphicsContext::GetGraphicsAPI())
{
@ -24,7 +25,7 @@ namespace Light {
return new glUserInterface(windowHandle);
case GraphicsAPI::DirectX: LT_WIN(
return new dxUserInterface(windowHandle, sharedContext);)
return new dxUserInterface(windowHandle, std::dynamic_pointer_cast<dxSharedContext>(sharedContext));)
default:
LT_ENGINE_ASSERT(false, "UserInterface::Create: invalid/unsupported GraphicsAPI {}", GraphicsContext::GetGraphicsAPI());
@ -37,13 +38,13 @@ namespace Light {
ImGuiIO& io = ImGui::GetIO();
switch (inputEvent.GetEventType())
{
// Mouse Events
case EventType::MouseMoved:
{
const MouseMovedEvent& event = (const MouseMovedEvent&)inputEvent;
ImGui::GetIO().MousePos = ImVec2(event.GetX(), event.GetY());
return;
}
case EventType::ButtonPressed:
{
const ButtonPressedEvent& event = (const ButtonPressedEvent&)inputEvent;
@ -56,7 +57,13 @@ namespace Light {
ImGui::GetIO().MouseDown[event.GetButton()] = false;
return;
}
case EventType::WheelScrolled:
{
const WheelScrolledEvent& event = (const WheelScrolledEvent&)inputEvent;
ImGui::GetIO().MouseWheel = event.GetOffset();
return;
}
// Keyboard Events
case EventType::KeyPressed:
{
const KeyPressedEvent& event = (const KeyPressedEvent&)inputEvent;
@ -69,12 +76,6 @@ namespace Light {
ImGui::GetIO().MouseDown[event.GetKey()] = false;
return;
}
case EventType::WheelScrolled:
{
const WheelScrolledEvent& event = (const WheelScrolledEvent&)inputEvent;
ImGui::GetIO().MouseWheel = event.GetOffset();
return;
}
}
}

View file

@ -7,11 +7,12 @@ struct GLFWwindow;
namespace Light {
class Event;
class SharedContext;
class UserInterface
{
public:
static UserInterface* Create(GLFWwindow* windowHandle, void* sharedContext);
static UserInterface* Create(GLFWwindow* windowHandle, std::shared_ptr<SharedContext> sharedContext);
UserInterface(const UserInterface&) = delete;
UserInterface operator=(const UserInterface&) = delete;

View file

@ -1,6 +1,8 @@
#include "ltpch.h"
#include "Stringifier.h"
#include "Graphics/GraphicsContext.h"
#include <glad/glad.h>
#include <spdlog/common.h>
@ -65,4 +67,17 @@ namespace Light {
}
}
std::string Stringifier::GraphicsAPIToString(GraphicsAPI api)
{
switch (api)
{
case Light::GraphicsAPI::Default: return "Default";
case Light::GraphicsAPI::OpenGL: return "OpenGL";
case Light::GraphicsAPI::DirectX: return "DirectX";
case Light::GraphicsAPI::Vulkan: return "Vulkan";
case Light::GraphicsAPI::Metal: return "Metal";
default: return "UNKNOWN";
}
}
}

View file

@ -4,6 +4,8 @@
namespace Light {
enum class GraphicsAPI;
class Stringifier
{
public:
@ -12,6 +14,8 @@ namespace Light {
static std::string glDebugMsgType(unsigned int type);
static std::string spdlogLevel(unsigned int level);
static std::string GraphicsAPIToString(GraphicsAPI api);
};
}

View file

@ -5,9 +5,9 @@
// Platform
#ifdef _WIN32
#define NOMINMAX
#include <Windows.h>
#undef NOMINMAX
#define NOMINMAX
#include <Windows.h>
#undef NOMINMAX
#endif
// Containers

View file

@ -1,5 +0,0 @@
#pragma once
#include "Base.h"
// DirectX Call

View file

@ -5,67 +5,65 @@
namespace Light {
dxVertexBuffer::dxVertexBuffer(float* vertices, unsigned int stride, unsigned int count, void* sharedContext)
: m_Stride(stride)
//* 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 };
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bd.ByteWidth = count * stride;
bd.StructureByteStride = stride;
// create buffer
HRESULT hr;
dxSharedContext* dxContext = static_cast<dxSharedContext*>(sharedContext);
LT_ENGINE_ASSERT(dxContext, "dxShader::dxShader: invalid dxContext");
m_Device = dxContext->device;
m_DeviceContext = dxContext->deviceContext;
D3D11_BUFFER_DESC desc = { 0 };
desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.ByteWidth = count * stride;
desc.StructureByteStride = stride;
DXC(m_Device->CreateBuffer(&desc, nullptr, &m_Buffer));
DXC(m_Context->device->CreateBuffer(&bd, nullptr, &m_Buffer));
}
dxVertexBuffer::~dxVertexBuffer()
{
UnBind();
}
void* dxVertexBuffer::Map()
{
m_DeviceContext->Map(m_Buffer.Get(), NULL, D3D11_MAP_WRITE_DISCARD, NULL, &m_Map);
m_Context->deviceContext->Map(m_Buffer.Get(), NULL, D3D11_MAP_WRITE_DISCARD, NULL, &m_Map);
return m_Map.pData;
}
void dxVertexBuffer::UnMap()
{
m_DeviceContext->Unmap(m_Buffer.Get(), NULL);
m_Context->deviceContext->Unmap(m_Buffer.Get(), NULL);
}
void dxVertexBuffer::Bind()
{
static const unsigned int offset = 0u;
m_DeviceContext->IASetVertexBuffers(0u, 1u, m_Buffer.GetAddressOf(), &m_Stride, &offset);
m_Context->deviceContext->IASetVertexBuffers(0u, 1u, m_Buffer.GetAddressOf(), &m_Stride, &offset);
}
void dxVertexBuffer::UnBind()
{
static const unsigned int offset = 0u;
static ID3D11Buffer* buffer = nullptr;
m_Context->deviceContext->IASetVertexBuffers(0u, 1u, &buffer, &m_Stride, &offset);
}
dxIndexBuffer::dxIndexBuffer(unsigned int* indices, unsigned int count, void* sharedContext)
//* INDEX BUFFER *//
dxIndexBuffer::dxIndexBuffer(unsigned int* indices, unsigned int count, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
HRESULT hr;
dxSharedContext* dxContext = static_cast<dxSharedContext*>(sharedContext);
LT_ENGINE_ASSERT(dxContext, "dxShader::dxShader: invalid dxContext");
m_Device = dxContext->device;
m_DeviceContext = dxContext->deviceContext;
// generate indices if not provided
bool hasIndices = !!indices;
if (!hasIndices)
{
// check
if (count % 6 != 0)
{
LT_ENGINE_WARN("dxIndexBuffer::dxIndexBuffer: indices can only be null if count is multiple of 6");
@ -73,6 +71,7 @@ namespace Light {
count = count + (6 - (count % 6));
}
// create indices
indices = new unsigned int[count];
unsigned int offset = 0;
for (unsigned int i = 0; i < count; i += 6)
@ -89,18 +88,23 @@ namespace Light {
}
}
D3D11_BUFFER_DESC bufferDesc = { 0 };
// buffer desc
D3D11_BUFFER_DESC bd = { 0 };
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = count * sizeof(unsigned int);
bd.StructureByteStride = sizeof(unsigned int);
// subresource data
D3D11_SUBRESOURCE_DATA sd = { 0 };
bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.ByteWidth = count * sizeof(unsigned int);
bufferDesc.StructureByteStride = sizeof(unsigned int);
sd.pSysMem = indices;
DXC(m_Device->CreateBuffer(&bufferDesc, &sd, &m_Buffer));
// create buffer
HRESULT hr;
DXC(m_Context->device->CreateBuffer(&bd, &sd, &m_Buffer));
// delete indices
if (!hasIndices)
{
delete[] indices;
@ -110,15 +114,20 @@ namespace Light {
dxIndexBuffer::~dxIndexBuffer()
{
UnBind();
}
void dxIndexBuffer::Bind()
{
m_DeviceContext->IASetIndexBuffer(m_Buffer.Get(), DXGI_FORMAT_R32_UINT, 0u);
m_Context->deviceContext->IASetIndexBuffer(m_Buffer.Get(), DXGI_FORMAT_R32_UINT, 0u);
}
void dxIndexBuffer::UnBind()
{
static const unsigned int offset = 0u;
static ID3D11Buffer* buffer = nullptr;
m_Context->deviceContext->IASetIndexBuffer(buffer, DXGI_FORMAT_R32_UINT, offset);
}
}

View file

@ -1,7 +1,6 @@
#pragma once
#include "Base.h"
#include "dxBase.h"
#include "Graphics/Buffers.h"
#include <d3d11.h>
@ -9,19 +8,21 @@
namespace Light {
class dxSharedContext;
//* VERTEX BUFFER *//
class dxVertexBuffer : public VertexBuffer
{
private:
std::shared_ptr<dxSharedContext> m_Context;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_Buffer;
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
D3D11_MAPPED_SUBRESOURCE m_Map;
unsigned int m_Stride;
public:
dxVertexBuffer(float* vertices, unsigned int stride, unsigned int count, void* sharedContext);
dxVertexBuffer(float* vertices, unsigned int stride, unsigned int count, std::shared_ptr<dxSharedContext> sharedContext);
~dxVertexBuffer();
void* Map() override;
@ -31,15 +32,16 @@ namespace Light {
void UnBind() override;
};
//* INDEX BUFFER *//
class dxIndexBuffer : public IndexBuffer
{
private:
std::shared_ptr<dxSharedContext> m_Context;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_Buffer;
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
public:
dxIndexBuffer(unsigned int* indices, unsigned int count, void* sharedContext);
dxIndexBuffer(unsigned int* indices, unsigned int count, std::shared_ptr<dxSharedContext> sharedContext);
~dxIndexBuffer();
void Bind() override;

View file

@ -9,6 +9,8 @@
#include "Graphics/VertexLayout.h"
#include "UserInterface/UserInterface.h"
#include "Events/WindowEvents.h"
#include <glfw/glfw3.h>
#define GLFW_EXPOSE_NATIVE_WIN32
@ -23,8 +25,7 @@ namespace Light {
{
m_GraphicsAPI = GraphicsAPI::DirectX;
HRESULT hr;
// swap chain desc
DXGI_SWAP_CHAIN_DESC sd = { 0 };
sd.OutputWindow = static_cast<HWND>(glfwGetWin32Window(windowHandle));
@ -53,20 +54,29 @@ namespace Light {
flags = D3D11_CREATE_DEVICE_DEBUG;
#endif
// create device and swap chain
HRESULT hr;
DXC(D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE,
NULL, flags, NULL, NULL, D3D11_SDK_VERSION,
&sd, &m_SwapChain, &m_Device, NULL, &m_DeviceContext));
// set primitive topology
m_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// create render target view
Microsoft::WRL::ComPtr<ID3D11Resource> backBuffer;
DXC(m_SwapChain->GetBuffer(0u, __uuidof(ID3D11Resource), &backBuffer));
DXC(m_Device->CreateRenderTargetView(backBuffer.Get(), nullptr, &m_RenderTargetView));
// set render target view
m_DeviceContext->OMSetRenderTargets(1u, m_RenderTargetView.GetAddressOf(), nullptr);
#ifdef LIGHT_DEBUG
// configure the debug interface
Microsoft::WRL::ComPtr<ID3D11InfoQueue> infoQueue;
DXC(m_Device.As(&debugInterface));
DXC(debugInterface.As(&infoQueue));
DXC(m_Device.As(&m_DebugInterface));
DXC(m_DebugInterface.As(&infoQueue));
D3D11_MESSAGE_ID hide[] =
{
@ -80,8 +90,20 @@ namespace Light {
filter.DenyList.NumIDs = _countof(hide);
filter.DenyList.pIDList = hide;
infoQueue->AddStorageFilterEntries(&filter);
#endif
// create shared context
m_SharedContext = std::make_shared<dxSharedContext>(m_Device, m_DeviceContext, m_SwapChain, m_RenderTargetView);
}
void dxGraphicsContext::OnWindowResize(const WindowResizedEvent& event)
{
SetResolution(event.GetSize());
}
void dxGraphicsContext::SetResolution(const glm::uvec2& resolution)
{
// viewport
D3D11_VIEWPORT viewport;
viewport.Width = 800.0f;
@ -92,17 +114,8 @@ namespace Light {
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
// set viewport
m_DeviceContext->RSSetViewports(1u, &viewport);
dxSharedContext* sharedContext = new dxSharedContext({m_DeviceContext, m_SwapChain, m_RenderTargetView, m_Device});
m_SharedContext = sharedContext;
}
void dxGraphicsContext::OnWindowResize(const WindowResizedEvent& event)
{
}
void dxGraphicsContext::LogDebugData()
@ -126,7 +139,7 @@ namespace Light {
DXGIDevice->Release();
DXGIAdapter->Release();
// log info // #todo: log more information
// #todo: log more information
LT_ENGINE_INFO("________________________________________");
LT_ENGINE_INFO("dxGraphicsContext:");
LT_ENGINE_INFO(" Renderer: {}", adapterDesc);

View file

@ -1,9 +1,10 @@
#pragma once
#include "Base.h"
#include "dxBase.h"
#include "Graphics/GraphicsContext.h"
#include <glm/glm.hpp>
#include <d3d11.h>
#include <wrl.h>
@ -21,7 +22,7 @@ namespace Light {
Microsoft::WRL::ComPtr<IDXGISwapChain> m_SwapChain;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_RenderTargetView;
Microsoft::WRL::ComPtr<ID3D11Debug> debugInterface;
Microsoft::WRL::ComPtr<ID3D11Debug> m_DebugInterface;
public:
dxGraphicsContext(GLFWwindow* windowHandle);
@ -29,6 +30,9 @@ namespace Light {
virtual void OnWindowResize(const WindowResizedEvent& event) override;
virtual void LogDebugData() override;
private:
void SetResolution(const glm::uvec2& resolution);
};
}

View file

@ -5,13 +5,9 @@
namespace Light {
dxRenderCommand::dxRenderCommand(void* sharedContext)
dxRenderCommand::dxRenderCommand(std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
dxSharedContext* dxContext = (dxSharedContext*)sharedContext;
m_DeviceContext = dxContext->deviceContext;
m_SwapChain = dxContext->swapChain;
m_RenderTargetView = dxContext->renderTargetView;
}
dxRenderCommand::~dxRenderCommand()
@ -20,23 +16,23 @@ namespace Light {
void dxRenderCommand::SwapBuffers()
{
m_SwapChain->Present(0, 0);
m_Context->swapChain->Present(0, 0);
}
void dxRenderCommand::ClearBackBuffer()
{
float colors[] = { 1.2f, 0.4f, 0.9f, 1.0f };
m_DeviceContext->ClearRenderTargetView(m_RenderTargetView.Get(), colors);
m_Context->deviceContext->ClearRenderTargetView(m_Context->renderTargetView.Get(), colors);
}
void dxRenderCommand::Draw(unsigned int count)
{
m_DeviceContext->Draw(count, 0u);
m_Context->deviceContext->Draw(count, 0u);
}
void dxRenderCommand::DrawIndexed(unsigned int count)
{
m_DeviceContext->DrawIndexed(count, 0u, 0u);
m_Context->deviceContext->DrawIndexed(count, 0u, 0u);
}
}

View file

@ -8,15 +8,15 @@
namespace Light {
class dxSharedContext;
class dxRenderCommand : public RenderCommand
{
private:
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
Microsoft::WRL::ComPtr<IDXGISwapChain> m_SwapChain;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> m_RenderTargetView;
std::shared_ptr<dxSharedContext> m_Context;
public:
dxRenderCommand(void* sharedContext);
dxRenderCommand(std::shared_ptr<dxSharedContext> sharedContext);
~dxRenderCommand();
virtual void SwapBuffers() override;

View file

@ -8,40 +8,40 @@
namespace Light {
dxShader::dxShader(const std::string& vertexSource, const std::string& pixelSource, void* sharedContext)
dxShader::dxShader(const std::string& vertexSource, const std::string& pixelSource, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
HRESULT hr;
dxSharedContext* dxContext = static_cast<dxSharedContext*>(sharedContext);
LT_ENGINE_ASSERT(dxContext, "dxShader::dxShader: invalid dxContext");
m_Device = dxContext->device;
m_DeviceContext = dxContext->deviceContext;
Microsoft::WRL::ComPtr<ID3DBlob> ps = nullptr, vsErr = nullptr, psErr = nullptr;
// 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));
// 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());
DXC(m_Device->CreateVertexShader(m_VertexBlob->GetBufferPointer(), m_VertexBlob->GetBufferSize(), NULL, &m_VertexShader));
DXC(m_Device->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), NULL, &m_PixelShader));
// 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));
}
dxShader::~dxShader()
{
UnBind();
}
void dxShader::Bind()
{
m_DeviceContext->VSSetShader(m_VertexShader.Get(), nullptr, 0u);
m_DeviceContext->PSSetShader(m_PixelShader.Get(), nullptr, 0u);
m_Context->deviceContext->VSSetShader(m_VertexShader.Get(), nullptr, 0u);
m_Context->deviceContext->PSSetShader(m_PixelShader.Get(), nullptr, 0u);
}
void dxShader::UnBind()
{
m_Context->deviceContext->VSSetShader(nullptr, nullptr, 0u);
m_Context->deviceContext->PSSetShader(nullptr, nullptr, 0u);
}
}

View file

@ -1,7 +1,6 @@
#pragma once
#include "Base.h"
#include "dxBase.h"
#include "Graphics/Shader.h"
#include <d3d11.h>
@ -9,18 +8,19 @@
namespace Light {
class dxSharedContext;
class dxShader : public Shader
{
private:
std::shared_ptr<dxSharedContext> m_Context;
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_VertexShader;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_PixelShader;
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
Microsoft::WRL::ComPtr<ID3DBlob> m_VertexBlob;
public:
dxShader(const std::string& vertexSource, const std::string& pixelSource, void* sharedContext);
dxShader(const std::string& vertexSource, const std::string& pixelSource, std::shared_ptr<dxSharedContext> sharedContext);
~dxShader();
void Bind() override;

View file

@ -1,19 +1,29 @@
#pragma once
#include "Base.h"
#include "dxBase.h"
#include "Graphics/SharedContext.h"
#include <d3d11.h>
#include <wrl.h>
namespace Light {
struct dxSharedContext
// #todo:
class dxSharedContext : public SharedContext
{
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)
{
}
Microsoft::WRL::ComPtr<ID3D11Device> device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> deviceContext;
Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> renderTargetView;
Microsoft::WRL::ComPtr<ID3D11Device> device;
};
}

View file

@ -13,24 +13,22 @@
namespace Light {
dxUserInterface::dxUserInterface(GLFWwindow* windowHandle, void* sharedContext)
dxUserInterface::dxUserInterface(GLFWwindow* windowHandle, std::shared_ptr<dxSharedContext> sharedContext)
{
// set dxContext
dxSharedContext* dxContext = static_cast<dxSharedContext*>(sharedContext);
LT_ENGINE_ASSERT(dxContext, "dxUserInterface::dxUserInterface: invalid sharedContext");
m_DeviceContext = dxContext->deviceContext;
m_Device = dxContext->device;
// create context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
// configure io
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
// style
ImGui::StyleColorsDark();
// init
ImGui_ImplWin32_Init(glfwGetWin32Window(windowHandle));
ImGui_ImplDX11_Init(m_Device.Get(), m_DeviceContext.Get());
ImGui_ImplDX11_Init(sharedContext->device.Get(), sharedContext->deviceContext.Get());
}
dxUserInterface::~dxUserInterface()
@ -46,7 +44,7 @@ namespace Light {
ImGui_ImplWin32_NewFrame();
ImGui::NewFrame();
// TEMP
//* TEMP_ IMGUI DEBUG WINDOW _TEMP *//
ImGui::ShowDemoWindow();
}
@ -58,6 +56,7 @@ namespace Light {
void dxUserInterface::LogDebugData()
{
// #todo: improve
LT_ENGINE_INFO("________________________________________");
LT_ENGINE_INFO("UserInterface::");
LT_ENGINE_INFO(" API : ImGui");

View file

@ -1,7 +1,6 @@
#pragma once
#include "Base.h"
#include "dxBase.h"
#include "UserInterface/UserInterface.h"
struct GLFWwindow;
@ -11,14 +10,12 @@ struct GLFWwindow;
namespace Light {
class dxSharedContext;
class dxUserInterface : public UserInterface
{
private:
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
public:
dxUserInterface(GLFWwindow* windowHandle, void* sharedContext);
dxUserInterface(GLFWwindow* windowHandle, std::shared_ptr<dxSharedContext> sharedContext);
~dxUserInterface();
void Begin() override;

View file

@ -6,68 +6,75 @@
namespace Light {
dxVertexLayout::dxVertexLayout(Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, void* sharedContext)
dxVertexLayout::dxVertexLayout(Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<dxSharedContext> sharedContext)
: m_Context(sharedContext)
{
HRESULT hr;
dxSharedContext* dxContext = static_cast<dxSharedContext*>(sharedContext);
LT_ENGINE_ASSERT(dxContext, "dxShader::dxShader: invalid dxContext");
m_Device = dxContext->device;
m_DeviceContext = dxContext->deviceContext;
// local
std::vector<D3D11_INPUT_ELEMENT_DESC> inputElementsDesc;
inputElementsDesc.reserve(elements.size());
// extract elements desc
for (const auto& element : elements)
{
inputElementsDesc.emplace_back(D3D11_INPUT_ELEMENT_DESC{
element.first.c_str(),
0u,
GetDxgiFormat(element.second),
0u,
D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA,
0u });
element.first.c_str(),
0u,
GetDxgiFormat(element.second),
0u,
D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA,
0u });
}
// #todo: take in shared_ptr
dxShader* dxpShader = static_cast<dxShader*>(shader);
LT_ENGINE_ASSERT(dxpShader, "dxVertexLayout::dxVertexLayout: failed to cast Shader to dxShader");
DXC(m_Device->CreateInputLayout(&inputElementsDesc[0], inputElementsDesc.size(), dxpShader->GetVertexBlob().Get()->GetBufferPointer(), dxpShader->GetVertexBlob().Get()->GetBufferSize(), &m_InputLayout));
// 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));
}
dxVertexLayout::~dxVertexLayout()
{
UnBind();
}
void dxVertexLayout::Bind()
{
m_DeviceContext->IASetInputLayout(m_InputLayout.Get());
m_Context->deviceContext->IASetInputLayout(m_InputLayout.Get());
}
void dxVertexLayout::UnBind()
{
m_Context->deviceContext->IASetInputLayout(nullptr);
}
DXGI_FORMAT dxVertexLayout::GetDxgiFormat(VertexElementType type)
{
switch (type)
{
// int
case Light::VertexElementType::Int1: return DXGI_FORMAT_R32_SINT;
case Light::VertexElementType::Int2: return DXGI_FORMAT_R32G32_SINT;
case Light::VertexElementType::Int3: return DXGI_FORMAT_R32G32B32_SINT;
case Light::VertexElementType::Int4: return DXGI_FORMAT_R32G32B32A32_SINT;
// uint
case Light::VertexElementType::UInt1: return DXGI_FORMAT_R32_UINT;
case Light::VertexElementType::UInt2: return DXGI_FORMAT_R32G32_UINT;
case Light::VertexElementType::UInt3: return DXGI_FORMAT_R32G32B32_UINT;
case Light::VertexElementType::UInt4: return DXGI_FORMAT_R32G32B32A32_UINT;
// float
case Light::VertexElementType::Float1: return DXGI_FORMAT_R32_FLOAT;
case Light::VertexElementType::Float2: return DXGI_FORMAT_R32G32_FLOAT;
case Light::VertexElementType::Float3: return DXGI_FORMAT_R32G32B32_FLOAT;
case Light::VertexElementType::Float4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
// TODO:
// #todo:
case Light::VertexElementType::Double1:
case Light::VertexElementType::Double2:
case Light::VertexElementType::Double3:

View file

@ -1,7 +1,6 @@
#pragma once
#include "Base.h"
#include "dxBase.h"
#include "Graphics/VertexLayout.h"
#include <d3d11.h>
@ -10,17 +9,17 @@
namespace Light {
class Shader;
class dxSharedContext;
class dxVertexLayout : public VertexLayout
{
private:
std::shared_ptr<dxSharedContext> m_Context;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_InputLayout;
Microsoft::WRL::ComPtr<ID3D11Device> m_Device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_DeviceContext;
public:
dxVertexLayout(Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, void* sharedContext);
dxVertexLayout(Shader* shader, const std::vector<std::pair<std::string, VertexElementType>>& elements, std::shared_ptr<dxSharedContext> sharedContext);
~dxVertexLayout();
void Bind() override;

View file

@ -38,9 +38,11 @@ namespace Light {
glIndexBuffer::glIndexBuffer(unsigned int* indices, unsigned int count)
{
// generate indices if not provided
bool hasIndices = !!indices;
if (!hasIndices)
{
// check
if (count % 6 != 0)
{
LT_ENGINE_WARN("glIndexBuffer::glIndexBuffer: count should be divisible by 6 when no indices is provided");
@ -48,6 +50,7 @@ namespace Light {
count = count + (6 - (count % 6));
}
// create indices
indices = new unsigned int[count];
unsigned int offset = 0;
for (unsigned int i = 0; i < count; i += 6)
@ -64,9 +67,11 @@ namespace Light {
}
}
// create buffer
glCreateBuffers(1, &m_BufferID);
glNamedBufferData(m_BufferID, count * sizeof(unsigned int), indices, GL_STATIC_DRAW);
// delete indices
if (!hasIndices)
delete[] indices;
}

View file

@ -84,6 +84,7 @@ namespace Light {
id);
LT_ENGINE_WARN(" {}", message);
return;
case GL_DEBUG_SEVERITY_NOTIFICATION:
LT_ENGINE_TRACE("glMessageCallback: Severity: {} :: Source: {} :: Type: {} :: ID: {}",
Stringifier::glDebugMsgSeverity(severity),

View file

@ -9,6 +9,7 @@ namespace Light {
{
m_ShaderID = glCreateProgram();
// create shaders
unsigned int vertexShader = glCreateShader(GL_VERTEX_SHADER);
unsigned int pixelShader = glCreateShader(GL_FRAGMENT_SHADER);
@ -16,13 +17,15 @@ namespace Light {
const char* lVertexSource = vertexSource.c_str();
const char* lFragmentSource = fragmentSource.c_str();
// set shaders' sorce code
glShaderSource(vertexShader, 1, &lVertexSource, NULL);
glShaderSource(pixelShader, 1, &lFragmentSource, NULL);
// compile shaders
glCompileShader(vertexShader);
glCompileShader(pixelShader);
// TEMP
//* TEMP__ HANDLE SHADER COMPILE FAILURE __TEMP **//
int isCompiled = 0;
glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &isCompiled);
if (isCompiled == GL_FALSE)
@ -47,16 +50,18 @@ namespace Light {
glDeleteShader(pixelShader);
}
// TEMP
//* TEMP__ HANDLE SHADER COMPILE FAILURE __TEMP **//
// attach and link shaders to the shader program
glAttachShader(m_ShaderID, vertexShader);
glAttachShader(m_ShaderID, pixelShader);
glLinkProgram(m_ShaderID);
// delete shaders (free memory)
glDeleteShader(vertexShader);
glDeleteShader(pixelShader);
// TODO: validate program
// #todo: validate program
}
glShader::~glShader()

View file

@ -0,0 +1,12 @@
#pragma once
#include "Base.h"
namespace Light {
struct glSharedContext
{
};
}

View file

@ -9,13 +9,18 @@ namespace Light {
glUserInterface::glUserInterface(GLFWwindow* windowHandle)
{
// create context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
// configure io
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
// style color
ImGui::StyleColorsDark();
// init
ImGui_ImplGlfw_InitForOpenGL(windowHandle, false);
ImGui_ImplOpenGL3_Init();
}
@ -33,7 +38,7 @@ namespace Light {
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// TEMP
//* TEMP_ IMGUI DEBUG WINDOW _TEMP *//
ImGui::ShowDemoWindow();
}
@ -45,6 +50,7 @@ namespace Light {
void glUserInterface::LogDebugData()
{
// #todo: improve
LT_ENGINE_INFO("________________________________________");
LT_ENGINE_INFO("UserInterface::");
LT_ENGINE_INFO(" API : ImGui");

View file

@ -13,22 +13,26 @@ namespace Light {
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");
// elements desc
// local
std::vector<glVertexElementDesc> elementsDesc;
elementsDesc.reserve(elements.size());
unsigned int stride = 0u;
// extract elements desc
for(const auto& element : elements)
{
elementsDesc.push_back(GetElementDesc(element.second, stride));
stride += elementsDesc.back().typeSize * elementsDesc.back().count;
}
// prepare
// create vertex array
glCreateVertexArrays(1, &m_ArrayID);
// bind buffer and array
buffer->Bind();
Bind();
// vertex attributes
// enable vertex attributes
unsigned int index = 0u;
for (const auto& elementDesc : elementsDesc)
{
@ -56,25 +60,30 @@ namespace Light {
{
switch (type)
{
// 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 };
// 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 };
// 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 };
// double
case VertexElementType::Double1: return { GL_DOUBLE, 1, sizeof(float), offset };
case VertexElementType::Double2: return { GL_DOUBLE, 2, sizeof(float), offset };
case VertexElementType::Double3: return { GL_DOUBLE, 3, sizeof(float), offset };
case VertexElementType::Double4: return { GL_DOUBLE, 4, sizeof(float), offset };
default:
LT_ENGINE_ASSERT(false, "glVertexLayout::GetElementDesc: invalid vertex element type");
return {};

View file

@ -20,16 +20,20 @@ namespace Light {
wWindow::wWindow(std::function<void(Event&)> callback)
: m_EventCallback(callback)
{
// init glfw
LT_ENGINE_ASSERT(glfwInit(), "wWindow::wWindow: failed to initialize glfw");
// create window
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");
// manage events
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");
}
@ -43,7 +47,7 @@ namespace Light {
{
m_Properties = properties;
glfwSetWindowSize(m_Handle, properties.size.x, properties.size.y);
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);
}
@ -91,10 +95,10 @@ namespace Light {
glfwSwapInterval(m_Properties.vsync);
}
void wWindow::SetSize(const glm::uvec2& size)
void wWindow::SetSize(const glm::uvec2& size, bool add /*= false*/)
{
m_Properties.size.x = size.x == 0u ? m_Properties.size.x : size.x;
m_Properties.size.y = size.y == 0u ? m_Properties.size.y : size.y;
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;
glfwSetWindowSize(m_Handle, m_Properties.size.x, m_Properties.size.y);
}
@ -136,10 +140,10 @@ namespace Light {
});
// Window Events //
glfwSetWindowCloseCallback(m_Handle, [](GLFWwindow* window)
glfwSetWindowPosCallback(m_Handle, [](GLFWwindow* window, int xpos, int ypos)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
callback(WindowClosedEvent());
callback(WindowMovedEvent(xpos, ypos));
});
glfwSetWindowSizeCallback(m_Handle, [](GLFWwindow* window, int width, int height)
@ -148,10 +152,10 @@ namespace Light {
callback(WindowResizedEvent(width, height));
});
glfwSetWindowPosCallback(m_Handle, [](GLFWwindow* window, int xpos, int ypos)
glfwSetWindowCloseCallback(m_Handle, [](GLFWwindow* window)
{
std::function<void(Event&)> callback = *(std::function<void(Event&)>*)glfwGetWindowUserPointer(window);
callback(WindowMovedEvent(xpos, ypos));
callback(WindowClosedEvent());
});
glfwSetWindowFocusCallback(m_Handle, [](GLFWwindow* window, int focus)

View file

@ -29,7 +29,7 @@ namespace Light {
void SetTitle(const std::string& title) override;
void SetSize(const glm::uvec2& size) override;
void SetSize(const glm::uvec2& size, bool add = false) override;
void SetVSync(bool vsync, bool toggle = false) override;
void SetVisibility(bool visible, bool toggle = false) override;

0
Sandbox/Log.txt Normal file
View file

View file

@ -1,10 +1,10 @@
[Window][Debug##Default]
Pos=60,60
Pos=60,-18
Size=400,400
Collapsed=0
[Window][Dear ImGui Demo]
Pos=1,-3
Pos=-16,5
Size=405,290
Collapsed=0