Add support for loading geometry shaders (and other shaders)

This commit is contained in:
Dan Paulat 2023-08-12 00:35:20 -05:00
parent 0c5a504ad5
commit 913151e063
2 changed files with 70 additions and 65 deletions

View file

@ -15,6 +15,11 @@ static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
static constexpr GLsizei kInfoLogBufSize = 512; static constexpr GLsizei kInfoLogBufSize = 512;
static const std::unordered_map<GLenum, std::string> kShaderNames_ {
{GL_VERTEX_SHADER, "vertex"},
{GL_GEOMETRY_SHADER, "geometry"},
{GL_FRAGMENT_SHADER, "fragment"}};
class ShaderProgram::Impl class ShaderProgram::Impl
{ {
public: public:
@ -30,6 +35,8 @@ public:
gl_.glDeleteProgram(id_); gl_.glDeleteProgram(id_);
} }
static std::string ShaderName(GLenum type);
OpenGLFunctions& gl_; OpenGLFunctions& gl_;
GLuint id_; GLuint id_;
@ -49,10 +56,27 @@ GLuint ShaderProgram::id() const
return p->id_; return p->id_;
} }
std::string ShaderProgram::Impl::ShaderName(GLenum type)
{
auto it = kShaderNames_.find(type);
if (it != kShaderNames_.cend())
{
return it->second;
}
return fmt::format("{:#06x}", type);
}
bool ShaderProgram::Load(const std::string& vertexPath, bool ShaderProgram::Load(const std::string& vertexPath,
const std::string& fragmentPath) const std::string& fragmentPath)
{ {
logger_->debug("Load: {}, {}", vertexPath, fragmentPath); return Load({{GL_VERTEX_SHADER, vertexPath}, //
{GL_FRAGMENT_SHADER, fragmentPath}});
}
bool ShaderProgram::Load(
std::initializer_list<std::pair<GLenum, std::string>> shaders)
{
logger_->debug("Load()");
OpenGLFunctions& gl = p->gl_; OpenGLFunctions& gl = p->gl_;
@ -61,81 +85,59 @@ bool ShaderProgram::Load(const std::string& vertexPath,
char infoLog[kInfoLogBufSize]; char infoLog[kInfoLogBufSize];
GLsizei logLength; GLsizei logLength;
QFile vertexFile(vertexPath.c_str()); std::vector<GLuint> shaderIds {};
QFile fragmentFile(fragmentPath.c_str());
vertexFile.open(QIODevice::ReadOnly | QIODevice::Text); for (auto& shader : shaders)
fragmentFile.open(QIODevice::ReadOnly | QIODevice::Text);
if (!vertexFile.isOpen())
{ {
logger_->error("Could not load vertex shader: {}", vertexPath); logger_->debug("Loading {} shader: {}",
return false; Impl::ShaderName(shader.first),
} shader.second);
if (!fragmentFile.isOpen()) QFile file(shader.second.c_str());
{ file.open(QIODevice::ReadOnly | QIODevice::Text);
logger_->error("Could not load fragment shader: {}", fragmentPath);
return false;
}
QTextStream vertexShaderStream(&vertexFile); if (!file.isOpen())
QTextStream fragmentShaderStream(&fragmentFile); {
logger_->error("Could not load shader");
success = false;
break;
}
vertexShaderStream.setEncoding(QStringConverter::Utf8); QTextStream shaderStream(&file);
fragmentShaderStream.setEncoding(QStringConverter::Utf8); shaderStream.setEncoding(QStringConverter::Utf8);
std::string vertexShaderSource = vertexShaderStream.readAll().toStdString(); std::string shaderSource = shaderStream.readAll().toStdString();
std::string fragmentShaderSource = const char* shaderSourceC = shaderSource.c_str();
fragmentShaderStream.readAll().toStdString();
const char* vertexShaderSourceC = vertexShaderSource.c_str(); // Create a vertex shader
const char* fragmentShaderSourceC = fragmentShaderSource.c_str(); GLuint shaderId = gl.glCreateShader(shader.first);
shaderIds.push_back(shaderId);
// Create a vertex shader // Attach the shader source code and compile the shader
GLuint vertexShader = gl.glCreateShader(GL_VERTEX_SHADER); gl.glShaderSource(shaderId, 1, &shaderSourceC, NULL);
gl.glCompileShader(shaderId);
// Attach the shader source code and compile the shader // Check for errors
gl.glShaderSource(vertexShader, 1, &vertexShaderSourceC, NULL); gl.glGetShaderiv(shaderId, GL_COMPILE_STATUS, &glSuccess);
gl.glCompileShader(vertexShader); gl.glGetShaderInfoLog(shaderId, kInfoLogBufSize, &logLength, infoLog);
if (!glSuccess)
// Check for errors {
gl.glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &glSuccess); logger_->error("Shader compilation failed: {}", infoLog);
gl.glGetShaderInfoLog(vertexShader, kInfoLogBufSize, &logLength, infoLog); success = false;
if (!glSuccess) break;
{ }
logger_->error("Vertex shader compilation failed: {}", infoLog); else if (logLength > 0)
success = false; {
} logger_->error("Shader compiled with warnings: {}", infoLog);
else if (logLength > 0) }
{
logger_->error("Vertex shader compiled with warnings: {}", infoLog);
}
// Create a fragment shader
GLuint fragmentShader = gl.glCreateShader(GL_FRAGMENT_SHADER);
// Attach the shader source and compile the shader
gl.glShaderSource(fragmentShader, 1, &fragmentShaderSourceC, NULL);
gl.glCompileShader(fragmentShader);
// Check for errors
gl.glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &glSuccess);
gl.glGetShaderInfoLog(fragmentShader, kInfoLogBufSize, &logLength, infoLog);
if (!glSuccess)
{
logger_->error("Fragment shader compilation failed: {}", infoLog);
success = false;
}
else if (logLength > 0)
{
logger_->error("Fragment shader compiled with warnings: {}", infoLog);
} }
if (success) if (success)
{ {
gl.glAttachShader(p->id_, vertexShader); for (auto& shaderId : shaderIds)
gl.glAttachShader(p->id_, fragmentShader); {
gl.glAttachShader(p->id_, shaderId);
}
gl.glLinkProgram(p->id_); gl.glLinkProgram(p->id_);
// Check for errors // Check for errors
@ -153,8 +155,10 @@ bool ShaderProgram::Load(const std::string& vertexPath,
} }
// Delete shaders // Delete shaders
gl.glDeleteShader(vertexShader); for (auto& shaderId : shaderIds)
gl.glDeleteShader(fragmentShader); {
gl.glDeleteShader(shaderId);
}
return success; return success;
} }

View file

@ -31,6 +31,7 @@ public:
GLuint id() const; GLuint id() const;
bool Load(const std::string& vertexPath, const std::string& fragmentPath); bool Load(const std::string& vertexPath, const std::string& fragmentPath);
bool Load(std::initializer_list<std::pair<GLenum, std::string>> shaderPaths);
void Use() const; void Use() const;