编写一个Shader类
为了方便日后复习文章都是以笔记形式记录。
由于每次创建shader都要经过繁琐的修改字符串、创建、合并这样的重复工作,因此将其抽象为一个类对象以方便代码的重复利用。
Shader.h
#ifndef SHADER_H
#define SHADER_H
#include <GL/glew.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
class Shader {
public:
Shader(const char* vertexPath, const char* fragmentPath);
void use();
void setBool(const std::string& name, bool value) const;
void setInt(const std::string& name, int value) const;
void setFloat(const std::string& name, float value) const;
private:
unsigned int m_ID;
};
#endif
Shader.cpp
#include "Shader.h"
Shader::Shader(const char* vertexPath, const char* fragmentPath) {
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
vShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
vShaderFile.open(vertexPath); //打开文件
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
vShaderStream << vShaderFile.rdbuf(); //将文件缓冲区的内容读入字符串流中
fShaderStream << fShaderFile.rdbuf();
vertexCode = vShaderStream.str(); //将流转换为字符串
fragmentCode = fShaderStream.str();
}
catch(std::ifstream::failure e) {
std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
}
const char* vShaderCode = vertexCode.c_str(); //将字符串转换c的字符指针
const char* fShaderCode = fragmentCode.c_str();
int success;
char infoLog[512];
//vertex shader
unsigned int vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, nullptr);
glCompileShader(vertex);
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success); //编译检错
if (!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
};
//fragment shader
unsigned int fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, nullptr);
glCompileShader(fragment);
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success); //编译检错
if (!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
};
//合并着色器成为着色器程序
Shader::m_ID = glCreateProgram();
glAttachShader(m_ID, vertex);
glAttachShader(m_ID, fragment);
glLinkProgram(m_ID);
//检查错误
glGetProgramiv(m_ID, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(m_ID, 512, NULL, infoLog);
std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
}
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::use() {
glUseProgram(m_ID);
}
void Shader::setBool(const std::string& name, bool value) const {
glUniform1i(glGetUniformLocation(m_ID, name.c_str()), value);
}
void Shader::setInt(const std::string& name, int value) const {
glUniform1i(glGetUniformLocation(m_ID, name.c_str()), value);
}
void Shader::setFloat(const std::string& name, float value) const {
glUniform1f(glGetUniformLocation(m_ID, name.c_str()), value);
}