Enhance OpenGLShader with comprehensive shader support
This commit is contained in:
@@ -2,27 +2,55 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace XCEngine {
|
namespace XCEngine {
|
||||||
namespace RHI {
|
namespace RHI {
|
||||||
|
|
||||||
|
enum class ShaderType {
|
||||||
|
Vertex,
|
||||||
|
Fragment,
|
||||||
|
Geometry,
|
||||||
|
Compute,
|
||||||
|
TessControl,
|
||||||
|
TessEvaluation
|
||||||
|
};
|
||||||
|
|
||||||
class OpenGLShader {
|
class OpenGLShader {
|
||||||
public:
|
public:
|
||||||
OpenGLShader();
|
OpenGLShader();
|
||||||
~OpenGLShader();
|
~OpenGLShader();
|
||||||
|
|
||||||
bool CompileFromFile(const char* vertexPath, const char* fragmentPath);
|
bool CompileFromFile(const char* vertexPath, const char* fragmentPath);
|
||||||
|
bool CompileFromFile(const char* vertexPath, const char* fragmentPath, const char* geometryPath);
|
||||||
bool Compile(const char* vertexSource, const char* fragmentSource);
|
bool Compile(const char* vertexSource, const char* fragmentSource);
|
||||||
|
bool Compile(const char* vertexSource, const char* fragmentSource, const char* geometrySource);
|
||||||
|
bool CompileCompute(const char* computeSource);
|
||||||
|
bool Compile(const char* source, ShaderType type);
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
void Use() const;
|
void Use() const;
|
||||||
|
void Bind() const { Use(); }
|
||||||
|
void Unbind() const;
|
||||||
|
|
||||||
void SetInt(const std::string& name, int value) const;
|
void SetInt(const std::string& name, int value) const;
|
||||||
|
void SetIntArray(const std::string& name, const int* values, unsigned int count) const;
|
||||||
void SetFloat(const std::string& name, float value) const;
|
void SetFloat(const std::string& name, float value) const;
|
||||||
|
void SetFloatArray(const std::string& name, const float* values, unsigned int count) const;
|
||||||
|
void SetVec2(const std::string& name, float x, float y) const;
|
||||||
|
void SetVec2(const std::string& name, const float* values) const;
|
||||||
void SetVec3(const std::string& name, float x, float y, float z) const;
|
void SetVec3(const std::string& name, float x, float y, float z) const;
|
||||||
void SetVec3(const std::string& name, const float* values) const;
|
void SetVec3(const std::string& name, const float* values) const;
|
||||||
|
void SetVec4(const std::string& name, float x, float y, float z, float w) const;
|
||||||
|
void SetVec4(const std::string& name, const float* values) const;
|
||||||
|
void SetMat2(const std::string& name, const float* value) const;
|
||||||
|
void SetMat3(const std::string& name, const float* value) const;
|
||||||
void SetMat4(const std::string& name, const float* value) const;
|
void SetMat4(const std::string& name, const float* value) const;
|
||||||
|
void SetMat4Array(const std::string& name, const float* values, unsigned int count) const;
|
||||||
|
|
||||||
|
int GetUniformLocation(const std::string& name) const;
|
||||||
unsigned int GetID() const { return m_program; }
|
unsigned int GetID() const { return m_program; }
|
||||||
|
bool IsValid() const { return m_program != 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned int m_program;
|
unsigned int m_program;
|
||||||
|
|||||||
@@ -37,18 +37,41 @@ bool OpenGLShader::CompileFromFile(const char* vertexPath, const char* fragmentP
|
|||||||
return Compile(vertexCode.c_str(), fragmentCode.c_str());
|
return Compile(vertexCode.c_str(), fragmentCode.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenGLShader::CompileFromFile(const char* vertexPath, const char* fragmentPath, const char* geometryPath) {
|
||||||
|
std::string vertexCode, fragmentCode, geometryCode;
|
||||||
|
std::ifstream vShaderFile(vertexPath), fShaderFile(fragmentPath), gShaderFile(geometryPath);
|
||||||
|
|
||||||
|
if (!vShaderFile.is_open() || !fShaderFile.is_open() || !gShaderFile.is_open()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::stringstream vShaderStream, fShaderStream, gShaderStream;
|
||||||
|
vShaderStream << vShaderFile.rdbuf();
|
||||||
|
fShaderStream << fShaderFile.rdbuf();
|
||||||
|
gShaderStream << gShaderFile.rdbuf();
|
||||||
|
vShaderFile.close();
|
||||||
|
fShaderFile.close();
|
||||||
|
gShaderFile.close();
|
||||||
|
|
||||||
|
vertexCode = vShaderStream.str();
|
||||||
|
fragmentCode = fShaderStream.str();
|
||||||
|
geometryCode = gShaderStream.str();
|
||||||
|
|
||||||
|
return Compile(vertexCode.c_str(), fragmentCode.c_str(), geometryCode.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource) {
|
bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource) {
|
||||||
unsigned int vertex, fragment;
|
unsigned int vertex, fragment;
|
||||||
|
|
||||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vertex, 1, &vertexSource, NULL);
|
glShaderSource(vertex, 1, &vertexSource, nullptr);
|
||||||
glCompileShader(vertex);
|
glCompileShader(vertex);
|
||||||
if (!CheckCompileErrors(vertex, "VERTEX")) {
|
if (!CheckCompileErrors(vertex, "VERTEX")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
glShaderSource(fragment, 1, &fragmentSource, NULL);
|
glShaderSource(fragment, 1, &fragmentSource, nullptr);
|
||||||
glCompileShader(fragment);
|
glCompileShader(fragment);
|
||||||
if (!CheckCompileErrors(fragment, "FRAGMENT")) {
|
if (!CheckCompileErrors(fragment, "FRAGMENT")) {
|
||||||
return false;
|
return false;
|
||||||
@@ -69,6 +92,116 @@ bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenGLShader::Compile(const char* vertexSource, const char* fragmentSource, const char* geometrySource) {
|
||||||
|
unsigned int vertex, fragment, geometry;
|
||||||
|
|
||||||
|
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
glShaderSource(vertex, 1, &vertexSource, nullptr);
|
||||||
|
glCompileShader(vertex);
|
||||||
|
if (!CheckCompileErrors(vertex, "VERTEX")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
glShaderSource(fragment, 1, &fragmentSource, nullptr);
|
||||||
|
glCompileShader(fragment);
|
||||||
|
if (!CheckCompileErrors(fragment, "FRAGMENT")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
geometry = glCreateShader(GL_GEOMETRY_SHADER);
|
||||||
|
glShaderSource(geometry, 1, &geometrySource, nullptr);
|
||||||
|
glCompileShader(geometry);
|
||||||
|
if (!CheckCompileErrors(geometry, "GEOMETRY")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_program = glCreateProgram();
|
||||||
|
glAttachShader(m_program, vertex);
|
||||||
|
glAttachShader(m_program, fragment);
|
||||||
|
glAttachShader(m_program, geometry);
|
||||||
|
glLinkProgram(m_program);
|
||||||
|
|
||||||
|
if (!CheckLinkErrors(m_program)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteShader(vertex);
|
||||||
|
glDeleteShader(fragment);
|
||||||
|
glDeleteShader(geometry);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLShader::CompileCompute(const char* computeSource) {
|
||||||
|
unsigned int compute = glCreateShader(GL_COMPUTE_SHADER);
|
||||||
|
glShaderSource(compute, 1, &computeSource, nullptr);
|
||||||
|
glCompileShader(compute);
|
||||||
|
if (!CheckCompileErrors(compute, "COMPUTE")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_program = glCreateProgram();
|
||||||
|
glAttachShader(m_program, compute);
|
||||||
|
glLinkProgram(m_program);
|
||||||
|
|
||||||
|
if (!CheckLinkErrors(m_program)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteShader(compute);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLShader::Compile(const char* source, ShaderType type) {
|
||||||
|
unsigned int shader = 0;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case ShaderType::Vertex:
|
||||||
|
shader = glCreateShader(GL_VERTEX_SHADER);
|
||||||
|
break;
|
||||||
|
case ShaderType::Fragment:
|
||||||
|
shader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||||
|
break;
|
||||||
|
case ShaderType::Geometry:
|
||||||
|
shader = glCreateShader(GL_GEOMETRY_SHADER);
|
||||||
|
break;
|
||||||
|
case ShaderType::Compute:
|
||||||
|
shader = glCreateShader(GL_COMPUTE_SHADER);
|
||||||
|
break;
|
||||||
|
case ShaderType::TessControl:
|
||||||
|
shader = glCreateShader(GL_TESS_CONTROL_SHADER);
|
||||||
|
break;
|
||||||
|
case ShaderType::TessEvaluation:
|
||||||
|
shader = glCreateShader(GL_TESS_EVALUATION_SHADER);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glShaderSource(shader, 1, &source, nullptr);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
const char* typeName[] = { "VERTEX", "FRAGMENT", "GEOMETRY", "COMPUTE", "TESS_CONTROL", "TESS_EVALUATION" };
|
||||||
|
if (!CheckCompileErrors(shader, typeName[(int)type])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_program == 0) {
|
||||||
|
m_program = glCreateProgram();
|
||||||
|
}
|
||||||
|
glAttachShader(m_program, shader);
|
||||||
|
glLinkProgram(m_program);
|
||||||
|
|
||||||
|
if (!CheckLinkErrors(m_program)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
glDeleteShader(shader);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::Shutdown() {
|
void OpenGLShader::Shutdown() {
|
||||||
if (m_program) {
|
if (m_program) {
|
||||||
glDeleteProgram(m_program);
|
glDeleteProgram(m_program);
|
||||||
@@ -80,14 +213,34 @@ void OpenGLShader::Use() const {
|
|||||||
glUseProgram(m_program);
|
glUseProgram(m_program);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::Unbind() const {
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::SetInt(const std::string& name, int value) const {
|
void OpenGLShader::SetInt(const std::string& name, int value) const {
|
||||||
glUniform1i(glGetUniformLocation(m_program, name.c_str()), value);
|
glUniform1i(glGetUniformLocation(m_program, name.c_str()), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetIntArray(const std::string& name, const int* values, unsigned int count) const {
|
||||||
|
glUniform1iv(glGetUniformLocation(m_program, name.c_str()), count, values);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::SetFloat(const std::string& name, float value) const {
|
void OpenGLShader::SetFloat(const std::string& name, float value) const {
|
||||||
glUniform1f(glGetUniformLocation(m_program, name.c_str()), value);
|
glUniform1f(glGetUniformLocation(m_program, name.c_str()), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetFloatArray(const std::string& name, const float* values, unsigned int count) const {
|
||||||
|
glUniform1fv(glGetUniformLocation(m_program, name.c_str()), count, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetVec2(const std::string& name, float x, float y) const {
|
||||||
|
glUniform2f(glGetUniformLocation(m_program, name.c_str()), x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetVec2(const std::string& name, const float* values) const {
|
||||||
|
glUniform2fv(glGetUniformLocation(m_program, name.c_str()), 1, values);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::SetVec3(const std::string& name, float x, float y, float z) const {
|
void OpenGLShader::SetVec3(const std::string& name, float x, float y, float z) const {
|
||||||
glUniform3f(glGetUniformLocation(m_program, name.c_str()), x, y, z);
|
glUniform3f(glGetUniformLocation(m_program, name.c_str()), x, y, z);
|
||||||
}
|
}
|
||||||
@@ -96,17 +249,41 @@ void OpenGLShader::SetVec3(const std::string& name, const float* values) const {
|
|||||||
glUniform3fv(glGetUniformLocation(m_program, name.c_str()), 1, values);
|
glUniform3fv(glGetUniformLocation(m_program, name.c_str()), 1, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetVec4(const std::string& name, float x, float y, float z, float w) const {
|
||||||
|
glUniform4f(glGetUniformLocation(m_program, name.c_str()), x, y, z, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetVec4(const std::string& name, const float* values) const {
|
||||||
|
glUniform4fv(glGetUniformLocation(m_program, name.c_str()), 1, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetMat2(const std::string& name, const float* value) const {
|
||||||
|
glUniformMatrix2fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetMat3(const std::string& name, const float* value) const {
|
||||||
|
glUniformMatrix3fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value);
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLShader::SetMat4(const std::string& name, const float* value) const {
|
void OpenGLShader::SetMat4(const std::string& name, const float* value) const {
|
||||||
glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value);
|
glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()), 1, GL_FALSE, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OpenGLShader::SetMat4Array(const std::string& name, const float* values, unsigned int count) const {
|
||||||
|
glUniformMatrix4fv(glGetUniformLocation(m_program, name.c_str()), count, GL_FALSE, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
int OpenGLShader::GetUniformLocation(const std::string& name) const {
|
||||||
|
return glGetUniformLocation(m_program, name.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
bool OpenGLShader::CheckCompileErrors(unsigned int shader, const char* type) {
|
bool OpenGLShader::CheckCompileErrors(unsigned int shader, const char* type) {
|
||||||
int success;
|
int success;
|
||||||
char infoLog[1024];
|
char infoLog[1024];
|
||||||
|
|
||||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
glGetShaderInfoLog(shader, 1024, NULL, infoLog);
|
glGetShaderInfoLog(shader, 1024, nullptr, infoLog);
|
||||||
std::cout << "ERROR::SHADER_COMPILATION_ERROR: " << type << "\n" << infoLog << std::endl;
|
std::cout << "ERROR::SHADER_COMPILATION_ERROR: " << type << "\n" << infoLog << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -119,7 +296,7 @@ bool OpenGLShader::CheckLinkErrors(unsigned int program) {
|
|||||||
|
|
||||||
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
glGetProgramInfoLog(program, 1024, NULL, infoLog);
|
glGetProgramInfoLog(program, 1024, nullptr, infoLog);
|
||||||
std::cout << "ERROR::PROGRAM_LINKING_ERROR\n" << infoLog << std::endl;
|
std::cout << "ERROR::PROGRAM_LINKING_ERROR\n" << infoLog << std::endl;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user