OpenGL中shader使用

来源:互联网 发布:杭州二更网络二次融资 编辑:程序博客网 时间:2024/04/29 05:41


       学了接近一个月的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://初始化shadervoid 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 shadershader = 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 itglUseProgram( shader);}bool CShader::setParameter(char* keyword,GLfloat fv){//find out where the flicker constant livesGLint 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 livesGLint 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()设置好参数就可以了。




 

 

原创粉丝点击