- Cleanup of shader maintenance code.

git-svn-id: http://mancubus.net/svn/hosted/gzdoom/trunk@530 b0f79afe-0144-0410-b225-9a4edf0717df
This commit is contained in:
Christoph Oelckers 2009-10-07 12:45:34 +00:00
parent c99241c60e
commit 007b6bade4
11 changed files with 305 additions and 298 deletions

View file

@ -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

View file

@ -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);

View file

@ -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
}

View file

@ -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() ;

View file

@ -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));

View file

@ -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;

View file

@ -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

View file

@ -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<FShaderContainer *> 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;i<AllContainers.Size();i++)
{
if (AllContainers[i]->TexFileName == sfn)
{
return AllContainers[i];
}
}
return AddShader(n, fn);
}
//==========================================================================
//
//
//
//==========================================================================
static TArray<GLShader *> 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;i<AllContainers.Size();i++)
{
delete AllContainers[i];
}
for(unsigned int i=0;i<AllShaders.Size();i++)
{
delete AllShaders[i];
}
AllContainers.Clear();
AllShaders.Clear();
delete FogboundaryShader;
delete SpheremapShader;
}
GLShader *GLShader::Find(const char * shn)
{
FName sfn = shn;
for(unsigned int i=0;i<AllShaders.Size();i++)
{
if (AllContainers[i]->Name == 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;i<NUM_EFFECTS;i++)
{
FShader *eff = new FShader();
if (!eff->Load(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;i<mTextureEffects.Size();i++)
{
if (mTextureEffects[i] != NULL) delete mTextureEffects[i];
}
for(int i=0;i<NUM_EFFECTS;i++)
{
if (mEffectShaders[i] != NULL) delete mEffectShaders[i];
}
}
//==========================================================================
//
//
//
//==========================================================================
int FShaderManager::Find(const char * shn)
{
FName sfn = shn;
for(unsigned int i=0;i<mTextureEffects.Size();i++)
{
if (mTextureEffects[i]->Name == 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;
}

View file

@ -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<FShaderContainer*> 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

View file

@ -17,6 +17,7 @@ enum RenderFlags
RFL_MAP_BUFFER_RANGE = 1024,
RFL_FRAMEBUFFER = 2048,
RFL_TEXTUREBUFFER = 4096,
RFL_UNIFORM1024 = 8192,
RFL_GL_20 = 0x10000000,

View file

@ -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);