C++ 重载“中的赋值运算符”;着色器";班
我需要在我的一个基于opengl的类中重载赋值:问题是这种情况并不简单,因为它使用opengl“对象”:所以复制类属性是不够的。那么,重载=、和复制构造函数方法的正确方法是什么呢?这是我的密码: Shader.h:C++ 重载“中的赋值运算符”;着色器";班,c++,opengl,C++,Opengl,我需要在我的一个基于opengl的类中重载赋值:问题是这种情况并不简单,因为它使用opengl“对象”:所以复制类属性是不够的。那么,重载=、和复制构造函数方法的正确方法是什么呢?这是我的密码: Shader.h: #pragma once #include <GL/glew.h> #include <map> #include <string> #include "alpha/LogManager.h" #include "alpha/Component.
#pragma once
#include <GL/glew.h>
#include <map>
#include <string>
#include "alpha/LogManager.h"
#include "alpha/Component.h"
#include "alpha/Exceptions.h"
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#define NUM_SHADER_TYPES 3
#define NO_UNIFORM -1
class Shader : public Component
{
public:
Shader();
virtual ~Shader();
void loadFromText(GLenum type, const std::string& src);
void loadFromFile(GLenum type, const char* fileName);
void loadFromPreCompiledText(GLenum type, const std::string& src){}
void loadFromPreCompiledFile(GLenum type, const char* fileName){}
void CreateAndLink();
GLuint GetObject() const;
///accesses elements : shaders/uniforms;
GLuint GetAttribLocation(const char* attrib);
GLuint GetUniformLocation(const char* unif);
void UpdateUniformMatrix4f(const char* unif, const glm::mat4& val, GLboolean inverse = false);
void UpdateUniformMatrix3f(const char* unif, const glm::mat3& val, GLboolean inverse = false);
void UpdateUniformMatrix2f(const char* unif, const glm::mat2& val, GLboolean inverse = false);
void Bind() const override;
void UnBind() const override;
void Dispose() override;
///MEMBER FUNCTION GENERATORS
#define __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(OGL_TYPE, TYPE_SUFFIX)\
void UpdateUniform1##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0); \
void UpdateUniform2##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1); \
void UpdateUniform3##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2); \
void UpdateUniform4##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2, OGL_TYPE v3); \
void UpdateUniform1##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);\
void UpdateUniform2##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);\
void UpdateUniform3##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);\
void UpdateUniform4##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count = 1);
///Implement Methods
__ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLfloat, f);
__ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLdouble, d);
__ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLint, i);
__ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(GLuint, ui);
///undef macro
#undef __ALPHA_SHADER_PROGRAM_UNIFORM_DECLERATION(OGL_TYPE, TYPE_SUFFIX)
Shader& operator=(const Shader& other) = delete;
Shader(const Shader& shader) = delete;
private:
enum ShaderType{
VERTEX_SHADER,
FRAGMENT_SHADER,
GEOMETRY_SHADER
};
int m_numShaders;
GLuint m_object;
bool _hasCreated;
bool _hasDisposed;
GLuint _shaders[NUM_SHADER_TYPES]; /// VERTEX, FRAGMENT, GEOMETRY
std::map<std::string, GLuint> _attribList;
std::map<std::string, GLuint> _unifLocationList;
std::map<std::string, bool> _registeredUnifs;
};
#pragma一次
#包括
#包括
#包括
#包括“alpha/LogManager.h”
#包括“alpha/Component.h”
#包括“alpha/Exceptions.h”
#包括
#包括
#定义NUM_着色器_类型3
#定义无统一-1
类着色器:公共组件
{
公众:
着色器();
虚拟~Shader();
void loadFromText(格伦类型、常量std::string和src);
void loadFromFile(GLenum类型,常量字符*文件名);
void loadFromPreCompiledText(GLenum类型,const std::string&src){}
void loadFromPreCompiledFile(GLenum类型,常量字符*文件名){}
void CreateAndLink();
GLuint GetObject()常量;
///访问元素:着色器/制服;
GLuint getAttrib(const char*attrib);
GLuint GetUniformLocation(常量字符*unif);
void UpdateUniformMatrix4f(常量char*unif,常量glm::mat4&val,GLboolean reverse=false);
void UpdateUniformMatrix3f(常量char*unif,常量glm::mat3&val,GLboolean reverse=false);
void UpdateUniformMatrix2f(const char*unif,const glm::mat2&val,GLboolean reverse=false);
void Bind()常量重写;
void UnBind()常量覆盖;
无效处理()覆盖;
///成员函数生成器
#定义\uuuuu ALPHA\uShader\uProgram\uUniform\uDeclaration(OGL\u类型,类型\u后缀)\
void UpdateUniform1##TYPE_后缀(const GLchar*name,OGL_TYPE v0)\
void UpdateUniform2##TYPE_后缀(常量GLchar*名称,OGL_类型v0,OGL_类型v1)\
void UpdateUniform3##TYPE_后缀(常量GLchar*名称,OGL_类型v0,OGL_类型v1,OGL_类型v2)\
void UpdateUniform4##TYPE_后缀(常量GLchar*名称,OGL_类型v0,OGL_类型v1,OGL_类型v2,OGL_类型v3)\
void UpdateUniform1##TYPE#u后缀##v(const GLchar*name,const OGL#u TYPE*v,GLsizei count=1)\
void UpdateUniform2##TYPE#u后缀##v(const GLchar*name,const OGL#u TYPE*v,GLsizei count=1)\
void UpdateUniform3###TYPE#u后缀##v(const GLchar*name,const OGL#u TYPE*v,GLsizei count=1)\
void UpdateUniform4##TYPE#u后缀##v(常量GLchar*name,常量OGL#u TYPE*v,GLsizei count=1);
///实施方法
__ALPHA_着色器_程序_均匀_偏差(GLfloat,f);
__ALPHA_着色器_程序_均匀_偏差(GLdouble,d);
__ALPHA_SHADER_PROGRAM_UNIFORM_Declaration(闪烁,i);
__ALPHA_着色器_程序_统一_偏差(GLuint,ui);
///未定义宏
#undef\uuuu ALPHA\u SHADER\u PROGRAM\u UNIFORM\u Declaration(OGL\u类型,类型\u后缀)
着色器和运算符=(常量着色器和其他)=删除;
着色器(常量着色器和着色器)=删除;
私人:
枚举着色器类型{
顶点着色器,
碎片_着色器,
几何体着色器
};
国际货币基金组织;
GLuint m_对象;
布尔乌创造了;
布尔(bool_)哈斯德;;
GLuint _着色器[NUM _着色器_类型];///顶点、片段、几何体
std::map_属性列表;
标准::地图UnilocationList;
std::map _registeredUnifs;
};
Shader.cpp
#include "alpha/Shader.h"
#include "alpha/LogManager.h"
#include <fstream>
#include <assert.h>
#define GL_NULL 0
Shader::Shader()
: m_numShaders(0), m_object(0), _hasCreated(false), _hasDisposed(false)
{
_shaders[VERTEX_SHADER] = 0;
_shaders[FRAGMENT_SHADER] = 0;
_shaders[GEOMETRY_SHADER] = 0;
_attribList.clear();
_unifLocationList.clear();
}
Shader::~Shader(){
Dispose();
}
void Shader::loadFromText(GLenum type, const std::string& text){
try
{
switch (type)
{
case GL_VERTEX_SHADER:
if(glIsShader(_shaders[VERTEX_SHADER]) == GL_TRUE)
throw TypeRegisteredTwiceException();
break;
case GL_FRAGMENT_SHADER:
if(glIsShader(_shaders[FRAGMENT_SHADER]) == GL_TRUE)
throw TypeRegisteredTwiceException();
break;
case GL_GEOMETRY_SHADER:
if(glIsShader(_shaders[GEOMETRY_SHADER]) == GL_TRUE )
throw TypeRegisteredTwiceException();
break;
default:
throw UnknownTypeException();
break;
}
GLuint shader = glCreateShader(type);
const char* cstr = text.c_str();
glShaderSource(shader, 1, &cstr, nullptr);
///compile + check shader load status
GLint status;
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
if(status == GL_FALSE){
GLint infoLogSize;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogSize);
GLchar *infoLog = new GLchar[infoLogSize];
glGetShaderInfoLog(shader, infoLogSize, nullptr, infoLog);
LOG_ERROR("Shader", infoLog);
delete [] infoLog; /// no throw between new and delete !
}
if(m_numShaders >= 4)
{
throw OutOfBoundsExcpetion();
}
_shaders[m_numShaders++]=shader;
}
catch(std::exception & e){
LOG_ERROR_INFO("AN ERROR OCCURED", "\n", e.what() );
LOG_ERROR("Shader", "IGNORING ADDED SHADER !");
}
}
void Shader::CreateAndLink(){
try{
if(glIsProgram(m_object) == GL_TRUE)
throw CreatedTwiceException();
m_object = glCreateProgram();
///OK CREATED PROGRAM !
_hasCreated = true;
if(_shaders[VERTEX_SHADER] != 0)
glAttachShader(m_object, _shaders[VERTEX_SHADER]);
else
throw NotLoadedException();
if(_shaders[FRAGMENT_SHADER] != 0)
glAttachShader(m_object, _shaders[FRAGMENT_SHADER]);
else
throw NotLoadedException();
if(_shaders[GEOMETRY_SHADER] != 0)
glAttachShader(m_object, _shaders[GEOMETRY_SHADER]);/// OK, not compulsary...
///link + check
GLint status;
glLinkProgram(m_object);
glGetProgramiv(m_object, GL_LINK_STATUS, &status);
if(status == GL_FALSE){
GLint infoLogSize;
glGetProgramiv(m_object, GL_INFO_LOG_LENGTH, &infoLogSize);
GLchar *infoLog = new GLchar[infoLogSize];
glGetProgramInfoLog(m_object, infoLogSize, nullptr, infoLog);
delete [] infoLog;
}
std::cout << "Shader created : ID = " << m_object << std::endl;
glDetachShader(m_object, _shaders[VERTEX_SHADER]);
glDetachShader(m_object, _shaders[FRAGMENT_SHADER]);
glDetachShader(m_object, _shaders[GEOMETRY_SHADER]);
glDeleteShader(_shaders[VERTEX_SHADER]);
glDeleteShader(_shaders[FRAGMENT_SHADER]);
glDeleteShader(_shaders[GEOMETRY_SHADER]);
}
catch(std::exception & e){
LOG_ERROR_INFO("Shader", "AN ERROR OCCURED\n", e.what() );
EXIT(1);
}
}
void Shader::Bind() const{
glUseProgram(m_object);
}
void Shader::UnBind() const{
glUseProgram(GL_NULL);
}
GLuint Shader::GetAttribLocation(const char* attrib){
auto it = _attribList.find(attrib);
if(it == _attribList.end())
{
GLuint loc = glGetAttribLocation(m_object, attrib);
if(loc == (unsigned)-1)
{
LOG_INFO("Shader Warning : Attrib", attrib, "is inactive !");
}
it = _attribList.insert({attrib, loc}).first;
}
return it->second;
}
GLuint Shader::GetUniformLocation(const char* unif){
auto it = _unifLocationList.find(unif);
if(it == _unifLocationList.end())
{
GLuint loc = glGetUniformLocation(m_object, unif);
if(loc == (unsigned)-1)
{
LOG_INFO("Shader Warning : Uniform", unif, "is inactive !");
}
it = _unifLocationList.insert({unif, loc}).first;
}
return it->second;
}
GLuint Shader::GetObject() const{ return m_object; }
void Shader::UpdateUniformMatrix4f(const char* unif, const glm::mat4& val, GLboolean inverse){
glUniformMatrix4fv(this->GetUniformLocation(unif), 1, inverse, glm::value_ptr(val));
}
void Shader::UpdateUniformMatrix3f(const char* unif, const glm::mat3& val, GLboolean inverse){
glUniformMatrix3fv(this->GetUniformLocation(unif), 1, inverse, glm::value_ptr(val));
}
void Shader::UpdateUniformMatrix2f(const char* unif, const glm::mat2& val, GLboolean inverse){
glUniformMatrix2fv(this->GetUniformLocation(unif), 1, inverse, glm::value_ptr(val));
}
#define __ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(OGL_TYPE, TYPE_SUFFIX)\
void Shader::UpdateUniform1##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0)\
{ glUniform1 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0); }\
\
void Shader::UpdateUniform2##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1)\
{ glUniform2 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0, v1); }\
\
void Shader::UpdateUniform3##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2)\
{ glUniform3 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0, v1, v2); }\
\
void Shader::UpdateUniform4##TYPE_SUFFIX(const GLchar* name, OGL_TYPE v0, OGL_TYPE v1, OGL_TYPE v2, OGL_TYPE v3)\
{ glUniform4 ## TYPE_SUFFIX (this->GetUniformLocation(name), v0, v1, v2, v3); }\
\
void Shader::UpdateUniform1##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
{ glUniform1 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
\
void Shader::UpdateUniform2##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
{ glUniform2 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
\
void Shader::UpdateUniform3##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
{ glUniform3 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
\
void Shader::UpdateUniform4##TYPE_SUFFIX##v(const GLchar* name, const OGL_TYPE* v, GLsizei count) /** sizei=1 by default */\
{ glUniform4 ## TYPE_SUFFIX ## v (this->GetUniformLocation(name), count, v); }\
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLfloat, f);
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLdouble, d);
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLint, i);
__ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION(GLuint, ui);
///undef macro
#undef __ALPHA_SHADER_PROGRAM_UNIFORM_IMPLEMENTATION()
void Shader::loadFromFile(GLenum which, const char* fileName){
std::ifstream fparser;
fparser.open(fileName, std::ios_base::in);
if(fparser){
///read + load
std::string buffer(std::istreambuf_iterator<char>(fparser), (std::istreambuf_iterator<char>()));
loadFromText(which, buffer);
}
else{
LOG_ERROR_INFO("Shader", "Invalid fileName path", fileName);
}
}
void Shader::Dispose(){
if(!_hasDisposed)
{
glDeleteProgram(m_object);
std::cout << "Disposed Shader object : ID was " << m_object << std::endl;
m_object = -1;
_hasDisposed = true;///no more calls of Dispose() !
}
}
#包括“alpha/Shader.h”
#包括“alpha/LogManager.h”
#包括
#包括
#定义GL_NULL 0
着色器::着色器()
:m_numShaders(0),m_object(0),_hasCreated(false),_hasDisposed(false)
{
_着色器[顶点着色器]=0;
_着色器[片段着色器]=0;
_着色器[几何体_着色器]=0;
_attribList.clear();
_unifLocationList.clear();
}
着色器::~Shader(){
处置();
}
void着色器::loadFromText(GLenum类型,常量std::字符串和文本){
尝试
{
开关(类型)
{
案例GL_顶点_着色器:
if(glishader(_着色器[顶点_着色器]])==GL_TRUE)
抛出TypeRegisteredWiceException();
打破
案例GL_片段_着色器:
if(glishader(_shaders[FRAGMENT_SHADER])==GL_TRUE)
抛出TypeRegisteredWiceException();
打破
案例GL_几何体_着色器:
if(glishader(_shaders[GEOMETRY_SHADER])==GL_TRUE)
抛出TypeRegisteredWiceException();
打破
违约:
抛出UnknownTypeException();
打破
}
GLuint着色器=glCreateShader(类型);
const char*cstr=text.c_str();
glShaderSource(着色器,1,&cstr,nullptr);
///编译并检查着色器加载状态
闪烁状态;
glCompileShader(着色器);
glGetShaderiv(着色器、GL\u编译状态和状态);
如果(状态==GL\U FALSE){
闪烁信息量;
glGetShaderiv(着色器、GL_INFO_LOG_LENGTH和infoLogSize);
GLchar*infoLog=新的GLchar[infoLogSize];
glGetShaderInfoLog(着色器、infoLogSize、nullptr、infoLog);
日志错误(“着色器”,infoLog);
delete[]infoLog;///新建和删除之间没有抛出!
}
如果(m_numShaders>=4)
{
扔掉boundsException();
}
_着色器[m_numShaders++]=着色器;
}
捕获(标准::异常&e){
日志错误信息(“发生了错误”,“\n”,例如what());
日志错误(“着色器”,“忽略添加的着色器!”);
}
}
void着色器::CreateAndLink(){
试一试{
if(程序(m_对象)=GL_真)
抛出CreatedTwiceException();
m_object=glCreateProgram();
///好的,创建程序!
_hasscreated=true;
如果(_着色器[顶点_着色器]!=0)
glAttachShader(m_对象,_着色器[顶点_着色器]);
其他的
抛出NotLoadedException();
如果(_着色器[片段_着色器]!=0)
glAttachShader(m_对象,_着色器[片段着色器]);
其他的
抛出NotLoadedException();
如果(_着色器[几何体_着色器]!=0)
Shader::Shader(Shader&& other){
this->m_object = other.m_object;
other.m_object = 0;
this->m_numShaders = other.m_numShaders;
this->_hasCreated = other._hasCreated;
this->_hasDisposed = other._hasDisposed;
for(unsigned i = 0; i < NUM_SHADER_TYPES; ++i)
{
this->_shaders[i] = other._shaders[i];
other._shaders[i] = 0;
}
this->_attribList = std::move(other._attribList);
this->_unifLocationList = std::move(other._unifLocationList);
this->_unifLocationList = std::move(other._unifLocationList);
}
Shader(const Shader &other)
{
DetachAllShaders();
GLuint shaders[NUM_SHADER_TYPES];
GLsizei shaderCount;
glGetAttachedShaders(other.GetObject(), NUM_SHADER_TYPES, &shaderCount, shaders);
for(auto shader : shaders)
{
glAttachShader(m_program, shader);
}
if(other.isLinked())
{
glLinkProgram(m_program);
}
}
Shader(Shader &&other)
{
m_object = other.m_object;
other.m_object = 0;
_attribList = std::move(other._attribList);
// ...etc
}