Move shader classes to C4DrawGL

issue1247
Armin Burgmeier 2014-10-07 15:57:02 -04:00
parent 787b7609c7
commit 1da4a9bd44
3 changed files with 147 additions and 136 deletions

View File

@ -36,6 +36,110 @@
#include <math.h>
#include <limits.h>
C4DrawGLShader::C4DrawGLShader(Type shader_type)
{
GLint gl_type;
switch(shader_type)
{
case FRAGMENT: gl_type = GL_FRAGMENT_SHADER_ARB; break;
case VERTEX: gl_type = GL_VERTEX_SHADER_ARB; break;
case GEOMETRY: gl_type = GL_GEOMETRY_SHADER_ARB; break;
default: assert(false); break;
}
Shader = glCreateShaderObjectARB(gl_type);
if(!Shader) throw C4DrawGLError(FormatString("Failed to create shader")); // TODO: custom error class?
}
C4DrawGLShader::~C4DrawGLShader()
{
glDeleteObjectARB(Shader);
}
void C4DrawGLShader::Load(const char* code)
{
glShaderSourceARB(Shader, 1, &code, NULL);
glCompileShaderARB(Shader);
GLint compile_status;
glGetObjectParameterivARB(Shader, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
if(compile_status != GL_TRUE)
{
const char* shader_type_str;
switch(GetType())
{
case VERTEX: shader_type_str = "vertex"; break;
case FRAGMENT: shader_type_str = "fragment"; break;
case GEOMETRY: shader_type_str = "geometry"; break;
default: assert(false); break;
}
GLint length;
glGetObjectParameterivARB(Shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
if(length > 0)
{
std::vector<char> error_message(length);
glGetInfoLogARB(Shader, length, NULL, &error_message[0]);
throw C4DrawGLError(FormatString("Failed to compile %s shader: %s", shader_type_str, &error_message[0]));
}
else
{
throw C4DrawGLError(FormatString("Failed to compile %s shader", shader_type_str));
}
}
}
StdMeshMaterialShader::Type C4DrawGLShader::GetType() const
{
GLint shader_type;
glGetObjectParameterivARB(Shader, GL_OBJECT_SUBTYPE_ARB, &shader_type);
switch(shader_type)
{
case GL_FRAGMENT_SHADER_ARB: return FRAGMENT;
case GL_VERTEX_SHADER_ARB: return VERTEX;
case GL_GEOMETRY_SHADER_ARB: return GEOMETRY;
default: assert(false); return static_cast<StdMeshMaterialShader::Type>(-1);
}
}
C4DrawGLProgram::C4DrawGLProgram(const C4DrawGLShader* fragment_shader, const C4DrawGLShader* vertex_shader, const C4DrawGLShader* geometry_shader)
{
Program = glCreateProgramObjectARB();
if(fragment_shader != NULL)
glAttachObjectARB(Program, fragment_shader->Shader);
if(vertex_shader != NULL)
glAttachObjectARB(Program, vertex_shader->Shader);
if(geometry_shader != NULL)
glAttachObjectARB(Program, geometry_shader->Shader);
glLinkProgramARB(Program);
GLint link_status;
glGetObjectParameterivARB(Program, GL_OBJECT_LINK_STATUS_ARB, &link_status);
if(link_status != GL_TRUE)
{
GLint length;
glGetObjectParameterivARB(Program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
if(length > 0)
{
std::vector<char> error_message(length);
glGetInfoLogARB(Program, length, NULL, &error_message[0]);
glDeleteObjectARB(Program);
throw C4DrawGLError(FormatString("Failed to link program: %s", &error_message[0]));
}
else
{
glDeleteObjectARB(Program);
throw C4DrawGLError(StdStrBuf("Failed to link program"));
}
}
}
C4DrawGLProgram::~C4DrawGLProgram()
{
glDeleteObjectARB(Program);
}
static void glColorDw(DWORD dwClr)
{
glColor4ub(GLubyte(dwClr>>16), GLubyte(dwClr>>8), GLubyte(dwClr), GLubyte(dwClr>>24));

View File

@ -37,6 +37,41 @@
class C4Window;
class C4DrawGLError: public std::exception
{
public:
C4DrawGLError(const StdStrBuf& buf): Buf(buf) {}
virtual ~C4DrawGLError() throw() {}
virtual const char* what() const throw() { return Buf.getData(); }
private:
StdCopyStrBuf Buf;
};
// GLSL shaders
class C4DrawGLShader: public StdMeshMaterialShader
{
public:
C4DrawGLShader(Type shader_type);
virtual ~C4DrawGLShader();
void Load(const char* code);
virtual Type GetType() const;
GLuint Shader;
};
class C4DrawGLProgram: public StdMeshMaterialProgram
{
public:
C4DrawGLProgram(const C4DrawGLShader* fragment_shader, const C4DrawGLShader* vertex_shader, const C4DrawGLShader* geometry_shader);
virtual ~C4DrawGLProgram();
GLuint Program;
};
// one OpenGL context
class CStdGLCtx
#ifdef USE_COCOA

View File

@ -169,38 +169,10 @@ namespace
}
} // anonymous namespace
class C4DrawMeshGLError: public std::exception
class C4DrawMeshGLProgram: public C4DrawGLProgram
{
public:
C4DrawMeshGLError(const StdStrBuf& buf): Buf(buf) {}
virtual ~C4DrawMeshGLError() throw() {}
virtual const char* what() const throw() { return Buf.getData(); }
private:
StdCopyStrBuf Buf;
};
class C4DrawMeshGLShader: public StdMeshMaterialShader
{
public:
C4DrawMeshGLShader(Type shader_type);
virtual ~C4DrawMeshGLShader();
void Load(const char* code);
virtual Type GetType() const;
GLuint Shader;
};
class C4DrawMeshGLProgram: public StdMeshMaterialProgram
{
public:
C4DrawMeshGLProgram(const C4DrawMeshGLShader* fragment_shader, const C4DrawMeshGLShader* vertex_shader, const C4DrawMeshGLShader* geometry_shader);
virtual ~C4DrawMeshGLProgram();
GLuint Program;
C4DrawMeshGLProgram(const C4DrawGLShader* fragment_shader, const C4DrawGLShader* vertex_shader, const C4DrawGLShader* geometry_shader);
GLint TexturesLocation;
GLint PlayerColorLocation;
@ -208,104 +180,9 @@ public:
GLint Mod2Location;
};
C4DrawMeshGLShader::C4DrawMeshGLShader(Type shader_type)
C4DrawMeshGLProgram::C4DrawMeshGLProgram(const C4DrawGLShader* fragment_shader, const C4DrawGLShader* vertex_shader, const C4DrawGLShader* geometry_shader):
C4DrawGLProgram(fragment_shader, vertex_shader, geometry_shader)
{
GLint gl_type;
switch(shader_type)
{
case FRAGMENT: gl_type = GL_FRAGMENT_SHADER_ARB; break;
case VERTEX: gl_type = GL_VERTEX_SHADER_ARB; break;
case GEOMETRY: gl_type = GL_GEOMETRY_SHADER_ARB; break;
default: assert(false); break;
}
Shader = glCreateShaderObjectARB(gl_type);
if(!Shader) throw C4DrawMeshGLError(FormatString("Failed to create shader")); // TODO: custom error class?
}
C4DrawMeshGLShader::~C4DrawMeshGLShader()
{
glDeleteObjectARB(Shader);
}
void C4DrawMeshGLShader::Load(const char* code)
{
glShaderSourceARB(Shader, 1, &code, NULL);
glCompileShaderARB(Shader);
GLint compile_status;
glGetObjectParameterivARB(Shader, GL_OBJECT_COMPILE_STATUS_ARB, &compile_status);
if(compile_status != GL_TRUE)
{
const char* shader_type_str;
switch(GetType())
{
case VERTEX: shader_type_str = "vertex"; break;
case FRAGMENT: shader_type_str = "fragment"; break;
case GEOMETRY: shader_type_str = "geometry"; break;
default: assert(false); break;
}
GLint length;
glGetObjectParameterivARB(Shader, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
if(length > 0)
{
std::vector<char> error_message(length);
glGetInfoLogARB(Shader, length, NULL, &error_message[0]);
throw C4DrawMeshGLError(FormatString("Failed to compile %s shader: %s", shader_type_str, &error_message[0]));
}
else
{
throw C4DrawMeshGLError(FormatString("Failed to compile %s shader", shader_type_str));
}
}
}
StdMeshMaterialShader::Type C4DrawMeshGLShader::GetType() const
{
GLint shader_type;
glGetObjectParameterivARB(Shader, GL_OBJECT_SUBTYPE_ARB, &shader_type);
switch(shader_type)
{
case GL_FRAGMENT_SHADER_ARB: return FRAGMENT;
case GL_VERTEX_SHADER_ARB: return VERTEX;
case GL_GEOMETRY_SHADER_ARB: return GEOMETRY;
default: assert(false); return static_cast<StdMeshMaterialShader::Type>(-1);
}
}
C4DrawMeshGLProgram::C4DrawMeshGLProgram(const C4DrawMeshGLShader* fragment_shader, const C4DrawMeshGLShader* vertex_shader, const C4DrawMeshGLShader* geometry_shader)
{
Program = glCreateProgramObjectARB();
if(fragment_shader != NULL)
glAttachObjectARB(Program, fragment_shader->Shader);
if(vertex_shader != NULL)
glAttachObjectARB(Program, vertex_shader->Shader);
if(geometry_shader != NULL)
glAttachObjectARB(Program, geometry_shader->Shader);
glLinkProgramARB(Program);
GLint link_status;
glGetObjectParameterivARB(Program, GL_OBJECT_LINK_STATUS_ARB, &link_status);
if(link_status != GL_TRUE)
{
GLint length;
glGetObjectParameterivARB(Program, GL_OBJECT_INFO_LOG_LENGTH_ARB, &length);
if(length > 0)
{
std::vector<char> error_message(length);
glGetInfoLogARB(Program, length, NULL, &error_message[0]);
glDeleteObjectARB(Program);
throw C4DrawMeshGLError(FormatString("Failed to link program: %s", &error_message[0]));
}
else
{
glDeleteObjectARB(Program);
throw C4DrawMeshGLError(StdStrBuf("Failed to link program"));
}
}
// TODO: Specify this as an addition to the OGRE params section
TexturesLocation = glGetUniformLocationARB(Program, "oc_Textures");
PlayerColorLocation = glGetUniformLocationARB(Program, "oc_PlayerColor");
@ -313,17 +190,12 @@ C4DrawMeshGLProgram::C4DrawMeshGLProgram(const C4DrawMeshGLShader* fragment_shad
Mod2Location = glGetUniformLocationARB(Program, "oc_Mod2");
}
C4DrawMeshGLProgram::~C4DrawMeshGLProgram()
{
glDeleteObjectARB(Program);
}
std::unique_ptr<StdMeshMaterialShader> CStdGL::CompileShader(const char* language, StdMeshMaterialShader::Type type, const char* text)
{
if(strcmp(language, "glsl") != 0)
throw C4DrawMeshGLError(StdStrBuf("Not a GLSL shader"));
throw C4DrawGLError(StdStrBuf("Not a GLSL shader"));
std::unique_ptr<C4DrawMeshGLShader> shader(new C4DrawMeshGLShader(type));
std::unique_ptr<C4DrawGLShader> shader(new C4DrawGLShader(type));
shader->Load(text);
return std::move(shader);
}
@ -506,10 +378,10 @@ bool CStdGL::PrepareMaterial(StdMeshMatManager& mat_manager, StdMeshMaterial& ma
}
// Then, link the program.
std::unique_ptr<C4DrawMeshGLProgram> program(new C4DrawMeshGLProgram(static_cast<const C4DrawMeshGLShader*>(pass.FragmentShader), static_cast<const C4DrawMeshGLShader*>(pass.VertexShader), static_cast<const C4DrawMeshGLShader*>(pass.GeometryShader)));
std::unique_ptr<C4DrawMeshGLProgram> program(new C4DrawMeshGLProgram(static_cast<const C4DrawGLShader*>(pass.FragmentShader), static_cast<const C4DrawGLShader*>(pass.VertexShader), static_cast<const C4DrawGLShader*>(pass.GeometryShader)));
pass.Program = &mat_manager.AddProgram(pass.FragmentShader, pass.VertexShader, pass.GeometryShader, std::move(program));
}
catch(const C4DrawMeshGLError& error)
catch(const C4DrawGLError& error)
{
technique.Available = false;
LogF("Failed to compile shader: %s\n", error.what());