summaryrefslogtreecommitdiffstats
path: root/src/graphics/opengl
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-07-01 22:59:22 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-07-01 22:59:22 +0200
commitd9c5a439d09211ec210195709d275596c6c3c9ba (patch)
treeb536721f8ac5f42649345eeb836259bbf6a887e3 /src/graphics/opengl
parent9bd4ec03b272e7925b11c3efc2bd8460894ea589 (diff)
downloadcolobot-d9c5a439d09211ec210195709d275596c6c3c9ba.tar.gz
colobot-d9c5a439d09211ec210195709d275596c6c3c9ba.tar.bz2
colobot-d9c5a439d09211ec210195709d275596c6c3c9ba.zip
CGLDevice implementation
- extended Gfx::CDevice interface - written OpenGL implementation in Gfx::CGLDevice - rewrote color and light module - added Gfx::VertexCol - added array casts to Math::Vector, Math::Matrix and Gfx::Color
Diffstat (limited to 'src/graphics/opengl')
-rw-r--r--src/graphics/opengl/gldevice.cpp567
-rw-r--r--src/graphics/opengl/gldevice.h65
2 files changed, 573 insertions, 59 deletions
diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp
index 9ef376f..d105a93 100644
--- a/src/graphics/opengl/gldevice.cpp
+++ b/src/graphics/opengl/gldevice.cpp
@@ -20,6 +20,35 @@
#include <GL/gl.h>
#include <GL/glu.h>
+#include <GL/glext.h>
+
+#include <SDL/SDL.h>
+
+#include <assert.h>
+
+namespace Gfx {
+
+struct GLDevicePrivate
+{
+ void (APIENTRY* glMultiTexCoord1fARB)(GLenum target, GLfloat s);
+ void (APIENTRY* glMultiTexCoord2fARB)(GLenum target, GLfloat s, GLfloat t);
+ void (APIENTRY* glMultiTexCoord3fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r);
+ void (APIENTRY* glMultiTexCoord4fARB)(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+ void (APIENTRY* glActiveTextureARB)(GLenum texture);
+ void (APIENTRY* glClientActiveTextureARB)(GLenum texture);
+
+ GLDevicePrivate()
+ {
+ glMultiTexCoord1fARB = NULL;
+ glMultiTexCoord2fARB = NULL;
+ glMultiTexCoord3fARB = NULL;
+ glMultiTexCoord4fARB = NULL;
+ glActiveTextureARB = NULL;
+ glClientActiveTextureARB = NULL;
+ }
+};
+
+}; // namespace Gfx
void Gfx::GLDeviceConfig::LoadDefault()
@@ -35,89 +64,194 @@ void Gfx::GLDeviceConfig::LoadDefault()
depthSize = 24;
}
+
+
+
Gfx::CGLDevice::CGLDevice()
{
- m_renderState = 0;
+ m_private = new Gfx::GLDevicePrivate();
+ m_wasInit = false;
}
Gfx::CGLDevice::~CGLDevice()
{
+ delete m_private;
+ m_private = NULL;
}
-void Gfx::CGLDevice::Initialize()
+bool Gfx::CGLDevice::GetWasInit()
{
- // TODO
+ return m_wasInit;
+}
+
+std::string Gfx::CGLDevice::GetError()
+{
+ return m_error;
+}
+
+bool Gfx::CGLDevice::Create()
+{
+ m_wasInit = true;
+
+ // TODO: move to functions?
+ glShadeModel(GL_SMOOTH);
+ glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+
+ std::string extensions = std::string( (char*) glGetString(GL_EXTENSIONS));
+
+ if (extensions.find("GL_ARB_multitexture") == std::string::npos)
+ {
+ m_error = "Required extension GL_ARB_multitexture not supported";
+ return false;
+ }
+
+ if (extensions.find("GL_EXT_texture_env_combine") == std::string::npos)
+ {
+ m_error = "Required extension GL_EXT_texture_env_combine not supported";
+ return false;
+ }
+
+ int maxTextures = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextures);
+ m_textures = std::vector<Gfx::Texture*>(maxTextures, NULL);
+
+ m_lights = std::vector<Gfx::Light>(GL_MAX_LIGHTS, Gfx::Light());
+ m_lightsEnabled = std::vector<bool>(GL_MAX_LIGHTS, false);
+
+ m_private->glMultiTexCoord1fARB = (PFNGLMULTITEXCOORD1FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord1fARB");
+ m_private->glMultiTexCoord2fARB = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
+ m_private->glMultiTexCoord3fARB = (PFNGLMULTITEXCOORD3FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord3fARB");
+ m_private->glMultiTexCoord4fARB = (PFNGLMULTITEXCOORD4FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord4fARB");
+ m_private->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
+ m_private->glClientActiveTextureARB = (PFNGLCLIENTACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glClientActiveTextureARB");
+
+ return true;
}
void Gfx::CGLDevice::Destroy()
{
- // TODO
+ m_private->glMultiTexCoord1fARB = NULL;
+ m_private->glMultiTexCoord2fARB = NULL;
+ m_private->glMultiTexCoord3fARB = NULL;
+ m_private->glMultiTexCoord4fARB = NULL;
+ m_private->glActiveTextureARB = NULL;
+ m_private->glClientActiveTextureARB = NULL;
+
+ // Delete the remaining textures
+ std::set<Gfx::Texture*>::iterator it;
+ for (it = m_allTextures.begin(); it != m_allTextures.end(); ++it)
+ delete *it;
+ m_allTextures.clear();
+
+ m_wasInit = false;
}
void Gfx::CGLDevice::BeginScene()
{
- // TODO
+ Clear();
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(m_projectionMat.Array());
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m_modelviewMat.Array());
}
void Gfx::CGLDevice::EndScene()
{
- // TODO
+ glFlush();
}
void Gfx::CGLDevice::Clear()
{
- // TODO
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Gfx::CGLDevice::SetTransform(Gfx::TransformType type, const Math::Matrix &matrix)
{
- switch (type)
+ if (type == Gfx::TRANSFORM_WORLD)
+ {
+ m_worldMat = matrix;
+ m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m_modelviewMat.Array());
+ }
+ else if (type == Gfx::TRANSFORM_VIEW)
+ {
+ m_viewMat = matrix;
+ m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m_modelviewMat.Array());
+ }
+ else if (type == Gfx::TRANSFORM_PROJECTION)
{
- case Gfx::TRANSFORM_WORLD:
- m_worldMat = matrix;
- // TODO
- break;
- case Gfx::TRANSFORM_VIEW:
- m_viewMat = matrix;
- // TODO
- break;
- case Gfx::TRANSFORM_PROJECTION:
- m_projectionMat = matrix;
- // TODO
- break;
- default:
- assert(false);
+ m_projectionMat = matrix;
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(m_projectionMat.Array());
+ }
+ else
+ {
+ assert(false);
}
}
const Math::Matrix& Gfx::CGLDevice::GetTransform(Gfx::TransformType type)
{
- switch (type)
- {
- case Gfx::TRANSFORM_WORLD:
- return m_worldMat;
- case Gfx::TRANSFORM_VIEW:
- return m_viewMat;
- case Gfx::TRANSFORM_PROJECTION:
- return m_projectionMat;
- default:
- assert(false);
- }
+ if (type == Gfx::TRANSFORM_WORLD)
+ return m_worldMat;
+ else if (type == Gfx::TRANSFORM_VIEW)
+ return m_viewMat;
+ else if (type == Gfx::TRANSFORM_PROJECTION)
+ return m_projectionMat;
+ else
+ assert(false);
return m_worldMat; // to avoid warning
}
void Gfx::CGLDevice::MultiplyTransform(Gfx::TransformType type, const Math::Matrix &matrix)
{
- // TODO
+ if (type == Gfx::TRANSFORM_WORLD)
+ {
+ m_worldMat = Math::MultiplyMatrices(m_worldMat, matrix);
+ m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m_modelviewMat.Array());
+ }
+ else if (type == Gfx::TRANSFORM_VIEW)
+ {
+ m_viewMat = Math::MultiplyMatrices(m_viewMat, matrix);
+ m_modelviewMat = Math::MultiplyMatrices(m_worldMat, m_viewMat);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(m_modelviewMat.Array());
+ }
+ else if (type == Gfx::TRANSFORM_PROJECTION)
+ {
+ m_projectionMat = Math::MultiplyMatrices(m_projectionMat, matrix);
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(m_projectionMat.Array());
+ }
+ else
+ {
+ assert(false);
+ }
}
-void Gfx::CGLDevice::SetMaterial(const Gfx::Material &material)
+void Gfx::CGLDevice::SetMaterial(Gfx::Material &material)
{
m_material = material;
- // TODO
+ glMaterialfv(GL_AMBIENT, GL_FRONT_AND_BACK, m_material.ambient.Array());
+ glMaterialfv(GL_DIFFUSE, GL_FRONT_AND_BACK, m_material.diffuse.Array());
+ glMaterialfv(GL_SPECULAR, GL_FRONT_AND_BACK, m_material.specular.Array());
}
const Gfx::Material& Gfx::CGLDevice::GetMaterial()
@@ -130,14 +264,35 @@ int Gfx::CGLDevice::GetMaxLightCount()
return m_lights.size();
}
-void Gfx::CGLDevice::SetLight(int index, const Gfx::Light &light)
+void Gfx::CGLDevice::SetLight(int index, Gfx::Light &light)
{
assert(index >= 0);
assert(index < (int)m_lights.size());
m_lights[index] = light;
- // TODO
+ // Indexing from GL_LIGHT0 should always work
+ glLightfv(GL_LIGHT0 + index, GL_AMBIENT, light.ambient.Array());
+ glLightfv(GL_LIGHT0 + index, GL_DIFFUSE, light.diffuse.Array());
+ glLightfv(GL_LIGHT0 + index, GL_SPECULAR, light.specular.Array());
+
+ GLfloat position[4] = { light.position.x, light.position.y, light.position.z, 0.0f };
+ if (light.type == LIGHT_DIRECTIONAL)
+ position[3] = 0.0f;
+ else
+ position[3] = 1.0f;
+ glLightfv(GL_LIGHT0 + index, GL_POSITION, position);
+
+ GLfloat direction[4] = { light.direction.x, light.direction.y, light.direction.z, 0.0f };
+ glLightfv(GL_LIGHT0 + index, GL_SPOT_DIRECTION, direction);
+
+ glLightf(GL_LIGHT0 + index, GL_SPOT_CUTOFF, light.range);
+
+ // TODO: falloff?, phi?, theta?
+
+ glLightf(GL_LIGHT0 + index, GL_CONSTANT_ATTENUATION, light.attenuation0);
+ glLightf(GL_LIGHT0 + index, GL_LINEAR_ATTENUATION, light.attenuation1);
+ glLightf(GL_LIGHT0 + index, GL_QUADRATIC_ATTENUATION, light.attenuation2);
}
const Gfx::Light& Gfx::CGLDevice::GetLight(int index)
@@ -155,7 +310,7 @@ void Gfx::CGLDevice::SetLightEnabled(int index, bool enabled)
m_lightsEnabled[index] = enabled;
- // TODO
+ glEnable(GL_LIGHT0 + index);
}
bool Gfx::CGLDevice::GetLightEnabled(int index)
@@ -171,7 +326,7 @@ int Gfx::CGLDevice::GetMaxTextureCount()
return m_textures.size();
}
-const Gfx::Texture& Gfx::CGLDevice::GetTexture(int index)
+Gfx::Texture* Gfx::CGLDevice::GetTexture(int index)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
@@ -179,7 +334,7 @@ const Gfx::Texture& Gfx::CGLDevice::GetTexture(int index)
return m_textures[index];
}
-void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture)
+void Gfx::CGLDevice::SetTexture(int index, Gfx::Texture *texture)
{
assert(index >= 0);
assert(index < (int)m_textures.size());
@@ -189,23 +344,339 @@ void Gfx::CGLDevice::SetTexture(int index, const Gfx::Texture &texture)
// TODO
}
+void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, Vertex *vertices, int vertexCount)
+{
+ if (type == Gfx::PRIMITIVE_LINES)
+ glBegin(GL_LINES);
+ else if (type == Gfx::PRIMITIVE_TRIANGLES)
+ glBegin(GL_TRIANGLES);
+ else if (type == Gfx::PRIMITIVE_TRIANGLE_STRIP)
+ glBegin(GL_TRIANGLE_STRIP);
+
+ for (int i = 0; i < vertexCount; ++i)
+ {
+ glNormal3fv((GLfloat*)vertices[i].normal.Array());
+ glTexCoord2fv((GLfloat*)vertices[i].texCoord.Array());
+ glVertex3fv((GLfloat*)vertices[i].coord.Array());
+ }
+
+ glEnd();
+}
+
+void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount)
+{
+ if (type == Gfx::PRIMITIVE_LINES)
+ glBegin(GL_LINES);
+ else if (type == Gfx::PRIMITIVE_TRIANGLES)
+ glBegin(GL_TRIANGLES);
+ else if (type == Gfx::PRIMITIVE_TRIANGLE_STRIP)
+ glBegin(GL_TRIANGLE_STRIP);
+
+ for (int i = 0; i < vertexCount; ++i)
+ {
+ // TODO: specular?
+ glColor4fv((GLfloat*)vertices[i].color.Array());
+ glTexCoord2fv((GLfloat*)vertices[i].texCoord.Array());
+ glVertex3fv((GLfloat*)vertices[i].coord.Array());
+ }
+
+ glEnd();
+}
+
+void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices, int vertexCount)
+{
+ if (type == Gfx::PRIMITIVE_LINES)
+ glBegin(GL_LINES);
+ else if (type == Gfx::PRIMITIVE_TRIANGLES)
+ glBegin(GL_TRIANGLES);
+ else if (type == Gfx::PRIMITIVE_TRIANGLE_STRIP)
+ glBegin(GL_TRIANGLE_STRIP);
+
+ for (int i = 0; i < vertexCount; ++i)
+ {
+ glNormal3fv((GLfloat*) vertices[i].normal.Array());
+ // TODO glMultiTexCoord2fARB(GL_TEXTURE0_ARB, vertices[i].texCoord.x, vertices[i].texCoord.y);
+ // TODO glMultiTexCoord2fARB(GL_TEXTURE1_ARB, vertices[i].texCoord2.x, vertices[i].texCoord2.y);
+ glVertex3fv((GLfloat*) vertices[i].coord.Array());
+ }
+
+ glEnd();
+}
+
void Gfx::CGLDevice::SetRenderState(Gfx::RenderState state, bool enabled)
{
- // TODO
+ if (state == RENDER_STATE_DEPTH_WRITE)
+ {
+ glDepthMask(enabled ? GL_TRUE : GL_FALSE);
+ return;
+ }
+ else if (state == RENDER_STATE_TEXTURING)
+ {
+ if (enabled)
+ {
+ glEnable(GL_TEXTURE_2D);
+ // TODO multitexture
+ }
+ else
+ {
+ glDisable(GL_TEXTURE_2D);
+ }
+ return;
+ }
+
+ GLenum flag = 0;
+
+ switch (state)
+ {
+ case Gfx::RENDER_STATE_LIGHTING: flag = GL_DEPTH_WRITEMASK; break;
+ case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
+ case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
+ case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
+ case Gfx::RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break;
+ case Gfx::RENDER_STATE_DITHERING: flag = GL_DITHER; break;
+ default: assert(false); break;
+ }
+
+ if (enabled)
+ glEnable(flag);
+ else
+ glDisable(flag);
}
bool Gfx::CGLDevice::GetRenderState(Gfx::RenderState state)
{
- // TODO
- return false;
+ GLenum flag = 0;
+
+ switch (state)
+ {
+ case Gfx::RENDER_STATE_DEPTH_WRITE: flag = GL_DEPTH_WRITEMASK; break;
+ case Gfx::RENDER_STATE_TEXTURING: flag = GL_TEXTURE_2D; break;
+ case Gfx::RENDER_STATE_LIGHTING: flag = GL_DEPTH_WRITEMASK; break;
+ case Gfx::RENDER_STATE_BLENDING: flag = GL_BLEND; break;
+ case Gfx::RENDER_STATE_FOG: flag = GL_FOG; break;
+ case Gfx::RENDER_STATE_DEPTH_TEST: flag = GL_DEPTH_TEST; break;
+ case Gfx::RENDER_STATE_ALPHA_TEST: flag = GL_ALPHA_TEST; break;
+ case Gfx::RENDER_STATE_DITHERING: flag = GL_DITHER; break;
+ default: assert(false); break;
+ }
+
+ GLboolean result = GL_FALSE;
+ glGetBooleanv(flag, &result);
+
+ return result == GL_TRUE;
}
-void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType, Vertex *vertices, int vertexCount)
+Gfx::CompFunc TranslateGLCompFunc(GLenum flag)
{
- // TODO
+ switch (flag)
+ {
+ case GL_NEVER: return Gfx::COMP_FUNC_NEVER;
+ case GL_LESS: return Gfx::COMP_FUNC_LESS;
+ case GL_EQUAL: return Gfx::COMP_FUNC_EQUAL;
+ case GL_NOTEQUAL: return Gfx::COMP_FUNC_NOTEQUAL;
+ case GL_LEQUAL: return Gfx::COMP_FUNC_LEQUAL;
+ case GL_GREATER: return Gfx::COMP_FUNC_GREATER;
+ case GL_GEQUAL: return Gfx::COMP_FUNC_GEQUAL;
+ case GL_ALWAYS: return Gfx::COMP_FUNC_ALWAYS;
+ default: assert(false); break;
+ }
+ return Gfx::COMP_FUNC_NEVER;
}
-void Gfx::CGLDevice::DrawPrimitive(Gfx::PrimitiveType, VertexTex2 *vertices, int vertexCount)
+GLenum TranslateGfxCompFunc(Gfx::CompFunc func)
{
- // TODO
+ switch (func)
+ {
+ case Gfx::COMP_FUNC_NEVER: return GL_NEVER;
+ case Gfx::COMP_FUNC_LESS: return GL_LESS;
+ case Gfx::COMP_FUNC_EQUAL: return GL_EQUAL;
+ case Gfx::COMP_FUNC_NOTEQUAL: return GL_NOTEQUAL;
+ case Gfx::COMP_FUNC_LEQUAL: return GL_LEQUAL;
+ case Gfx::COMP_FUNC_GREATER: return GL_GREATER;
+ case Gfx::COMP_FUNC_GEQUAL: return GL_GEQUAL;
+ case Gfx::COMP_FUNC_ALWAYS: return GL_ALWAYS;
+ default: assert(false); break;
+ }
+ return 0;
+}
+
+void Gfx::CGLDevice::SetDepthTestFunc(Gfx::CompFunc func)
+{
+ glDepthFunc(TranslateGfxCompFunc(func));
+}
+
+Gfx::CompFunc Gfx::CGLDevice::GetDepthTestFunc()
+{
+ GLenum flag = 0;
+ glGetIntegerv(GL_DEPTH_FUNC, (GLint*)&flag);
+ return TranslateGLCompFunc(flag);
+}
+
+void Gfx::CGLDevice::SetDepthBias(float factor)
+{
+ glPolygonOffset(factor, 0.0f);
+}
+
+float Gfx::CGLDevice::GetDepthBias()
+{
+ GLfloat result = 0.0f;
+ glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &result);
+ return result;
+}
+
+void Gfx::CGLDevice::SetAlphaTestFunc(Gfx::CompFunc func, float refValue)
+{
+ glAlphaFunc(TranslateGfxCompFunc(func), refValue);
+}
+
+void Gfx::CGLDevice::GetAlphaTestFunc(Gfx::CompFunc &func, float &refValue)
+{
+ GLenum flag = 0;
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint*)&flag);
+ func = TranslateGLCompFunc(flag);
+
+ glGetFloatv(GL_ALPHA_TEST_REF, (GLfloat*) &refValue);
+}
+
+Gfx::BlendFunc TranslateGLBlendFunc(GLenum flag)
+{
+ switch (flag)
+ {
+ case GL_ZERO: return Gfx::BLEND_ZERO;
+ case GL_ONE: return Gfx::BLEND_ONE;
+ case GL_SRC_COLOR: return Gfx::BLEND_SRC_COLOR;
+ case GL_ONE_MINUS_SRC_COLOR: return Gfx::BLEND_INV_SRC_COLOR;
+ case GL_DST_COLOR: return Gfx::BLEND_DST_COLOR;
+ case GL_ONE_MINUS_DST_COLOR: return Gfx::BLEND_INV_DST_COLOR;
+ case GL_SRC_ALPHA: return Gfx::BLEND_SRC_ALPHA;
+ case GL_ONE_MINUS_SRC_ALPHA: return Gfx::BLEND_INV_SRC_ALPHA;
+ case GL_DST_ALPHA: return Gfx::BLEND_DST_ALPHA;
+ case GL_ONE_MINUS_DST_ALPHA: return Gfx::BLEND_INV_DST_ALPHA;
+ case GL_SRC_ALPHA_SATURATE: return Gfx::BLEND_SRC_ALPHA_SATURATE;
+ default: assert(false); break;
+ }
+
+ return Gfx::BLEND_ZERO;
+}
+
+GLenum TranslateGfxBlendFunc(Gfx::BlendFunc func)
+{
+ switch (func)
+ {
+ case Gfx::BLEND_ZERO: return GL_ZERO;
+ case Gfx::BLEND_ONE: return GL_ONE;
+ case Gfx::BLEND_SRC_COLOR: return GL_SRC_COLOR;
+ case Gfx::BLEND_INV_SRC_COLOR: return GL_ONE_MINUS_SRC_COLOR;
+ case Gfx::BLEND_DST_COLOR: return GL_DST_COLOR;
+ case Gfx::BLEND_INV_DST_COLOR: return GL_ONE_MINUS_DST_COLOR;
+ case Gfx::BLEND_SRC_ALPHA: return GL_SRC_ALPHA;
+ case Gfx::BLEND_INV_SRC_ALPHA: return GL_ONE_MINUS_SRC_ALPHA;
+ case Gfx::BLEND_DST_ALPHA: return GL_DST_ALPHA;
+ case Gfx::BLEND_INV_DST_ALPHA: return GL_ONE_MINUS_DST_ALPHA;
+ case Gfx::BLEND_SRC_ALPHA_SATURATE: return GL_SRC_ALPHA_SATURATE;
+ default: assert(false); break;
+ }
+ return 0;
+}
+
+void Gfx::CGLDevice::SetBlendFunc(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend)
+{
+ glBlendFunc(TranslateGfxBlendFunc(srcBlend), TranslateGfxBlendFunc(dstBlend));
+}
+
+void Gfx::CGLDevice::GetBlendFunc(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend)
+{
+ GLenum srcFlag = 0;
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint*)&srcFlag);
+ srcBlend = TranslateGLBlendFunc(srcFlag);
+
+ GLenum dstFlag = 0;
+ glGetIntegerv(GL_ALPHA_TEST_FUNC, (GLint*)&dstFlag);
+ dstBlend = TranslateGLBlendFunc(dstFlag);
+}
+
+void Gfx::CGLDevice::SetClearColor(Gfx::Color color)
+{
+ glClearColor(color.r, color.g, color.b, color.a);
+}
+
+Gfx::Color Gfx::CGLDevice::GetClearColor()
+{
+ float color[4] = { 0.0f };
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, color);
+ return Gfx::Color(color[0], color[1], color[2], color[3]);
+}
+
+void Gfx::CGLDevice::SetGlobalAmbient(Gfx::Color color)
+{
+ glLightModelfv(GL_LIGHT_MODEL_AMBIENT, color.Array());
+}
+
+Gfx::Color Gfx::CGLDevice::GetGlobalAmbient()
+{
+ float color[4] = { 0.0f };
+ glGetFloatv(GL_LIGHT_MODEL_AMBIENT, color);
+ return Gfx::Color(color[0], color[1], color[2], color[3]);
+}
+
+void Gfx::CGLDevice::SetFogParams(Gfx::FogMode mode, Gfx::Color color, float start, float end, float density)
+{
+ if (mode == Gfx::FOG_LINEAR) glFogi(GL_FOG_MODE, GL_LINEAR);
+ else if (mode == Gfx::FOG_EXP) glFogi(GL_FOG_MODE, GL_EXP);
+ else if (mode == Gfx::FOG_EXP2) glFogi(GL_FOG_MODE, GL_EXP2);
+ else assert(false);
+
+ glFogf(GL_FOG_START, start);
+ glFogf(GL_FOG_END, end);
+ glFogf(GL_FOG_DENSITY, density);
+}
+
+void Gfx::CGLDevice::GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density)
+{
+ GLenum flag = 0;
+ glGetIntegerv(GL_FOG_MODE, (GLint*)&flag);
+ if (flag == GL_LINEAR) mode = Gfx::FOG_LINEAR;
+ else if (flag == GL_EXP) mode = Gfx::FOG_EXP;
+ else if (flag == GL_EXP2) mode = Gfx::FOG_EXP2;
+ else assert(false);
+
+ glGetFloatv(GL_FOG_START, (GLfloat*)&start);
+ glGetFloatv(GL_FOG_END, (GLfloat*)&end);
+ glGetFloatv(GL_FOG_DENSITY, (GLfloat*)&density);
+}
+
+void Gfx::CGLDevice::SetCullMode(Gfx::CullMode mode)
+{
+ if (mode == Gfx::CULL_CW) glCullFace(GL_CW);
+ else if (mode == Gfx::CULL_CCW) glCullFace(GL_CCW);
+ else assert(false);
+}
+
+Gfx::CullMode Gfx::CGLDevice::GetCullMode()
+{
+ GLenum flag = 0;
+ glGetIntegerv(GL_CULL_FACE, (GLint*)&flag);
+ if (flag == GL_CW) return Gfx::CULL_CW;
+ else if (flag == GL_CCW) return Gfx::CULL_CCW;
+ else assert(false);
+ return Gfx::CULL_CW;
+}
+
+void Gfx::CGLDevice::SetFillMode(Gfx::FillMode mode)
+{
+ if (mode == Gfx::FILL_POINT) glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
+ else if (mode == Gfx::FILL_LINES) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+ else if (mode == Gfx::FILL_FILL) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ else assert(false);
+}
+
+Gfx::FillMode Gfx::CGLDevice::GetFillMode()
+{
+ GLenum flag = 0;
+ glGetIntegerv(GL_POLYGON_MODE, (GLint*)&flag);
+ if (flag == GL_POINT) return Gfx::FILL_POINT;
+ else if (flag == GL_LINE) return Gfx::FILL_LINES;
+ else if (flag == GL_FILL) return Gfx::FILL_FILL;
+ else assert(false);
+ return Gfx::FILL_POINT;
}
diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h
index 0b4702a..298eb56 100644
--- a/src/graphics/opengl/gldevice.h
+++ b/src/graphics/opengl/gldevice.h
@@ -21,8 +21,9 @@
#include "graphics/common/device.h"
-
+#include <string>
#include <vector>
+#include <set>
namespace Gfx {
@@ -53,6 +54,8 @@ struct GLDeviceConfig : public DeviceConfig
void LoadDefault();
};
+struct GLDevicePrivate;
+
/**
\class CGLDevice
\brief Implementation of CDevice interface in OpenGL
@@ -70,7 +73,10 @@ public:
CGLDevice();
virtual ~CGLDevice();
- virtual void Initialize();
+ virtual bool GetWasInit();
+ virtual std::string GetError();
+
+ virtual bool Create();
virtual void Destroy();
virtual void BeginScene();
@@ -82,30 +88,67 @@ public:
virtual const Math::Matrix& GetTransform(Gfx::TransformType type);
virtual void MultiplyTransform(Gfx::TransformType type, const Math::Matrix &matrix);
- virtual void SetMaterial(const Gfx::Material &material);
+ virtual void SetMaterial(Gfx::Material &material);
virtual const Gfx::Material& GetMaterial();
virtual int GetMaxLightCount();
- virtual void SetLight(int index, const Gfx::Light &light);
+ virtual void SetLight(int index, Gfx::Light &light);
virtual const Gfx::Light& GetLight(int index);
virtual void SetLightEnabled(int index, bool enabled);
virtual bool GetLightEnabled(int index);
virtual int GetMaxTextureCount();
- virtual const Gfx::Texture& GetTexture(int index);
- virtual void SetTexture(int index, const Gfx::Texture &texture);
+ virtual void SetTexture(int index, Gfx::Texture *texture);
+ virtual Gfx::Texture* GetTexture(int index);
+
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, Vertex *vertices, int vertexCount);
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, Gfx::VertexCol *vertices, int vertexCount);
+ virtual void DrawPrimitive(Gfx::PrimitiveType type, VertexTex2 *vertices, int vertexCount);
+
virtual void SetRenderState(Gfx::RenderState state, bool enabled);
virtual bool GetRenderState(Gfx::RenderState state);
- virtual void DrawPrimitive(Gfx::PrimitiveType, Vertex *vertices, int vertexCount);
- virtual void DrawPrimitive(Gfx::PrimitiveType, VertexTex2 *vertices, int vertexCount);
+ virtual void SetDepthTestFunc(Gfx::CompFunc func);
+ virtual Gfx::CompFunc GetDepthTestFunc();
+
+ virtual void SetDepthBias(float factor);
+ virtual float GetDepthBias();
+
+ virtual void SetAlphaTestFunc(Gfx::CompFunc func, float refValue);
+ virtual void GetAlphaTestFunc(Gfx::CompFunc &func, float &refValue);
+
+ virtual void SetBlendFunc(Gfx::BlendFunc srcBlend, Gfx::BlendFunc dstBlend);
+ virtual void GetBlendFunc(Gfx::BlendFunc &srcBlend, Gfx::BlendFunc &dstBlend);
+
+ virtual void SetClearColor(Gfx::Color color);
+ virtual Gfx::Color GetClearColor();
+
+ virtual void SetGlobalAmbient(Gfx::Color color);
+ virtual Gfx::Color GetGlobalAmbient();
+
+ virtual void SetFogParams(Gfx::FogMode mode, Gfx::Color color, float start, float end, float density);
+ virtual void GetFogParams(Gfx::FogMode &mode, Gfx::Color &color, float &start, float &end, float &density);
+
+ virtual void SetCullMode(Gfx::CullMode mode);
+ virtual Gfx::CullMode GetCullMode();
+
+ virtual void SetFillMode(Gfx::FillMode mode) ;
+ virtual Gfx::FillMode GetFillMode();
private:
+ //! Private, OpenGL-specific data
+ GLDevicePrivate* m_private;
+ //! Was initialized?
+ bool m_wasInit;
+ //! Last encountered error
+ std::string m_error;
//! Current world matrix
Math::Matrix m_worldMat;
//! Current view matrix
Math::Matrix m_viewMat;
+ //! OpenGL modelview matrix = world matrix * view matrix
+ Math::Matrix m_modelviewMat;
//! Current projection matrix
Math::Matrix m_projectionMat;
//! The current material
@@ -115,9 +158,9 @@ private:
//! Current lights enable status
std::vector<bool> m_lightsEnabled;
//! Current textures
- std::vector<Gfx::Texture> m_textures;
- //! Current render state
- unsigned long m_renderState;
+ std::vector<Gfx::Texture*> m_textures;
+ //! Set of all created textures
+ std::set<Gfx::Texture*> m_allTextures;
};
}; // namespace Gfx