编译与运行GLSL的代码与普通的代码不一样,GLSL的编译发生在C++运行时
GLSL的代码并没有在CPU中运行而是在GPU中运行,因此操作系统并不能捕获OpenGL运行时的错误
以上两点让调试变得很困难,我们常常很难判断着色器的运行是否失败,以及为什么失败。
PrintShaderLog():当GLSL代码编译失败时,显示OpenGL日志内容。
PrintProgramLog():当GLSL链接失败时,显示OpenGL日志内容。
CheckOpenGLError():检查OpenGL错误标志,即是否发生OpenGL错误。(既可以用于检查GLSL代码编译错误,又可以见检查OpenGL运行时的错误,强烈推荐使用。)
void glGetShaderiv(GLuint shader,GLenum pname,GLint *params);
指定要查询的着色器对象,直接放入需要检查的着色器即可。
指定着色器对象的参数。 可接受的符号名称为
shader_type:着色器类型 用来判断并返回着色器类型,若是顶点着色器返回GL_VERTEX_SHADER,若为片元着色器返回GL_FRAGMENT_SHADER.
detele status:删除状态 判断着色器是否被删除,是返回GL_TRUE,否则返回GL_FALSE,
compile_status:编译状态 用于检测编译是否成功,成功为GL_TRUE,否则为GL_FALSE.
information log length: log是日志的意思,所以是返回着色器的信息日志的长度 用于返回着色器的信息日志的长度,包括空终止字符(即存储信息日志所需的字符缓冲区的大小)。 如果着色器没有信息日志,则返回值0。
SHADER_SOURCE_LENGTH:着色器源码长度 返回着色器源码长度,不存在则返回0;
函数将返回的结果存储在输入的第三个参数中,因为这个函数得到的结果有很多种,所以要单独放在第三个参数当中,所以是void glGetShaderiv而不是GLuint。
void glGetShaderInfoLog(GLuint shader, GLsizei maxLength, GLsizei *length, GLchar *infoLog);
指定需要查询日志信息的 shader 对象。
指定储存日志信息的字符缓存大小。
返回 infoLog(不包括空结尾符)的字符串长度。
指定用于返回日志信息的字符数组。
glGetShaderInfoLog 返回指定 shader 对象的日志信息。一个shader 对象的日志信息会在 shader 编译是修改。返回的字符串将以空字符结尾。
glGetShaderInfoLog 返回 infoLog 的maxLength最大长度的字符的能填入的日志信息。返回的是实际的字符需要的数量,不包含空结尾符,而是指定 length 的长度。如果不需要返回字符串的长度,那么 length 传入 NULL。获取需要日志信息缓存的大小,可通过 只用 GL_INFO_LOG_LENGTH 来调用 glGetShader 。
一个 shader 对象的日志信息可能包含诊断信息,警告信息,和其他关于编译操作的信息。当一个 shader 对象被创建时,它的日志信息将会被设置为一个 0 长度的字符串。
一个 shader 对象的日志信息是 OpenGL 实现的编译相关过程的主要机制。因此,日志信息对于应用程序开发者在开发过程是很有帮助的,即使编译是成功的。
如果 shader 参数不是 OpenGL 生成的,那么生成 GL_INVALID_VALUE 错误。
如果 shader 参数不是一个 shader 对象,那么省 GL_INVALID_OPERATION 错误。
如果 maxLength 小于0,那么生成 GL_INVALID_VALUE 错误。
添加三个函数
//添加三个函数
//捕获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;
}
修改unsigned int CreateShaderProgram()函数进行测试
//修改unsigned int CreateShaderProgram()函数进行测试
unsigned int CreateShaderProgram()
{
const char* vShaderSource =
"#version 430 \n"
"void main(void) \n"
"{gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
//gl_Position内置的坐标变量,前三个参数对应坐标的(x,y,z),第四个参数为矩阵变换时会用到的值,变换矩阵是4x4,所有我们 //还需要添加一位才能进行矩阵的乘法
const char* fShaderSource =
"#version 430 \n"
"out vec4 color; \n"
"void main(void) \n"
"{ if(gl_FragCoord.x < 255) color = vec4(1.0, 0.0, 1.0); else color = vec4(0.0, 0.0, 1.0, 1.0);}";
+//捕获编译着色器时的错误
+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, &vShaderSource, NULL);
glShaderSource(fShader, 1, &fShaderSource, 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;
}
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#define numVAOs 1
unsigned int renderingProgram;
unsigned int vao[numVAOs];//顶点数组,必须要有
unsigned int CreateShaderProgram();
//捕获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()
{
const char* vShaderSource =
"#version 430 \n"
"void main(void) \n"
"{gl_Position = vec4(0.0, 0.0, 0.0, 1.0);}";
//gl_Position内置的坐标变量,前三个参数对应坐标的(x,y,z),第四个参数为矩阵变换时会用到的值,变换矩阵是4x4,所有我们 //还需要添加一位才能进行矩阵的乘法
const char* fShaderSource =
"#version 430 \n"
"out vec4 color; \n"
"void main(void) \n"
"{ if(gl_FragCoord.x < 255) color = vec4(1.0, 0.0, 1.0); else color = vec4(0.0, 0.0, 1.0, 1.0);}";
//捕获编译着色器时的错误
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, &vShaderSource, NULL);
glShaderSource(fShader, 1, &fShaderSource, 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);
}
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务