I've tried to create a small OpenGL abstraction layer.
I've tried to favor composition over inheritance but somehow it added extra complexity to my code. I probably overused it.
shader.h
#ifndef SHADER_H
#define SHADER_H
#include "filereader.h"
#include <string>
#include <iostream>
#include <GL/glew.h>
#include <memory>
class HandleInterface {
protected:
GLuint handle_;
public:
virtual void SetHandle( GLuint )=0;
virtual ~HandleInterface() {}
virtual GLuint GetHandle() const=0;
};
class BaseHandle : public HandleInterface {
public:
virtual void SetHandle( GLuint i ) {
handle_ = i;
}
virtual GLuint GetHandle() const {
return handle_;
}
};
class Handle {
std::unique_ptr<HandleInterface> handle_;
protected:
virtual void SetHandle( GLuint i );
public:
Handle();
Handle( std::unique_ptr<HandleInterface> handle_ptr );
virtual void SetHandleInterface( std::unique_ptr<HandleInterface> handle_ptr );
virtual GLuint GetHandle() const;
};
class ShaderInterface {
public:
virtual ~ShaderInterface() {}
virtual void SetShaderSourceFromFile( std::string path ) = 0;
virtual void SetShaderSourceFromString( std::string source ) = 0;
virtual void CreateShader() = 0;
virtual GLenum GetShadertype() = 0;
};
class BaseShader : public Handle ,public ShaderInterface {
std::string shader_source_;
public:
~BaseShader() {
glDeleteShader( GetHandle() );
}
virtual void SetShaderSourceFromFile( std::string path );
virtual void SetShaderSourceFromString( std::string source );
virtual void CreateShader();
};
class VertexShader : public BaseShader {
public:
GLenum GetShadertype() {
return GL_VERTEX_SHADER;
}
};
class FragmentShader : public BaseShader {
public:
GLenum GetShadertype() {
return GL_FRAGMENT_SHADER;
}
};
class ComputeShader : public BaseShader {
public:
GLenum GetShadertype() {
return GL_COMPUTE_SHADER;
}
};
class TesselationControlShader : public BaseShader {
public:
GLenum GetShadertype() {
return GL_TESS_CONTROL_SHADER;
}
};
class TesselationEvaluationShader : public BaseShader {
public:
GLenum GetShadertype() {
return GL_TESS_EVALUATION_SHADER;
}
};
class ShaderProgramInterface {
public:
virtual void AttachShader( const BaseShader &s ) = 0;
virtual void Link() = 0;
virtual void Use() = 0;
};
class ShaderProgram : public Handle , public ShaderProgramInterface {
public:
ShaderProgram();
void AttachShader( const BaseShader &s );
void Link();
void Use();
};
class VertexBufferInterface {
public:
virtual ~VertexBufferInterface() {}
virtual void bind( GLenum ) = 0;
virtual void setBufferData( GLenum,GLsizeiptr,const GLvoid*,GLenum )= 0;
};
class VertexBuffer : public Handle, public VertexBufferInterface {
public:
VertexBuffer();
~VertexBuffer() {}
void bind( GLenum );
void setBufferType( GLenum );
void setBufferData(GLenum target, GLsizeiptr size, const GLvoid*data, GLenum usage );
};
#endif // SHADER_H
shader.cpp
#include "shader.h"
/*#############################
Base
##############################*/
GLuint Handle::GetHandle() const {
return handle_->GetHandle();
}
void Handle::SetHandle( GLuint i ) {
handle_->SetHandle( i );
}
void Handle::SetHandleInterface( std::unique_ptr<HandleInterface> handle_ptr ) {
handle_ = std::move( handle_ptr );
}
Handle::Handle( std::unique_ptr<HandleInterface> handle_ptr ) {
SetHandleInterface( std::move( handle_ptr ) );
}
Handle::Handle()
: Handle( std::unique_ptr<HandleInterface>( new BaseHandle() ) ) {
}
/*#############################
BaseShader
##############################*/
void BaseShader::CreateShader() {
SetHandle( glCreateShader( GetShadertype() ) );
GLint length[1];
length[0] = BaseShader::shader_source_.size();
const GLchar* p[1];
p[0] = BaseShader::shader_source_.c_str();
glShaderSource( BaseShader::GetHandle(),1,p,length );
glCompileShader( GetHandle() );
GLint success;
glGetShaderiv( GetHandle(), GL_COMPILE_STATUS, &success );
if ( !success ) {
// todo throw something?
}
}
void BaseShader::SetShaderSourceFromFile( std::string path ) {
FileReader fileReader( path );
BaseShader::shader_source_ = fileReader.get();
}
void BaseShader::SetShaderSourceFromString( std::string source ) {
BaseShader::shader_source_ = source;
}
/*#############################
ShaderProgram
##############################*/
void ShaderProgram::AttachShader( const BaseShader &s ) {
glAttachShader( ShaderProgram::GetHandle(), s.GetHandle() );
}
void ShaderProgram::Use() {
glUseProgram( GetHandle() );
}
void ShaderProgram::Link() {
glLinkProgram( GetHandle() );
}
ShaderProgram::ShaderProgram() {
Handle();
SetHandle( glCreateProgram() );
}
/*#############################
VertexBuffer
##############################*/
void VertexBuffer::bind( GLenum buffertype ) {
glBindBuffer( buffertype, GetHandle() );
}
VertexBuffer::VertexBuffer() {
GLuint handle;
glGenBuffers( 1,&handle );
SetHandle( handle );
}
void VertexBuffer::setBufferData(GLenum target, GLsizeiptr s,const GLvoid * data, GLenum usage ) {
glBufferData( target, s, data, usage );
}