- Added Texture and glTexture class ( no dx implementation yet )
- Added TextureRendererProgram to Renderer
- Added LoadTexture to ResourceManager
- Added TextureShader
- Added awesomeface.png
- Removed unused shader files from Sandbox/res
- Fixed gladLoadGLLoader call in glGraphicsContext
- Enabled alpha blending in glGraphicsContext
- Added stb_image library
This commit is contained in:
Light 2021-06-29 11:01:11 +04:30
parent 2b87fd22fe
commit c9352407e1
17 changed files with 8187 additions and 56 deletions

7871
Dependencies/stb_image/stb_image.h vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -48,6 +48,7 @@ project "Engine"
(dependenciesdir .. "GLAD/include"),
(dependenciesdir .. "imgui/backends"),
(dependenciesdir .. "imgui/"),
(dependenciesdir .. "stb_image/"),
(dependenciesdir .. "glm/"),
}

View file

@ -0,0 +1,35 @@
#define LT_ENGINE_RESOURCES_TEXTURE_SHADER_VS \
R"(
+GLSL
#version 440 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec2 a_TexCoords;
out vec2 texCoords;
void main()
{
gl_Position = vec4(a_Position, 1.0);
texCoords = a_TexCoords;
}
-GLSL
)"
#define LT_ENGINE_RESOURCES_TEXTURE_SHADER_PS \
R"(
+GLSL
#version 440 core
in vec2 texCoords;
uniform sampler2D u_Texture;
out vec4 FragmentColor;
void main()
{
FragmentColor = texture(u_Texture, texCoords);
}
-GLSL
)"

View file

@ -68,7 +68,8 @@ namespace Light {
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));
// sanity check
// 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

@ -6,9 +6,12 @@
#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;
@ -19,13 +22,21 @@ namespace Light {
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);
// QUADRENDERER //
//** 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));
// QUADRENDERER //
//** 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 },{ "TEXCOORDS", VertexElementType::Float2 } }, m_SharedContext));
//** texture rendererc **//
}
Renderer* Renderer::Create(std::shared_ptr<RenderCommand> renderCommand, std::shared_ptr<SharedContext> sharedContext)
@ -38,6 +49,11 @@ namespace Light {
s_Context->DrawQuadImpl(position, size, tint);
}
void Renderer::DrawQuad(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture)
{
s_Context->DrawQuadImpl(position, size, texture);
}
void Renderer::DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, const glm::vec4& tint)
{
// check
@ -58,7 +74,7 @@ namespace Light {
// TOP_LEFT
m_QuadRenderer.mapCurrent[0].position = { xMin, yMin, position.z };
m_QuadRenderer.mapCurrent[0].tint = tint;
// TOP_RIGHT
m_QuadRenderer.mapCurrent[1].position = { xMax, yMin, position.z };
m_QuadRenderer.mapCurrent[1].tint = tint;
@ -76,9 +92,51 @@ namespace Light {
m_QuadRenderer.quadCount++;
}
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
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_RIGHT
m_TextureRenderer.mapCurrent[1].position = { xMax, yMin, position.z };
m_TextureRenderer.mapCurrent[1].uv = { 1, 0 };
// BOTTOM_RIGHT
m_TextureRenderer.mapCurrent[2].position = { xMax, yMax, position.z };
m_TextureRenderer.mapCurrent[2].uv = { 1, 1 };
// BOTTOM_LEFT
m_TextureRenderer.mapCurrent[3].position = { xMin, yMax, position.z };
m_TextureRenderer.mapCurrent[3].uv = { 0, 1 };
// advance
m_TextureRenderer.mapCurrent += 4;
m_TextureRenderer.quadCount++;
}
void Renderer::BeginScene()
{
m_QuadRenderer.Map();
m_TextureRenderer.Map();
}
void Renderer::EndScene()
@ -90,6 +148,14 @@ namespace Light {
m_RenderCommand->DrawIndexed(m_QuadRenderer.quadCount * 6);
m_QuadRenderer.quadCount = 0;
}
if (m_TextureRenderer.quadCount)
{
m_TextureRenderer.Bind();
m_RenderCommand->DrawIndexed(m_TextureRenderer.quadCount * 6);
m_TextureRenderer.quadCount = 0;
}
}
}

View file

@ -17,6 +17,8 @@ namespace Light {
class RenderCommand;
class SharedContext;
class Texture;
struct RendererProgram
{
virtual void Map() = 0;
@ -62,17 +64,57 @@ namespace Light {
}
};
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::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 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);
void BeginScene();
void EndScene();
@ -81,6 +123,7 @@ namespace Light {
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);
void DrawQuadImpl(const glm::vec3& position, const glm::vec2& size, std::shared_ptr<Texture> texture);
};
}

View file

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

View file

@ -0,0 +1,25 @@
#pragma once
#include "Base.h"
namespace Light {
class SharedContext;
class Texture
{
public:
static Texture* Create(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels, std::shared_ptr<SharedContext> sharedContext);
Texture(const Texture&) = delete;
Texture& operator=(const Texture&) = delete;
virtual ~Texture() = default;
virtual void Bind(unsigned int slot = 0) = 0;
protected:
Texture() = default;
};
}

