First pass of new shader manager

This commit is contained in:
2023-04-04 21:49:20 -07:00
parent e51818f748
commit 685bc5b9c9
27 changed files with 303 additions and 32 deletions

View File

@ -2,7 +2,7 @@
<asset type="texture" name="texture_urchin" /> <asset type="texture" name="texture_urchin" />
<MeshRenderer /> <MeshRenderer />
<QuadMeshHost /> <QuadMeshHost />
<SimpleTexturedMaterial texture="texture_urchin" /> <SimpleBillboardedMaterial texture="texture_urchin" />
<EntityHealth /> <EntityHealth />
<EntityFaction faction="FACTION_ENEMY" /> <EntityFaction faction="FACTION_ENEMY" />

View File

@ -14,4 +14,5 @@ target_sources(${DAWN_TARGET_NAME}
# Subdirs # Subdirs
add_subdirectory(animation) add_subdirectory(animation)
add_subdirectory(font) add_subdirectory(font)
add_subdirectory(mesh) add_subdirectory(mesh)
add_subdirectory(shader)

View File

@ -18,7 +18,7 @@ RenderPipeline::RenderPipeline(RenderManager *renderManager) {
} }
void RenderPipeline::init() { void RenderPipeline::init() {
this->renderManager->getShaderManager()->lockShader<SimpleTexturedShader>();
} }
void RenderPipeline::render() { void RenderPipeline::render() {
@ -160,7 +160,7 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
&lineMesh, &lineMesh,
&lineIndex, &lineIndex,
camera, camera,
&this->renderManager->simpleShader this->renderManager->getShaderManager()->getShader<SimpleTexturedShader>(this->simpleTexturedShaderLock)
); );
shaderPassItems.push_back(item); shaderPassItems.push_back(item);
itDebugLine = scene->debugLines.erase(itDebugLine); itDebugLine = scene->debugLines.erase(itDebugLine);
@ -262,5 +262,5 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
} }
RenderPipeline::~RenderPipeline() { RenderPipeline::~RenderPipeline() {
this->renderManager->getShaderManager()->releaseShader<SimpleTexturedShader>(this->simpleTexturedShaderLock);
} }

View File

