diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 03f3372f06..dfac22fe03 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1114,6 +1114,7 @@ set( FASTMATH_SOURCES gl/shaders/gl_presentshader.cpp gl/shaders/gl_bloomshader.cpp gl/shaders/gl_blurshader.cpp + gl/shaders/gl_colormapshader.cpp gl/shaders/gl_tonemapshader.cpp gl/shaders/gl_lensshader.cpp gl/system/gl_interface.cpp diff --git a/src/gl/compatibility/gl_20.cpp b/src/gl/compatibility/gl_20.cpp index 97abc0d82f..fdda991303 100644 --- a/src/gl/compatibility/gl_20.cpp +++ b/src/gl/compatibility/gl_20.cpp @@ -66,42 +66,39 @@ void gl_PatchMenu() { - if (gl.legacyMode) + // Radial fog and Doom lighting are not available without full shader support. + + FOptionValues **opt = OptionValues.CheckKey("LightingModes"); + if (opt != NULL) { - // Radial fog and Doom lighting are not available without full shader support. - - FOptionValues **opt = OptionValues.CheckKey("LightingModes"); - if (opt != NULL) + for(int i = (*opt)->mValues.Size()-1; i>=0; i--) { - for(int i = (*opt)->mValues.Size()-1; i>=0; i--) + // Delete 'Doom' lighting mode + if ((*opt)->mValues[i].Value == 2.0 || (*opt)->mValues[i].Value == 8.0) { - // Delete 'Doom' lighting mode - if ((*opt)->mValues[i].Value == 2.0 || (*opt)->mValues[i].Value == 8.0) - { - (*opt)->mValues.Delete(i); - } + (*opt)->mValues.Delete(i); } } - - opt = OptionValues.CheckKey("FogMode"); - if (opt != NULL) - { - for(int i = (*opt)->mValues.Size()-1; i>=0; i--) - { - // Delete 'Radial' fog mode - if ((*opt)->mValues[i].Value == 2.0) - { - (*opt)->mValues.Delete(i); - } - } - } - - // disable features that don't work without shaders. - if (gl_lightmode == 2 || gl_lightmode == 8) gl_lightmode = 3; - if (gl_fogmode == 2) gl_fogmode = 1; - - // todo: remove more unsupported stuff like postprocessing options. } + + opt = OptionValues.CheckKey("FogMode"); + if (opt != NULL) + { + for(int i = (*opt)->mValues.Size()-1; i>=0; i--) + { + // Delete 'Radial' fog mode + if ((*opt)->mValues[i].Value == 2.0) + { + (*opt)->mValues.Delete(i); + } + } + } + + // disable features that don't work without shaders. + if (gl_lightmode == 2 || gl_lightmode == 8) gl_lightmode = 3; + if (gl_fogmode == 2) gl_fogmode = 1; + + // todo: remove more unsupported stuff like postprocessing options. } diff --git a/src/gl/renderer/gl_lightdata.cpp b/src/gl/renderer/gl_lightdata.cpp index 5d153894fc..c2329879c6 100644 --- a/src/gl/renderer/gl_lightdata.cpp +++ b/src/gl/renderer/gl_lightdata.cpp @@ -71,7 +71,7 @@ CUSTOM_CVAR(Bool, gl_enhanced_nightvision, true, CVAR_ARCHIVE|CVAR_NOINITCALL) { // The fixed colormap state needs to be reset because if this happens when // a shader is set to CM_LITE or CM_TORCH it won't register the change in behavior caused by this CVAR. - if (GLRenderer != NULL && GLRenderer->mShaderManager != NULL) + if (GLRenderer != nullptr && GLRenderer->mShaderManager != nullptr) { GLRenderer->mShaderManager->ResetFixedColormap(); } diff --git a/src/gl/renderer/gl_postprocess.cpp b/src/gl/renderer/gl_postprocess.cpp index 0471535542..77ee5cd799 100644 --- a/src/gl/renderer/gl_postprocess.cpp +++ b/src/gl/renderer/gl_postprocess.cpp @@ -71,6 +71,7 @@ #include "gl/shaders/gl_bloomshader.h" #include "gl/shaders/gl_blurshader.h" #include "gl/shaders/gl_tonemapshader.h" +#include "gl/shaders/gl_colormapshader.h" #include "gl/shaders/gl_lensshader.h" #include "gl/shaders/gl_presentshader.h" #include "gl/renderer/gl_2ddrawer.h" @@ -284,6 +285,38 @@ void FGLRenderer::ClearTonemapPalette() mTonemapPalette = nullptr; } +//----------------------------------------------------------------------------- +// +// Colormap scene texture and place the result in the HUD/2D texture +// +//----------------------------------------------------------------------------- + +void FGLRenderer::ColormapScene() +{ + if (gl_fixedcolormap < CM_FIRSTSPECIALCOLORMAP || gl_fixedcolormap >= CM_MAXCOLORMAP) + return; + + FGLDebug::PushGroup("ColormapScene"); + + FGLPostProcessState savedState; + + mBuffers->BindNextFB(); + mBuffers->BindCurrentTexture(0); + mColormapShader->Bind(); + + 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 }; + + mColormapShader->MapStart.Set(scm->ColorizeStart[0], scm->ColorizeStart[1], scm->ColorizeStart[2], 0.f); + mColormapShader->MapRange.Set(m); + + RenderScreenQuad(); + mBuffers->NextTexture(); + + FGLDebug::PopGroup(); +} + //----------------------------------------------------------------------------- // // Apply lens distortion and place the result in the HUD/2D texture diff --git a/src/gl/renderer/gl_renderbuffers.cpp b/src/gl/renderer/gl_renderbuffers.cpp index f8b5dfcdde..35be00abc8 100644 --- a/src/gl/renderer/gl_renderbuffers.cpp +++ b/src/gl/renderer/gl_renderbuffers.cpp @@ -55,7 +55,14 @@ #include "doomerrors.h" CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); -CVAR(Bool, gl_renderbuffers, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG); +CUSTOM_CVAR(Bool, gl_renderbuffers, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL) +{ + // this CVAR alters some fixed colormap related settings + if (GLRenderer != nullptr && GLRenderer->mShaderManager != nullptr) + { + //GLRenderer->mShaderManager->ResetFixedColormap(); + } +} //========================================================================== // diff --git a/src/gl/renderer/gl_renderer.cpp b/src/gl/renderer/gl_renderer.cpp index 20126ba77c..6cd38390f8 100644 --- a/src/gl/renderer/gl_renderer.cpp +++ b/src/gl/renderer/gl_renderer.cpp @@ -67,6 +67,7 @@ #include "gl/shaders/gl_bloomshader.h" #include "gl/shaders/gl_blurshader.h" #include "gl/shaders/gl_tonemapshader.h" +#include "gl/shaders/gl_colormapshader.h" #include "gl/shaders/gl_lensshader.h" #include "gl/shaders/gl_presentshader.h" #include "gl/textures/gl_texture.h" @@ -97,21 +98,30 @@ CVAR(Bool, gl_scale_viewport, true, 0); FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb) { framebuffer = fb; - mClipPortal = NULL; - mCurrentPortal = NULL; + mClipPortal = nullptr; + mCurrentPortal = nullptr; mMirrorCount = 0; mPlaneMirrorCount = 0; mLightCount = 0; mAngles = FRotator(0.f, 0.f, 0.f); mViewVector = FVector2(0,0); - mVBO = NULL; - mSkyVBO = NULL; + mVBO = nullptr; + mSkyVBO = nullptr; gl_spriteindex = 0; - mShaderManager = NULL; - gllight = glpart2 = glpart = mirrortexture = NULL; - mLights = NULL; + mShaderManager = nullptr; + gllight = glpart2 = glpart = mirrortexture = nullptr; + mLights = nullptr; m2DDrawer = nullptr; mTonemapPalette = nullptr; + mBuffers = nullptr; + mPresentShader = nullptr; + mBloomExtractShader = nullptr; + mBloomCombineShader = nullptr; + mBlurShader = nullptr; + mTonemapShader = nullptr; + mTonemapPalette = nullptr; + mColormapShader = nullptr; + mLensShader = nullptr; } void gl_LoadModels(); @@ -124,6 +134,7 @@ void FGLRenderer::Initialize(int width, int height) mBloomCombineShader = new FBloomCombineShader(); mBlurShader = new FBlurShader(); mTonemapShader = new FTonemapShader(); + mColormapShader = new FColormapShader(); mTonemapPalette = nullptr; mLensShader = new FLensShader(); mPresentShader = new FPresentShader(); @@ -184,6 +195,7 @@ FGLRenderer::~FGLRenderer() if (mBlurShader) delete mBlurShader; if (mTonemapShader) delete mTonemapShader; if (mTonemapPalette) delete mTonemapPalette; + if (mColormapShader) delete mColormapShader; if (mLensShader) delete mLensShader; } diff --git a/src/gl/renderer/gl_renderer.h b/src/gl/renderer/gl_renderer.h index 4b663680f6..120f6a4490 100644 --- a/src/gl/renderer/gl_renderer.h +++ b/src/gl/renderer/gl_renderer.h @@ -23,6 +23,7 @@ class FBloomExtractShader; class FBloomCombineShader; class FBlurShader; class FTonemapShader; +class FColormapShader; class FLensShader; class FPresentShader; class F2DDrawer; @@ -93,6 +94,7 @@ public: FBloomCombineShader *mBloomCombineShader; FBlurShader *mBlurShader; FTonemapShader *mTonemapShader; + FColormapShader *mColormapShader; FHardwareTexture *mTonemapPalette; FLensShader *mLensShader; FPresentShader *mPresentShader; @@ -166,6 +168,7 @@ public: void EndDrawScene(sector_t * viewsector); void BloomScene(); void TonemapScene(); + void ColormapScene(); void BindTonemapPalette(int texunit); void ClearTonemapPalette(); void LensDistortScene(); diff --git a/src/gl/renderer/gl_renderstate.cpp b/src/gl/renderer/gl_renderstate.cpp index caf276d37e..c3cc905e56 100644 --- a/src/gl/renderer/gl_renderstate.cpp +++ b/src/gl/renderer/gl_renderstate.cpp @@ -49,6 +49,7 @@ #include "gl/renderer/gl_renderstate.h" #include "gl/renderer/gl_colormap.h" #include "gl/dynlights//gl_lightbuffer.h" +#include "gl/renderer/gl_renderbuffers.h" void gl_SetTextureMode(int type); @@ -220,15 +221,24 @@ bool FRenderState::ApplyShader() { activeShader->muFixedColormap.Set(0); } - else if (mColormapState < CM_MAXCOLORMAP) + else if (mColormapState > CM_DEFAULT && 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 }; + if (FGLRenderBuffers::IsEnabled()) + { + // When using postprocessing to apply the colormap, we must render the image fullbright here. + activeShader->muFixedColormap.Set(2); + activeShader->muColormapStart.Set(1, 1, 1, 1.f); + } + else + { + 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); + 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) { diff --git a/src/gl/scene/gl_scene.cpp b/src/gl/scene/gl_scene.cpp index 7d634054a4..ab3fe744db 100644 --- a/src/gl/scene/gl_scene.cpp +++ b/src/gl/scene/gl_scene.cpp @@ -635,9 +635,9 @@ void FGLRenderer::DrawBlend(sector_t * viewsector) V_AddBlend (player->BlendR, player->BlendG, player->BlendB, player->BlendA, blend); } + gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); if (blend[3]>0.0f) { - gl_RenderState.BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); gl_RenderState.SetColor(blend[0], blend[1], blend[2], blend[3]); gl_FillScreen(); } @@ -676,16 +676,19 @@ void FGLRenderer::EndDrawScene(sector_t * viewsector) { DrawPlayerSprites (viewsector, false); } - int cm = gl_RenderState.GetFixedColormap(); + if (gl.legacyMode) + { + int cm = gl_RenderState.GetFixedColormap(); + gl_RenderState.SetFixedColormap(cm); + gl_RenderState.DrawColormapOverlay(); + } + gl_RenderState.SetFixedColormap(CM_DEFAULT); gl_RenderState.SetSoftLightLevel(-1); DrawTargeterSprites(); - DrawBlend(viewsector); - if (gl.legacyMode) + if (FGLRenderBuffers::IsEnabled()) { - gl_RenderState.SetFixedColormap(cm); - gl_RenderState.DrawColormapOverlay(); - gl_RenderState.SetFixedColormap(CM_DEFAULT); + DrawBlend(viewsector); } // Restore standard rendering state @@ -851,7 +854,9 @@ sector_t * FGLRenderer::RenderViewpoint (AActor * camera, GL_IRECT * bounds, flo mBuffers->BlitSceneToTexture(); BloomScene(); TonemapScene(); + ColormapScene(); LensDistortScene(); + DrawBlend(viewsector); // This should be done after postprocessing, not before. } mDrawingScene2D = false; eye->TearDown(); diff --git a/src/gl/shaders/gl_colormapshader.cpp b/src/gl/shaders/gl_colormapshader.cpp new file mode 100644 index 0000000000..f280031504 --- /dev/null +++ b/src/gl/shaders/gl_colormapshader.cpp @@ -0,0 +1,67 @@ +/* +** gl_colormapshader.cpp +** Applies a fullscreen colormap to the scene +** +**--------------------------------------------------------------------------- +** Copyright 2016 Christoph Oelckers +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** 4. When not used as part of GZDoom or a GZDoom derivative, this code will be +** covered by the terms of the GNU Lesser General Public License as published +** by the Free Software Foundation; either version 2.1 of the License, or (at +** your option) any later version. +** 5. Full disclosure of the entire project's source code, except for third +** party libraries is mandatory. (NOTE: This clause is non-negotiable!) +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + +#include "gl/system/gl_system.h" +#include "files.h" +#include "m_swap.h" +#include "v_video.h" +#include "gl/gl_functions.h" +#include "vectors.h" +#include "gl/system/gl_interface.h" +#include "gl/system/gl_framebuffer.h" +#include "gl/system/gl_cvars.h" +#include "gl/shaders/gl_colormapshader.h" + +void FColormapShader::Bind() +{ + auto &shader = mShader; + if (!shader) + { + shader.Compile(FShaderProgram::Vertex, "shaders/glsl/screenquad.vp", "", 330); + shader.Compile(FShaderProgram::Fragment, "shaders/glsl/colormap.fp", "", 330); + shader.SetFragDataLocation(0, "FragColor"); + shader.Link("shaders/glsl/colormap"); + shader.SetAttribLocation(0, "PositionInProjection"); + MapStart.Init(shader, "uFixedColormapStart"); + MapRange.Init(shader, "uFixedColormapRange"); + } + shader.Bind(); +} + diff --git a/src/gl/shaders/gl_colormapshader.h b/src/gl/shaders/gl_colormapshader.h new file mode 100644 index 0000000000..b20c23a4ce --- /dev/null +++ b/src/gl/shaders/gl_colormapshader.h @@ -0,0 +1,20 @@ +#ifndef __GL_COLORMAPSHADER_H +#define __GL_COLORMAPSHADER_H + +#include "gl_shaderprogram.h" + +class FColormapShader +{ +public: + void Bind(); + + FBufferedUniformSampler SceneTexture; + FUniform4f MapStart; + FUniform4f MapRange; + +private: + + FShaderProgram mShader; +}; + +#endif \ No newline at end of file diff --git a/wadsrc/static/shaders/glsl/colormap.fp b/wadsrc/static/shaders/glsl/colormap.fp new file mode 100644 index 0000000000..e86429c379 --- /dev/null +++ b/wadsrc/static/shaders/glsl/colormap.fp @@ -0,0 +1,16 @@ + +in vec2 TexCoord; +out vec4 FragColor; + +uniform sampler2D tex; +uniform vec4 uFixedColormapStart; +uniform vec4 uFixedColormapRange; + +void main() +{ + vec4 frag = texture(tex, TexCoord); + float gray = (frag.r * 0.3 + frag.g * 0.56 + frag.b * 0.14); + vec4 cm = uFixedColormapStart + gray * uFixedColormapRange; + FragColor = vec4(clamp(cm.rgb, 0.0, 1.0), frag.a); +} +