| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217 |
- #include "shader.h"
- #include <QByteArray>
- #include <QDebug>
- #include <QFile>
- #include <QTextStream>
- namespace Render::GL {
- Shader::Shader() {}
- Shader::~Shader() {
- if (m_program != 0) {
- glDeleteProgram(m_program);
- }
- }
- bool Shader::loadFromFiles(const QString &vertexPath,
- const QString &fragmentPath) {
- QFile vertexFile(vertexPath);
- QFile fragmentFile(fragmentPath);
- if (!vertexFile.open(QIODevice::ReadOnly) ||
- !fragmentFile.open(QIODevice::ReadOnly)) {
- qWarning() << "Failed to open shader files";
- return false;
- }
- QTextStream vertexStream(&vertexFile);
- QTextStream fragmentStream(&fragmentFile);
- QString vertexSource = vertexStream.readAll();
- QString fragmentSource = fragmentStream.readAll();
- return loadFromSource(vertexSource, fragmentSource);
- }
- bool Shader::loadFromSource(const QString &vertexSource,
- const QString &fragmentSource) {
- initializeOpenGLFunctions();
- m_uniformCache.clear();
- GLuint vertexShader = compileShader(vertexSource, GL_VERTEX_SHADER);
- GLuint fragmentShader = compileShader(fragmentSource, GL_FRAGMENT_SHADER);
- if (vertexShader == 0 || fragmentShader == 0) {
- return false;
- }
- bool success = linkProgram(vertexShader, fragmentShader);
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- return success;
- }
- void Shader::use() {
- initializeOpenGLFunctions();
- glUseProgram(m_program);
- }
- void Shader::release() {
- initializeOpenGLFunctions();
- glUseProgram(0);
- }
- Shader::UniformHandle Shader::uniformHandle(const char *name) {
- if (!name || *name == '\0' || m_program == 0) {
- return InvalidUniform;
- }
- auto it = m_uniformCache.find(name);
- if (it != m_uniformCache.end()) {
- return it->second;
- }
- initializeOpenGLFunctions();
- UniformHandle location = glGetUniformLocation(m_program, name);
- m_uniformCache.emplace(name, location);
- return location;
- }
- void Shader::setUniform(UniformHandle handle, float value) {
- initializeOpenGLFunctions();
- if (handle != InvalidUniform) {
- glUniform1f(handle, value);
- }
- }
- void Shader::setUniform(UniformHandle handle, const QVector3D &value) {
- initializeOpenGLFunctions();
- if (handle != InvalidUniform) {
- glUniform3f(handle, value.x(), value.y(), value.z());
- }
- }
- void Shader::setUniform(UniformHandle handle, const QVector2D &value) {
- initializeOpenGLFunctions();
- if (handle != InvalidUniform) {
- glUniform2f(handle, value.x(), value.y());
- }
- }
- void Shader::setUniform(UniformHandle handle, const QMatrix4x4 &value) {
- initializeOpenGLFunctions();
- if (handle != InvalidUniform) {
- glUniformMatrix4fv(handle, 1, GL_FALSE, value.constData());
- }
- }
- void Shader::setUniform(UniformHandle handle, int value) {
- initializeOpenGLFunctions();
- if (handle != InvalidUniform) {
- glUniform1i(handle, value);
- }
- }
- void Shader::setUniform(UniformHandle handle, bool value) {
- setUniform(handle, static_cast<int>(value));
- }
- void Shader::setUniform(const char *name, float value) {
- setUniform(uniformHandle(name), value);
- }
- void Shader::setUniform(const char *name, const QVector3D &value) {
- setUniform(uniformHandle(name), value);
- }
- void Shader::setUniform(const char *name, const QVector2D &value) {
- setUniform(uniformHandle(name), value);
- }
- void Shader::setUniform(const char *name, const QMatrix4x4 &value) {
- setUniform(uniformHandle(name), value);
- }
- void Shader::setUniform(const char *name, int value) {
- setUniform(uniformHandle(name), value);
- }
- void Shader::setUniform(const char *name, bool value) {
- setUniform(uniformHandle(name), value);
- }
- void Shader::setUniform(const QString &name, float value) {
- const QByteArray utf8 = name.toUtf8();
- setUniform(utf8.constData(), value);
- }
- void Shader::setUniform(const QString &name, const QVector3D &value) {
- const QByteArray utf8 = name.toUtf8();
- setUniform(utf8.constData(), value);
- }
- void Shader::setUniform(const QString &name, const QVector2D &value) {
- const QByteArray utf8 = name.toUtf8();
- setUniform(utf8.constData(), value);
- }
- void Shader::setUniform(const QString &name, const QMatrix4x4 &value) {
- const QByteArray utf8 = name.toUtf8();
- setUniform(utf8.constData(), value);
- }
- void Shader::setUniform(const QString &name, int value) {
- const QByteArray utf8 = name.toUtf8();
- setUniform(utf8.constData(), value);
- }
- void Shader::setUniform(const QString &name, bool value) {
- setUniform(name, static_cast<int>(value));
- }
- GLuint Shader::compileShader(const QString &source, GLenum type) {
- initializeOpenGLFunctions();
- GLuint shader = glCreateShader(type);
- QByteArray sourceBytes = source.toUtf8();
- const char *sourcePtr = sourceBytes.constData();
- glShaderSource(shader, 1, &sourcePtr, nullptr);
- glCompileShader(shader);
- GLint success;
- glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
- if (!success) {
- GLchar infoLog[512];
- glGetShaderInfoLog(shader, 512, nullptr, infoLog);
- qWarning() << "Shader compilation failed:" << infoLog;
- glDeleteShader(shader);
- return 0;
- }
- return shader;
- }
- bool Shader::linkProgram(GLuint vertexShader, GLuint fragmentShader) {
- initializeOpenGLFunctions();
- m_program = glCreateProgram();
- glAttachShader(m_program, vertexShader);
- glAttachShader(m_program, fragmentShader);
- glLinkProgram(m_program);
- GLint success;
- glGetProgramiv(m_program, GL_LINK_STATUS, &success);
- if (!success) {
- GLchar infoLog[512];
- glGetProgramInfoLog(m_program, 512, nullptr, infoLog);
- qWarning() << "Shader linking failed:" << infoLog;
- glDeleteProgram(m_program);
- m_program = 0;
- return false;
- }
- return true;
- }
- } // namespace Render::GL
|