@ -17,6 +17,7 @@ namespace Dawn {
class RenderPipeline { class RenderPipeline {
private: private:
int_fast16_t renderId = -1; int_fast16_t renderId = -1;
shaderlock_t simpleTexturedShaderLock;
public: public:
RenderManager *renderManager; RenderManager *renderManager;

View File

@ -4,8 +4,8 @@
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "RenderTarget.hpp"
#include "util/flag.hpp" #include "util/flag.hpp"
#include "RenderTarget.hpp"
#define RENDER_MANAGER_RENDER_FLAG_DEPTH_TEST FLAG_DEFINE(0) #define RENDER_MANAGER_RENDER_FLAG_DEPTH_TEST FLAG_DEFINE(0)
#define RENDER_MANAGER_RENDER_FLAG_BLEND FLAG_DEFINE(1) #define RENDER_MANAGER_RENDER_FLAG_BLEND FLAG_DEFINE(1)
@ -14,6 +14,7 @@ typedef flag_t renderflag_t;
namespace Dawn { namespace Dawn {
class DawnGame; class DawnGame;
class RenderPipeline; class RenderPipeline;
class ShaderManager;
class IRenderManager { class IRenderManager {
protected: protected:
@ -21,7 +22,6 @@ namespace Dawn {
public: public:
DawnGame *game; DawnGame *game;
RenderPipeline *renderPipeline;
/** /**
* Default constructor for a render manager instance. * Default constructor for a render manager instance.
@ -48,6 +48,13 @@ namespace Dawn {
* @return Reference to the currently active main scene render pipeline. * @return Reference to the currently active main scene render pipeline.
*/ */
virtual RenderPipeline * getRenderPipeline() = 0; virtual RenderPipeline * getRenderPipeline() = 0;
/**
* Returns the shader manager that this render manager uses.
*
* @return Reference to the shader manager.
*/
virtual ShaderManager * getShaderManager() = 0;
/** /**
* Sets the render flags for the render manager to use. * Sets the render flags for the render manager to use.

View File

@ -0,0 +1,10 @@
# Copyright (c) 2023 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DAWN_TARGET_NAME}
PRIVATE
ShaderManager.cpp
)

View File

@ -38,6 +38,7 @@ namespace Dawn {
class Shader { class Shader {
public: public:
int32_t shaderId = -1;
int_fast16_t renderId = 0; int_fast16_t renderId = 0;
/** /**

View File

@ -0,0 +1,20 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "ShaderManager.hpp"
using namespace Dawn;
ShaderManager::ShaderManager() {
this->nextLock = 0;
}
ShaderManager::~ShaderManager() {
auto it = this->shaders.begin();
while(it != this->shaders.end()) {
delete it->second;
++it;
}
}

View File

@ -0,0 +1,108 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "display/shader/Shader.hpp"
namespace Dawn {
typedef int64_t shaderlock_t;
typedef int16_t shaderid_t;
class ShaderManager {
private:
int32_t nextId;
shaderlock_t nextLock;
std::map<shaderid_t, Shader*> shaders;
std::map<shaderlock_t, shaderid_t> shaderLocks;
std::map<shaderid_t, std::vector<shaderlock_t>> shaderLocksByShader;
/**
* Returns the shader id for the given shader type, or -1 if it is not
* loaded.
*
* @return The shader id for the shader, or -1 if it is not loaded.
*/
template<class T>
shaderid_t getShaderId() {
auto it = shaders.begin();
while(it != shaders.end()) {
auto asT = dynamic_cast<T*>(it->second);
if(asT != nullptr) return asT->shaderId;
++it;
}
return -1;
}
public:
/**
* Creates a new shader manager.
*/
ShaderManager();
/**
* Locks a shader of the given type. If the shader is not already loaded,
* it will be loaded. If the shader is already loaded, it will be
* returned.
*
* @return The shader lock for the shader of the given type.
*/
template<class T>
shaderlock_t lockShader() {
auto shaderId = this->getShaderId<T>();
if(shaderId == -1) {
T* shader = new T();
shader->compile();
shader->shaderId = this->nextId++;
this->shaders[shader->shaderId] = shader;
shaderId = shader->shaderId;
}
shaderlock_t lock = this->nextId++;
this->shaderLocks[lock] = shaderId;
this->shaderLocksByShader[shaderId].push_back(lock);
return lock;
}
/**
* Returns the shader for the given lock.
*
* @param lock The shader lock.
* @return The shader for the given lock.
*/
template<class T>
T * getShader(shaderlock_t lock) {
auto shaderId = this->shaderLocks[lock];
return (T*)this->shaders[shaderId];
}
/**
* Releases the shader for the given lock. This will unload any shader
* that is no longer in use.
*
* @param lock Lock to release.
*/
template<class T>
void releaseShader(shaderlock_t lock) {
auto shaderId = this->shaderLocks[lock];
this->shaderLocks.erase(lock);
auto& locks = this->shaderLocksByShader[shaderId];
auto it = std::find(locks.begin(), locks.end(), lock);
if(it != locks.end()) locks.erase(it);
if(locks.size() == 0) {
this->shaderLocksByShader.erase(shaderId);
auto shader = (T*)this->shaders[shaderId];
delete shader;
this->shaders.erase(shaderId);
}
}
/**
* Destroys the shader manager.
*/
~ShaderManager();
};
}

View File

@ -7,15 +7,6 @@
#include "display/Texture.hpp" #include "display/Texture.hpp"
namespace Dawn { namespace Dawn {
// class Material;
// enum ShaderParameterType {
// SHADER_PARAMETER_TYPE_MATRIX,
// SHADER_PARAMETER_TYPE_BOOLEAN,
// SHADER_PARAMETER_TYPE_COLOR,
// SHADER_PARAMETER_TYPE_VECTOR3,
// SHADER_PARAMETER_TYPE_TEXTURE,
// SHADER_PARAMETER_TYPE_FLOAT
// };
template<typename T> template<typename T>
class IShaderProgram { class IShaderProgram {

View File

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "event/Event.hpp" #include "event/Event.hpp"
#include "asset/Asset.hpp" #include "asset/Asset.hpp"
#include "display/shader/ShaderManager.hpp"
#include "scene/debug/SceneDebugLine.hpp" #include "scene/debug/SceneDebugLine.hpp"
#include "physics/ScenePhysicsManager.hpp" #include "physics/ScenePhysicsManager.hpp"
#include "state/StateEvent.hpp" #include "state/StateEvent.hpp"

View File

@ -5,7 +5,7 @@
#pragma once #pragma once
#include "scene/SceneItemComponent.hpp" #include "scene/SceneItemComponent.hpp"
#include "display/shader/Shader.hpp" #include "display/shader/ShaderManager.hpp"
namespace Dawn { namespace Dawn {
class Material : public SceneItemComponent { class Material : public SceneItemComponent {

View File

@ -6,7 +6,6 @@
#pragma once #pragma once
#include "scene/SceneItemComponent.hpp" #include "scene/SceneItemComponent.hpp"
#include "UICanvas.hpp" #include "UICanvas.hpp"
#include "display/shader/Shader.hpp"
#include "util/mathutils.hpp" #include "util/mathutils.hpp"
namespace Dawn { namespace Dawn {

View File

@ -29,7 +29,7 @@ std::vector<struct ShaderPassItem> UIImage::getPassItems(
glm::mat4 proj, glm::mat4 view glm::mat4 proj, glm::mat4 view
) { ) {
struct ShaderPassItem item; struct ShaderPassItem item;
auto shader = &getGame()->renderManager.uiShaderProgram; auto shader = &getGame()->renderManager.uiShader->program;
item.shaderProgram = shader; item.shaderProgram = shader;
item.colorValues[shader->paramColor] = this->color; item.colorValues[shader->paramColor] = this->color;
item.matrixValues[shader->paramProjection] = proj; item.matrixValues[shader->paramProjection] = proj;

View File

@ -63,7 +63,7 @@ std::vector<struct ShaderPassItem> UILabel::getPassItems(
this->updateMesh(); this->updateMesh();
struct ShaderPassItem item; struct ShaderPassItem item;
auto shader = &getGame()->renderManager.uiShaderProgram; auto shader = &getGame()->renderManager.uiShader->program;
item.shaderProgram = shader; item.shaderProgram = shader;
item.colorValues[shader->paramColor] = textColor; item.colorValues[shader->paramColor] = textColor;
item.matrixValues[shader->paramProjection] = proj; item.matrixValues[shader->paramProjection] = proj;

View File

@ -6,7 +6,7 @@
#pragma once #pragma once
#include "display/Color.hpp" #include "display/Color.hpp"
#include "display/mesh/Mesh.hpp" #include "display/mesh/Mesh.hpp"
#include "display/shader/Shader.hpp" #include "display/shader/ShaderManager.hpp"
#define SCENE_DEBUG_LINE_VERTICE_COUNT 2 #define SCENE_DEBUG_LINE_VERTICE_COUNT 2
#define SCENE_DEBUG_LINE_INDICE_COUNT 2 #define SCENE_DEBUG_LINE_INDICE_COUNT 2

View File

@ -17,9 +17,14 @@ RenderManager::RenderManager(DawnGame *game) :
} }
void RenderManager::init() { void RenderManager::init() {
// Lock the common shaders
this->lockSimpleTextured = this->shaderManager.lockShader<SimpleTexturedShader>();
this->lockUIShaderProgram = this->shaderManager.lockShader<SimpleTexturedShader>();
this->simpleTexturedShader = this->shaderManager.getShader<SimpleTexturedShader>(this->lockSimpleTextured);
this->uiShader = this->shaderManager.getShader<SimpleTexturedShader>(this->lockUIShaderProgram);
this->renderPipeline.init(); this->renderPipeline.init();
this->simpleShader.compile();
this->uiShaderProgram.compile();
// Prepare the initial values // Prepare the initial values
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
@ -37,6 +42,10 @@ RenderPipeline * RenderManager::getRenderPipeline() {
return &this->renderPipeline; return &this->renderPipeline;
} }
ShaderManager * RenderManager::getShaderManager() {
return &this->shaderManager;
}
void RenderManager::setRenderFlags(renderflag_t flags) { void RenderManager::setRenderFlags(renderflag_t flags) {
this->renderFlags = flags; this->renderFlags = flags;
@ -58,4 +67,6 @@ void RenderManager::update() {
} }
RenderManager::~RenderManager() { RenderManager::~RenderManager() {
this->shaderManager.releaseShader<SimpleTexturedShader>(this->lockSimpleTextured);
this->shaderManager.releaseShader<SimpleTexturedShader>(this->lockUIShaderProgram);
} }

View File

@ -6,6 +6,7 @@
#pragma once #pragma once
#include "display/_RenderManager.hpp" #include "display/_RenderManager.hpp"
#include "display/BackBufferRenderTarget.hpp" #include "display/BackBufferRenderTarget.hpp"
#include "display/shader/ShaderManager.hpp"
#include "display/shader/SimpleTexturedShader.hpp" #include "display/shader/SimpleTexturedShader.hpp"
#include "display/shader/UIShaderProgram.hpp" #include "display/shader/UIShaderProgram.hpp"
#include "display/RenderPipeline.hpp" #include "display/RenderPipeline.hpp"
@ -15,11 +16,14 @@ namespace Dawn {
class RenderManager : public IRenderManager { class RenderManager : public IRenderManager {
private: private:
RenderPipeline renderPipeline; RenderPipeline renderPipeline;
ShaderManager shaderManager;
shaderlock_t lockSimpleTextured = -1;
shaderlock_t lockUIShaderProgram = -1;
public: public:
BackBufferRenderTarget backBuffer; BackBufferRenderTarget backBuffer;
SimpleTexturedShader simpleShader; SimpleTexturedShader *simpleTexturedShader = nullptr;
UIShaderProgram uiShaderProgram; SimpleTexturedShader *uiShader = nullptr;
ExampleFont defaultFont; ExampleFont defaultFont;
/** /**
@ -29,6 +33,7 @@ namespace Dawn {
RenderTarget * getBackBuffer() override; RenderTarget * getBackBuffer() override;
RenderPipeline * getRenderPipeline() override; RenderPipeline * getRenderPipeline() override;
ShaderManager * getShaderManager() override;
void setRenderFlags(renderflag_t renderFlags) override; void setRenderFlags(renderflag_t renderFlags) override;
void init() override; void init() override;
void update() override; void update() override;

View File

@ -8,4 +8,5 @@ target_sources(${DAWN_TARGET_NAME}
PRIVATE PRIVATE
ShaderProgram.cpp ShaderProgram.cpp
SimpleTexturedShader.cpp SimpleTexturedShader.cpp
SimpleBillboardedShader.cpp
) )

View File

@ -4,6 +4,8 @@
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#include "SimpleBillboardedShader.hpp" #include "SimpleBillboardedShader.hpp"
#include "scene/components/display/mesh/MeshRenderer.hpp"
#include "scene/components/display/Camera.hpp"
using namespace Dawn; using namespace Dawn;
@ -25,9 +27,9 @@ void SimpleBillboardedShaderProgram::compile() {
"out vec2 o_TextCoord;\n" "out vec2 o_TextCoord;\n"
"void main() {\n" "void main() {\n"
"vec3 camRight = vec3(view[0][0], view[1][0], view[2][0]);\n" "vec3 camRight = vec3(u_View[0][0], u_View[1][0], u_View[2][0]);\n"
"vec3 camUp = vec3(view[0][1], view[1][1], view[2][1]);\n" "vec3 camUp = vec3(u_View[0][1], u_View[1][1], u_View[2][1]);\n"
"vec3 billboardPos = view[3].xyz + position.x * camRight + position.y * camUp;\n" "vec3 billboardPos = u_View[3].xyz + aPos.x * camRight + aPos.y * camUp;\n"
"gl_Position = u_Proj * u_View * u_Model * vec4(billboardPos, 1.0);\n" "gl_Position = u_Proj * u_View * u_Model * vec4(billboardPos, 1.0);\n"
"o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\n" "o_TextCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
"}", "}",
@ -56,4 +58,43 @@ void SimpleBillboardedShaderProgram::compile() {
this->paramColor = this->getParameterByName("u_Color"); this->paramColor = this->getParameterByName("u_Color");
this->paramTexture = this->getParameterByName("u_Text"); this->paramTexture = this->getParameterByName("u_Text");
this->paramHasTexture = this->getParameterByName("u_HasTexture"); this->paramHasTexture = this->getParameterByName("u_HasTexture");
}
void SimpleBillboardedShader::compile() {
this->program.compile();
}
std::vector<struct ShaderPassItem> SimpleBillboardedShader::getPassItems(
Mesh *mesh,
Material *material,
Camera *camera
) {
auto simpleMaterial = dynamic_cast<SimpleBillboardedMaterial*>(material);
assertNotNull(simpleMaterial);
struct ShaderPassItem onlyPass;
onlyPass.mesh = mesh;
onlyPass.shaderProgram = &program;
onlyPass.colorValues[program.paramColor] = simpleMaterial->color;
onlyPass.matrixValues[program.paramModel] = material->transform->getWorldTransform();
onlyPass.matrixValues[program.paramView] = camera->transform->getWorldTransform();
onlyPass.matrixValues[program.paramProjection] = camera->getProjection();
onlyPass.renderFlags = (
RENDER_MANAGER_RENDER_FLAG_BLEND |
RENDER_MANAGER_RENDER_FLAG_DEPTH_TEST
);
if(simpleMaterial->texture != nullptr) {
onlyPass.boolValues[program.paramHasTexture] = true;
onlyPass.textureSlots[0] = simpleMaterial->texture;
onlyPass.textureValues[program.paramTexture] = 0;
} else {
onlyPass.boolValues[program.paramHasTexture] = false;
}
std::vector<struct ShaderPassItem> passes;
passes.push_back(onlyPass);
return passes;
} }

View File

@ -4,10 +4,10 @@
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "display/shader/Shader.hpp" #include "scene/components/display/material/SimpleBillboardedMaterial.hpp"
namespace Dawn { namespace Dawn {
class SimpleBillboardedShader : public ShaderProgram { class SimpleBillboardedShaderProgram : public ShaderProgram {
public: public:
shaderparameter_t paramProjection; shaderparameter_t paramProjection;
shaderparameter_t paramView; shaderparameter_t paramView;

View File

@ -4,7 +4,7 @@
// https://opensource.org/licenses/MIT // https://opensource.org/licenses/MIT
#pragma once #pragma once
#include "display/shader/Shader.hpp" #include "display/shader/ShaderManager.hpp"
#include "scene/components/display/material/SimpleTexturedMaterial.hpp" #include "scene/components/display/material/SimpleTexturedMaterial.hpp"
namespace Dawn { namespace Dawn {

View File

@ -7,4 +7,5 @@
target_sources(${DAWN_TARGET_NAME} target_sources(${DAWN_TARGET_NAME}
PRIVATE PRIVATE
SimpleTexturedMaterial.cpp SimpleTexturedMaterial.cpp
SimpleBillboardedMaterial.cpp
) )

View File

@ -0,0 +1,27 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#include "display/shader/SimpleBillboardedShader.hpp"
#include "SimpleBillboardedMaterial.hpp"
#include "game/DawnGame.hpp"
using namespace Dawn;
SimpleBillboardedMaterial::SimpleBillboardedMaterial(SceneItem *i) :
Material(i)
{
}
void SimpleBillboardedMaterial::onStart() {
this->shaderLock = this->getGame()->renderManager.getShaderManager()->lockShader<SimpleBillboardedShader>();
}
void SimpleBillboardedMaterial::onDispose() {
this->getGame()->renderManager.getShaderManager()->releaseShader<SimpleBillboardedShader>(this->shaderLock);
}
Shader * SimpleBillboardedMaterial::getShader() {
return this->getGame()->renderManager.getShaderManager()->getShader<SimpleBillboardedShader>(this->shaderLock);
}

View File

@ -0,0 +1,32 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "scene/components/display/Material.hpp"
namespace Dawn {
class SimpleBillboardedMaterial : public Material {
private:
shaderlock_t shaderLock = -1;
public:
// @optional
Texture *texture = nullptr;
// @optional
struct Color color = COLOR_WHITE;
/**
* SimpleBillboardMaterial scene item component interface.
*
* @param i Scene Item this interface belongs to.
*/
SimpleBillboardedMaterial(SceneItem *i);
void onStart() override;
void onDispose() override;
Shader * getShader() override;
};
}

View File

@ -13,6 +13,14 @@ SimpleTexturedMaterial::SimpleTexturedMaterial(SceneItem *i) :
{ {
} }
void SimpleTexturedMaterial::onStart() {
this->shaderLock = this->getGame()->renderManager.getShaderManager()->lockShader<SimpleTexturedShader>();
}
void SimpleTexturedMaterial::onDispose() {
this->getGame()->renderManager.getShaderManager()->releaseShader<SimpleTexturedShader>(this->shaderLock);
}
Shader * SimpleTexturedMaterial::getShader() { Shader * SimpleTexturedMaterial::getShader() {
return &this->getGame()->renderManager.simpleShader; return this->getGame()->renderManager.getShaderManager()->getShader<SimpleTexturedShader>(this->shaderLock);
} }

View File

@ -8,6 +8,9 @@
namespace Dawn { namespace Dawn {
class SimpleTexturedMaterial : public Material { class SimpleTexturedMaterial : public Material {
private:
shaderlock_t shaderLock = -1;
public: public:
// @optional // @optional
Texture *texture = nullptr; Texture *texture = nullptr;
@ -20,6 +23,9 @@ namespace Dawn {
* @param i Scene Item this interface belongs to. * @param i Scene Item this interface belongs to.
*/ */
SimpleTexturedMaterial(SceneItem *i); SimpleTexturedMaterial(SceneItem *i);
void onStart() override;
void onDispose() override;
Shader * getShader() override; Shader * getShader() override;
}; };