View file

@ -2,7 +2,9 @@
#include "ResourceManager.h"
#include "Graphics/GraphicsContext.h"
#include "Graphics/Shader.h"
#include "Graphics/Texture.h"
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>g
@ -21,6 +23,8 @@ namespace Light {
{
LT_ENGINE_ASSERT(!s_Context, "ResourceManager::ResourceManager: an instance of 'resource manager' 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)
@ -86,6 +90,24 @@ 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)
{
// 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);
if (components != desiredComponents)
{
LT_ENGINE_WARN("ResourceManager::LoadTexture: image file compoenents != desired components ({} - {})", components, desiredComponents);
LT_ENGINE_WARN("ResourceManager::LoadTexture: <{}> path: {}", name, path);
}
// create texture
m_Textures[name] = std::shared_ptr<Texture>(Texture::Create(width, height, components, pixels, m_SharedContext));
}
void ResourceManager::ExtractShaderSource(std::string& src, const std::string& delim)
{
size_t begDelimPos, endDelimPos;

View file

@ -7,12 +7,15 @@
namespace Light {
class Shader;
class Texture;
class SharedContext;
class ResourceManager
{
private:
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;
@ -25,7 +28,10 @@ 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 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]; }
private:
ResourceManager(std::shared_ptr<SharedContext> sharedContext);
@ -33,6 +39,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);
private:
void ExtractShaderSource(std::string& src, const std::string& delim);
};

View file

@ -25,10 +25,11 @@ namespace Light {
glfwMakeContextCurrent(windowHandle);
if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
{ exit(1); }
LT_ENGINE_ASSERT(gladLoadGLLoader((GLADloadproc)glfwGetProcAddress), "glGraphicsContext::glGraphicsContext: failed to initialize opengl (glad)");
// #todo: add blender
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void glGraphicsContext::OnWindowResize(const WindowResizedEvent& event)

View file

@ -0,0 +1,49 @@
#include "ltpch.h"
#include "glTexture.h"
#include <glad/glad.h>
namespace Light {
glTexture::glTexture(unsigned int width, unsigned int height, unsigned int components, unsigned char* pixels)
{
// create texture
glCreateTextures(GL_TEXTURE_2D, 1, &m_TextureID);
// 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
unsigned int format = components == 4u ? GL_RGBA :
components == 3u ? GL_RGB :
components == 2u ? GL_RG :
components == 1u ? GL_RED : NULL;
unsigned int internalFormat = format == GL_RGBA ? GL_RGBA8 :
format == GL_RGB ? GL_RGB8 :
format == GL_RG ? GL_RG8 :
format == GL_RED ? GL_R8 : NULL;
// check
LT_ENGINE_ASSERT(format, "glTexture::glTexture: invalid number of components: {}", components);
Bind();
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, width, height, 0, format, GL_UNSIGNED_BYTE, pixels);
glGenerateMipmap(GL_TEXTURE_2D);
}
glTexture::~glTexture()
{
glDeleteTextures(1, &m_TextureID);
}
void glTexture::Bind(unsigned int slot/*= 0*/)
{
glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(GL_TEXTURE_2D, m_TextureID);
}
}

View file

@ -0,0 +1,21 @@
#pragma once
#include "Base.h"
#include "Graphics/Texture.h"
namespace Light {
class glTexture : public Texture
{
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;
};
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

View file

@ -1,18 +0,0 @@
+GLSL
#version 440 core
in vec4 fragColor;
out vec4 FragmentColor;
void main()
{
FragmentColor = fragColor;
}
-GLSL
+HLSL
float4 main(float4 Color : COLOR) : SV_Target
{
return Color;
}
-HLSL

View file

@ -1,29 +0,0 @@
+GLSL
#version 440 core
layout(location = 0) in vec3 a_Position;
layout(location = 1) in vec4 a_Color;
out vec4 fragColor;
void main()
{
gl_Position = vec4(a_Position, 1.0);
fragColor = a_Color;
}
-GLSL
+HLSL
struct VertexOut
{
float4 Color : COLOR;
float4 Position : SV_Position;
};
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

View file

@ -2,15 +2,23 @@
class SandboxLayer : public Light::Layer
{
private:
std::shared_ptr<Light::Texture> m_AwesomefaceTexture;
public:
SandboxLayer(const std::string& name): Light::Layer(name) {}
SandboxLayer(const std::string& name) : Light::Layer(name)
{
Light::ResourceManager::LoadTexture("awesomeface", "res/Textures/awesomeface.png");
m_AwesomefaceTexture = Light::ResourceManager::GetTexture("awesomeface");
}
void OnRender() override
{
Light::Renderer::DrawQuad(glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec2(1.f, 1.f), glm::vec4(1.12f, 1.41f, 1.72f, 1.0f));
Light::Renderer::DrawQuad(glm::vec3(-0.75f, -0.75f, 0.0f), glm::vec2(0.7f, 0.1f), glm::vec4(1.f, .2f, .2f, 1.0f));
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);
}
};