您的位置:首页 > 运维架构

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

2017-10-19 00:56 197 查看
之前都是通过读取着色器字符串来创建着色器,这样耦合程度很高,并且生成、链接着色器程序也需要写很繁杂的过程。现在我编写一个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::if
4000
stream::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();
...
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: