diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index acec4e33..e1d9e185 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -40,6 +40,7 @@ #include "gl/system/gl_system.h" +#include "gl/system/gl_cvars.h" #include "gl/data/gl_data.h" #include "gl/renderer/gl_colormap.h" #include "gl/renderer/gl_lightdata.h" @@ -62,6 +63,28 @@ CVAR(Int, gl_weaponlight, 8, CVAR_ARCHIVE); CVAR(Bool,gl_enhanced_nightvision,true,CVAR_ARCHIVE) + +//========================================================================== +// +// +// +//========================================================================== + +bool gl_BrightmapsActive() +{ + return gl.shadermodel == 4 || (gl.shadermodel == 3 && gl_brightmap_shader); +} + +bool gl_GlowActive() +{ + return gl.shadermodel == 4 || (gl.shadermodel == 3 && gl_glow_shader); +} + +bool gl_ExtFogActive() +{ + return gl.shadermodel == 4; +} + //========================================================================== // // Sets up the fog tables diff --git a/src/gl/renderer/gl_lightdata.h b/src/gl/renderer/gl_lightdata.h index c26b1a3f..52f70118 100644 --- a/src/gl/renderer/gl_lightdata.h +++ b/src/gl/renderer/gl_lightdata.h @@ -5,6 +5,10 @@ #include "r_blend.h" #include "gl/renderer/gl_colormap.h" +bool gl_BrightmapsActive(); +bool gl_GlowActive(); +bool gl_ExtFogActive(); + void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending, int *tm, int *sb, int *db, int *be); void gl_SetFogParams(int _fogdensity, PalEntry _outsidefogcolor, int _outsidefogdensity, int _skyfog); diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 98a18389..a0e2390e 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -95,7 +95,7 @@ void FGLRenderer::Initialize() mFBID = 0; //if (gl.flags & RFL_TEXTUREBUFFER) mLightBuffer = new FLightBuffer; SetupLevel(); - gl_InitShaders(); + mShaderManager = new FShaderManager; #ifdef TESTING gl.GenBuffers(1, &idbuffer); @@ -151,7 +151,7 @@ void FGLRenderer::Initialize() FGLRenderer::~FGLRenderer() { FMaterial::FlushAll(); - gl_ClearShaders(); + if (mShaderManager != NULL) delete mShaderManager; if (mVBO != NULL) delete mVBO; if (mLightBuffer != NULL) delete mLightBuffer; if (glpart2) delete glpart2; @@ -175,7 +175,7 @@ void FGLRenderer::SetupLevel() void FGLRenderer::SetPaused() { - gl_DisableShader(); + mShaderManager->SetActiveShader(NULL); gl_RenderState.SetTextureMode(-1); // something invalid } diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index e810c586..c870d80d 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -12,6 +12,7 @@ class OpenGLFrameBuffer; struct FDrawInfo; struct pspdef_t; class FLightBuffer; +class FShaderManager; extern int extralight; @@ -51,6 +52,7 @@ public: float mCurrentFoV; AActor *mViewActor; FLightBuffer *mLightBuffer; + FShaderManager *mShaderManager; int gl_spriteindex; unsigned int mFBID; @@ -81,6 +83,7 @@ public: mVBO = NULL; gl_spriteindex = 0; mLightBuffer = NULL; + mShaderManager = NULL; glpart2 = glpart = gllight = mirrortexture = NULL; } ~FGLRenderer() ; diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 5ab55408..de7bafd5 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -41,15 +41,12 @@ #include "gl/system/gl_system.h" #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_shader.h" +#include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_colormap.h" FRenderState gl_RenderState; int FStateAttr::ChangeCounter; -extern FShader *FogboundaryShader; -extern FShader *SpheremapShader; - - //========================================================================== // @@ -119,23 +116,12 @@ bool FRenderState::ApplyShader() bool useshaders = false; FShader *activeShader = NULL; - switch (mSpecialEffect) + if (mSpecialEffect > 0) + { + activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect); + } + else { - case EFF_FOGBOUNDARY: - FogboundaryShader->Bind(0); - activeShader = FogboundaryShader; - break; - - case EFF_SPHEREMAP: - if (gl.shadermodel == 4 || (gl.shadermodel == 3 && gl_fog_shader)) - { - SpheremapShader->Bind(0); - activeShader = SpheremapShader; - } - break; - - default: - switch (gl.shadermodel) { case 2: @@ -167,8 +153,7 @@ bool FRenderState::ApplyShader() if (useshaders) { - // we need a shader - GLShader *shd = GLShader::Find(mTextureEnabled? mEffectState : 4); + FShaderContainer *shd = GLRenderer->mShaderManager->Get(mTextureEnabled? mEffectState : 4); if (shd != NULL) { @@ -224,6 +209,11 @@ bool FRenderState::ApplyShader() gl.Uniform4f (activeShader->fogcolor_index, mFogColor.r/255.f, mFogColor.g/255.f, mFogColor.b/255.f, mFogDensity * (-LOG2E / 64000.f)); } + if (mGlowEnabled) + { + gl.Uniform4fv(activeShader->glowtopcolor_index, 1, mGlowTop.vec); + gl.Uniform4fv(activeShader->glowbottomcolor_index, 1, mGlowBottom.vec); + } return true; } return false; @@ -240,7 +230,7 @@ void FRenderState::Apply(bool forcenoshader) { if (forcenoshader || !ApplyShader()) { - gl_DisableShader(); + GLRenderer->mShaderManager->SetActiveShader(NULL); if (mTextureMode != ffTextureMode) { gl.SetTextureMode((ffTextureMode = mTextureMode)); diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 46aac048..773b339a 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -12,6 +12,17 @@ struct FStateAttr { mLastChange = -1; } + + bool operator == (const FStateAttr &other) + { + return mLastChange == other.mLastChange; + } + + bool operator != (const FStateAttr &other) + { + return mLastChange != other.mLastChange; + } + }; struct FStateVec3 : public FStateAttr @@ -37,6 +48,30 @@ struct FStateVec3 : public FStateAttr } }; +struct FStateVec4 : public FStateAttr +{ + float vec[4]; + + bool Update(FStateVec4 *other) + { + if (mLastChange != other->mLastChange) + { + *this = *other; + return true; + } + return false; + } + + void Set(float x, float y, float z, float w) + { + vec[0] = x; + vec[1] = z; + vec[2] = y; + vec[3] = w; + mLastChange = ++ChangeCounter; + } +}; + enum EEffect { @@ -57,6 +92,7 @@ class FRenderState float mLightParms[2]; FStateVec3 mCameraPos; + FStateVec4 mGlowTop, mGlowBottom; PalEntry mFogColor; float mFogDensity; @@ -133,6 +169,12 @@ public: mCameraPos.Set(x,y,z); } + void SetGlowParams(float *t, float *b) + { + mGlowTop.Set(t[0], t[1], t[2], t[3]); + mGlowBottom.Set(b[0], b[1], b[2], b[3]); + } + void SetFog(PalEntry c, float d) { mFogColor = c; diff --git a/src/gl/scene/gl_walls_draw.cpp b/src/gl/scene/gl_walls_draw.cpp index 3cbe24cb..3338ff13 100644 --- a/src/gl/scene/gl_walls_draw.cpp +++ b/src/gl/scene/gl_walls_draw.cpp @@ -140,13 +140,9 @@ void GLWall::RenderWall(int textured, float * color2, ADynamicLight * light) glowing = false; } - gl_RenderState.Apply(!!(flags & GLWF_NOSHADER)); + if (glowing) gl_RenderState.SetGlowParams(topglowcolor, bottomglowcolor); - if (glowing) - { - // must be done after gl_ApplyShader! - gl_SetGlowParams(topglowcolor, topglowcolor[3], bottomglowcolor, bottomglowcolor[3]); - } + gl_RenderState.Apply(!!(flags & GLWF_NOSHADER)); // the rest of the code is identical for textured rendering and lights diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index 9cc4afc4..e498bce0 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -47,6 +47,7 @@ #include "doomerrors.h" #include "v_palette.h" +#include "gl/renderer/gl_renderer.h" #include "gl/renderer/gl_renderstate.h" #include "gl/system/gl_cvars.h" #include "gl/shaders/gl_shader.h" @@ -63,30 +64,6 @@ CVAR(Bool, gl_glow_shader, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) extern long gl_frameMS; -static FShader *gl_activeShader; - - -void FShader::SetColormapColor(float r, float g, float b, float r1, float g1, float b1) -{ - //if (fac != currentlightfactor) - { - //currentlightfactor = fac; - gl.Uniform4f(colormapstart_index, r,g,b,0); - gl.Uniform4f(colormaprange_index, r1-r,g1-g,b1-b,0); - } -} - -void FShader::SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight) -{ - gl.Uniform4f(glowtopcolor_index, topcolors[0], topcolors[1], topcolors[2], topheight); - gl.Uniform4f(glowbottomcolor_index, bottomcolors[0], bottomcolors[1], bottomcolors[2], bottomheight); -} - -void FShader::SetLightRange(int start, int end, int forceadd) -{ - gl.Uniform3i(lightrange_index, start, end, forceadd); -} - //========================================================================== // // @@ -208,41 +185,11 @@ FShader::~FShader() bool FShader::Bind(float Speed) { - if (gl_activeShader!=this) - { - gl.UseProgram(hShader); - gl_activeShader=this; - } + GLRenderer->mShaderManager->SetActiveShader(this); if (timer_index >=0 && Speed > 0.f) gl.Uniform1f(timer_index, gl_frameMS*Speed/1000.f); return true; } - - -//========================================================================== -// -// This class contains the shaders for the different lighting modes -// that are required (e.g. special colormaps etc.) -// -//========================================================================== -struct FShaderContainer -{ - friend class GLShader; - - FName Name; - FName TexFileName; - - enum { NUM_SHADERS = 8 }; - - FShader *shader[NUM_SHADERS]; - FShader *shader_cm; // the shader for fullscreen colormaps - -public: - FShaderContainer(const char *ShaderName, const char *ShaderPath); - ~FShaderContainer(); - -}; - //========================================================================== // // @@ -349,157 +296,31 @@ FShaderContainer::~FShaderContainer() // // //========================================================================== -struct FDefaultShader -{ - const char * ShaderName; - const char * gettexelfunc; -}; -static FDefaultShader defaultshaders[]= - { - {"Default", "shaders/glsl/func_normal.fp"}, - {"Warp 1", "shaders/glsl/func_warp1.fp"}, - {"Warp 2", "shaders/glsl/func_warp2.fp"}, - {"Brightmap","shaders/glsl/func_brightmap.fp"}, - {"No Texture", "shaders/glsl/func_notexture.fp"}, - {NULL,NULL} - - }; - -static TArray AllContainers; - -FShader *FogboundaryShader; -FShader *SpheremapShader; - -//========================================================================== -// -// -// -//========================================================================== - -static FShaderContainer * AddShader(const char * name, const char * texfile) -{ - FShaderContainer *sh = new FShaderContainer(name, texfile); - AllContainers.Push(sh); - return sh; -} - - - -static FShaderContainer * GetShader(const char * n,const char * fn) -{ - FName sfn = fn; - - for(unsigned int i=0;iTexFileName == sfn) - { - return AllContainers[i]; - } - } - return AddShader(n, fn); -} - - -//========================================================================== -// -// -// -//========================================================================== - -static TArray AllShaders; - -void GLShader::Initialize() -{ - if (gl.shadermodel > 0) - { - for(int i=0;defaultshaders[i].ShaderName != NULL;i++) - { - FShaderContainer * shc = AddShader(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc); - GLShader * shd = new GLShader; - shd->container = shc; - shd->Name = defaultshaders[i].ShaderName; - AllShaders.Push(shd); - if (gl.shadermodel <= 2) break; // SM2 will only initialize the default shader - } - } - FogboundaryShader = new FShader(); - if (!FogboundaryShader->Load("fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "#define NO_GLOW\n")) - { - delete FogboundaryShader; - FogboundaryShader = NULL; - } - - SpheremapShader = new FShader(); - if (!SpheremapShader->Load("spheremap", "shaders/glsl/main_spheremap.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define NO_GLOW\n#define NO_DESATURATE\n")) - { - delete SpheremapShader; - SpheremapShader = NULL; - } -} - -void GLShader::Clear() -{ - for(unsigned int i=0;iName == sfn) - { - return AllShaders[i]; - } - } - return NULL; -} - -GLShader *GLShader::Find(unsigned int warp) -{ - // indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom - if (warp < AllShaders.Size()) - { - return AllShaders[warp]; - } - return NULL; -} - - -FShader *GLShader::Bind(int cm, bool glowing, float Speed, bool lights) +FShader *FShaderContainer::Bind(int cm, bool glowing, float Speed, bool lights) { FShader *sh=NULL; if (cm >= CM_FIRSTSPECIALCOLORMAP && cm < CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size()) { // these are never used with any kind of lighting or fog - sh = container->shader_cm; + sh = shader_cm; // [BB] If there was a problem when loading the shader, sh is NULL here. if( sh ) { FSpecialColormap *map = &SpecialColormaps[cm - CM_FIRSTSPECIALCOLORMAP]; sh->Bind(Speed); - sh->SetColormapColor(map->ColorizeStart[0], map->ColorizeStart[1], map->ColorizeStart[2], - map->ColorizeEnd[0], map->ColorizeEnd[1], map->ColorizeEnd[2]); + float m[3]= {map->ColorizeEnd[0] - map->ColorizeStart[0], + map->ColorizeEnd[1] - map->ColorizeStart[1], map->ColorizeEnd[2] - map->ColorizeStart[2]}; + + gl.Uniform3fv(sh->colormapstart_index, 1, map->ColorizeStart); + gl.Uniform3fv(sh->colormaprange_index, 1, m); } } else { bool desat = cm>=CM_DESAT1 && cm<=CM_DESAT31; - sh = container->shader[glowing + 2*desat + 4*lights]; + sh = shader[glowing + 2*desat + 4*lights]; // [BB] If there was a problem when loading the shader, sh is NULL here. if( sh ) { @@ -513,71 +334,163 @@ FShader *GLShader::Bind(int cm, bool glowing, float Speed, bool lights) return sh; } -void GLShader::Unbind() + +//========================================================================== +// +// +// +//========================================================================== +struct FDefaultShader { - if (gl.shadermodel > 0 && gl_activeShader != NULL) + const char * ShaderName; + const char * gettexelfunc; +}; + +static const FDefaultShader defaultshaders[]= +{ + {"Default", "shaders/glsl/func_normal.fp"}, + {"Warp 1", "shaders/glsl/func_warp1.fp"}, + {"Warp 2", "shaders/glsl/func_warp2.fp"}, + {"Brightmap","shaders/glsl/func_brightmap.fp"}, + {"No Texture", "shaders/glsl/func_notexture.fp"}, + {NULL,NULL} + +}; + +struct FEffectShader +{ + const char *ShaderName; + const char *vp; + const char *fp1; + const char *fp2; + const char *defines; +}; + +static const FEffectShader effectshaders[]= +{ + {"fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "#define NO_GLOW\n"}, + {"spheremap", "shaders/glsl/main_spheremap.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define NO_GLOW\n#define NO_DESATURATE\n"} +}; + + +//========================================================================== +// +// +// +//========================================================================== + +FShaderManager::FShaderManager() +{ + mActiveShader = mEffectShaders[0] = mEffectShaders[1] = NULL; + if (gl.shadermodel > 0) { - gl.UseProgram(0); - gl_activeShader=NULL; + for(int i=0;defaultshaders[i].ShaderName != NULL;i++) + { + FShaderContainer * shc = new FShaderContainer(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc); + mTextureEffects.Push(shc); + if (gl.shadermodel <= 2) return; // SM2 will only initialize the default shader + } + + for(int i=0;iLoad(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, + effectshaders[i].fp2, effectshaders[i].defines)) + { + delete eff; + } + else mEffectShaders[i] = eff; + } } } +//========================================================================== +// +// +// +//========================================================================== + +FShaderManager::~FShaderManager() +{ + SetActiveShader(NULL); + for(unsigned int i=0;iName == sfn) + { + return i; + } + } + return -1; +} + +//========================================================================== +// +// +// +//========================================================================== + +void FShaderManager::SetActiveShader(FShader *sh) +{ + // shadermodel needs to be tested here because without it UseProgram will be NULL. + if (gl.shadermodel > 0 && mActiveShader != sh) + { + gl.UseProgram(sh == NULL? 0 : sh->GetHandle()); + mActiveShader = sh; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +FShader *FShaderManager::BindEffect(int effect) +{ + if (effect > 0 && effect <= NUM_EFFECTS) + { + mEffectShaders[effect-1]->Bind(0); + return mEffectShaders[effect-1]; + } + return NULL; +} + //========================================================================== // // Dynamic light stuff // //========================================================================== +/* +void FShader::SetLightRange(int start, int end, int forceadd) +{ + gl.Uniform3i(lightrange_index, start, end, forceadd); +} + void gl_SetLightRange(int first, int last, int forceadd) { if (gl_activeShader) gl_activeShader->SetLightRange(first, last, forceadd); } +*/ -//========================================================================== -// -// Glow stuff -// -//========================================================================== - - -void gl_SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight) -{ - if (gl_activeShader) gl_activeShader->SetGlowParams(topcolors, topheight, bottomcolors, bottomheight); -} - -//========================================================================== -// -// -// -//========================================================================== - -void gl_InitShaders() -{ - GLShader::Initialize(); -} - -void gl_DisableShader() -{ - GLShader::Unbind(); -} - -void gl_ClearShaders() -{ - GLShader::Clear(); -} - -bool gl_BrightmapsActive() -{ - return gl.shadermodel == 4 || (gl.shadermodel == 3 && gl_brightmap_shader); -} - -bool gl_GlowActive() -{ - return gl.shadermodel == 4 || (gl.shadermodel == 3 && gl_glow_shader); -} - -bool gl_ExtFogActive() -{ - return gl.shadermodel == 4; -} diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index 3d183b07..c3324303 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -16,24 +16,9 @@ const int VATTR_GLOWDISTANCE = 15; // //========================================================================== -bool gl_BrightmapsActive(); -bool gl_GlowActive(); -bool gl_ExtFogActive(); - -void gl_DisableShader(); -void gl_ClearShaders(); -void gl_InitShaders(); - -void gl_EnableShader(bool on); - - -void gl_SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight); -void gl_SetLightRange(int first, int last, int forceadd); - - class FShader { - friend class GLShader; + friend class FShaderContainer; friend class FRenderState; unsigned int hShader; @@ -81,28 +66,70 @@ public: void SetLightRange(int start, int end, int forceadd); bool Bind(float Speed); + unsigned int GetHandle() const { return hShader; } }; -struct FShaderContainer; +//========================================================================== +// +// This class contains the shaders for the different lighting modes +// that are required (e.g. special colormaps etc.) +// +//========================================================================== -class GLShader +class FShaderContainer { + friend class FShaderManager; + FName Name; - FShaderContainer *container; + + enum { NUM_SHADERS = 8 }; + + FShader *shader[NUM_SHADERS]; + FShader *shader_cm; // the shader for fullscreen colormaps public: - - static void Initialize(); - static void Clear(); - static GLShader *Find(const char * shn); - static GLShader *Find(unsigned int warp); + FShaderContainer(const char *ShaderName, const char *ShaderPath); + ~FShaderContainer(); FShader *Bind(int cm, bool glowing, float Speed, bool lights); - static void Unbind(); - + }; +//========================================================================== +// +// The global shader manager +// +//========================================================================== +class FShaderManager +{ + enum { NUM_EFFECTS = 2 }; + + TArray mTextureEffects; + FShader *mActiveShader; + FShader *mEffectShaders[NUM_EFFECTS]; + +public: + FShaderManager(); + ~FShaderManager(); + int Find(const char *mame); + FShader *BindEffect(int effect); + void SetActiveShader(FShader *sh); + + FShaderContainer *Get(unsigned int eff) + { + // indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom + if (eff < mTextureEffects.Size()) + { + return mTextureEffects[eff]; + } + return NULL; + } + + + +}; + #endif diff --git a/src/gl/system/gl_interface.h b/src/gl/system/gl_interface.h index 08b5dca5..7a459f96 100644 --- a/src/gl/system/gl_interface.h +++ b/src/gl/system/gl_interface.h @@ -17,6 +17,7 @@ enum RenderFlags RFL_MAP_BUFFER_RANGE = 1024, RFL_FRAMEBUFFER = 2048, RFL_TEXTUREBUFFER = 4096, + RFL_UNIFORM1024 = 8192, RFL_GL_20 = 0x10000000, diff --git a/src/gl/utility/gl_geometric.h b/src/gl/utility/gl_geometric.h index 61e71b0f..3d9955d4 100644 --- a/src/gl/utility/gl_geometric.h +++ b/src/gl/utility/gl_geometric.h @@ -23,6 +23,14 @@ public: m_length=-1.0f; } + Vector(float *v) + { + SetX(v[0]); + SetY(v[1]); + SetZ(v[2]); + m_length=-1.0f; + } + Vector(vertex_t * v) { SetX(v->fx);