mirror of
https://github.com/MadeOfJelly/MushMachine.git
synced 2024-12-04 19:23:28 +01:00
refactor opengl shader and add shader builder
This commit is contained in:
parent
5ee0b7017f
commit
8e74256670
@ -38,6 +38,11 @@ namespace MM::OpenGL {
|
||||
glBindBuffer(target, 0);
|
||||
}
|
||||
|
||||
// for transform feedback
|
||||
void bindBase(GLuint index, GLenum target = GL_TRANSFORM_FEEDBACK_BUFFER) const {
|
||||
glBindBufferBase(target, index, _handle);
|
||||
}
|
||||
|
||||
void resize(size_t size, GLenum usage) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, _handle);
|
||||
glBufferData(GL_ARRAY_BUFFER, size * sizeof(TInstance), nullptr, usage);
|
||||
|
@ -1,6 +1,10 @@
|
||||
#include "./shader.hpp"
|
||||
|
||||
#include <map>
|
||||
#ifdef MM_OPENGL_3_GLES
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <glad/glad.h>
|
||||
#endif
|
||||
|
||||
#include <mm/services/filesystem.hpp>
|
||||
|
||||
|
@ -6,12 +6,6 @@
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
|
||||
#ifdef MM_OPENGL_3_GLES
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <glad/glad.h>
|
||||
#endif
|
||||
|
||||
#include <glm/fwd.hpp>
|
||||
#include <glm/mat3x3.hpp>
|
||||
|
||||
@ -22,7 +16,12 @@ namespace MM {
|
||||
|
||||
namespace MM::OpenGL {
|
||||
|
||||
// fwd
|
||||
class ShaderBuilder;
|
||||
|
||||
class Shader {
|
||||
friend ShaderBuilder;
|
||||
|
||||
private:
|
||||
uint32_t _rendererID;
|
||||
std::unordered_map<std::string, int32_t> _uniformLocationCache;
|
||||
@ -50,6 +49,7 @@ namespace MM::OpenGL {
|
||||
void setUniformMat4f(const std::string& name, const glm::mat4& matrix);
|
||||
void setUniformMat3f(const std::string& name, const glm::mat3& matrix);
|
||||
|
||||
// prefere ShaderBuilder
|
||||
static std::shared_ptr<Shader> createF(Engine& engine, const char* vertexShaderPath, const char* fragmentShaderPath);
|
||||
static std::shared_ptr<Shader> create(const std::string& vertexShader, const std::string& fragmentShader);
|
||||
|
||||
|
145
framework/opengl_primitives/src/mm/opengl/shader_builder.cpp
Normal file
145
framework/opengl_primitives/src/mm/opengl/shader_builder.cpp
Normal file
@ -0,0 +1,145 @@
|
||||
#include "./shader_builder.hpp"
|
||||
|
||||
#ifdef MM_OPENGL_3_GLES
|
||||
#include <GLES3/gl3.h>
|
||||
#else
|
||||
#include <glad/glad.h>
|
||||
#endif
|
||||
|
||||
#include <mm/services/filesystem.hpp>
|
||||
|
||||
#include <mm/logger.hpp>
|
||||
#define LOG_CRIT(...) __LOG_CRIT( "OpenGL", __VA_ARGS__)
|
||||
#define LOG_ERROR(...) __LOG_ERROR("OpenGL", __VA_ARGS__)
|
||||
#define LOG_WARN(...) __LOG_WARN( "OpenGL", __VA_ARGS__)
|
||||
#define LOG_INFO(...) __LOG_INFO( "OpenGL", __VA_ARGS__)
|
||||
#define LOG_DEBUG(...) __LOG_DEBUG("OpenGL", __VA_ARGS__)
|
||||
#define LOG_TRACE(...) __LOG_TRACE("OpenGL", __VA_ARGS__)
|
||||
|
||||
namespace MM::OpenGL {
|
||||
|
||||
ShaderBuilder::ShaderBuilder(void) {
|
||||
}
|
||||
|
||||
ShaderBuilder::~ShaderBuilder(void) {
|
||||
// after linking or in case of error, stages can be deleted
|
||||
for (auto& stage : _stages) {
|
||||
if (stage.id != 0) {
|
||||
glDeleteShader(stage.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ShaderBuilder ShaderBuilder::start(void) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::shared_ptr<Shader> ShaderBuilder::finish(void) {
|
||||
// check
|
||||
for (auto& stage : _stages) {
|
||||
if (stage.fail) {
|
||||
// log error
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t program = glCreateProgram();
|
||||
|
||||
// attach
|
||||
for (auto& stage : _stages) {
|
||||
if (stage.id != 0) {
|
||||
glAttachShader(program, stage.id);
|
||||
}
|
||||
}
|
||||
|
||||
// tf varying
|
||||
if (!_tfs.empty()) {
|
||||
std::vector<const char*> tmp_vars;
|
||||
|
||||
for (auto& tfv : _tfs) {
|
||||
tmp_vars.push_back(tfv.var.c_str());
|
||||
}
|
||||
|
||||
glTransformFeedbackVaryings(program, tmp_vars.size(), tmp_vars.data(), _tf_interleaved ? GL_INTERLEAVED_ATTRIBS : GL_SEPARATE_ATTRIBS);
|
||||
|
||||
}
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
// diagnostics
|
||||
GLint isLinked = 0;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
|
||||
if (isLinked == GL_FALSE) {
|
||||
GLint maxLength = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
|
||||
// The maxLength includes the NULL character
|
||||
std::vector<GLchar> infoLog(maxLength);
|
||||
glGetProgramInfoLog(program, maxLength, &maxLength, infoLog.data());
|
||||
LOG_ERROR("Linking Shader Programs: {}", infoLog.data());
|
||||
|
||||
// The program is useless now. So delete it.
|
||||
glDeleteProgram(program);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
glValidateProgram(program);
|
||||
GLint isValid = 0;
|
||||
glGetProgramiv(program, GL_VALIDATE_STATUS, &isValid);
|
||||
if (isValid == GL_FALSE) {
|
||||
GLint maxLength = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
|
||||
// The maxLength includes the NULL character
|
||||
std::vector<GLchar> infoLog(maxLength);
|
||||
glGetProgramInfoLog(program, maxLength, &maxLength, infoLog.data());
|
||||
LOG_ERROR("Validating Shader Programs: {}", infoLog.data());
|
||||
|
||||
// The program is useless now. So delete it.
|
||||
glDeleteProgram(program);
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
|
||||
return std::shared_ptr<Shader>(new Shader(program));
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::addStageVertex(const std::string& shader_code) {
|
||||
_stages[VERTEX].id = Shader::compile(GL_VERTEX_SHADER, shader_code);
|
||||
if (_stages[VERTEX].id == 0) {
|
||||
_stages[VERTEX].fail = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::addStageVertexF(MM::Engine& engine, const std::string& file_path) {
|
||||
return addStageVertex(Shader::parse(engine, file_path));
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::addStageFragment(const std::string& shader_code) {
|
||||
_stages[FRAGMENT].id = Shader::compile(GL_FRAGMENT_SHADER, shader_code);
|
||||
if (_stages[FRAGMENT].id == 0) {
|
||||
_stages[FRAGMENT].fail = true;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::addStageFragmentF(MM::Engine& engine, const std::string& file_path) {
|
||||
return addStageFragment(Shader::parse(engine, file_path));
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::addTransformFeedbackVarying(const std::string& var_name) {
|
||||
if (var_name.empty()) {
|
||||
// log waring
|
||||
return *this;
|
||||
}
|
||||
|
||||
_tfs.push_back({var_name});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // MM::OpenGL
|
||||
|
52
framework/opengl_primitives/src/mm/opengl/shader_builder.hpp
Normal file
52
framework/opengl_primitives/src/mm/opengl/shader_builder.hpp
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "./shader.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace MM::OpenGL {
|
||||
|
||||
class ShaderBuilder {
|
||||
private:
|
||||
ShaderBuilder(void);
|
||||
|
||||
struct stage_t {
|
||||
uint32_t id = 0;
|
||||
bool fail = false;
|
||||
};
|
||||
|
||||
enum stage_e {
|
||||
VERTEX = 0,
|
||||
FRAGMENT,
|
||||
stage_e_MAX
|
||||
};
|
||||
|
||||
stage_t _stages[stage_e_MAX];
|
||||
|
||||
struct transform_feedback_varying_t {
|
||||
std::string var;
|
||||
};
|
||||
std::vector<transform_feedback_varying_t> _tfs;
|
||||
|
||||
bool _tf_interleaved = false;
|
||||
|
||||
public:
|
||||
~ShaderBuilder(void);
|
||||
ShaderBuilder& operator=(ShaderBuilder&) = delete;
|
||||
|
||||
static ShaderBuilder start(void);
|
||||
std::shared_ptr<Shader> finish(void);
|
||||
|
||||
public:
|
||||
ShaderBuilder& addStageVertex(const std::string& shader_code);
|
||||
ShaderBuilder& addStageVertexF(MM::Engine& engine, const std::string& file_path);
|
||||
ShaderBuilder& addStageFragment(const std::string& shader_code);
|
||||
ShaderBuilder& addStageFragmentF(MM::Engine& engine, const std::string& file_path);
|
||||
// TODO: geometry and tesselation stages
|
||||
|
||||
ShaderBuilder& addTransformFeedbackVarying(const std::string& var_name);
|
||||
ShaderBuilder& setTransformFeedbackInterleaved(bool interleaved = true);
|
||||
};
|
||||
|
||||
} // MM::OpenGL
|
||||
|
Loading…
Reference in New Issue
Block a user