GLSL程序对象的C++封装
Posted 周旭光
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GLSL程序对象的C++封装相关的知识,希望对你有一定的参考价值。
在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; //片段shader
std::map<const char *, int> mAttributeLocs; //attribute属性变量的map
std::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
以上是关于GLSL程序对象的C++封装的主要内容,如果未能解决你的问题,请参考以下文章
如何在 C++ 中为 GLSL 片段着色器实现 iGlobalTime?
我的OpenGL学习进阶之旅如何抽取着色器代码到assets目录下的GLSL文件,以及如何通过Java或者C++代码来加载着GLSL文件?