在OpenGL的shader編程中,最常用的可能就是程式對象了,GLSL的程式對象的建立、載入shader等步驟都是固定的,如果每次都寫同樣的代碼,覺得十分浪費時間,所以現在就將我在Shader學習過程中自己封裝的GLSLProgram類奉獻出來供大家參考:
標頭檔如下:
/* * GLSLProgram.h * * Created * Author: zhouxuguang */#ifndef GLSLPROGRAM_H_#define GLSLPROGRAM_H_#include "GLPrecompile.h"class GLSLProgram {public: GLSLProgram(); GLSLProgram(const char* pVertexSource, const char* pFragmentSource); ~GLSLProgram(); void InitWithShader(const char* pVertexSource, const char* pFragmentSource); //編譯和串連程式 void LinkProgram();//載入二進位shader程式void LoadProgramBinary( const char * fileName, GLenum format );//使用程式對象void Use();//使用固定管線void UseFixedFunction();//綁定屬性變數void BindAttribLocation (unsigned int index, const char *name); void BindFragDataLocation(unsigned int index , const char *name);//獲得屬性變數GLint GetAttributeLocation(const char* attrName);//獲得指定Uniform變數的位置GLint GetUniformLocation( const char* uniName);GLint GetUniformBlockIndex( const char* uniName);//設定屬性變數的值//void SetAttributeVariable( char *, int );void SetAttributeVariable( const char *, float );void SetAttributeVariable( const char *, float, float, float );void SetAttributeVariable( const char *, float[3] );//設定uniform變數的值void SetUniformVariable( const char *, int );void SetUniformVariable( const char *, float );void SetUniformVariable( const char *, float, float, float );void SetUniformVariable( const char *, float[3] );void SetUniformMatrix2f(const char* name,int count, bool transpose, const float *value);void SetUniformMatrix3f(const char* name,int count, bool transpose, const float *value);void SetUniformMatrix4f(const char* name,int count, bool transpose, const float *value);void GetActiveUniformBlockiv(const char* uniName, GLenum pname, GLint *params);void GetUniformIndices ( GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices);void GetActiveUniformsiv ( GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); //載入shader static GLuint LoadShader(GLenum shaderType, const char* pSource); static bool LoadShaderFile(const char* pShaderFile,std::string &shaderString);private:GLuint mProgram;//程式對象 GLuint mVertexShader; //頂點shader GLuint mFragmentShader; //片段shaderstd::map<const char *, int>mAttributeLocs;//attribute屬性變數的mapstd::map<const char *, int> mUniformLocs;//Uniform變數的map};#endif /* GLSLPROGRAM_H_ */
實現檔案如下:
/* * GLSLProgram.cpp * * Created on: * Author: zhouxuguang */#include "GLSLProgram.h"GLuint GLSLProgram::LoadShader(GLenum shaderType, const char* pSource) { GLuint shader = glCreateShader(shaderType); if (shader) { glShaderSource(shader, 1, &pSource, NULL); glCompileShader(shader); GLint compiled = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint infoLen = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen) { char* buf = (char*) malloc(infoLen); if (buf != NULL) { glGetShaderInfoLog(shader, infoLen, NULL, buf); //LOGE("Could not compile shader %d:\n%s\n",shaderType, buf); free(buf); } glDeleteShader(shader); shader = 0; } } } return shader;}bool GLSLProgram::LoadShaderFile(const char *pShaderFile,std::string &shaderString){ FILE *fpin = fopen( pShaderFile, "rb" ); if( fpin == NULL ) { return false; } fseek( fpin, 0, SEEK_END ); long length = (long)ftell( fpin ); char *buffer = new char[ length ]; rewind( fpin ); fread( buffer, length, 1, fpin ); fclose( fpin ); shaderString = buffer; delete []buffer; return true;}GLSLProgram::GLSLProgram():mVertexShader(0),mFragmentShader(0),mProgram(0){}GLSLProgram::GLSLProgram(const char* pVertexSource, const char* pFragmentSource){ InitWithShader(pVertexSource,pFragmentSource);}GLSLProgram::~GLSLProgram(){ if (mProgram) { glDetachShader(mProgram, mVertexShader); glDetachShader(mProgram, mFragmentShader); glDeleteShader(mVertexShader); mVertexShader = 0; glDeleteShader(mFragmentShader); mFragmentShader = 0; glDeleteProgram(mProgram); mProgram = 0; }}void GLSLProgram::InitWithShader(const char *pVertexSource, const char *pFragmentSource){ mVertexShader = GLSLProgram::LoadShader(GL_VERTEX_SHADER, pVertexSource); if (!mVertexShader) { return; } mFragmentShader = GLSLProgram::LoadShader(GL_FRAGMENT_SHADER, pFragmentSource); if (!mFragmentShader) { return; } mProgram = glCreateProgram();}void GLSLProgram::LinkProgram(){ if (mProgram) { glAttachShader(mProgram, mVertexShader); glAttachShader(mProgram, mFragmentShader); glLinkProgram(mProgram); GLint linkStatus = GL_FALSE; glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus); if (linkStatus != GL_TRUE) { GLint bufLength = 0; glGetProgramiv(mProgram, GL_INFO_LOG_LENGTH, &bufLength); if (bufLength) { char* buf = (char*) malloc(bufLength); if (buf) { glGetProgramInfoLog(mProgram, bufLength, NULL, buf); free(buf); } } glDeleteProgram(mProgram); mProgram = 0; } }}void GLSLProgram::LoadProgramBinary(const char * fileName, GLenum format){FILE *fpin = fopen( fileName, "rb" );if( fpin == NULL ){fprintf( stderr, "Cannot open input GLSL binary file '%s'\n", fileName );return;}fseek( fpin, 0, SEEK_END );GLint length = (GLint)ftell( fpin );GLubyte *buffer = new GLubyte[ length ];rewind( fpin );fread( buffer, length, 1, fpin );fclose( fpin );glProgramBinary( this->mProgram, format, buffer, length );delete [] buffer;GLint success;glGetProgramiv( this->mProgram, GL_LINK_STATUS, &success );if( !success ){fprintf( stderr, "Did not successfully load the GLSL binary file '%s'\n", fileName );return;}}void GLSLProgram::Use(){glUseProgram(mProgram);}void GLSLProgram::UseFixedFunction(){glUseProgram(0);}void GLSLProgram::BindAttribLocation (unsigned int index, const char *name){glBindAttribLocation(mProgram,(GLuint)index,(const GLchar*)name);}void GLSLProgram::BindFragDataLocation(unsigned int index, const char *name){ //只有案頭版本支援}GLint GLSLProgram::GetAttributeLocation(const char* attrName){std::map<const char *, int>::iterator iter = mAttributeLocs.find(attrName);if(iter == mAttributeLocs.end()){mAttributeLocs[attrName] = glGetAttribLocation(mProgram, attrName);}return mAttributeLocs[attrName];}GLint GLSLProgram::GetUniformLocation(const char* uniName){std::map<const char*, int>::iterator iter = mUniformLocs.find(uniName);if(iter == mUniformLocs.end()){mUniformLocs[uniName] = glGetUniformLocation(mProgram, uniName);}return mUniformLocs[uniName];}GLint GLSLProgram::GetUniformBlockIndex(const char* uniName){return glGetUniformBlockIndex(mProgram, uniName);}//void GLSLProgram::SetAttributeVariable( char* name, int val )//{//int loc;//if( ( loc = GetAttributeLocation( name ) ) >= 0 )//{//this->Use();//glVertexAttrib1i( loc, val );//}//};void GLSLProgram::SetAttributeVariable( const char* name, float val ){int loc;if( ( loc = GetAttributeLocation( name ) ) >= 0 ){this->Use();glVertexAttrib1f( loc, val );}};void GLSLProgram::SetAttributeVariable( const char* name, float val0, float val1, float val2 ){int loc;if( ( loc = GetAttributeLocation( name ) ) >= 0 ){this->Use();glVertexAttrib3f( loc, val0, val1, val2 );}};void GLSLProgram::SetAttributeVariable( const char* name, float vals[3] ){int loc;if( ( loc = GetAttributeLocation( name ) ) >= 0 ){this->Use();glVertexAttrib3fv( loc, vals );}};void GLSLProgram::SetUniformVariable( const char* name, int val ){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniform1i( loc, val );}};void GLSLProgram::SetUniformVariable( const char* name, float val ){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniform1f( loc, val );}};void GLSLProgram::SetUniformVariable( const char* name, float val0, float val1, float val2 ){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniform3f( loc, val0, val1, val2 );}};void GLSLProgram::SetUniformVariable( const char* name, float vals[3] ){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniform3fv( loc, 3, vals );}};void GLSLProgram::SetUniformMatrix2f(const char* name ,int count, bool transpose, const float *value){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniformMatrix2fv( loc, count, transpose, value );}}void GLSLProgram::SetUniformMatrix3f(const char* name ,int count, bool transpose, const float *value){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniformMatrix3fv( loc, count, transpose, value );}}void GLSLProgram::SetUniformMatrix4f(const char* name ,int count, bool transpose, const float *value){int loc;if( ( loc = GetUniformLocation( name ) ) >= 0 ){this->Use();glUniformMatrix4fv( loc, count, transpose, value );}}void GLSLProgram::GetActiveUniformBlockiv(const char* uniName, GLenum pname, GLint *params){int loc;if ( (loc = GetUniformBlockIndex(uniName)) >= 0){this->Use();glGetActiveUniformBlockiv(mProgram,loc,pname,params);}}void GLSLProgram::GetUniformIndices(GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices){glGetUniformIndices(mProgram,uniformCount,uniformNames,uniformIndices);}void GLSLProgram::GetActiveUniformsiv(GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params){glGetActiveUniformsiv(mProgram,uniformCount,uniformIndices,pname,params);}
這裡還引入了一個標頭檔,其實就是在不同平台上引入相應的標頭檔,標頭檔內容如下:
//// GLPrecompile.h// GLUtilBox//// Created by zhouxuguang .// Copyright © 2016年 zhouxuguang. All rights reserved.//#ifndef GLPrecompile_hpp#define GLPrecompile_hpp#include <stdio.h>#include <stdlib.h>#include <string.h>#include <string>#include <vector>#include <map>#ifdef __ANDROID__#include <GLES/gl.h>#include <GLES2/gl2.h>#include <GLES3/gl3.h>#elif defined(__IOS__)#include <OpenGLES/ES1/gl.h>#include <OpenGLES/ES1/glext.h>#include <OpenGLES/ES2/gl.h>#include <OpenGLES/ES2/glext.h>#include <OpenGLES/ES3/gl.h>#include <OpenGLES/ES3/glext.h>#endif#endif /* GLPrecompile_hpp */
希望對大家有用 ,案頭版本的OpenGL標頭檔沒有處理,大家有需要也可以根據自己需要改一下就OK