mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 03:50:05 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			169 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
	
		
			4.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <scwx/qt/gl/shader_program.hpp>
 | |
| #include <scwx/util/logger.hpp>
 | |
| 
 | |
| #include <QFile>
 | |
| 
 | |
| namespace scwx
 | |
| {
 | |
| namespace qt
 | |
| {
 | |
| namespace gl
 | |
| {
 | |
| 
 | |
| static const std::string logPrefix_ = "scwx::qt::gl::shader_program";
 | |
| static const auto        logger_    = scwx::util::Logger::Create(logPrefix_);
 | |
| 
 | |
| static constexpr GLsizei kInfoLogBufSize = 512;
 | |
| 
 | |
| class ShaderProgram::Impl
 | |
| {
 | |
| public:
 | |
|    explicit Impl(OpenGLFunctions& gl) : gl_(gl), id_ {GL_INVALID_INDEX}
 | |
|    {
 | |
|       // Create shader program
 | |
|       id_ = gl_.glCreateProgram();
 | |
|    }
 | |
| 
 | |
|    ~Impl()
 | |
|    {
 | |
|       // Delete shader program
 | |
|       gl_.glDeleteProgram(id_);
 | |
|    }
 | |
| 
 | |
|    OpenGLFunctions& gl_;
 | |
| 
 | |
|    GLuint id_;
 | |
| };
 | |
| 
 | |
| ShaderProgram::ShaderProgram(OpenGLFunctions& gl) :
 | |
|     p(std::make_unique<Impl>(gl))
 | |
| {
 | |
| }
 | |
| ShaderProgram::~ShaderProgram() = default;
 | |
| 
 | |
| ShaderProgram::ShaderProgram(ShaderProgram&&) noexcept            = default;
 | |
| ShaderProgram& ShaderProgram::operator=(ShaderProgram&&) noexcept = default;
 | |
| 
 | |
| GLuint ShaderProgram::id() const
 | |
| {
 | |
|    return p->id_;
 | |
| }
 | |
| 
 | |
| bool ShaderProgram::Load(const std::string& vertexPath,
 | |
|                          const std::string& fragmentPath)
 | |
| {
 | |
|    logger_->debug("Load: {}, {}", vertexPath, fragmentPath);
 | |
| 
 | |
|    OpenGLFunctions& gl = p->gl_;
 | |
| 
 | |
|    GLint   glSuccess;
 | |
|    bool    success = true;
 | |
|    char    infoLog[kInfoLogBufSize];
 | |
|    GLsizei logLength;
 | |
| 
 | |
|    QFile vertexFile(vertexPath.c_str());
 | |
|    QFile fragmentFile(fragmentPath.c_str());
 | |
| 
 | |
|    vertexFile.open(QIODevice::ReadOnly | QIODevice::Text);
 | |
|    fragmentFile.open(QIODevice::ReadOnly | QIODevice::Text);
 | |
| 
 | |
|    if (!vertexFile.isOpen())
 | |
|    {
 | |
|       logger_->error("Could not load vertex shader: {}", vertexPath);
 | |
|       return false;
 | |
|    }
 | |
| 
 | |
|    if (!fragmentFile.isOpen())
 | |
|    {
 | |
|       logger_->error("Could not load fragment shader: {}", fragmentPath);
 | |
|       return false;
 | |
|    }
 | |
| 
 | |
|    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();
 | |
| 
 | |
|    // Create a vertex shader
 | |
|    GLuint vertexShader = gl.glCreateShader(GL_VERTEX_SHADER);
 | |
| 
 | |
|    // Attach the shader source code and compile the shader
 | |
|    gl.glShaderSource(vertexShader, 1, &vertexShaderSourceC, NULL);
 | |
|    gl.glCompileShader(vertexShader);
 | |
| 
 | |
|    // Check for errors
 | |
|    gl.glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &glSuccess);
 | |
|    gl.glGetShaderInfoLog(vertexShader, kInfoLogBufSize, &logLength, infoLog);
 | |
|    if (!glSuccess)
 | |
|    {
 | |
|       logger_->error("Vertex shader compilation failed: {}", infoLog);
 | |
|       success = false;
 | |
|    }
 | |
|    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)
 | |
|    {
 | |
|       gl.glAttachShader(p->id_, vertexShader);
 | |
|       gl.glAttachShader(p->id_, fragmentShader);
 | |
|       gl.glLinkProgram(p->id_);
 | |
| 
 | |
|       // Check for errors
 | |
|       gl.glGetProgramiv(p->id_, GL_LINK_STATUS, &glSuccess);
 | |
|       gl.glGetProgramInfoLog(p->id_, kInfoLogBufSize, &logLength, infoLog);
 | |
|       if (!glSuccess)
 | |
|       {
 | |
|          logger_->error("Shader program link failed: {}", infoLog);
 | |
|          success = false;
 | |
|       }
 | |
|       else if (logLength > 0)
 | |
|       {
 | |
|          logger_->error("Shader program linked with warnings: {}", infoLog);
 | |
|       }
 | |
|    }
 | |
| 
 | |
|    // Delete shaders
 | |
|    gl.glDeleteShader(vertexShader);
 | |
|    gl.glDeleteShader(fragmentShader);
 | |
| 
 | |
|    return success;
 | |
| }
 | |
| 
 | |
| void ShaderProgram::Use() const
 | |
| {
 | |
|    p->gl_.glUseProgram(p->id_);
 | |
| }
 | |
| 
 | |
| } // namespace gl
 | |
| } // namespace qt
 | |
| } // namespace scwx
 | 
