首页 > 代码库 > OpenGL中shader使用

OpenGL中shader使用


       学了接近一个月的OpenGL,最终要排上用场了...好吧,就从学到的shader(着色器)开刀吧。

       先简单的介绍shader,shader事实上是显卡的功能,就是利用显卡的GPU去做图像处理的工作,而不是CPU,这样能够在一些复杂的大程序中释放CPU空间而提高效率。这篇文章仅仅是简单的介绍shader的使用,并没有介绍着色语言的语法结构等方面内容。后面等自己研究好了继续更新。

       使用shader,一般要经过一下几个步骤:

1、创建shader,这里会使用到glew的拓展库,应该包括glew.h和glew32.lib。利用一下函数创建:

GLhandleARB frag_shader;//创建fragment Shader//--------------------------------------------------------------------// GLuint glCreateShader(GLenum shaderType);  // 參数:  // ·shaderType – GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.  //--------------------------------------------------------------------frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);


2、向shader中导入着色程序,利用一下函数:

//---------------------------------------------------------------------------------------------------------------------//void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);  //參数:  //·shader – the handler to the shader.  //·numOfStrings – the number of strings in the array.  //·strings – the array of strings.  //·lenOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated. //----------------------------------------------------------------------------------------------------------------------glShaderSourceARB(frag_shader,1,(const char**)&inShader,NULL);

3、编译shader,就是将着色程序编译成shader能够识别的程序,以便使用:

//---------------------------------------------------------//void glCompileShader(GLuint shader);  //參数:  //.shader – the handler to the shader.  //----------------------------------------------------------glCompileShaderARB(frag_shader);

4、查询shader的状态,shader并不能向C/C++编译器那样能够print信息出来以參考,可是能够通过logInfo来看:

