OpenGL自制3D游戏引擎入门VI
Shader II 创建自己的着色器类
一、从文件读取
- 我们从C++文件流读取着色器内容,存储到几个String对象中
Shader.h代码如下
#pragma once
#include <string>
using namespace std;
class Shader
{
public:
Shader(const char* vertexPath, const char* fragmentPath);
//~Shader();
string vertexString;
string fragmentString;
const char* vertexSource;
const char* fragmentSource;
};
Shader.cpp代码如下
#include <iostream>
#include <fstream>
#include <sstream>
#include "Shader.h"
using namespace std;
Shader::Shader(const char* vertexPath, const char* fragmentPath)
{
ifstream vertexFile;
ifstream fragmentFile;
stringstream vertexSStream;
stringstream frangmentSStream;
vertexFile.open(vertexPath);
fragmentFile.open(fragmentPath);
vertexFile.exceptions(ifstream::failbit || ifstream::badbit);
fragmentFile.exceptions(ifstream::failbit || ifstream::badbit);
try
{
if (!vertexFile.is_open() || !fragmentFile.is_open())
{
throw exception("open File error");
}
vertexSStream << vertexFile.rdbuf();
frangmentSStream << fragmentFile.rdbuf();
vertexString = vertexSStream.str();
fragmentString = frangmentSStream.str();
vertexSource = vertexString.c_str();
fragmentSource = fragmentString.c_str();
printf(vertexSource);
printf("\n");
printf(fragmentSource);
}
catch (const exception& e)
{
printf(e.what());
}
}
main函数中声明着色器类并修改对应文件
Shader* testShader = new Shader("vertexSource.txt", "fragmentSource.txt");
unsigned int vertexShader;
vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertexShader, 1, &testShader->vertexSource, NULL);
glCompileShader(vertexShader);
unsigned int fragmentShader;
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragmentShader, 1, &testShader->fragmentSource, NULL);
glCompileShader(fragmentShader);
二、编译和链接着色器
Shader.cpp
#include <iostream> #include <fstream> #include <sstream> #include <GL/glew.h> #include <GLFW/glfw3.h> #include "Shader.h" using namespace std; Shader::Shader(const char* vertexPath, const char* fragmentPath) { ifstream vertexFile; ifstream fragmentFile; stringstream vertexSStream; stringstream frangmentSStream; vertexFile.open(vertexPath); fragmentFile.open(fragmentPath); vertexFile.exceptions(ifstream::failbit || ifstream::badbit); fragmentFile.exceptions(ifstream::failbit || ifstream::badbit); try { if (!vertexFile.is_open() || !fragmentFile.is_open()) { throw exception("open File error"); } vertexSStream << vertexFile.rdbuf(); frangmentSStream << fragmentFile.rdbuf(); vertexString = vertexSStream.str(); fragmentString = frangmentSStream.str(); vertexSource = vertexString.c_str(); fragmentSource = fragmentString.c_str(); unsigned int vertex, fragment; vertex = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertex, 1, &vertexSource, NULL); glCompileShader(vertex); fragment = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragment, 1, &fragmentSource, NULL); glCompileShader(fragment); ID = glCreateProgram(); glAttachShader(ID, vertex); glAttachShader(ID, fragment); glLinkProgram(ID); glDeleteShader(vertex); glDeleteShader(fragment); } catch (const exception& e) { printf(e.what()); } } void Shader::use() { glUseProgram(ID); }
Shader.h
#pragma once #include <string> using namespace std; class Shader { public: Shader(const char* vertexPath, const char* fragmentPath); //~Shader(); string vertexString; string fragmentString; const char* vertexSource; const char* fragmentSource; unsigned int ID; // shaderProgram ID void use(); };
main函数中对应的部分就可以删掉啦
三、收集错误信息
添加一个私有函数checkCompileError
void Shader::checkCompileError(unsigned int ID,string type) { int success; char infoLog[512]; if (type != "PROGRAM") { glGetShaderiv(ID, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(ID, 512, NULL, infoLog);; cout << "Shader compile error:" << infoLog << endl; } } else { glGetShaderiv(ID,GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(ID, 512, NULL, infoLog); cout << "Program compile error:" << infoLog << endl; } } }
放在glCompileShader、glLinkProgram函数之后收集错误信息
(下接 OpenGL入门VII)
OpenGL自制3D游戏引擎入门VI
https://baifabaiquan.cn/2021/03/25/OpenGL入门VI/