diff --git a/src/gl/renderer/gl_colormap.h b/src/gl/renderer/gl_colormap.h index 7d2bdb7ee..8126cb5d4 100644 --- a/src/gl/renderer/gl_colormap.h +++ b/src/gl/renderer/gl_colormap.h @@ -15,13 +15,11 @@ enum EColorManipulation CM_DEFAULT=0, // untranslated CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap - // special internal values for texture creation - CM_SHADE= 0x10000002, // alpha channel texture + CM_FOGLAYER = 0x10000000, // Sprite shaped fog layer // These are not to be passed to the texture manager CM_LITE = 0x20000000, // special values to handle these items without excessive hacking CM_TORCH= 0x20000010, // These are not real color manipulations - CM_FOGLAYER= 0x20000020, // Sprite shaped fog layer }; #define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size()) diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index 71198bafe..7efa1d30f 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -38,6 +38,7 @@ ** */ +#include "templates.h" #include "gl/system/gl_system.h" #include "gl/system/gl_interface.h" #include "gl/data/gl_data.h" @@ -51,7 +52,6 @@ void gl_SetTextureMode(int type); FRenderState gl_RenderState; -int FStateAttr::ChangeCounter; CVAR(Bool, gl_direct_state_change, true, 0) @@ -71,6 +71,7 @@ void FRenderState::Reset() mFogColor.d = ffFogColor.d = -1; mFogDensity = ffFogDensity = 0; mTextureMode = ffTextureMode = -1; + mDesaturation = 0; mSrcBlend = GL_SRC_ALPHA; mDstBlend = GL_ONE_MINUS_SRC_ALPHA; glSrcBlend = glDstBlend = -1; @@ -83,6 +84,7 @@ void FRenderState::Reset() m2D = true; mVertexBuffer = mCurrentVertexBuffer = NULL; mColormapState = CM_DEFAULT; + mLightParms[3] = -1.f; } @@ -128,11 +130,12 @@ bool FRenderState::ApplyShader() { activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect); } - FShaderContainer *shd = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4); + FShader *shd = GLRenderer->mShaderManager->Get(mTextureEnabled? mEffectState : 4); if (shd != NULL) { - activeShader = shd->Bind(mColormapState, mGlowEnabled, mWarpTime, mLightEnabled); + activeShader = shd; + shd->Bind(); } int fogset = 0; @@ -149,74 +152,93 @@ bool FRenderState::ApplyShader() } } - if (fogset != activeShader->currentfogenabled) - { - glUniform1i(activeShader->fogenabled_index, (activeShader->currentfogenabled = fogset)); - } - if (mTextureMode != activeShader->currenttexturemode) - { - glUniform1i(activeShader->texturemode_index, (activeShader->currenttexturemode = mTextureMode)); - } - if (activeShader->currentcamerapos.Update(&mCameraPos)) - { - glUniform3fv(activeShader->camerapos_index, 1, mCameraPos.vec); - } - /*if (mLightParms[0] != activeShader->currentlightfactor || - mLightParms[1] != activeShader->currentlightdist || - mFogDensity != activeShader->currentfogdensity)*/ - { - const float LOG2E = 1.442692f; // = 1/log(2) - //activeShader->currentlightdist = mLightParms[1]; - //activeShader->currentlightfactor = mLightParms[0]; - //activeShader->currentfogdensity = mFogDensity; - // premultiply the density with as much as possible here to reduce shader - // execution time. - glVertexAttrib4f(VATTR_FOGPARAMS, mLightParms[0], mLightParms[1], mFogDensity * (-LOG2E / 64000.f), 0); - } - if (mFogColor != activeShader->currentfogcolor) - { - activeShader->currentfogcolor = mFogColor; + glColor4fv(mColor.vec); + + activeShader->muDesaturation.Set(mDesaturation); + activeShader->muFogEnabled.Set(fogset); + activeShader->muTextureMode.Set(mTextureMode); + activeShader->muCameraPos.Set(mCameraPos.vec); + activeShader->muLightParms.Set(mLightParms); + activeShader->muFogColor.Set(mFogColor); + activeShader->muObjectColor.Set(mObjectColor); + activeShader->muDynLightColor.Set(mDynColor); - glUniform4f (activeShader->fogcolor_index, mFogColor.r/255.f, mFogColor.g/255.f, - mFogColor.b/255.f, 0); - } if (mGlowEnabled) { - glUniform4fv(activeShader->glowtopcolor_index, 1, mGlowTop.vec); - glUniform4fv(activeShader->glowbottomcolor_index, 1, mGlowBottom.vec); - glUniform4fv(activeShader->glowtopplane_index, 1, mGlowTopPlane.vec); - glUniform4fv(activeShader->glowbottomplane_index, 1, mGlowBottomPlane.vec); + activeShader->muGlowTopColor.Set(mGlowTop.vec); + activeShader->muGlowBottomColor.Set(mGlowBottom.vec); + activeShader->muGlowTopPlane.Set(mGlowTopPlane.vec); + activeShader->muGlowBottomPlane.Set(mGlowBottomPlane.vec); activeShader->currentglowstate = 1; } else if (activeShader->currentglowstate) { // if glowing is on, disable it. - glUniform4f(activeShader->glowtopcolor_index, 0.f, 0.f, 0.f, 0.f); - glUniform4f(activeShader->glowbottomcolor_index, 0.f, 0.f, 0.f, 0.f); + static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f }; + activeShader->muGlowTopColor.Set(nulvec); + activeShader->muGlowBottomColor.Set(nulvec); + activeShader->muGlowTopPlane.Set(nulvec); + activeShader->muGlowBottomPlane.Set(nulvec); activeShader->currentglowstate = 0; } if (mLightEnabled) { - glUniform3iv(activeShader->lightrange_index, 1, mNumLights); - glUniform4fv(activeShader->lights_index, mNumLights[2], mLightData); + activeShader->muLightRange.Set(mNumLights); + glUniform4fv(activeShader->lights_index, mNumLights[3], mLightData); } - if (mObjectColor != activeShader->currentobjectcolor) + else { - activeShader->currentobjectcolor = mObjectColor; - glUniform4f(activeShader->objectcolor_index, mObjectColor.r / 255.f, mObjectColor.g / 255.f, mObjectColor.b / 255.f, mObjectColor.a / 255.f); - } - if (mDynColor != activeShader->currentdlightcolor) - { - activeShader->currentobjectcolor = mObjectColor; - glUniform4f(activeShader->dlightcolor_index, mDynColor.r / 255.f, mDynColor.g / 255.f, mDynColor.b / 255.f, 0); + static const int nulint[] = { 0, 0, 0, 0 }; + activeShader->muLightRange.Set(nulint); } - if (glset.lightmode == 8) + if (mColormapState != activeShader->currentfixedcolormap) { - glVertexAttrib1f(VATTR_LIGHTLEVEL, mSoftLight / 255.f); - } + float r, g, b; + activeShader->currentfixedcolormap = mColormapState; + if (mColormapState == CM_DEFAULT) + { + activeShader->muFixedColormap.Set(0); + } + else if (mColormapState < CM_MAXCOLORMAP) + { + FSpecialColormap *scm = &SpecialColormaps[gl_fixedcolormap - CM_FIRSTSPECIALCOLORMAP]; + float m[] = { scm->ColorizeEnd[0] - scm->ColorizeStart[0], + scm->ColorizeEnd[1] - scm->ColorizeStart[1], scm->ColorizeEnd[2] - scm->ColorizeStart[2], 0.f }; + activeShader->muFixedColormap.Set(1); + activeShader->muColormapStart.Set(scm->ColorizeStart[0], scm->ColorizeStart[1], scm->ColorizeStart[2], 0.f); + activeShader->muColormapRange.Set(m); + } + else if (mColormapState == CM_FOGLAYER) + { + activeShader->muFixedColormap.Set(3); + } + else if (mColormapState == CM_LITE) + { + if (gl_enhanced_nightvision) + { + r = 0.375f, g = 1.0f, b = 0.375f; + } + else + { + r = g = b = 1.f; + } + activeShader->muFixedColormap.Set(2); + activeShader->muColormapStart.Set(r, g, b, 1.f); + } + else if (mColormapState >= CM_TORCH) + { + int flicker = mColormapState - CM_TORCH; + r = (0.8f + (7 - flicker) / 70.0f); + if (r > 1.0f) r = 1.0f; + b = g = r; + if (gl_enhanced_nightvision) b = g * 0.75f; + activeShader->muFixedColormap.Set(2); + activeShader->muColormapStart.Set(r, g, b, 1.f); + } + } return true; } return false; @@ -326,6 +348,14 @@ void FRenderState::Apply(bool forcenoshader) } ffSpecialEffect = mSpecialEffect; } + // Now compose the final color for this... + float realcolor[4]; + realcolor[0] = clamp((mColor.vec[0] + mDynColor.r / 255.f), 0.f, 1.f) * (mObjectColor.r / 255.f); + realcolor[1] = clamp((mColor.vec[1] + mDynColor.g / 255.f), 0.f, 1.f) * (mObjectColor.g / 255.f); + realcolor[2] = clamp((mColor.vec[2] + mDynColor.b / 255.f), 0.f, 1.f) * (mObjectColor.b / 255.f); + realcolor[3] = mColor.vec[3] * (mObjectColor.a / 255.f); + glColor4fv(realcolor); + } } diff --git a/src/gl/renderer/gl_renderstate.h b/src/gl/renderer/gl_renderstate.h index 5308da42b..e8de712f6 100644 --- a/src/gl/renderer/gl_renderstate.h +++ b/src/gl/renderer/gl_renderstate.h @@ -3,6 +3,7 @@ #include #include "gl/system/gl_interface.h" +#include "gl/data/gl_data.h" #include "c_cvars.h" #include "r_defs.h" @@ -10,81 +11,29 @@ class FVertexBuffer; EXTERN_CVAR(Bool, gl_direct_state_change) -struct FStateAttr -{ - static int ChangeCounter; - int mLastChange; - - 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 -{ - float vec[3]; - - bool Update(FStateVec3 *other) - { - if (mLastChange != other->mLastChange) - { - *this = *other; - return true; - } - return false; - } - - void Set(float x, float y, float z) - { - vec[0] = x; - vec[1] = z; - vec[2] = y; - mLastChange = ++ChangeCounter; - } -}; - -struct FStateVec4 : public FStateAttr +struct FStateVec4 { float vec[4]; - bool Update(FStateVec4 *other) - { - if (mLastChange != other->mLastChange) - { - *this = *other; - return true; - } - return false; - } - void Set(float r, float g, float b, float a) { vec[0] = r; vec[1] = g; vec[2] = b; vec[3] = a; - mLastChange = ++ChangeCounter; } }; enum EEffect { - EFF_NONE, + EFF_NONE=-1, EFF_FOGBOUNDARY, EFF_SPHEREMAP, + EFF_BURN, + EFF_STENCIL, + + MAX_EFFECTS }; class FRenderState @@ -96,9 +45,10 @@ class FRenderState bool mBrightmapEnabled; int mSpecialEffect; int mTextureMode; + int mDesaturation; int mSoftLight; - float mLightParms[2]; - int mNumLights[3]; + float mLightParms[4]; + int mNumLights[4]; float *mLightData; int mSrcBlend, mDstBlend; int mAlphaFunc; @@ -109,7 +59,7 @@ class FRenderState FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer; FStateVec4 mColor; - FStateVec3 mCameraPos; + FStateVec4 mCameraPos; FStateVec4 mGlowTop, mGlowBottom; FStateVec4 mGlowTopPlane, mGlowBottomPlane; PalEntry mFogColor; @@ -155,25 +105,25 @@ public: void SetColor(float r, float g, float b, float a = 1.f, int desat = 0) { mColor.Set(r, g, b, a); - glColor4fv(mColor.vec); + mDesaturation = desat; } void SetColor(PalEntry pe, int desat = 0) { mColor.Set(pe.r/255.f, pe.g/255.f, pe.b/255.f, pe.a/255.f); - glColor4fv(mColor.vec); + mDesaturation = desat; } void SetColorAlpha(PalEntry pe, float alpha = 1.f, int desat = 0) { mColor.Set(pe.r/255.f, pe.g/255.f, pe.b/255.f, alpha); - glColor4fv(mColor.vec); + mDesaturation = desat; } void ResetColor() { mColor.Set(1,1,1,1); - glColor4fv(mColor.vec); + mDesaturation = 0; } void SetTextureMode(int mode) @@ -213,7 +163,7 @@ public: void SetCameraPos(float x, float y, float z) { - mCameraPos.Set(x,y,z); + mCameraPos.Set(x, z, y, 0); } void SetGlowParams(float *t, float *b) @@ -224,7 +174,8 @@ public: void SetSoftLightLevel(int level) { - mSoftLight = level; + if (glset.lightmode == 8) mLightParms[3] = level / 255.f; + else mLightParms[3] = -1.f; } void SetGlowPlanes(const secplane_t &top, const secplane_t &bottom) @@ -235,7 +186,7 @@ public: void SetDynLight(float r, float g, float b) { - mDynColor = PalEntry(xs_CRoundToInt(r*255), xs_CRoundToInt(g*255), xs_CRoundToInt(b*255)); + mDynColor = PalEntry(255, xs_CRoundToInt(r*255), xs_CRoundToInt(g*255), xs_CRoundToInt(b*255)); } void SetDynLight(PalEntry pe) @@ -250,21 +201,23 @@ public: void SetFog(PalEntry c, float d) { + const float LOG2E = 1.442692f; // = 1/log(2) mFogColor = c; - if (d >= 0.0f) mFogDensity = d; + if (d >= 0.0f) mLightParms[2] = d * (-LOG2E / 64000.f); } void SetLightParms(float f, float d) { - mLightParms[0] = f; - mLightParms[1] = d; + mLightParms[1] = f; + mLightParms[0] = d; } void SetLights(int *numlights, float *lightdata) { - mNumLights[0] = numlights[0]; - mNumLights[1] = numlights[1]; - mNumLights[2] = numlights[2]; + mNumLights[0] = 0; + mNumLights[1] = numlights[0]; + mNumLights[2] = numlights[1]; + mNumLights[3] = numlights[2]; mLightData = lightdata; // caution: the data must be preserved by the caller until the 'apply' call! } diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 3804ea048..8670c1d49 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -842,6 +842,7 @@ void FGLRenderer::EndDrawScene(sector_t * viewsector) DrawPlayerSprites (viewsector, false); } gl_RenderState.SetFixedColormap(CM_DEFAULT); + gl_RenderState.SetSoftLightLevel(-1); DrawTargeterSprites(); DrawBlend(viewsector); @@ -1059,6 +1060,7 @@ void FGLRenderer::WriteSavePic (player_t *player, FILE *file, int width, int hei FieldOfView * 360.0f / FINEANGLES, 1.6f, 1.6f, true, false); glDisable(GL_STENCIL_TEST); gl_RenderState.SetFixedColormap(CM_DEFAULT); + gl_RenderState.SetSoftLightLevel(-1); screen->Begin2D(false); DrawBlend(viewsector); glFlush(); diff --git a/src/gl/scene/gl_sprite.cpp b/src/gl/scene/gl_sprite.cpp index 41e94a73b..84ecbf0a1 100644 --- a/src/gl/scene/gl_sprite.cpp +++ b/src/gl/scene/gl_sprite.cpp @@ -287,7 +287,7 @@ void GLSprite::Draw(int pass) { // If we get here we know that we have colored fog and no fixed colormap. gl_SetFog(foglevel, rel, &Colormap, additivefog); - //gl_RenderState.SetFixedColormap(CM_FOGLAYER); fixme: does not work yet. + gl_RenderState.SetFixedColormap(CM_FOGLAYER); gl_RenderState.BlendEquation(GL_FUNC_ADD); gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.Apply(); @@ -308,7 +308,7 @@ void GLSprite::Draw(int pass) glVertex3fv(&v4[0]); } glEnd(); - + gl_RenderState.SetFixedColormap(CM_DEFAULT); } } else diff --git a/src/gl/scene/gl_weapon.cpp b/src/gl/scene/gl_weapon.cpp index c6cd3c5dd..6991bed5c 100644 --- a/src/gl/scene/gl_weapon.cpp +++ b/src/gl/scene/gl_weapon.cpp @@ -283,6 +283,7 @@ void FGLRenderer::DrawPlayerSprites(sector_t * viewsector, bool hudModelStep) } PalEntry ThingColor = (playermo->RenderStyle.Flags & STYLEF_ColorIsFixed) ? playermo->fillcolor : 0xffffff; + ThingColor.a = 255; visstyle_t vis; diff --git a/src/gl/shaders/gl_shader.cpp b/src/gl/shaders/gl_shader.cpp index a132e65dd..35916bd00 100644 --- a/src/gl/shaders/gl_shader.cpp +++ b/src/gl/shaders/gl_shader.cpp @@ -57,17 +57,6 @@ #include "gl/shaders/gl_shader.h" #include "gl/textures/gl_material.h" -// these will only have an effect on SM3 cards. -// For SM4 they are always on and for SM2 always off -CVAR(Bool, gl_warp_shader, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) -CVAR(Bool, gl_fog_shader, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) -CVAR(Bool, gl_colormap_shader, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) -CVAR(Bool, gl_brightmap_shader, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) -CVAR(Bool, gl_glow_shader, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) - - -extern long gl_frameMS; - //========================================================================== // // @@ -81,6 +70,10 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (gl.hasGLSL()) { + int i_lump = Wads.CheckNumForFullName("shaders/glsl/shaderdefs.i"); + if (i_lump == -1) I_Error("Unable to load 'shaders/glsl/shaderdefs.i'"); + FMemLump i_data = Wads.ReadLump(i_lump); + int vp_lump = Wads.CheckNumForFullName(vert_prog_lump); if (vp_lump == -1) I_Error("Unable to load '%s'", vert_prog_lump); FMemLump vp_data = Wads.ReadLump(vp_lump); @@ -90,12 +83,18 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * FMemLump fp_data = Wads.ReadLump(fp_lump); - FString vp_comb; - FString fp_comb; - vp_comb = defines; - fp_comb = vp_comb; - // This uses GetChars on the strings to get rid of terminating 0 characters. + // + // The following code uses GetChars on the strings to get rid of terminating 0 characters. Do not remove or the code may break! + // + + FString vp_comb = "#version 130\n"; + if (gl.glslversion >= 3.3f) vp_comb = "#version 330 compatibility\n"; // I can't shut up the deprecation warnings in GLSL 1.3 so if available use a version with compatibility profile. + // todo when using shader storage buffers, add + // "#version 400 compatibility\n#extension GL_ARB_shader_storage_buffer_object : require\n" instead. + vp_comb << defines << i_data.GetString().GetChars(); + FString fp_comb = vp_comb; + vp_comb << vp_data.GetString().GetChars() << "\n"; fp_comb << fp_data.GetString().GetChars() << "\n"; @@ -107,12 +106,27 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * if (pp_lump == -1) I_Error("Unable to load '%s'", proc_prog_lump); FMemLump pp_data = Wads.ReadLump(pp_lump); + if (pp_data.GetString().IndexOf("ProcessTexel") < 0) + { + // this looks like an old custom hardware shader. + // We need to replace the ProcessTexel call to make it work. + + fp_comb.Substitute("vec4 frag = ProcessTexel();", "vec4 frag = Process(vec4(1.0));"); + } fp_comb << pp_data.GetString().GetChars(); + + if (pp_data.GetString().IndexOf("ProcessLight") < 0) + { + int pl_lump = Wads.CheckNumForFullName("shaders/glsl/func_defaultlight.fp"); + if (pl_lump == -1) I_Error("Unable to load '%s'", "shaders/glsl/func_defaultlight.fp"); + FMemLump pl_data = Wads.ReadLump(pl_lump); + fp_comb << "\n" << pl_data.GetString().GetChars(); + } } - else + else { // Proc_prog_lump is not a lump name but the source itself (from generated shaders) - fp_comb << proc_prog_lump+1; + fp_comb << proc_prog_lump + 1; } } @@ -137,9 +151,6 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * glAttachShader(hShader, hVertProg); glAttachShader(hShader, hFragProg); - glBindAttribLocation(hShader, VATTR_FOGPARAMS, "fogparams"); - glBindAttribLocation(hShader, VATTR_LIGHTLEVEL, "lightlevel_in"); // Korshun. - glLinkProgram(hShader); glGetShaderInfoLog(hVertProg, 10000, NULL, buffer); @@ -159,30 +170,34 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * error << "Linking:\n" << buffer << "\n"; } int linked; - glGetShaderiv(hShader, GL_LINK_STATUS, &linked); + glGetProgramiv(hShader, GL_LINK_STATUS, &linked); if (linked == 0) { // only print message if there's an error. - Printf("Init Shader '%s':\n%s\n", name, error.GetChars()); + I_Error("Init Shader '%s':\n%s\n", name, error.GetChars()); } - timer_index = glGetUniformLocation(hShader, "timer"); - desaturation_index = glGetUniformLocation(hShader, "desaturation_factor"); - fogenabled_index = glGetUniformLocation(hShader, "fogenabled"); - texturemode_index = glGetUniformLocation(hShader, "texturemode"); - camerapos_index = glGetUniformLocation(hShader, "camerapos"); - lightparms_index = glGetUniformLocation(hShader, "lightparms"); - colormapstart_index = glGetUniformLocation(hShader, "colormapstart"); - colormaprange_index = glGetUniformLocation(hShader, "colormaprange"); - lightrange_index = glGetUniformLocation(hShader, "lightrange"); - fogcolor_index = glGetUniformLocation(hShader, "fogcolor"); - lights_index = glGetUniformLocation(hShader, "lights"); - dlightcolor_index = glGetUniformLocation(hShader, "dlightcolor"); - objectcolor_index = glGetUniformLocation(hShader, "objectcolor"); - glowbottomcolor_index = glGetUniformLocation(hShader, "bottomglowcolor"); - glowtopcolor_index = glGetUniformLocation(hShader, "topglowcolor"); - glowbottomplane_index = glGetUniformLocation(hShader, "glowbottomplane"); - glowtopplane_index = glGetUniformLocation(hShader, "glowtopplane"); + + muDesaturation.Init(hShader, "uDesaturationFactor"); + muFogEnabled.Init(hShader, "uFogEnabled"); + muTextureMode.Init(hShader, "uTextureMode"); + muCameraPos.Init(hShader, "uCameraPos"); + muLightParms.Init(hShader, "uLightAttr"); + muColormapStart.Init(hShader, "uFixedColormapStart"); + muColormapRange.Init(hShader, "uFixedColormapRange"); + muLightRange.Init(hShader, "uLightRange"); + muFogColor.Init(hShader, "uFogColor"); + muDynLightColor.Init(hShader, "uDynLightColor"); + muObjectColor.Init(hShader, "uObjectColor"); + muGlowBottomColor.Init(hShader, "uGlowBottomColor"); + muGlowTopColor.Init(hShader, "uGlowTopColor"); + muGlowBottomPlane.Init(hShader, "uGlowBottomPlane"); + muGlowTopPlane.Init(hShader, "uGlowTopPlane"); + muFixedColormap.Init(hShader, "uFixedColormap"); + + timer_index = glGetUniformLocation(hShader, "timer"); + lights_index = glGetUniformLocation(hShader, "lights"); + glUseProgram(hShader); @@ -203,9 +218,12 @@ bool FShader::Load(const char * name, const char * vert_prog_lump, const char * FShader::~FShader() { - glDeleteProgram(hShader); - glDeleteShader(hVertProg); - glDeleteShader(hFragProg); + if (gl.hasGLSL()) + { + glDeleteProgram(hShader); + glDeleteShader(hVertProg); + glDeleteShader(hFragProg); + } } @@ -215,202 +233,41 @@ FShader::~FShader() // //========================================================================== -bool FShader::Bind(float Speed) +bool FShader::Bind() { GLRenderer->mShaderManager->SetActiveShader(this); - if (timer_index >=0 && Speed > 0.f) glUniform1f(timer_index, gl_frameMS*Speed/1000.f); return true; } //========================================================================== // -// +// Since all shaders are REQUIRED, any error here needs to be fatal // //========================================================================== -FShaderContainer::FShaderContainer(const char *ShaderName, const char *ShaderPath) +FShader *FShaderManager::Compile (const char *ShaderName, const char *ShaderPath) { - const char * shaderdefines[] = { - "#define NO_GLOW\n#define NO_DESATURATE\n", - "#define NO_DESATURATE\n", - "#define NO_GLOW\n", - "\n", - "#define NO_GLOW\n#define NO_DESATURATE\n#define DYNLIGHT\n", - "#define NO_DESATURATE\n#define DYNLIGHT\n", - "#define NO_GLOW\n#define DYNLIGHT\n", - "\n#define DYNLIGHT\n", - "#define NO_GLOW\n#define NO_DESATURATE\n#define SOFTLIGHT\n", - "#define NO_DESATURATE\n#define SOFTLIGHT\n", - "#define NO_GLOW\n#define SOFTLIGHT\n", - "\n#define SOFTLIGHT\n", - "#define NO_GLOW\n#define NO_DESATURATE\n#define DYNLIGHT\n#define SOFTLIGHT\n", - "#define NO_DESATURATE\n#define DYNLIGHT\n#define SOFTLIGHT\n", - "#define NO_GLOW\n#define DYNLIGHT\n#define SOFTLIGHT\n", - "\n#define DYNLIGHT\n#define SOFTLIGHT\n" - }; - - const char * shaderdesc[] = { - "::default", - "::glow", - "::desaturate", - "::glow+desaturate", - "::default+dynlight", - "::glow+dynlight", - "::desaturate+dynlight", - "::glow+desaturate+dynlight", - "::softlight", - "::glow+softlight", - "::desaturate+softlight", - "::glow+desaturate+softlight", - "::default+dynlight+softlight", - "::glow+dynlight+softlight", - "::desaturate+dynlight+softlight", - "::glow+desaturate+dynlight+softlight", - }; - - FString name; - - name << ShaderName << "::colormap"; + // this can't be in the shader code due to ATI strangeness. + const char *str = (gl.MaxLights() == 128)? "#define MAXLIGHTS128\n" : ""; + FShader *shader = NULL; try { - shader_cm = new FShader; - if (!shader_cm->Load(name, "shaders/glsl/main.vp", "shaders/glsl/main_colormap.fp", ShaderPath, "#define NO_FOG\n#define NO_GLOW\n")) + shader = new FShader(ShaderName); + if (!shader->Load(ShaderName, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, str)) { - delete shader_cm; - shader_cm = NULL; + I_Error("Unable to load shader %s\n", ShaderName); } } catch(CRecoverableError &err) { - shader_cm = NULL; - I_Error("Unable to load shader %s:\n%s\n", name.GetChars(), err.GetMessage()); - } - - name << ShaderName << "::foglayer"; - - try - { - shader_fl = new FShader; - if (!shader_fl->Load(name, "shaders/glsl/main.vp", "shaders/glsl/main_foglayer.fp", ShaderPath, "#define NO_GLOW\n")) - { - delete shader_fl; - shader_fl = NULL; - } - } - catch (CRecoverableError &err) - { - shader_fl = NULL; - I_Error("Unable to load shader %s:\n%s\n", name.GetChars(), err.GetMessage()); - } - - for(int i = 0;i < NUM_SHADERS; i++) - { - FString name; - - name << ShaderName << shaderdesc[i]; - - try - { - FString str; - if ((i&4) != 0) - { - if (gl.maxuniforms < 1024) - { - shader[i] = NULL; - continue; - } - // this can't be in the shader code due to ATI strangeness. - str = "#version 120\n#extension GL_EXT_gpu_shader4 : enable\n"; - if (gl.MaxLights() == 128) str += "#define MAXLIGHTS128\n"; - } - str += shaderdefines[i]; - shader[i] = new FShader; - if (!shader[i]->Load(name, "shaders/glsl/main.vp", "shaders/glsl/main.fp", ShaderPath, str.GetChars())) - { - delete shader[i]; - shader[i] = NULL; - } - } - catch(CRecoverableError &err) - { - shader[i] = NULL; - I_Error("Unable to load shader %s:\n%s\n", name.GetChars(), err.GetMessage()); - } + if (shader != NULL) delete shader; + shader = NULL; + I_Error("Unable to load shader %s:\n%s\n", ShaderName, err.GetMessage()); } + return shader; } -//========================================================================== -// -// -// -//========================================================================== -FShaderContainer::~FShaderContainer() -{ - if (shader_cm != NULL) delete shader_cm; - if (shader_fl != NULL) delete shader_fl; - for (int i = 0; i < NUM_SHADERS; i++) - { - if (shader[i] != NULL) - { - delete shader[i]; - shader[i] = NULL; - } - } -} - -//========================================================================== -// -// -// -//========================================================================== - -FShader *FShaderContainer::Bind(int cm, bool glowing, float Speed, bool lights) -{ - FShader *sh=NULL; - - if (cm == CM_FOGLAYER) - { - if (shader_fl) - { - shader_fl->Bind(Speed); - } - return shader_fl; - } - else if (cm >= CM_FIRSTSPECIALCOLORMAP && cm < CM_MAXCOLORMAP) - { - // these are never used with any kind of lighting or fog - 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); - float m[3]= {map->ColorizeEnd[0] - map->ColorizeStart[0], - map->ColorizeEnd[1] - map->ColorizeStart[1], map->ColorizeEnd[2] - map->ColorizeStart[2]}; - - glUniform3fv(sh->colormapstart_index, 1, map->ColorizeStart); - glUniform3fv(sh->colormaprange_index, 1, m); - } - } - else - { - bool desat = false;// cm >= CM_DESAT1 && cm <= CM_DESAT31; - sh = shader[glowing + 2*desat + 4*lights + (glset.lightmode & 8)]; - // [BB] If there was a problem when loading the shader, sh is NULL here. - if( sh ) - { - sh->Bind(Speed); - if (desat) - { - //glUniform1f(sh->desaturation_index, 1.f-float(cm-CM_DESAT0)/(CM_DESAT31-CM_DESAT0)); - } - } - } - return sh; -} - - //========================================================================== // // @@ -454,8 +311,10 @@ struct FEffectShader static const FEffectShader effectshaders[]= { - {"fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "#define NO_GLOW\n"}, - {"spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define NO_GLOW\n#define NO_DESATURATE\n#define SPHEREMAP\n#define SPHEREMAP_0\n"} + { "fogboundary", "shaders/glsl/main.vp", "shaders/glsl/fogboundary.fp", NULL, "" }, + { "spheremap", "shaders/glsl/main.vp", "shaders/glsl/main.fp", "shaders/glsl/func_normal.fp", "#define SPHEREMAP\n" }, + { "burn", "shaders/glsl/burn.vp", "shaders/glsl/burn.fp", NULL, "" }, + { "stencil", "shaders/glsl/stencil.vp", "shaders/glsl/stencil.fp", NULL, "" }, }; @@ -489,35 +348,46 @@ FShaderManager::~FShaderManager() void FShaderManager::CompileShaders() { - mActiveShader = mEffectShaders[0] = mEffectShaders[1] = NULL; - if (gl.hasGLSL()) + try { - for(int i=0;defaultshaders[i].ShaderName != NULL;i++) + mActiveShader = mEffectShaders[0] = mEffectShaders[1] = NULL; + if (gl.hasGLSL()) { - FShaderContainer * shc = new FShaderContainer(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc); - mTextureEffects.Push(shc); - } - - for(unsigned i = 0; i < usershaders.Size(); i++) - { - FString name = ExtractFileBase(usershaders[i]); - FName sfn = name; - - FShaderContainer * shc = new FShaderContainer(sfn, usershaders[i]); - mTextureEffects.Push(shc); - } - - for(int i=0;iLoad(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, - effectshaders[i].fp2, effectshaders[i].defines)) + for (int i = 0; defaultshaders[i].ShaderName != NULL; i++) { - delete eff; + FShader *shc = Compile(defaultshaders[i].ShaderName, defaultshaders[i].gettexelfunc); + mTextureEffects.Push(shc); + } + + for (unsigned i = 0; i < usershaders.Size(); i++) + { + FString name = ExtractFileBase(usershaders[i]); + FName sfn = name; + + FShader *shc = Compile(sfn, usershaders[i]); + mTextureEffects.Push(shc); + } + + for (int i = 0; i < MAX_EFFECTS; i++) + { + FShader *eff = new FShader(effectshaders[i].ShaderName); + if (!eff->Load(effectshaders[i].ShaderName, effectshaders[i].vp, effectshaders[i].fp1, + effectshaders[i].fp2, effectshaders[i].defines)) + { + delete eff; + } + else mEffectShaders[i] = eff; } - else mEffectShaders[i] = eff; } } + catch (CRecoverableError &err) + { + // If shader compilation failed we can still run the fixed function mode so do that instead of aborting. + Printf("%s\n", err.GetMessage()); + Printf(PRINT_HIGH, "Failed to compile shaders. Reverting to fixed function mode\n"); + gl_usevbo = false; + gl.glslversion = 0.0; + } } //========================================================================== @@ -528,17 +398,22 @@ void FShaderManager::CompileShaders() void FShaderManager::Clean() { - SetActiveShader(NULL); - for(unsigned int i=0;iName == sfn) + if (mTextureEffects[i]->mName == sfn) { return i; } @@ -569,26 +444,42 @@ int FShaderManager::Find(const char * shn) void FShaderManager::SetActiveShader(FShader *sh) { - // shadermodel needs to be tested here because without it UseProgram will be NULL. if (gl.hasGLSL() && mActiveShader != sh) { - glUseProgram(sh == NULL? 0 : sh->GetHandle()); + glUseProgram(sh!= NULL? sh->GetHandle() : NULL); mActiveShader = sh; } } + //========================================================================== // +// To avoid maintenance this will be set when a warped texture is bound +// because at that point the draw buffer needs to be flushed anyway. // +//========================================================================== + +void FShaderManager::SetWarpSpeed(unsigned int eff, float speed) +{ + // indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom + if (eff < mTextureEffects.Size()) + { + FShader *sh = mTextureEffects[eff]; + + float warpphase = gl_frameMS * speed / 1000.f; + glProgramUniform1f(sh->GetHandle(), sh->timer_index, warpphase); + } +} + // //========================================================================== FShader *FShaderManager::BindEffect(int effect) { - if (effect > 0 && effect <= NUM_EFFECTS && mEffectShaders[effect-1] != NULL) + if (effect >= 0 && effect < MAX_EFFECTS && mEffectShaders[effect] != NULL) { - mEffectShaders[effect-1]->Bind(0); - return mEffectShaders[effect-1]; + mEffectShaders[effect]->Bind(); + return mEffectShaders[effect]; } return NULL; } diff --git a/src/gl/shaders/gl_shader.h b/src/gl/shaders/gl_shader.h index 62c87c1f9..3497ed3b0 100644 --- a/src/gl/shaders/gl_shader.h +++ b/src/gl/shaders/gl_shader.h @@ -7,80 +7,198 @@ extern bool gl_shaderactive; -const int VATTR_FOGPARAMS = 14; -const int VATTR_LIGHTLEVEL = 13; // Korshun. +//========================================================================== +// +// +//========================================================================== + +class FUniform1i +{ + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + } + + void Set(int newvalue) + { + glUniform1i(mIndex, newvalue); + } +}; + +class FBufferedUniform1i +{ + int mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(int newvalue) + { + if (newvalue != mBuffer) + { + mBuffer = newvalue; + glUniform1i(mIndex, newvalue); + } + } +}; + +class FBufferedUniform4i +{ + int mBuffer[4]; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + memset(mBuffer, 0, sizeof(mBuffer)); + } + + void Set(const int *newvalue) + { + if (memcmp(newvalue, mBuffer, sizeof(mBuffer))) + { + memcpy(mBuffer, newvalue, sizeof(mBuffer)); + glUniform4iv(mIndex, 1, newvalue); + } + } +}; + +class FBufferedUniform1f +{ + int mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(float newvalue) + { + if (newvalue != mBuffer) + { + mBuffer = newvalue; + glUniform1f(mIndex, newvalue); + } + } +}; + +class FBufferedUniform4f +{ + float mBuffer[4]; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + memset(mBuffer, 0, sizeof(mBuffer)); + } + + void Set(const float *newvalue) + { + if (memcmp(newvalue, mBuffer, sizeof(mBuffer))) + { + memcpy(mBuffer, newvalue, sizeof(mBuffer)); + glUniform4fv(mIndex, 1, newvalue); + } + } +}; + +class FUniform4f +{ + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + } + + void Set(const float *newvalue) + { + glUniform4fv(mIndex, 1, newvalue); + } + + void Set(float a, float b, float c, float d) + { + glUniform4f(mIndex, a, b, c, d); + } +}; + +class FBufferedUniformPE +{ + PalEntry mBuffer; + int mIndex; + +public: + void Init(GLuint hShader, const GLchar *name) + { + mIndex = glGetUniformLocation(hShader, name); + mBuffer = 0; + } + + void Set(PalEntry newvalue) + { + if (newvalue != mBuffer) + { + mBuffer = newvalue; + glUniform4f(mIndex, newvalue.r/255.f, newvalue.g/255.f, newvalue.b/255.f, newvalue.a/255.f); + } + } +}; -//========================================================================== -// -// -//========================================================================== class FShader { - friend class FShaderContainer; + friend class FShaderManager; friend class FRenderState; unsigned int hShader; unsigned int hVertProg; unsigned int hFragProg; + FName mName; + FBufferedUniform1f muDesaturation; + FBufferedUniform1i muFogEnabled; + FBufferedUniform1i muTextureMode; + FBufferedUniform4f muCameraPos; + FBufferedUniform4f muLightParms; + FUniform1i muFixedColormap; + FUniform4f muColormapStart; + FUniform4f muColormapRange; + FBufferedUniform4i muLightRange; + FBufferedUniformPE muFogColor; + FBufferedUniformPE muDynLightColor; + FBufferedUniformPE muObjectColor; + FUniform4f muGlowBottomColor; + FUniform4f muGlowTopColor; + FUniform4f muGlowBottomPlane; + FUniform4f muGlowTopPlane; + int timer_index; - int desaturation_index; - int fogenabled_index; - int texturemode_index; - int camerapos_index; - int lightparms_index; - int colormapstart_index; - int colormaprange_index; - int lightrange_index; - int fogcolor_index; int lights_index; - int dlightcolor_index; - int glowbottomcolor_index; - int glowtopcolor_index; - int glowbottomplane_index; - int glowtopplane_index; - int objectcolor_index; - - PalEntry currentdlightcolor; - PalEntry currentobjectcolor; int currentglowstate; - int currentfogenabled; - int currenttexturemode; - float currentlightfactor; - float currentlightdist; - - PalEntry currentfogcolor; - float currentfogdensity; - - FStateVec3 currentcamerapos; + int currentfixedcolormap; public: - FShader() + FShader(const char *name) + : mName(name) { hShader = hVertProg = hFragProg = 0; - currentglowstate = currentfogenabled = currenttexturemode = 0; - currentlightfactor = currentlightdist = 0.0f; - currentfogdensity = -1; - currentdlightcolor = currentobjectcolor = currentfogcolor = 0; - - timer_index = -1; - desaturation_index = -1; - fogenabled_index = -1; - texturemode_index = -1; - camerapos_index = -1; - lightparms_index = -1; - colormapstart_index = -1; - colormaprange_index = -1; - lightrange_index = -1; - fogcolor_index = -1; - lights_index = -1; - dlightcolor_index = -1; - objectcolor_index = -1; - glowtopplane_index = -1; - glowbottomplane_index = -1; - glowtopcolor_index = -1; - glowbottomcolor_index = -1; + currentglowstate = 0; + currentfixedcolormap = 0; } ~FShader(); @@ -91,34 +209,10 @@ public: void SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight); void SetLightRange(int start, int end, int forceadd); - bool Bind(float Speed); + bool Bind(); unsigned int GetHandle() const { return hShader; } -}; -//========================================================================== -// -// This class contains the shaders for the different lighting modes -// that are required (e.g. special colormaps etc.) -// -//========================================================================== - -class FShaderContainer -{ - friend class FShaderManager; - - FName Name; - - enum { NUM_SHADERS = 16 }; - - FShader *shader[NUM_SHADERS]; - FShader *shader_cm; // the shader for fullscreen colormaps - FShader *shader_fl; // the shader for the fog layer - -public: - FShaderContainer(const char *ShaderName, const char *ShaderPath); - ~FShaderContainer(); - FShader *Bind(int cm, bool glowing, float Speed, bool lights); }; @@ -129,14 +223,9 @@ public: //========================================================================== class FShaderManager { - enum - { - NUM_EFFECTS = 2 - }; - - TArray mTextureEffects; + TArray mTextureEffects; FShader *mActiveShader; - FShader *mEffectShaders[NUM_EFFECTS]; + FShader *mEffectShaders[MAX_EFFECTS]; void Clean(); void CompileShaders(); @@ -144,11 +233,13 @@ class FShaderManager public: FShaderManager(); ~FShaderManager(); + FShader *Compile(const char *ShaderName, const char *ShaderPath); int Find(const char *mame); FShader *BindEffect(int effect); void SetActiveShader(FShader *sh); + void SetWarpSpeed(unsigned int eff, float speed); - FShaderContainer *Get(unsigned int eff) + FShader *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()) diff --git a/src/gl/textures/gl_bitmap.cpp b/src/gl/textures/gl_bitmap.cpp index 51e03aa98..83a92e0fe 100644 --- a/src/gl/textures/gl_bitmap.cpp +++ b/src/gl/textures/gl_bitmap.cpp @@ -136,7 +136,7 @@ void FGLBitmap::CopyPixelData(int originx, int originy, const BYTE * patch, int { BYTE *buffer = GetPixels() + 4*originx + Pitch*originy; - // CM_SHADE is an alpha map with 0==transparent and 1==opaque + // alpha map with 0==transparent and 1==opaque if (alphatex) { for(int i=0;i<256;i++) diff --git a/wadsrc/static/shaders/glsl/fogboundary.fp b/wadsrc/static/shaders/glsl/fogboundary.fp index 5ab8ac717..0d4fb9a0d 100644 --- a/wadsrc/static/shaders/glsl/fogboundary.fp +++ b/wadsrc/static/shaders/glsl/fogboundary.fp @@ -1,8 +1,5 @@ -uniform int fogenabled; -uniform vec4 fogcolor; -uniform vec3 camerapos; -varying vec4 pixelpos; -varying vec4 fogparm; +in vec4 pixelpos; +in vec2 glowdist; //=========================================================================== // @@ -18,15 +15,15 @@ void main() // // calculate fog factor // - if (fogenabled == -1) + if (uFogEnabled == -1) { fogdist = pixelpos.w; } else { - fogdist = max(16.0, distance(pixelpos.xyz, camerapos)); + fogdist = max(16.0, distance(pixelpos.xyz, uCameraPos.xyz)); } - fogfactor = exp2 (fogparm.z * fogdist); - gl_FragColor = vec4(fogcolor.rgb, 1.0 - fogfactor); + fogfactor = exp2 (uFogDensity * fogdist); + gl_FragColor = vec4(uFogColor.rgb, 1.0 - fogfactor); } diff --git a/wadsrc/static/shaders/glsl/func_brightmap.fp b/wadsrc/static/shaders/glsl/func_brightmap.fp index e8ad0bb3d..b8b2a9f20 100644 --- a/wadsrc/static/shaders/glsl/func_brightmap.fp +++ b/wadsrc/static/shaders/glsl/func_brightmap.fp @@ -1,9 +1,12 @@ uniform sampler2D texture2; -vec4 Process(vec4 color) +vec4 ProcessTexel() { - vec4 brightpix = desaturate(texture2D(texture2, gl_TexCoord[0].st)); - vec4 texel = getTexel(gl_TexCoord[0].st); - return vec4(texel.rgb * min (color.rgb + brightpix.rgb, 1.0), texel.a*color.a); + return getTexel(gl_TexCoord[0].st); } +vec4 ProcessLight(vec4 color) +{ + vec4 brightpix = desaturate(texture2D(texture2, gl_TexCoord[0].st)); + return vec4(min (color.rgb + brightpix.rgb, 1.0), color.a); +} diff --git a/wadsrc/static/shaders/glsl/func_defaultlight.fp b/wadsrc/static/shaders/glsl/func_defaultlight.fp new file mode 100644 index 000000000..227d38c6a --- /dev/null +++ b/wadsrc/static/shaders/glsl/func_defaultlight.fp @@ -0,0 +1,5 @@ + +vec4 ProcessLight(vec4 color) +{ + return color; +} diff --git a/wadsrc/static/shaders/glsl/func_normal.fp b/wadsrc/static/shaders/glsl/func_normal.fp index f9297ca6f..d3b0d182c 100644 --- a/wadsrc/static/shaders/glsl/func_normal.fp +++ b/wadsrc/static/shaders/glsl/func_normal.fp @@ -1,7 +1,6 @@ -vec4 Process(vec4 color) +vec4 ProcessTexel() { - vec4 pix = getTexel(gl_TexCoord[0].st); - return pix * color; + return getTexel(gl_TexCoord[0].st); } diff --git a/wadsrc/static/shaders/glsl/func_notexture.fp b/wadsrc/static/shaders/glsl/func_notexture.fp index 904d4a6cd..9337ad6b1 100644 --- a/wadsrc/static/shaders/glsl/func_notexture.fp +++ b/wadsrc/static/shaders/glsl/func_notexture.fp @@ -1,6 +1,6 @@ -vec4 Process(vec4 color) +vec4 ProcessTexel() { - return color*objectcolor; + return desaturate(uObjectColor); } diff --git a/wadsrc/static/shaders/glsl/func_warp1.fp b/wadsrc/static/shaders/glsl/func_warp1.fp index c4acb8854..2dbf8a420 100644 --- a/wadsrc/static/shaders/glsl/func_warp1.fp +++ b/wadsrc/static/shaders/glsl/func_warp1.fp @@ -1,6 +1,6 @@ uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; @@ -12,6 +12,6 @@ vec4 Process(vec4 color) texCoord += offset; - return getTexel(texCoord) * color; + return getTexel(texCoord); } diff --git a/wadsrc/static/shaders/glsl/func_warp2.fp b/wadsrc/static/shaders/glsl/func_warp2.fp index 9d5b8f9db..78044f970 100644 --- a/wadsrc/static/shaders/glsl/func_warp2.fp +++ b/wadsrc/static/shaders/glsl/func_warp2.fp @@ -1,6 +1,6 @@ uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; @@ -13,6 +13,6 @@ vec4 Process(vec4 color) texCoord += offset; - return getTexel(texCoord) * color; + return getTexel(texCoord); } diff --git a/wadsrc/static/shaders/glsl/func_wavex.fp b/wadsrc/static/shaders/glsl/func_wavex.fp index d90486358..5172239c7 100644 --- a/wadsrc/static/shaders/glsl/func_wavex.fp +++ b/wadsrc/static/shaders/glsl/func_wavex.fp @@ -1,6 +1,6 @@ uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; @@ -8,6 +8,6 @@ vec4 Process(vec4 color) texCoord.x += sin(pi * 2.0 * (texCoord.y + timer * 0.125)) * 0.1; - return getTexel(texCoord) * color; + return getTexel(texCoord); } diff --git a/wadsrc/static/shaders/glsl/fuzz_jagged.fp b/wadsrc/static/shaders/glsl/fuzz_jagged.fp index d1d1c9727..103f34689 100644 --- a/wadsrc/static/shaders/glsl/fuzz_jagged.fp +++ b/wadsrc/static/shaders/glsl/fuzz_jagged.fp @@ -1,7 +1,7 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; @@ -10,7 +10,7 @@ vec4 Process(vec4 color) texSplat.x = texCoord.x + mod(sin(pi * 2.0 * (texCoord.y + timer * 2.0)),0.1) * 0.1; texSplat.y = texCoord.y + mod(cos(pi * 2.0 * (texCoord.x + timer * 2.0)),0.1) * 0.1; - vec4 basicColor = getTexel(texSplat) * color; + vec4 basicColor = getTexel(texSplat); float texX = sin(texCoord.x * 100.0 + timer*5.0); float texY = cos(texCoord.x * 100.0 + timer*5.0); diff --git a/wadsrc/static/shaders/glsl/fuzz_noise.fp b/wadsrc/static/shaders/glsl/fuzz_noise.fp index 7e08646cb..02985a122 100644 --- a/wadsrc/static/shaders/glsl/fuzz_noise.fp +++ b/wadsrc/static/shaders/glsl/fuzz_noise.fp @@ -1,10 +1,10 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; - vec4 basicColor = getTexel(texCoord) * color; + vec4 basicColor = getTexel(texCoord); texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0; texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0; diff --git a/wadsrc/static/shaders/glsl/fuzz_smooth.fp b/wadsrc/static/shaders/glsl/fuzz_smooth.fp index 9cb840e78..597debb53 100644 --- a/wadsrc/static/shaders/glsl/fuzz_smooth.fp +++ b/wadsrc/static/shaders/glsl/fuzz_smooth.fp @@ -1,10 +1,10 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; - vec4 basicColor = getTexel(texCoord) * color; + vec4 basicColor = getTexel(texCoord); float texX = texCoord.x / 3.0 + 0.66; float texY = 0.34 - texCoord.y / 3.0; diff --git a/wadsrc/static/shaders/glsl/fuzz_smoothnoise.fp b/wadsrc/static/shaders/glsl/fuzz_smoothnoise.fp index 4c796de60..196cca33a 100644 --- a/wadsrc/static/shaders/glsl/fuzz_smoothnoise.fp +++ b/wadsrc/static/shaders/glsl/fuzz_smoothnoise.fp @@ -1,10 +1,10 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; - vec4 basicColor = getTexel(texCoord) * color; + vec4 basicColor = getTexel(texCoord); float texX = sin(mod(texCoord.x * 100.0 + timer*5.0, 3.489)) + texCoord.x / 4.0; float texY = cos(mod(texCoord.y * 100.0 + timer*5.0, 3.489)) + texCoord.y / 4.0; diff --git a/wadsrc/static/shaders/glsl/fuzz_smoothtranslucent.fp b/wadsrc/static/shaders/glsl/fuzz_smoothtranslucent.fp index 074e5f10d..bfd60de57 100644 --- a/wadsrc/static/shaders/glsl/fuzz_smoothtranslucent.fp +++ b/wadsrc/static/shaders/glsl/fuzz_smoothtranslucent.fp @@ -1,10 +1,10 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; - vec4 basicColor = getTexel(texCoord) * color; + vec4 basicColor = getTexel(texCoord); float texX = sin(texCoord.x * 100.0 + timer*5.0); float texY = cos(texCoord.x * 100.0 + timer*5.0); diff --git a/wadsrc/static/shaders/glsl/fuzz_standard.fp b/wadsrc/static/shaders/glsl/fuzz_standard.fp index a93bef849..a1bd0ebaf 100644 --- a/wadsrc/static/shaders/glsl/fuzz_standard.fp +++ b/wadsrc/static/shaders/glsl/fuzz_standard.fp @@ -1,10 +1,10 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; - vec4 basicColor = getTexel(texCoord) * color; + vec4 basicColor = getTexel(texCoord); texCoord.x = float( int(texCoord.x * 128.0) ) / 128.0; texCoord.y = float( int(texCoord.y * 128.0) ) / 128.0; diff --git a/wadsrc/static/shaders/glsl/fuzz_swirly.fp b/wadsrc/static/shaders/glsl/fuzz_swirly.fp index 19816f8f4..de91e47d6 100644 --- a/wadsrc/static/shaders/glsl/fuzz_swirly.fp +++ b/wadsrc/static/shaders/glsl/fuzz_swirly.fp @@ -1,10 +1,10 @@ //created by Evil Space Tomato uniform float timer; -vec4 Process(vec4 color) +vec4 ProcessTexel() { vec2 texCoord = gl_TexCoord[0].st; - vec4 basicColor = getTexel(texCoord) * color; + vec4 basicColor = getTexel(texCoord); float texX = sin(texCoord.x * 100.0 + timer*5.0); float texY = cos(texCoord.x * 100.0 + timer*5.0); diff --git a/wadsrc/static/shaders/glsl/main.fp b/wadsrc/static/shaders/glsl/main.fp index 086cda7f9..db5b8cb19 100644 --- a/wadsrc/static/shaders/glsl/main.fp +++ b/wadsrc/static/shaders/glsl/main.fp @@ -1,56 +1,93 @@ - -// Changing this constant gives results very similar to changing r_visibility. -// Default is 232, it seems to give exactly the same light bands as software renderer. -#define DOOMLIGHTFACTOR 232.0 +in vec4 pixelpos; +in vec2 glowdist; -#ifdef DYNLIGHT - -// ATI does not like this inside an #ifdef so it will be prepended by the compiling code inside the .EXE now. -//#version 120 -//#extension GL_EXT_gpu_shader4 : enable - -uniform ivec3 lightrange; -#ifndef MAXLIGHTS128 -uniform vec4 lights[256]; +#ifdef SHADER_STORAGE_LIGHTS + layout(std430, binding = 3) buffer ParameterBuffer + { + vec4 lights[]; + }; +#elif defined MAXLIGHTS128 + uniform vec4 lights[256]; #else -uniform vec4 lights[128]; -#endif - + uniform vec4 lights[128]; #endif - -uniform int fogenabled; -uniform vec4 fogcolor; -uniform vec4 objectcolor; -uniform vec4 dlightcolor; -uniform vec3 camerapos; -varying vec4 pixelpos; -varying vec4 fogparm; -//uniform vec2 lightparms; -uniform float desaturation_factor; - -uniform vec4 topglowcolor; -uniform vec4 bottomglowcolor; -varying vec2 glowdist; - -uniform int texturemode; uniform sampler2D tex; vec4 Process(vec4 color); +vec4 ProcessTexel(); +vec4 ProcessLight(vec4 color); -varying float lightlevel; +//=========================================================================== +// +// Desaturate a color +// +//=========================================================================== -#ifdef SOFTLIGHT +vec4 desaturate(vec4 texel) +{ + if (uDesaturationFactor > 0.0) + { + float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); + return mix (vec4(gray,gray,gray,texel.a), texel, uDesaturationFactor); + } + else + { + return texel; + } +} + +//=========================================================================== +// +// This function is common for all (non-special-effect) fragment shaders +// +//=========================================================================== + +vec4 getTexel(vec2 st) +{ + vec4 texel = texture2D(tex, st); + + // + // Apply texture modes + // + switch (uTextureMode) + { + case 1: + texel.rgb = vec3(1.0,1.0,1.0); + break; + + case 2: + texel.a = 1.0; + break; + + case 3: + texel = vec4(1.0-texel.r, 1.0-texel.b, 1.0-texel.g, texel.a); + break; + } + texel *= uObjectColor; + + return desaturate(texel); +} + +//=========================================================================== +// // Doom lighting equation ripped from EDGE. // Big thanks to EDGE developers for making the only port // that actually replicates software renderer's lighting in OpenGL. // Float version. // Basically replace int with float and divide all constants by 31. +// +//=========================================================================== + float R_DoomLightingEquation(float light, float dist) { + // Changing this constant gives results very similar to changing r_visibility. + // Default is 232, it seems to give exactly the same light bands as software renderer. + #define DOOMLIGHTFACTOR 232.0 + /* L in the range 0 to 63 */ float L = light * 63.0/31.0; @@ -66,106 +103,97 @@ float R_DoomLightingEquation(float light, float dist) /* result is colormap index (0 bright .. 31 dark) */ return clamp(index, min_L, 1.0); } -#endif - -//=========================================================================== -// -// Desaturate a color -// -//=========================================================================== - -vec4 desaturate(vec4 texel) -{ - #ifndef NO_DESATURATE - float gray = (texel.r * 0.3 + texel.g * 0.56 + texel.b * 0.14); - return mix (vec4(gray,gray,gray,texel.a), texel, desaturation_factor); - #else - return texel; - #endif -} //=========================================================================== // // Calculate light // +// It is important to note that the light color is not desaturated +// due to ZDoom's implementation weirdness. Everything that's added +// on top of it, e.g. dynamic lights and glows are, though, because +// the objects emitting these lights are also. +// +// This is making this a bit more complicated than it needs to +// because we can't just desaturate the final fragment color. +// //=========================================================================== vec4 getLightColor(float fogdist, float fogfactor) { vec4 color = gl_Color; - #ifdef SOFTLIGHT - float newlightlevel = 1.0 - R_DoomLightingEquation(lightlevel, gl_FragCoord.z); - color.rgb *= clamp(vec3(newlightlevel), 0.0, 1.0); - #endif - #ifndef NO_FOG - // - // apply light diminishing - // - if (fogenabled > 0) + + if (uLightLevel >= 0.0) { - #if (defined(DOOMLIGHT)) && !defined SOFTLIGHT - // special lighting mode 'Doom' not available on older cards for performance reasons. - if (fogdist < fogparm.y) - { - color.rgb *= fogparm.x - (fogdist / fogparm.y) * (fogparm.x - 1.0); - } - #endif + float newlightlevel = 1.0 - R_DoomLightingEquation(uLightLevel, gl_FragCoord.z); + color.rgb *= newlightlevel; + } + else if (uFogEnabled > 0.0) + { + // brightening around the player for light mode 2 + if (fogdist < uLightDist) + { + color.rgb *= uLightFactor - (fogdist / uLightDist) * (uLightFactor - 1.0); + } - //color = vec4(color.rgb * (1.0 - fogfactor), color.a); + // + // apply light diminishing through fog equation + // color.rgb = mix(vec3(0.0, 0.0, 0.0), color.rgb, fogfactor); } - #endif - #ifndef NO_GLOW // // handle glowing walls // - if (topglowcolor.a > 0.0 && glowdist.x < topglowcolor.a) + if (uGlowTopColor.a > 0.0 && glowdist.x < uGlowTopColor.a) { - color.rgb += desaturate(topglowcolor * (1.0 - glowdist.x / topglowcolor.a)).rgb; + color.rgb += desaturate(uGlowTopColor * (1.0 - glowdist.x / uGlowTopColor.a)).rgb; } - if (bottomglowcolor.a > 0.0 && glowdist.y < bottomglowcolor.a) + if (uGlowBottomColor.a > 0.0 && glowdist.y < uGlowBottomColor.a) { - color.rgb += desaturate(bottomglowcolor * (1.0 - glowdist.y / bottomglowcolor.a)).rgb; + color.rgb += desaturate(uGlowBottomColor * (1.0 - glowdist.y / uGlowBottomColor.a)).rgb; } color = min(color, 1.0); - #endif - - // calculation of actual light color is complete. - return color; -} -//=========================================================================== -// -// Gets a texel and performs common manipulations -// -//=========================================================================== - -vec4 getTexel(vec2 st) -{ - vec4 texel = texture2D(tex, st); - - #ifndef NO_TEXTUREMODE // - // Apply texture modes + // apply brightmaps (or other light manipulation by custom shaders. // - if (texturemode == 3) - { - texel *=objectcolor; - texel = vec4(1.0-texel.r, 1.0-texel.g, 1.0-texel.b, texel.a); - return texel; - } - else if (texturemode == 2) - { - texel.a = 1.0; - } - else if (texturemode == 1) - { - texel.rgb = vec3(1.0,1.0,1.0); - } - #endif + color = ProcessLight(color); - return desaturate(texel * objectcolor); + // + // apply dynamic lights (except additive) + // + + vec4 dynlight = uDynLightColor; + + if (uLightRange.z > uLightRange.x) + { + // + // modulated lights + // + for(int i=uLightRange.x; i uLightRange.z) + { + vec4 addlight = vec4(0.0,0.0,0.0,0.0); + + // + // additive lights - these can be done after the alpha test. + // + for(int i=uLightRange.z; i