glGetObjectParameterivARB(frag_shader,GL_OBJECT_COMPILE_STATUS_ARB,&result);if(!result){	char str[4096] = {0};	//------------------------------------------------------------------------------------	//将调试信息放入infoLog中	//void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);	//void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);	//參数:	//·object – the handler to the object. Either a shader or a program	//·maxLen – The maximum number of chars to retrieve from the InfoLog.	//·len – returns the actual length of the retrieved InfoLog.	//·log – The log itself.	//------------------------------------------------------------------------------	glGetInfoLogARB(frag_shader,sizeof(str),NULL,str);	glDeleteObjectARB(frag_shader);	return ;}

5、连接shader,前面仅仅是把着色程序编译OK,如今要给创建好的shader使用:

shader = link(1,frag_shader);

6、link()函数是我自己写的,以下是link函数的代码:

GLhandleARB CShader::link(int shader_count,...){	//创建一个程序	GLhandleARB program = glCreateProgramObjectARB();	GLhandleARB shaderT = NULL;	va_list marker;	//初始化	va_start(marker,shader_count);	for(int i = 0; i< shader_count; i++)	{		shaderT = va_arg(marker,GLhandleARB);		//------------------------------------------------------------		//void glAttachShader(GLuint program, GLuint shader);  		//參数:  		//	·program – the handler to the program.  		//	·shader – the handler to the shader you want to attach.  		//-------------------------------------------------------------		glAttachObjectARB(program,shaderT);	}	va_end(marker);	//连接程序	glLinkProgramARB(program);	int result = 0;	glGetObjectParameterivARB(program,GL_OBJECT_LINK_STATUS_ARB,&result);	if(!result)	{		char str[4096] = {0};		glGetInfoLogARB(program,sizeof(str),NULL,str);		glDeleteObjectARB(program);		return NULL;	}	return program;}

事实上这个函数能够将多个着色程序给一个shader使用。

7、后面就是怎么使用Shader了,使用glUseProgram(program)和glUseProgram(NULL)要使用和卸载shader,

     还有能够从C++代码中传递给着色程序的參数。

8、还有就是怎么把着色程序导入到shader中,这里事实上是一个纯读取文档的过程,并不难。

这里给出整个shader的程序:

CShader.h

#pragma once #ifndef GL_ARB_shader_objectstypedef GLhandleARBtypedef GLcharARB#endifclass CShader{public:	CShader(void);public:	~CShader(void);public:	//初始化shader	void init(const char* inShader);	//绑定纹理	void bind();	//撤销纹理	void unBind();	bool setParameter(char* keyword, GLfloat fv);	bool setParameter(char* keyword, GLuint texID);	char* loadShaderTex(const char* fileName);private:	GLhandleARB link(int shader_count,...);public:	GLhandleARB shader;};


CShader.cpp

#include "stdafx.h"#include <gl/glew.h>#include "CShader.h"#include <stdlib.h>#include <stdarg.h>#pragma comment(lib,"glew32.lib")CShader::CShader(void){}CShader::~CShader(void){}void CShader::init(const char* inShader){	GLhandleARB frag_shader;	//创建fragment Shader	//--------------------------------------------------------------------	// GLuint glCreateShader(GLenum shaderType);  	// 參数:  	// ·shaderType – GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.  	//--------------------------------------------------------------------	frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);	//---------------------------------------------------------------------------------------------------------------------	//void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);  	//參数:  	//	·shader – the handler to the shader.  	//	·numOfStrings – the number of strings in the array.  	//	·strings – the array of strings.  	//	·lenOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated. 	//----------------------------------------------------------------------------------------------------------------------	glShaderSourceARB(frag_shader,1,(const char**)&inShader,NULL);		//---------------------------------------------------------	//void glCompileShader(GLuint shader);  	//參数:  	//	.shader – the handler to the shader.  	//----------------------------------------------------------	glCompileShaderARB(frag_shader);	int result = 0;	//查询状态	glGetObjectParameterivARB(frag_shader,GL_OBJECT_COMPILE_STATUS_ARB,&result);	if(!result)	{		char str[4096] = {0};		//------------------------------------------------------------------------------------		//将调试信息放入infoLog中		//void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);		//void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);		//參数:		//	·object – the handler to the object. Either a shader or a program		//	·maxLen – The maximum number of chars to retrieve from the InfoLog.		//	·len – returns the actual length of the retrieved InfoLog.		//	·log – The log itself.		//------------------------------------------------------------------------------		glGetInfoLogARB(frag_shader,sizeof(str),NULL,str);		glDeleteObjectARB(frag_shader);		return ;	}	//Compile shader	shader = link(1,frag_shader);	glDeleteObjectARB(frag_shader);}GLhandleARB CShader::link(int shader_count,...){	//创建一个程序	GLhandleARB program = glCreateProgramObjectARB();	GLhandleARB shaderT = NULL;	va_list marker;	//初始化	va_start(marker,shader_count);	for(int i = 0; i< shader_count; i++)	{		shaderT = va_arg(marker,GLhandleARB);		//------------------------------------------------------------		//void glAttachShader(GLuint program, GLuint shader);  		//參数:  		//	·program – the handler to the program.  		//	·shader – the handler to the shader you want to attach.  		//-------------------------------------------------------------		glAttachObjectARB(program,shaderT);	}	va_end(marker);	//连接程序	glLinkProgramARB(program);	int result = 0;	glGetObjectParameterivARB(program,GL_OBJECT_LINK_STATUS_ARB,&result);	if(!result)	{		char str[4096] = {0};		glGetInfoLogARB(program,sizeof(str),NULL,str);		glDeleteObjectARB(program);		return NULL;	}	return program;}void CShader::bind(){	//if shader link successfully,then use it	glUseProgram( shader);	}bool CShader::setParameter(char* keyword,GLfloat fv){	//find out where the flicker constant lives	GLint ret = glGetUniformLocation(shader, keyword);	if(ret != -1)	{		glUniform1f(ret,fv);		return true;	}	return false;}bool CShader::setParameter(char* keyword,GLuint texID){	//Find out where the flicker constant lives	GLint ret = glGetUniformLocation(shader,keyword);	if(ret != -1)	{		glUniform1iARB(ret, texID);		return true;	}	return false;}void CShader::unBind(){	glUseProgramObjectARB(NULL);}char* CShader::loadShaderTex(const char* fileName){	char* shaderText = NULL;	GLint shaderLength = 0;	FILE *fp;	fp = fopen(fileName,"r");	if(fp != NULL)	{		//get the char length 		while(fgetc(fp) != EOF)		{			shaderLength++;		}		rewind(fp);		shaderText = (GLchar*)malloc(shaderLength);		if(shaderText != NULL)		{			fread(shaderText,1,shaderLength,fp);		}		shaderText[shaderLength] = ‘\0‘;		fclose(fp);	}	return shaderText;}

上面有把shader仅仅用写成接口,并没有给出着色程序的代码,你须要将着色程序保存为文本文档,然后用loadShaderText()读取程序,然后就是init(),利用setParameter()设置好參数就能够了。




 

 

OpenGL中shader使用