我们为什么要选择从文件中读取GLSL源代码
-
当程序变得复杂时,再将GLSL着色器源代码内联存储在字符串中就不合适了。
我们将两个着色器的源代码从主文件中剪切放在对应的文件vertShader.glsl和fragShader.glsl中
代码实现
1.分别在两个.glsl文件中写入对应的代码
//vertShader.glsl文件
#version 430
void main(void)
{
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
}
//fragShader.glsl文件
#version 430
out vec4 color;
void main(void)
{
if(gl_FragCoord.x < 255)
color = vec4(1.0, 0.0, 0.0, 1.0);
else color = vec4(0.0, 0.0, 1.0, 1.0);
}
2.新增函数ReadShaderSource读取文件
//新增两个头文件
#include <fstream>
#include <string>
std::string ReadShaderSource(const char* filePath)
{
std::string content;
std::ifstream fileStream(filePath, std::ios::in);
std::string line = "";
while (!fileStream.eof())
{
getline(fileStream, line);
content.append(line + '\n');
}
fileStream.close();
return content;
}
3.在CreateShaderProgram函数中对文件进行读取
unsigned int CreateShaderProgram()
{
std::string vertShaderStr = readShaderSource("./res/shaders/vertShader.glsl");
std::string fragShaderStr = readShaderSource("./res/shaders/fragShader.glsl");
const char* vertShaderSrc = vertShaderStr.c_str();
const char* fragShaderSrc = fragShaderStr.c_str();
//捕获编译着色器时的错误
int vertComplied;
int fragComplied;
int linked;
//创建顶点着色器和片段着色器
unsigned int vShader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vShader, 1, &vertShaderSrc, NULL);
glShaderSource(fShader, 1, &fragShaderSrc, NULL);
}
4..cpp完整代码
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <fstream>
#include <string>
#define numVAOs 1
unsigned int renderingProgram;
unsigned int vao[numVAOs];//顶点数组,必须要有
unsigned int CreateShaderProgram();
//读取文件中的GLSL的源代码
std::string ReadShaderSource(const char* filePath)
{
std::string content;
std::ifstream fileStream(filePath, std::ios::in);
std::string line = "";
while (!fileStream.eof())
{
getline(fileStream, line);
content.append(line + '\n');
}
fileStream.close();
return content;
}
//捕获GLSL代码编译失败信息函数
void PrintShaderLog(unsigned int shader)
{
int len = 0;
int chWrittn = 0;
char* log;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &len);
if (len > 0)
{
log = (char*)malloc(len);
glGetShaderInfoLog(shader, len, &chWrittn, log);
std::cout << "Shader Info Log: " << log << std::endl;
free(log);
}
}
//捕获GLSL链接失败信息函数
void PrintProgramLog(int prog)
{
int len = 0;
int chWrittn = 0;
char* log;
glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &len);
if (len > 0)
{
log = (char*)malloc(len);
glGetProgramInfoLog(prog, len, &chWrittn, log);
std::cout << "Program Info Log: " << std::endl;
free(log);
}
}
//检查OpenGL错误函数
bool CheckOpenGLError()
{
bool foundError = false;
int glErr = glGetError();
while (glErr != GL_NO_ERROR)
{
std::cout << "glError: " << glErr << std::endl;
foundError = true;
glErr = glGetError();
}
return foundError;
}
void Init(GLFWwindow* window)
{
renderingProgram = CreateShaderProgram();
glGenVertexArrays(numVAOs, vao);//生成顶点数组对象名称,用numVAOs存储
glBindVertexArray(vao[0]);//绑定vao[0]
}
void Display(GLFWwindow* window, double currentTime)
{
glUseProgram(renderingProgram);//激活程序对象
glPointSize(430.0f);//设置点的大小
glDrawArrays(GL_POINTS, 0, 1);//绘制方式,绘制一个点
}
unsigned int CreateShaderProgram()
{
//从文件读取GLSL代码
std::string vertShaderStr = ReadShaderSource("./res/shaders/vertShader.glsl");
std::string fragShaderStr = ReadShaderSource("./res/shaders/fragShader.glsl");
const char* vertShaderSrc = vertShaderStr.c_str();
const char* fragShaderSrc = fragShaderStr.c_str();
//捕获编译着色器时的错误
int vertComplied;
int fragComplied;
int linked;
//创建顶点着色器和片段着色器
unsigned int vShader = glCreateShader(GL_VERTEX_SHADER);
unsigned int fShader = glCreateShader(GL_FRAGMENT_SHADER);
//替换vShader,fShader中的源代码,使用自定义的编码
glShaderSource(vShader, 1, &vertShaderSrc, NULL);
glShaderSource(fShader, 1, &fragShaderSrc, NULL);
//对着色器对象进行编译
glCompileShader(vShader);
CheckOpenGLError();
glGetShaderiv(vShader, GL_COMPILE_STATUS, &vertComplied);
if (vertComplied != 1)
{
std::cout << "vertex compilation faild" << std::endl;
PrintShaderLog(vShader);
}
glCompileShader(fShader);
CheckOpenGLError();
glGetShaderiv(fShader, GL_COMPILE_STATUS, &fragComplied);
if (fragComplied != 1)
{
std::cout << "fragment compilation faild" << std::endl;
PrintShaderLog(fShader);
}
//创建一个Program链接着色器对象,执行的就是链接有着色器对象的程序
unsigned int vfProgram = glCreateProgram();
//把之前编译的着色器附加到程序对象上,然后用glLinkProgram链接它们
glAttachShader(vfProgram, vShader);
glAttachShader(vfProgram, fShader);
glLinkProgram(vfProgram);
CheckOpenGLError();
glGetProgramiv(vfProgram, GL_LINK_STATUS, &linked);
if (linked != 1)
{
std::cout << "linking faild" << std::endl;
PrintProgramLog(vfProgram);
}
//返回连接好的着色器程序
return vfProgram;
}
int main()
{
if (!glfwInit())
exit(EXIT_FAILURE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
GLFWwindow* window = glfwCreateWindow(600, 600, "Hello, world", nullptr, nullptr);
glfwMakeContextCurrent(window);
if (glewInit() != GLEW_OK)
exit(EXIT_FAILURE);
glfwSwapInterval(1);
Init(window);
while (!glfwWindowShouldClose(window))
{
Display(window, glfwGetTime());
glfwSwapBuffers(window);
glfwPollEvents();
}
glfwDestroyWindow(window);
glfwTerminate();
exit(EXIT_SUCCESS);
}