Shaders now compile all the way to OpenGL
This commit is contained in:
@ -25,6 +25,7 @@ set(DAWN_TEMP_DIR "${DAWN_BUILD_DIR}/temp")
|
||||
|
||||
# Options
|
||||
option(DAWN_ENABLE_PHYSICS "Enable Physics" OFF)
|
||||
option(DAWN_DEBUG_SHADERS "Enable Debug Shaders" ON)
|
||||
|
||||
# Initialize Project First.
|
||||
project(Dawn
|
||||
|
@ -1,11 +1,7 @@
|
||||
struct MVP {
|
||||
struct Uniforms {
|
||||
float4x4 projection;
|
||||
float4x4 view;
|
||||
float4x4 model;
|
||||
}
|
||||
|
||||
struct Uniforms {
|
||||
MVP mvp;
|
||||
float4 u_Color;
|
||||
bool u_HasTexture;
|
||||
Sampler2D u_Texture;
|
||||
@ -29,9 +25,10 @@ float4 someFunction(float4 color) {
|
||||
return color * float4(0.5, 0.5, 0.5, 1.0);
|
||||
}
|
||||
|
||||
uniform ParameterBlock<Uniforms> uniforms;
|
||||
|
||||
[shader("vertex")]
|
||||
VertexStageOutput vertexMain(
|
||||
uniform ParameterBlock<Uniforms> uniforms,
|
||||
AssembledVertex assembledVertex
|
||||
) {
|
||||
VertexStageOutput output;
|
||||
@ -42,7 +39,7 @@ VertexStageOutput vertexMain(
|
||||
|
||||
output.sv_position = mul(
|
||||
float4(position, 1.0),
|
||||
mul(uniforms.mvp.model, mul(uniforms.mvp.view, uniforms.mvp.projection))
|
||||
mul(uniforms.model, mul(uniforms.view, uniforms.projection))
|
||||
);
|
||||
|
||||
return output;
|
||||
@ -50,7 +47,6 @@ VertexStageOutput vertexMain(
|
||||
|
||||
[shader("fragment")]
|
||||
Fragment fragmentMain(
|
||||
uniform ParameterBlock<Uniforms> uniforms,
|
||||
float2 uv: UV
|
||||
) : SV_Target {
|
||||
Fragment output;
|
||||
|
@ -19,6 +19,12 @@ target_include_directories(${DAWN_TARGET_NAME}
|
||||
${CMAKE_CURRENT_LIST_DIR}
|
||||
)
|
||||
|
||||
# Definitions
|
||||
target_compile_definitions(${DAWN_TARGET_NAME}
|
||||
PUBLIC
|
||||
DAWN_DEBUG_SHADERS=$<BOOL:${DAWN_DEBUG_SHADERS}>
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
add_subdirectory(assert)
|
||||
add_subdirectory(asset)
|
||||
|
@ -20,6 +20,8 @@ AssetLoader::AssetLoader(
|
||||
{
|
||||
assertNotNull(assetManager, "AssetManager cannot be null");
|
||||
assertTrue(name.size() > 0, "Name cannot be empty");
|
||||
|
||||
std::cout << "Loading: " << name << std::endl;
|
||||
}
|
||||
|
||||
std::shared_ptr<AssetManager> AssetLoader::getAssetManager() {
|
||||
@ -36,4 +38,5 @@ void AssetLoader::loadImmediately() {
|
||||
|
||||
AssetLoader::~AssetLoader() {
|
||||
this->loaded = false;
|
||||
std::cout << "Unloading: " << name << std::endl;
|
||||
}
|
@ -8,6 +8,10 @@
|
||||
#include "asset/AssetManager.hpp"
|
||||
#include "game/Game.hpp"
|
||||
|
||||
#if DAWN_DEBUG_SHADERS
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
const std::string ShaderLoader::ASSET_TYPE = "shader";
|
||||
@ -91,9 +95,21 @@ void ShaderLoader::updateSync() {
|
||||
}
|
||||
|
||||
// Get the stage information
|
||||
auto entryPointReflection = layout->getEntryPointByIndex(0);
|
||||
auto entryPointReflection = layout->getEntryPointByIndex(i);
|
||||
auto stage = entryPointReflection->getStage();
|
||||
|
||||
// Write out to file for debugging
|
||||
#if DAWN_DEBUG_SHADERS
|
||||
std::filesystem::path filePath =
|
||||
"debug/shaders/" + this->name + "/" + std::to_string(i) + ".glsl"
|
||||
;
|
||||
std::filesystem::create_directories(filePath.parent_path());
|
||||
std::cout << "Writing shader to " << filePath << std::endl;
|
||||
std::ofstream file(filePath);
|
||||
file << (const char*)blob->getBufferPointer();
|
||||
file.close();
|
||||
#endif
|
||||
|
||||
// Create the shader entry
|
||||
auto shaderStage = std::make_shared<ShaderStage>();
|
||||
shaderStage->init(
|
||||
|
@ -9,6 +9,7 @@
|
||||
using namespace Dawn;
|
||||
|
||||
void Material::onInit() {
|
||||
this->initShaderPrograms();
|
||||
}
|
||||
|
||||
void Material::onDispose() {
|
||||
|
@ -12,9 +12,13 @@ namespace Dawn {
|
||||
public SceneComponent,
|
||||
public IRenderableComponent
|
||||
{
|
||||
private:
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Load the shaders for this material.
|
||||
*/
|
||||
virtual void initShaderPrograms(
|
||||
|
||||
) = 0;
|
||||
|
||||
public:
|
||||
void onInit() override;
|
||||
|
@ -6,9 +6,14 @@
|
||||
#include "SimpleTexturedMaterial.hpp"
|
||||
#include "util/JSON.hpp"
|
||||
#include "asset/loader/TextureLoader.hpp"
|
||||
#include "asset/loader/ShaderLoader.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void SimpleTexturedMaterial::initShaderPrograms() {
|
||||
this->shader = getGame()->assetManager->get<ShaderLoader>("shaders/hello-world.slang")->getShader();
|
||||
}
|
||||
|
||||
void SimpleTexturedMaterial::load(std::shared_ptr<SceneLoadContext> ctx) {
|
||||
if(ctx->data.contains("color")) {
|
||||
this->setColor(JSON::color(ctx->data["color"]));
|
||||
@ -27,13 +32,13 @@ struct Color SimpleTexturedMaterial::getColor() {
|
||||
}
|
||||
|
||||
std::shared_ptr<Texture> SimpleTexturedMaterial::getTexture() {
|
||||
return this->texture;
|
||||
return this->data.texture;
|
||||
}
|
||||
|
||||
void SimpleTexturedMaterial::setTexture(
|
||||
const std::shared_ptr<Texture> texture
|
||||
) {
|
||||
this->texture = texture;
|
||||
this->data.texture = texture;
|
||||
}
|
||||
|
||||
void SimpleTexturedMaterial::setColor(const struct Color color) {
|
||||
@ -59,10 +64,13 @@ std::vector<std::shared_ptr<RenderPass>> SimpleTexturedMaterial::getPasses(
|
||||
// }
|
||||
|
||||
return {
|
||||
// createRenderPass<SimpleTexturedShader, struct SimpleTexturedShaderData>(
|
||||
// *this,
|
||||
// data,
|
||||
// textures
|
||||
// )
|
||||
std::make_shared<RenderPass>(
|
||||
*this,
|
||||
nullptr,// Get mesh automatically.
|
||||
MeshDrawMode::TRIANGLES,// Move this later.
|
||||
0,// Move this later.
|
||||
-1,// Move this later.
|
||||
this->shader
|
||||
)
|
||||
};
|
||||
}
|
||||
|
@ -15,14 +15,16 @@ namespace Dawn {
|
||||
glm::mat4 projection;
|
||||
glm::mat4 view;
|
||||
bool hasTexture;
|
||||
std::shared_ptr<Texture> texture;
|
||||
};
|
||||
|
||||
class SimpleTexturedMaterial : public Material {
|
||||
private:
|
||||
struct SimpleTexturedMaterialShaderData data;
|
||||
std::shared_ptr<Texture> texture;
|
||||
std::shared_ptr<ShaderProgram> shader;
|
||||
|
||||
protected:
|
||||
void initShaderPrograms() override;
|
||||
|
||||
public:
|
||||
void load(std::shared_ptr<SceneLoadContext> ctx) override;
|
||||
|
@ -13,12 +13,14 @@ RenderPass::RenderPass(
|
||||
const std::shared_ptr<Mesh> mesh,
|
||||
const enum MeshDrawMode drawMode,
|
||||
const int32_t indiceStart,
|
||||
const int32_t indiceCount
|
||||
const int32_t indiceCount,
|
||||
const std::shared_ptr<ShaderProgram> shaderProgram
|
||||
) :
|
||||
mesh(mesh),
|
||||
drawMode(drawMode),
|
||||
indiceStart(indiceStart),
|
||||
indiceCount(indiceCount)
|
||||
indiceCount(indiceCount),
|
||||
shaderProgram(shaderProgram)
|
||||
{
|
||||
// Need mesh?
|
||||
if(!this->mesh) {
|
||||
@ -28,5 +30,9 @@ RenderPass::RenderPass(
|
||||
}
|
||||
|
||||
void RenderPass::draw() {
|
||||
mesh->draw(drawMode, indiceStart, indiceCount);
|
||||
// mesh->draw(drawMode, indiceStart, indiceCount);
|
||||
}
|
||||
|
||||
RenderPass::~RenderPass() {
|
||||
|
||||
}
|
@ -6,11 +6,13 @@
|
||||
#pragma once
|
||||
#include "display/mesh/Mesh.hpp"
|
||||
#include "scene/SceneComponent.hpp"
|
||||
#include "display/shader/ShaderProgram.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class RenderPass {
|
||||
private:
|
||||
std::shared_ptr<Mesh> mesh;
|
||||
std::shared_ptr<ShaderProgram> shaderProgram;
|
||||
const enum MeshDrawMode drawMode;
|
||||
const int32_t indiceStart;
|
||||
const int32_t indiceCount;
|
||||
@ -20,18 +22,21 @@ namespace Dawn {
|
||||
* Constructs a new RenderPass.
|
||||
*
|
||||
* @param self Self component instance that is creating this render pass.
|
||||
* @param d The data to use for this render pass.
|
||||
* @param mesh The mesh to use for this render pass.
|
||||
* @param drawMode The draw mode to use for this render pass.
|
||||
* @param indiceStart The indice to start drawing from.
|
||||
* @param indiceCount The number of indices to draw.
|
||||
* @param shaderProgram The shader program to use for this render pass.
|
||||
*/
|
||||
RenderPass(
|
||||
SceneComponent &self,
|
||||
|
||||
const std::shared_ptr<Mesh> mesh,
|
||||
const enum MeshDrawMode drawMode,
|
||||
const int32_t indiceStart,
|
||||
const int32_t indiceCount
|
||||
const int32_t indiceCount,
|
||||
|
||||
const std::shared_ptr<ShaderProgram> shaderProgram
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -14,13 +14,22 @@ namespace Dawn {
|
||||
|
||||
public:
|
||||
/**
|
||||
* Initialize the IShaderProgram2 object
|
||||
* Initialize the ShaderProgram. In your render hosts' implementation
|
||||
* this would initialize the shader on your GPU and ideally set the
|
||||
* initial values for uniforms and objects.
|
||||
*
|
||||
* @param stages The list of shader stages to initialize with.
|
||||
* Provided stages will already be "initialized" (at least as far as the
|
||||
* engine is concerned), and should be ready to be used. If your render
|
||||
* host needs the program to be initialized prior to the stages you will
|
||||
* need to modify how stages are initialized, this is by design as we are
|
||||
* loading the shader code and "initializing" the stages before we create
|
||||
* and initialize the program which will use and link the stages.
|
||||
*
|
||||
* @param stages The stages to use in this program.
|
||||
*/
|
||||
virtual void init(
|
||||
const std::vector<std::shared_ptr<ShaderStage>> &stages
|
||||
) = 0;
|
||||
);
|
||||
|
||||
/**
|
||||
* Destroy the IShaderProgram2 object
|
||||
|
@ -46,7 +46,6 @@ SlangResult ShaderManagerSlangFileSystem::loadFile(
|
||||
|
||||
if(!String::endsWith(path, ".slang")) return SLANG_E_NOT_FOUND;
|
||||
|
||||
std::cout << "Loading: " << path << std::endl;
|
||||
auto loader = shaderManager->getGame()->assetManager->get<StringLoader>(path);
|
||||
loader->loadImmediately();
|
||||
|
||||
@ -54,7 +53,6 @@ SlangResult ShaderManagerSlangFileSystem::loadFile(
|
||||
blob->str = loader->data;
|
||||
*outBlob = blob;
|
||||
|
||||
std::cout << "Loaded: " << path << std::endl;
|
||||
return SLANG_OK;
|
||||
}
|
||||
|
||||
|
@ -4,14 +4,54 @@
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "ShaderProgram.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
#include "assert/assertgl.hpp"
|
||||
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
void ShaderProgram::init(
|
||||
const std::vector<std::shared_ptr<ShaderStage>> &stages
|
||||
) {
|
||||
assertTrue(this->id == -1, "ShaderProgram already initialized?");
|
||||
|
||||
IShaderProgram::init(stages);
|
||||
|
||||
// Create the program
|
||||
this->id = glCreateProgram();
|
||||
assertNoGLError();
|
||||
|
||||
// Attach all the shader stages
|
||||
for(auto stage : stages) {
|
||||
glAttachShader(this->id, stage->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
// Link and verify the program
|
||||
glLinkProgram(this->id);
|
||||
assertNoGLError();
|
||||
|
||||
GLint status;
|
||||
glGetProgramiv(this->id, GL_LINK_STATUS, &status);
|
||||
assertNoGLError();
|
||||
|
||||
if(!status) {
|
||||
// Failed to link
|
||||
GLint logLength;
|
||||
glGetProgramiv(this->id, GL_INFO_LOG_LENGTH, &logLength);
|
||||
assertNoGLError();
|
||||
|
||||
GLchar *log = new GLchar[logLength];
|
||||
glGetProgramInfoLog(this->id, logLength, NULL, log);
|
||||
assertNoGLError();
|
||||
assertUnreachable("Failed to link shader program:\n%s", log);
|
||||
}
|
||||
}
|
||||
|
||||
ShaderProgram::~ShaderProgram() {
|
||||
// Delete the shader program
|
||||
if(this->id != -1) {
|
||||
glDeleteProgram(this->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
}
|
@ -5,9 +5,13 @@
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/IShaderProgram.hpp"
|
||||
#include "dawnopengl.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class ShaderProgram : public IShaderProgram {
|
||||
private:
|
||||
GLuint id = -1;
|
||||
|
||||
public:
|
||||
void init(
|
||||
const std::vector<std::shared_ptr<ShaderStage>> &stages
|
||||
|
@ -4,6 +4,8 @@
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "ShaderStage.hpp"
|
||||
#include "assert/assert.hpp"
|
||||
#include "assert/assertgl.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
@ -11,7 +13,56 @@ void ShaderStage::init(
|
||||
const SlangStage &stage,
|
||||
const std::string &code
|
||||
) {
|
||||
assertTrue(this->id == -1, "ShaderStage already initialized?");
|
||||
|
||||
// Determine GL Shader type from slang shader type.
|
||||
switch(stage) {
|
||||
case SlangStage::SLANG_STAGE_VERTEX:
|
||||
shaderType = GL_VERTEX_SHADER;
|
||||
break;
|
||||
|
||||
case SlangStage::SLANG_STAGE_FRAGMENT:
|
||||
shaderType = GL_FRAGMENT_SHADER;
|
||||
break;
|
||||
|
||||
default:
|
||||
assertUnreachable("Unknown Slang Shader type\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Initialize the shader.
|
||||
this->id = glCreateShader(shaderType);
|
||||
assertNoGLError();
|
||||
|
||||
// Compile
|
||||
const char_t* cSource = code.c_str();
|
||||
glShaderSource(this->id, 1, &cSource, nullptr);
|
||||
assertNoGLError();
|
||||
|
||||
glCompileShader(this->id);
|
||||
assertNoGLError();
|
||||
|
||||
// Validate shader compiled successfully.
|
||||
GLint status;
|
||||
glGetShaderiv(this->id, GL_COMPILE_STATUS, &status);
|
||||
assertNoGLError();
|
||||
|
||||
if(!status) {
|
||||
// Failed to compile
|
||||
GLint logLength;
|
||||
glGetShaderiv(this->id, GL_INFO_LOG_LENGTH, &logLength);
|
||||
assertNoGLError();
|
||||
|
||||
GLchar *log = new GLchar[logLength];
|
||||
glGetShaderInfoLog(this->id, logLength, NULL, log);
|
||||
assertNoGLError();
|
||||
assertUnreachable("Failed to compile shader stage %i:\n%s", shaderType, log);
|
||||
}
|
||||
}
|
||||
|
||||
ShaderStage::~ShaderStage() {
|
||||
if(this->id != -1) {
|
||||
glDeleteShader(this->id);
|
||||
assertNoGLError();
|
||||
}
|
||||
}
|
@ -5,14 +5,24 @@
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/IShaderStage.hpp"
|
||||
#include "dawnopengl.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
class ShaderProgram;
|
||||
|
||||
class ShaderStage : public IShaderStage {
|
||||
protected:
|
||||
GLenum shaderType;
|
||||
GLuint id = -1;
|
||||
|
||||
public:
|
||||
void init(
|
||||
const SlangStage &stage,
|
||||
const std::string &code
|
||||
) override;
|
||||
|
||||
~ShaderStage();
|
||||
|
||||
friend class ShaderProgram;
|
||||
};
|
||||
}
|
@ -18,7 +18,7 @@ target_include_directories(${DAWN_TARGET_NAME}
|
||||
# Define for use in C pragmas
|
||||
target_compile_definitions(${DAWN_TARGET_NAME}
|
||||
PUBLIC
|
||||
DAWN_ENABLE_PHYSICS="${DAWN_ENABLE_PHYSICS}"
|
||||
DAWN_ENABLE_PHYSICS="${DAWN_ENABLE_PHYSICS}"
|
||||
)
|
||||
|
||||
# Subdirs
|
||||
|
@ -5,11 +5,9 @@
|
||||
|
||||
#include "Game.hpp"
|
||||
#include "component/SceneComponentRegistry.hpp"
|
||||
|
||||
#include "component/RPGEntity.hpp"
|
||||
#include "component/RPGPlayer.hpp"
|
||||
#include "component/RPGMap.hpp"
|
||||
#include "asset/loader/ShaderLoader.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
@ -26,9 +24,6 @@ std::string Game::getInitialScene() {
|
||||
void Game::initManagers() {
|
||||
this->rpgManager = std::make_shared<RPGManager>();
|
||||
this->rpgManager->init(shared_from_this());
|
||||
|
||||
auto sl = assetManager->get<ShaderLoader>("shaders/hello-world.slang");
|
||||
sl->loadImmediately();
|
||||
}
|
||||
|
||||
Game::~Game() {
|
||||
|
Reference in New Issue
Block a user