OpenGL编译着色器程序

编译着色器程序

由于着色器是在GPU中执行,因此想要使用写好的着色器,必须使用特定的编译器来解析数据,编译代码,生成可执行程序。在OpenGL调用相关的API就可以实现。

流程如下:

 

相关API如下

GLuint glCreateShader(GLenum type)

功  能:创建着色器对象

返回值:一个非0整数,如果是0则说明发送了错误

参  数:顶点着色器对应GL_VERTEX_SHADER,其他各着色阶段对应不同的参数

 

void glShaderSource(GLuint shader, GLsizei count, const GLchar* *string, const GLint *length)

功  能:将着色器源码关联到着色器对象

返回值:void

参  数:shader 着色器对象

count  个数

string  着色器源码

length  NULL

 

void glCompileShader(GLuint shader)

功  能:编译着色器

返回值:void

参  数:shader 着色器对象

 

void glGetShaderiv(GLuint shader, GLenum pname, GLint *params)

功  能:错误检查

返回值:void

参  数:shader 着色器对象

pname  GL_COMPILE_STATUS

params 输出参数,判断是否编译错误,如果是个非零值则编译成功。

 

void glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)

功  能:打印编译错误信息

返回值:void

参  数:shader 着色器对象

bufSize  buffer的大小

length   NULL

infoLog  返回的错误信息

 

GLuint glCreateProgram(void)

功  能:创建着色器程序

返回值:返回一个着色器程序ID

参  数:void


 

void glAttachShader(GLuint program, GLuint shader)

功  能:把着色器对象附件到着色器程序

返回值:void

参  数:program  着色器程序

shader   着色器对象

 

void glLinkProgram(GLuint program)

功  能:链接到着色器程序

返回值:void

参  数:program  着色器程序

 

void glGetProgramiv(GLuint program, GLenum pname, GLint *params)

功  能:着色器程序错误检查

返回值:void

参  数:program  着色器程序ID

pname   GL_LINK_STATUS

params   输出参数,如果是个非零值则成功。

 

void glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog)功  能:打印错误信息

返回值:void

参  数:shader着色器对象

bufSize  buffer的大小

length   NULL

infoLog  输出参数,返回的错误信息

 

 实现:

 

/加载着色器程序
/*
*  id  返回参数,返回着色器ID
*  vertexPath       顶点着色器
*  fragmentPath     片元着色器
*  geometryPath     几何着色器
*/
void QOPenWidget::CompileShader(unsigned int *id, const char* vertexPath, const char* fragmentPath, const char* geometryPath)
{
	std::string vertexCode;
	std::string fragmentCode;
	std::string geometryCode;
	std::ifstream vShaderFile;
	std::ifstream fShaderFile;
	std::ifstream gShaderFile;


	// 打开文件
	vShaderFile.open(vertexPath);
	fShaderFile.open(fragmentPath);
	std::stringstream vShaderStream, fShaderStream;
	// 读取文件的缓冲内容到数据流中
	vShaderStream << vShaderFile.rdbuf();
	fShaderStream << fShaderFile.rdbuf();
	// 关闭文件处理器
	vShaderFile.close();
	fShaderFile.close();
	// 转换数据流到string
	vertexCode = vShaderStream.str();
	fragmentCode = fShaderStream.str();

	if (geometryPath != NULL)
	{
		gShaderFile.open(geometryPath);
		std::stringstream gShaderStream;
		gShaderStream << gShaderFile.rdbuf();
		gShaderFile.close();
		geometryCode = gShaderStream.str();
	}

	const char* vShaderCode = vertexCode.c_str();
	const char* fShaderCode = fragmentCode.c_str();

	// 2. 编译着色器
	unsigned int vertex, fragment;
	int success;
	char infoLog[512];

	// 顶点着色器
	vertex = glCreateShader(GL_VERTEX_SHADER);
	glShaderSource(vertex, 1, &vShaderCode, NULL);
	//编译着色器
	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 = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragment, 1, &fShaderCode, NULL);
	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;
	}

	//几何着色器
	unsigned int geometry;
	if (geometryPath != nullptr)
	{
		const char * gShaderCode = geometryCode.c_str();
		geometry = glCreateShader(GL_GEOMETRY_SHADER);
		glShaderSource(geometry, 1, &gShaderCode, NULL);
		glCompileShader(geometry);
	}


	// 着色器程序
	*id = glCreateProgram();
	glAttachShader(*id, vertex);
	glAttachShader(*id, fragment);
	if (geometryPath != nullptr)
		glAttachShader(*id, geometry);
	glLinkProgram(*id);
	//检测错误
	glGetProgramiv(*id, GL_LINK_STATUS, &success);
	if (!success)
	{
		//获取错误信息
		glGetProgramInfoLog(ID, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}

	// 删除着色器,它们已经链接到我们的程序中了,已经不再需要了
	glDeleteShader(vertex);
	glDeleteShader(fragment);
	if (geometryPath != nullptr)
		glDeleteShader(geometry);
}

参见:《OpenGL编程指南》第八版第2

      LearnOpenGL教程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值