Added support for shader structures.
This commit is contained in:
@ -34,11 +34,10 @@ std::vector<std::shared_ptr<IRenderPass>> UICanvas::getPasses(
|
||||
.view = ctx.camera->getItem()->getWorldTransform(),
|
||||
.model = selfTransform
|
||||
};
|
||||
|
||||
data.colors[0] = COLOR_WHITE;
|
||||
data.colors[1] = COLOR_RED;
|
||||
data.colors[2] = COLOR_GREEN;
|
||||
data.colors[3] = COLOR_BLUE;
|
||||
|
||||
data.test.first = COLOR_RED;
|
||||
data.test.random = glm::vec3(0, 1, 0);
|
||||
data.test.second = COLOR_BLUE;
|
||||
|
||||
auto pass = createRenderPass<UIShader, UIShaderData>(
|
||||
std::ref(*this),
|
||||
|
@ -10,4 +10,5 @@ target_sources(${DAWN_TARGET_NAME}
|
||||
ShaderStage.cpp
|
||||
SimpleTexturedShader.cpp
|
||||
UIShader.cpp
|
||||
ShaderParameter.cpp
|
||||
)
|
@ -11,6 +11,9 @@
|
||||
#include "display/Color.hpp"
|
||||
#include "display/Texture.hpp"
|
||||
|
||||
#include "ShaderParameter.hpp"
|
||||
#include "ShaderStructure.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
typedef GLuint shadertexturebinding_t;
|
||||
|
||||
@ -18,53 +21,32 @@ namespace Dawn {
|
||||
GLSL_330_CORE
|
||||
};
|
||||
|
||||
struct ShaderOpenGLParameter {
|
||||
std::string name;
|
||||
size_t offset;
|
||||
enum ShaderParameterType type;
|
||||
int32_t count;
|
||||
|
||||
GLint location = -1;
|
||||
|
||||
ShaderOpenGLParameter(
|
||||
const std::string &name,
|
||||
const void *offset,
|
||||
const enum ShaderParameterType type
|
||||
) {
|
||||
this->name = name;
|
||||
this->offset = (size_t)offset;
|
||||
this->type = type;
|
||||
this->count = 1;
|
||||
}
|
||||
|
||||
ShaderOpenGLParameter(
|
||||
const std::string &name,
|
||||
const void *offset,
|
||||
const enum ShaderParameterType type,
|
||||
const int32_t count
|
||||
) {
|
||||
this->name = name;
|
||||
this->offset = (size_t)offset;
|
||||
this->type = type;
|
||||
this->count = count;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class Shader : public IShader<T> {
|
||||
private:
|
||||
std::vector<std::shared_ptr<ShaderStage>> stages;
|
||||
std::vector<struct ShaderOpenGLParameter> parameters;
|
||||
std::vector<struct ShaderParameter> parameters;
|
||||
std::vector<struct IShaderStructure> structures;
|
||||
enum ShaderOpenGLVariant variant;
|
||||
|
||||
GLuint shaderProgram = -1;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Overridable function to get the stages for the shader.
|
||||
*
|
||||
* @param variant The variant of the shader to use.
|
||||
* @param rel The relative data to use.
|
||||
* @param stages The stages to add to.
|
||||
* @param parameters The parameters to add to.
|
||||
* @param structures The structures to add to.
|
||||
*/
|
||||
virtual void getStages(
|
||||
const enum ShaderOpenGLVariant variant,
|
||||
const T *rel,
|
||||
std::vector<std::shared_ptr<ShaderStage>> &stages,
|
||||
std::vector<struct ShaderOpenGLParameter> ¶meters
|
||||
std::vector<struct ShaderParameter> ¶meters,
|
||||
std::vector<struct IShaderStructure> &structures
|
||||
) = 0;
|
||||
|
||||
public:
|
||||
@ -82,7 +64,8 @@ namespace Dawn {
|
||||
variant,
|
||||
&dummy,
|
||||
stages,
|
||||
parameters
|
||||
parameters,
|
||||
structures
|
||||
);
|
||||
|
||||
// Create the shader program
|
||||
@ -108,7 +91,7 @@ namespace Dawn {
|
||||
std::for_each(
|
||||
parameters.begin(),
|
||||
parameters.end(),
|
||||
[&](struct ShaderOpenGLParameter ¶m) {
|
||||
[&](struct ShaderParameter ¶m) {
|
||||
// Correct offset
|
||||
param.offset = param.offset - (size_t)(&dummy);
|
||||
param.location = glGetUniformLocation(
|
||||
@ -124,6 +107,28 @@ namespace Dawn {
|
||||
}
|
||||
);
|
||||
|
||||
// Map structures
|
||||
std::for_each(
|
||||
structures.begin(),
|
||||
structures.end(),
|
||||
[&](struct IShaderStructure &structure) {
|
||||
structure.offset = structure.offset - (size_t)(&dummy);
|
||||
structure.location = glGetUniformBlockIndex(
|
||||
shaderProgram,
|
||||
structure.structureName.c_str()
|
||||
);
|
||||
assertNoGLError();
|
||||
assertTrue(
|
||||
structure.location != -1,
|
||||
"Failed to get location for structure %s.",
|
||||
structure.structureName.c_str()
|
||||
);
|
||||
|
||||
// Create the buffer
|
||||
glGenBuffers(1, &structure.buffer);
|
||||
}
|
||||
);
|
||||
|
||||
this->bind();
|
||||
}
|
||||
|
||||
@ -191,9 +196,43 @@ namespace Dawn {
|
||||
default:
|
||||
assertUnreachable("Unsupported ShaderOpenGLVariant");
|
||||
}
|
||||
|
||||
// Upload structures
|
||||
for(auto structure : structures) {
|
||||
switch(structure.structureType) {
|
||||
case ShaderOpenGLStructureType::STD140: {
|
||||
// Upload the data
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, structure.buffer);
|
||||
assertNoGLError();
|
||||
glBindBufferBase(GL_UNIFORM_BUFFER, structure.location, structure.buffer);
|
||||
assertNoGLError();
|
||||
glBufferData(
|
||||
GL_UNIFORM_BUFFER,
|
||||
structure.size,
|
||||
(void*)((size_t)&this->data + (size_t)structure.offset),
|
||||
GL_STATIC_DRAW
|
||||
);
|
||||
assertNoGLError();
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assertUnreachable("Unsupported ShaderOpenGLStructureType");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~Shader() {
|
||||
// Delete the structures
|
||||
for(auto structure : structures) {
|
||||
assertTrue(structure.buffer != -1, "Invalid buffer.");
|
||||
glDeleteBuffers(1, &structure.buffer);
|
||||
assertNoGLError();
|
||||
}
|
||||
|
||||
// Delete the shader program
|
||||
glDeleteProgram(shaderProgram);
|
||||
assertNoGLError();
|
||||
}
|
||||
};
|
||||
}
|
20
src/dawnopengl/display/shader/ShaderParameter.cpp
Normal file
20
src/dawnopengl/display/shader/ShaderParameter.cpp
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#include "ShaderParameter.hpp"
|
||||
|
||||
using namespace Dawn;
|
||||
|
||||
ShaderParameter::ShaderParameter(
|
||||
const std::string &name,
|
||||
const void *offset,
|
||||
const enum ShaderParameterType type,
|
||||
const size_t count
|
||||
) {
|
||||
this->name = name;
|
||||
this->offset = (size_t)offset;
|
||||
this->type = type;
|
||||
this->count = count;
|
||||
}
|
33
src/dawnopengl/display/shader/ShaderParameter.hpp
Normal file
33
src/dawnopengl/display/shader/ShaderParameter.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma once
|
||||
#include "display/shader/IShader.hpp"
|
||||
#include "dawnopengl.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct ShaderParameter {
|
||||
std::string name;
|
||||
size_t offset;
|
||||
enum ShaderParameterType type;
|
||||
size_t count;
|
||||
GLint location = -1;
|
||||
|
||||
/**
|
||||
* Construct a new shader parameter.
|
||||
*
|
||||
* @param name Name of the parameter within the shader.
|
||||
* @param offset Offset, relative to the structure of the data.
|
||||
* @param type Type of the parameter.
|
||||
* @param count How many elements in the array (if multiple).
|
||||
*/
|
||||
ShaderParameter(
|
||||
const std::string &name,
|
||||
const void *offset,
|
||||
const enum ShaderParameterType type,
|
||||
const size_t count = 1
|
||||
);
|
||||
};
|
||||
}
|
81
src/dawnopengl/display/shader/ShaderStructure.hpp
Normal file
81
src/dawnopengl/display/shader/ShaderStructure.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2023 Dominic Masters
|
||||
//
|
||||
// This software is released under the MIT License.
|
||||
// https://opensource.org/licenses/MIT
|
||||
|
||||
#pragma ocne
|
||||
#include "display/shader/ShaderParameter.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
enum class ShaderOpenGLStructureType {
|
||||
STD140
|
||||
};
|
||||
|
||||
struct IShaderStructure {
|
||||
std::string structureName;
|
||||
size_t offset;
|
||||
enum ShaderOpenGLStructureType structureType;
|
||||
size_t size;
|
||||
// size_t count;
|
||||
std::vector<struct ShaderParameter> parameters;
|
||||
GLint location = -1;
|
||||
GLuint buffer = -1;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ShaderStructure final : public IShaderStructure {
|
||||
public:
|
||||
/**
|
||||
* Constructs a new shader structure. Shader structures allow for larger
|
||||
* amounts/volumes of data to be passed to the shader in a single call.
|
||||
* Ideally I wouldn't really need this as I wanted the entire shader to
|
||||
* basically be a single large structure, but OpenGL doesn't support that
|
||||
* so I have to do this instead.
|
||||
*
|
||||
* @param structureName Structure name within the shader.
|
||||
* @param offset Offset, within the data structure, that this structure
|
||||
* starts at.
|
||||
* @param structureType The type of structure data format to use.
|
||||
* @param getParameters A callback that, when invoked, will populate the
|
||||
* parameters vector with the parameters for this
|
||||
* structure.
|
||||
*/
|
||||
ShaderStructure(
|
||||
const std::string &structureName,
|
||||
const void *offset,
|
||||
const enum ShaderOpenGLStructureType structureType,
|
||||
std::function<
|
||||
void(const T&, std::vector<struct ShaderParameter>&)
|
||||
> getParameters
|
||||
) {
|
||||
this->structureName = structureName;
|
||||
this->offset = (size_t)offset;
|
||||
this->structureType = structureType;
|
||||
this->size = sizeof(T);
|
||||
this->parameters = std::vector<struct ShaderParameter>();
|
||||
|
||||
T dummy;
|
||||
getParameters(dummy, this->parameters);
|
||||
|
||||
// Update offsets.
|
||||
std::for_each(
|
||||
this->parameters.begin(),
|
||||
this->parameters.end(),
|
||||
[&](struct ShaderParameter ¶m) {
|
||||
param.offset -= (size_t)(&dummy);
|
||||
|
||||
// Check for non-aligned OpenGL structures.
|
||||
if(param.offset % sizeof(glm::vec4) != 0) {
|
||||
assertUnreachable(
|
||||
"%s%s%s",
|
||||
"Non-aligned OpenGL structure detected on param ",
|
||||
param.name.c_str(),
|
||||
"!\nEnsure you have padded correctly."
|
||||
);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
@ -11,7 +11,8 @@ void SimpleTexturedShader::getStages(
|
||||
const enum ShaderOpenGLVariant variant,
|
||||
const struct SimpleTexturedShaderData *rel,
|
||||
std::vector<std::shared_ptr<ShaderStage>> &stages,
|
||||
std::vector<struct ShaderOpenGLParameter> ¶meters
|
||||
std::vector<struct ShaderParameter> ¶meters,
|
||||
std::vector<struct IShaderStructure> &structures
|
||||
) {
|
||||
// Stages
|
||||
std::shared_ptr<ShaderStage> vertex;
|
||||
@ -61,37 +62,37 @@ void SimpleTexturedShader::getStages(
|
||||
stages.push_back(fragment);
|
||||
|
||||
// Parameters
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_Projection",
|
||||
&rel->projection,
|
||||
ShaderParameterType::MAT4
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_View",
|
||||
&rel->view,
|
||||
ShaderParameterType::MAT4
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_Model",
|
||||
&rel->model,
|
||||
ShaderParameterType::MAT4
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_Color",
|
||||
&rel->color,
|
||||
ShaderParameterType::COLOR
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_HasTexture",
|
||||
&rel->hasTexture,
|
||||
ShaderParameterType::BOOLEAN
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_Texture",
|
||||
&rel->texture,
|
||||
ShaderParameterType::TEXTURE
|
||||
|
@ -22,7 +22,8 @@ namespace Dawn {
|
||||
const enum ShaderOpenGLVariant variant,
|
||||
const struct SimpleTexturedShaderData *rel,
|
||||
std::vector<std::shared_ptr<ShaderStage>> &stages,
|
||||
std::vector<struct ShaderOpenGLParameter> ¶meters
|
||||
std::vector<struct ShaderParameter> ¶meters,
|
||||
std::vector<struct IShaderStructure> &structures
|
||||
) override;
|
||||
};
|
||||
}
|
@ -11,7 +11,8 @@ void UIShader::getStages(
|
||||
const enum ShaderOpenGLVariant variant,
|
||||
const struct UIShaderData *rel,
|
||||
std::vector<std::shared_ptr<ShaderStage>> &stages,
|
||||
std::vector<struct ShaderOpenGLParameter> ¶meters
|
||||
std::vector<struct ShaderParameter> ¶meters,
|
||||
std::vector<struct IShaderStructure> &structures
|
||||
) {
|
||||
// Stages
|
||||
std::shared_ptr<ShaderStage> vertex;
|
||||
@ -38,10 +39,14 @@ void UIShader::getStages(
|
||||
ShaderStageType::FRAGMENT,
|
||||
"#version 330 core\n"
|
||||
"in vec2 o_TextCoord;\n"
|
||||
"uniform vec4 u_Color[4];\n"
|
||||
"layout (std140) uniform ub_Color {\n"
|
||||
"vec4 first;\n"
|
||||
"vec3 random;\n"
|
||||
"vec4 second;\n"
|
||||
"};\n"
|
||||
"out vec4 o_Color;\n"
|
||||
"void main() {\n"
|
||||
"o_Color = u_Color[2];\n"
|
||||
"o_Color = second;\n"
|
||||
"}\n"
|
||||
);
|
||||
break;
|
||||
@ -55,46 +60,46 @@ void UIShader::getStages(
|
||||
stages.push_back(fragment);
|
||||
|
||||
// Parameters
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_Projection",
|
||||
&rel->projection,
|
||||
ShaderParameterType::MAT4
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_View",
|
||||
&rel->view,
|
||||
ShaderParameterType::MAT4
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
parameters.push_back(ShaderParameter(
|
||||
"u_Model",
|
||||
&rel->model,
|
||||
ShaderParameterType::MAT4
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderOpenGLParameter(
|
||||
"u_Color",
|
||||
&rel->colors,
|
||||
ShaderParameterType::COLOR,
|
||||
4
|
||||
structures.push_back(ShaderStructure<struct TestStruct>(
|
||||
"ub_Color",
|
||||
&rel->test,
|
||||
ShaderOpenGLStructureType::STD140,
|
||||
[&](const struct TestStruct &rel, std::vector<struct ShaderParameter> ¶meters) {
|
||||
parameters.push_back(ShaderParameter(
|
||||
"first",
|
||||
&rel.first,
|
||||
ShaderParameterType::COLOR
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderParameter(
|
||||
"random",
|
||||
&rel.random,
|
||||
ShaderParameterType::VEC3
|
||||
));
|
||||
|
||||
parameters.push_back(ShaderParameter(
|
||||
"second",
|
||||
&rel.second,
|
||||
ShaderParameterType::COLOR
|
||||
));
|
||||
}
|
||||
));
|
||||
|
||||
// parameters.push_back(ShaderOpenGLParameter(
|
||||
// "u_Color",
|
||||
// &rel->color,
|
||||
// ShaderParameterType::COLOR
|
||||
// ));
|
||||
|
||||
// parameters.push_back(ShaderOpenGLParameter(
|
||||
// "u_HasTexture",
|
||||
// &rel->hasTexture,
|
||||
// ShaderParameterType::BOOLEAN
|
||||
// ));
|
||||
|
||||
// parameters.push_back(ShaderOpenGLParameter(
|
||||
// "u_Texture",
|
||||
// &rel->texture,
|
||||
// ShaderParameterType::TEXTURE
|
||||
// ));
|
||||
}
|
@ -7,11 +7,18 @@
|
||||
#include "display/shader/Shader.hpp"
|
||||
|
||||
namespace Dawn {
|
||||
struct TestStruct {
|
||||
struct Color first;
|
||||
glm::vec3 random;
|
||||
float_t padded;
|
||||
struct Color second;
|
||||
};
|
||||
|
||||
struct UIShaderData {
|
||||
glm::mat4 projection;
|
||||
glm::mat4 view;
|
||||
glm::mat4 model;
|
||||
struct Color colors[4];
|
||||
struct TestStruct test;
|
||||
};
|
||||
|
||||
class UIShader : public Shader<UIShaderData> {
|
||||
@ -20,7 +27,8 @@ namespace Dawn {
|
||||
const enum ShaderOpenGLVariant variant,
|
||||
const struct UIShaderData *rel,
|
||||
std::vector<std::shared_ptr<ShaderStage>> &stages,
|
||||
std::vector<struct ShaderOpenGLParameter> ¶meters
|
||||
std::vector<struct ShaderParameter> ¶meters,
|
||||
std::vector<struct IShaderStructure> &structures
|
||||
) override;
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user