OpenGL_11:封装一个自己的着色器类

14 篇文章 0 订阅

之前都是通过读取着色器字符串来创建着色器,这样耦合程度很高,并且生成、链接着色器程序也需要写很繁杂的过程。现在我编写一个Shader类来读取着色器文本文件,并且封装那些繁杂的步骤。


Shader头文件:

#ifndef INC_10_SHADER_LOADER_SHADER_H
#define INC_10_SHADER_LOADER_SHADER_H

#include <glad/glad.h>
#include <string>
#include <fstream>      
#include <sstream>      
#include <iostream>


class Shader {
private:
    unsigned int id;

public:
    Shader(const char* vertexPath, const char* fragmentShader);
    void use();
    void setBool(const char* name, bool value) const;
    void setInt(const char* name, int value) const;
    void setFloat(const char* name, float value) const;

private:
    void checkCompileErrors(unsigned int shader, std::string type);
};


#endif //INC_10_SHADER_LOADER_SHADER_H

Shader.cpp:

#include "Shader.h"

Shader::Shader(const char *vertexShaderPath, const char *fragmentShaderPath) {
    
    std::string vertexCode;
    std::string fragmentCode;
    std::ifstream vShaderFile;
    std::ifstream fShaderFile;
    //保证ifstream对象可以抛出异常
    vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
    try {
        //打开文件
        vShaderFile.open(vertexShaderPath);
        fShaderFile.open(fragmentShaderPath);
        //读取文件缓冲内容到数据流里
        std::stringstream vShaderStream, fShaderStream;
        vShaderStream << vShaderFile.rdbuf();
        fShaderStream << fShaderFile.rdbuf();
        //关闭文件处理器
        vShaderFile.close();
        fShaderFile.close();
        //把数据流转换成string
        vertexCode = vShaderStream.str();
        fragmentCode = fShaderStream.str();
    } catch (std::ifstream::failure e){
        std::cout << "Failed to read shaderFile" << std::endl;
    }
    //再转换成字符数组
    const char* vShaderSource = vertexCode.c_str();
    const char* fShaderSource = fragmentCode.c_str();

    //接着就可以开始编译和连接着色器了
    unsigned int vertexShader, fragmentShader;

    //编译顶点着色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vShaderSource, NULL);
    glCompileShader(vertexShader);
    checkCompileErrors(vertexShader, "VERTEX");

    //编译片段着色器
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fShaderSource, NULL);
    glCompileShader(fragmentShader);
    checkCompileErrors(vertexShader, "FRAGMENT");

    //链接着色器
    id = glCreateProgram();
    glAttachShader(id, vertexShader);
    glAttachShader(id, fragmentShader);
    glLinkProgram(id);
    checkCompileErrors(id, "PROGRAM");

    //当着色器链接到了程序中,就不再需要了
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);

}

//激活着色器
void Shader::use() {
    glUseProgram(this->id);
}

//设置uniform变量
void Shader::setBool(const char *name, bool value) const {
    glUniform1i(glGetUniformLocation(this->id, name), (int)value);
}
//设置uniform变量
void Shader::setInt(const char *name, int value) const {
    glUniform1i(glGetUniformLocation(this->id, name), value);
}
//设置uniform变量
void Shader::setFloat(const char *name, float value) const {
    glUniform1f(glGetUniformLocation(this->id, name), value);
}

//输出shader编译或program链接的错误信息
void Shader::checkCompileErrors(unsigned int shader, std::string type) {
    int success;
    char infoLog[512];
    if (type != "PROGRAM"){
        glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
        if (!success){
            glGetShaderInfoLog(shader, 512, NULL, infoLog);
            std::cout << "ERROR: Failed to compile shader of type:"<< type <<std::endl;
        }
    }
    else {
        glGetShaderiv(shader, GL_LINK_STATUS, &success);
        if (!success){
            glGetShaderInfoLog(shader, 512, NULL, infoLog);
            std::cout << "ERROR: Failed to link program of type:"<< type <<std::endl;
        }
    }
}

使用步骤:

    Shader *shader = new Shader("../../vertex.glsl", "../../fragment.glsl");
    在渲染循环中{
        ...
        shader->use();
        ...
    }


  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值