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

View file

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