#include "irender.h"
#include "itextures.h"
#include "igl.h"
+#include "iglrender.h"
#include "renderable.h"
#include "qerplugin.h"
bool g_bumpGLSLPass_enabled = false;
bool g_depthfillPass_enabled = false;
-class GLProgram
-{
-public:
- virtual void enable() = 0;
- virtual void disable() = 0;
- virtual void setParameters(const Vector3& viewer, const Matrix4& localToWorld, const Vector3& origin, const Vector3& colour, const Matrix4& world2light) = 0;
-};
-
class GLSLBumpProgram : public GLProgram
{
public:
bool g_texcoordArray_enabled = false;
bool g_colorArray_enabled = false;
-//! A collection of opengl state information.
-class OpenGLState
-{
-public:
- enum ESort
- {
- eSortFirst = 0,
- eSortOpaque = 1,
- eSortMultiFirst = 2,
- eSortMultiLast = 1023,
- eSortOverbrighten = 1024,
- eSortFullbright = 1025,
- eSortHighlight = 1026,
- eSortTranslucent = 1027,
- eSortOverlayFirst = 1028,
- eSortOverlayLast = 2047,
- eSortControlFirst = 2048,
- eSortControlLast = 3071,
- eSortGUI0 = 3072,
- eSortGUI1 = 3073,
- eSortLast = 4096,
- };
-
- unsigned int m_state;
- std::size_t m_sort;
- GLint m_texture;
- GLint m_texture1;
- GLint m_texture2;
- GLint m_texture3;
- GLint m_texture4;
- GLint m_texture5;
- GLint m_texture6;
- GLint m_texture7;
- Vector4 m_colour;
- GLenum m_blend_src, m_blend_dst;
- GLenum m_depthfunc;
- GLenum m_alphafunc;
- GLfloat m_alpharef;
- GLfloat m_linewidth;
- GLfloat m_pointsize;
- GLint m_linestipple_factor;
- GLushort m_linestipple_pattern;
- GLProgram* m_program;
-
- OpenGLState() : m_program(0)
- {
- }
-};
-
inline bool OpenGLState_less(const OpenGLState& self, const OpenGLState& other)
{
//! Sort by sort-order override.
state.m_linestipple_factor = 1;
state.m_linestipple_pattern = 0xaaaa;
+
+ state.m_fog = OpenGLFogState();
}
}
};
+inline void setFogState(const OpenGLFogState& state)
+{
+ glFogi(GL_FOG_MODE, state.mode);
+ glFogf(GL_FOG_DENSITY, state.density);
+ glFogf(GL_FOG_START, state.start);
+ glFogf(GL_FOG_END, state.end);
+ glFogi(GL_FOG_INDEX, state.index);
+ glFogfv(GL_FOG_COLOR, vector4_to_array(state.colour));
+}
+
#define DEBUG_SHADERS 0
class OpenGLShaderCache : public ShaderCache, public TexturesCacheObserver, public ModuleObserver
glLineWidth(1);
glPointSize(1);
+ glHint(GL_FOG_HINT, GL_NICEST);
+ glDisable(GL_FOG);
+ setFogState(OpenGLFogState());
+
GlobalOpenGL_debugAssertNoErrors();
debug_string("begin rendering");
{
ASSERT_MESSAGE(!m_traverseRenderablesMutex, "for-each during traversal");
m_traverseRenderablesMutex = true;
- for(Renderables::iterator i = m_renderables.begin(); i != m_renderables.end(); ++i)
+ for(Renderables::const_iterator i = m_renderables.begin(); i != m_renderables.end(); ++i)
{
callback(*(*i));
}
}
}
+inline void setState(unsigned int state, unsigned int delta, unsigned int flag, GLenum glflag)
+{
+ if(delta & state & flag)
+ {
+ glEnable(glflag);
+ GlobalOpenGL_debugAssertNoErrors();
+ }
+ else if(delta & ~state & flag)
+ {
+ glDisable(glflag);
+ GlobalOpenGL_debugAssertNoErrors();
+ }
+}
+
void OpenGLState_apply(const OpenGLState& self, OpenGLState& current, unsigned int globalstate)
{
debug_int("sort", int(self.m_sort));
GlobalOpenGL_debugAssertNoErrors();
}
- if(delta & state & RENDER_OFFSETLINE)
- {
- glEnable(GL_POLYGON_OFFSET_LINE);
- }
- else if(delta & ~state & RENDER_OFFSETLINE)
- {
- glDisable(GL_POLYGON_OFFSET_LINE);
- }
+ setState(state, delta, RENDER_OFFSETLINE, GL_POLYGON_OFFSET_LINE);
if(delta & state & RENDER_LIGHTING)
{
GlobalOpenGL_debugAssertNoErrors();
}
- if(delta & state & RENDER_CULLFACE)
- {
- glEnable(GL_CULL_FACE);
- GlobalOpenGL_debugAssertNoErrors();
- }
- else if(delta & ~state & RENDER_CULLFACE)
- {
- glDisable(GL_CULL_FACE);
- GlobalOpenGL_debugAssertNoErrors();
- }
+ setState(state, delta, RENDER_CULLFACE, GL_CULL_FACE);
if(delta & state & RENDER_SMOOTH)
{
GlobalOpenGL_debugAssertNoErrors();
}
- if(delta & state & RENDER_SCALED)
- {
- //qglEnable(GL_RESCALE_NORMAL);
- glEnable(GL_NORMALIZE);
- GlobalOpenGL_debugAssertNoErrors();
- }
- else if(delta & ~state & RENDER_SCALED)
- {
- //qglDisable(GL_RESCALE_NORMAL);
- glDisable(GL_NORMALIZE);
- GlobalOpenGL_debugAssertNoErrors();
- }
+ setState(state, delta, RENDER_SCALED, GL_NORMALIZE); // not GL_RESCALE_NORMAL
- if(delta & state & RENDER_DEPTHTEST)
- {
- glEnable(GL_DEPTH_TEST);
- GlobalOpenGL_debugAssertNoErrors();
- }
- else if(delta & ~state & RENDER_DEPTHTEST)
- {
- glDisable(GL_DEPTH_TEST);
- GlobalOpenGL_debugAssertNoErrors();
- }
+ setState(state, delta, RENDER_DEPTHTEST, GL_DEPTH_TEST);
if(delta & state & RENDER_DEPTHWRITE)
{
GlobalOpenGL_debugAssertNoErrors();
}
- if(delta & state & RENDER_ALPHATEST)
- {
- glEnable(GL_ALPHA_TEST);
- GlobalOpenGL_debugAssertNoErrors();
- }
- else if(delta & ~state & RENDER_ALPHATEST)
- {
- glDisable(GL_ALPHA_TEST);
- GlobalOpenGL_debugAssertNoErrors();
- }
+ setState(state, delta, RENDER_ALPHATEST, GL_ALPHA_TEST);
- if(delta & state & RENDER_COLOUR)
+ if(delta & state & RENDER_COLOURARRAY)
{
glEnableClientState(GL_COLOR_ARRAY);
GlobalOpenGL_debugAssertNoErrors();
debug_colour("enabling color_array");
g_colorArray_enabled = true;
}
- else if(delta & ~state & RENDER_COLOUR)
+ else if(delta & ~state & RENDER_COLOURARRAY)
{
glDisableClientState(GL_COLOR_ARRAY);
glColor4fv(vector4_to_array(self.m_colour));
g_colorArray_enabled = false;
}
- if(delta & state & RENDER_LINESTIPPLE)
- {
- glEnable(GL_LINE_STIPPLE);
- GlobalOpenGL_debugAssertNoErrors();
- }
- else if(delta & ~state & RENDER_LINESTIPPLE)
+ if(delta & ~state & RENDER_COLOURCHANGE)
{
- glDisable(GL_LINE_STIPPLE);
+ glColor4fv(vector4_to_array(self.m_colour));
GlobalOpenGL_debugAssertNoErrors();
}
- if(delta & state & RENDER_POLYGONSTIPPLE)
- {
- glEnable(GL_POLYGON_STIPPLE);
- GlobalOpenGL_debugAssertNoErrors();
- }
- else if(delta & ~state & RENDER_POLYGONSTIPPLE)
+ setState(state, delta, RENDER_LINESTIPPLE, GL_LINE_STIPPLE);
+ setState(state, delta, RENDER_LINESMOOTH, GL_LINE_SMOOTH);
+
+ setState(state, delta, RENDER_POLYGONSTIPPLE, GL_POLYGON_STIPPLE);
+ setState(state, delta, RENDER_POLYGONSMOOTH, GL_POLYGON_SMOOTH);
+
+ setState(state, delta, RENDER_FOG, GL_FOG);
+
+ if((state & RENDER_FOG) != 0)
{
- glDisable(GL_POLYGON_STIPPLE);
+ setFogState(self.m_fog);
GlobalOpenGL_debugAssertNoErrors();
+ current.m_fog = self.m_fog;
}
if(state & RENDER_DEPTHTEST && self.m_depthfunc != current.m_depthfunc)
}
}
+
+class OpenGLStateMap : public OpenGLStateLibrary
+{
+ typedef std::map<CopiedString, OpenGLState> States;
+ States m_states;
+public:
+ ~OpenGLStateMap()
+ {
+ ASSERT_MESSAGE(m_states.empty(), "OpenGLStateMap::~OpenGLStateMap: not empty");
+ }
+
+ typedef States::iterator iterator;
+ iterator begin()
+ {
+ return m_states.begin();
+ }
+ iterator end()
+ {
+ return m_states.end();
+ }
+
+ void getDefaultState(OpenGLState& state) const
+ {
+ OpenGLState_constructDefault(state);
+ }
+
+ void insert(const char* name, const OpenGLState& state)
+ {
+ bool inserted = m_states.insert(States::value_type(name, state)).second;
+ ASSERT_MESSAGE(inserted, "OpenGLStateMap::insert: " << name << " already exists");
+ }
+ void erase(const char* name)
+ {
+ std::size_t count = m_states.erase(name);
+ ASSERT_MESSAGE(count == 1, "OpenGLStateMap::erase: " << name << " does not exist");
+ }
+
+ iterator find(const char* name)
+ {
+ return m_states.find(name);
+ }
+};
+
+OpenGLStateMap* g_openglStates = 0;
+
inline GLenum convertBlendFactor(BlendFactor factor)
{
switch(factor)
break;
case '$':
+ {
+ OpenGLStateMap::iterator i = g_openglStates->find(name);
+ if(i != g_openglStates->end())
+ {
+ state = (*i).second;
+ break;
+ }
+ }
if(string_equal(name+1, "POINT"))
{
- state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
+ state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
state.m_sort = OpenGLState::eSortControlFirst;
state.m_pointsize = 4;
}
else if(string_equal(name+1, "SELPOINT"))
{
- state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
+ state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
state.m_sort = OpenGLState::eSortControlFirst + 1;
state.m_pointsize = 4;
}
else if(string_equal(name+1, "BIGPOINT"))
{
- state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
+ state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
state.m_sort = OpenGLState::eSortControlFirst;
state.m_pointsize = 6;
}
else if(string_equal(name+1, "PIVOT"))
{
- state.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_DEPTHWRITE;
+ state.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_DEPTHWRITE;
state.m_sort = OpenGLState::eSortGUI1;
state.m_linewidth = 2;
state.m_depthfunc = GL_LEQUAL;
OpenGLState& hiddenLine = appendDefaultPass();
- hiddenLine.m_state = RENDER_COLOUR|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_LINESTIPPLE;
+ hiddenLine.m_state = RENDER_COLOURARRAY|RENDER_COLOURWRITE|RENDER_DEPTHTEST|RENDER_LINESTIPPLE;
hiddenLine.m_sort = OpenGLState::eSortGUI0;
hiddenLine.m_linewidth = 2;
hiddenLine.m_depthfunc = GL_GREATER;
state.m_colour[2] = 0;
state.m_colour[3] = 0.3f;
state.m_state = RENDER_FILL|RENDER_DEPTHTEST|RENDER_CULLFACE|RENDER_BLEND|RENDER_COLOURWRITE|RENDER_DEPTHWRITE;
- state.m_sort = OpenGLState::eSortHighlight;
+
+ // The bug "Selecting translucent brushes, such as clip, cause them to disappear leaving
+ // only the red selection box." seems to be fixed by removing the next line.
+
+ // state.m_sort = OpenGLState::eSortHighlight;
state.m_depthfunc = GL_LEQUAL;
}
else if(string_equal(name+1, "CAM_OVERLAY"))
}
else if(string_equal(name+1, "DEBUG_CLIPPED"))
{
- state.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
+ state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE;
state.m_sort = OpenGLState::eSortLast;
}
else if(string_equal(name+1, "POINTFILE"))
else if(string_equal(name+1, "WIRE_OVERLAY"))
{
#if 0
- state.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
+ state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
state.m_sort = OpenGLState::eSortOverlayFirst;
#else
- state.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
+ state.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
state.m_sort = OpenGLState::eSortGUI1;
state.m_depthfunc = GL_LEQUAL;
OpenGLState& hiddenLine = appendDefaultPass();
- hiddenLine.m_state = RENDER_COLOUR | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE;
+ hiddenLine.m_state = RENDER_COLOURARRAY | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_LINESTIPPLE;
hiddenLine.m_sort = OpenGLState::eSortGUI0;
hiddenLine.m_depthfunc = GL_GREATER;
#endif
}
else if(string_equal(name+1, "FLATSHADE_OVERLAY"))
{
- state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOUR | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
+ state.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE;
state.m_sort = OpenGLState::eSortGUI1;
state.m_depthfunc = GL_LEQUAL;
OpenGLState& hiddenLine = appendDefaultPass();
- hiddenLine.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOUR | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_POLYGONSTIPPLE;
+ hiddenLine.m_state = RENDER_CULLFACE | RENDER_LIGHTING | RENDER_SMOOTH | RENDER_SCALED | RENDER_COLOURARRAY | RENDER_FILL | RENDER_COLOURWRITE | RENDER_DEPTHWRITE | RENDER_DEPTHTEST | RENDER_OVERRIDE | RENDER_POLYGONSTIPPLE;
hiddenLine.m_sort = OpenGLState::eSortGUI0;
hiddenLine.m_depthfunc = GL_GREATER;
}
#include "modulesystem/singletonmodule.h"
#include "modulesystem/moduleregistry.h"
-class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef
+class OpenGLStateLibraryAPI
+{
+ OpenGLStateMap m_stateMap;
+public:
+ typedef OpenGLStateLibrary Type;
+ STRING_CONSTANT(Name, "*");
+
+ OpenGLStateLibraryAPI()
+ {
+ g_openglStates = &m_stateMap;
+ }
+ ~OpenGLStateLibraryAPI()
+ {
+ g_openglStates = 0;
+ }
+ OpenGLStateLibrary* getTable()
+ {
+ return &m_stateMap;
+ }
+};
+
+typedef SingletonModule<OpenGLStateLibraryAPI> OpenGLStateLibraryModule;
+typedef Static<OpenGLStateLibraryModule> StaticOpenGLStateLibraryModule;
+StaticRegisterModule staticRegisterOpenGLStateLibrary(StaticOpenGLStateLibraryModule::instance());
+
+class ShaderCacheDependencies : public GlobalShadersModuleRef, public GlobalTexturesModuleRef, public GlobalOpenGLStateLibraryModuleRef
{
public:
ShaderCacheDependencies() :
typedef SingletonModule<ShaderCacheAPI, ShaderCacheDependencies> ShaderCacheModule;
typedef Static<ShaderCacheModule> StaticShaderCacheModule;
StaticRegisterModule staticRegisterShaderCache(StaticShaderCacheModule::instance());
+
+