先简单的介绍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#include "CShader.h"#include #include #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()设置好參数就能够了。