2013-06-23 07:49:34 +00:00
|
|
|
/*
|
|
|
|
** gl_renderstate.cpp
|
|
|
|
** Render state maintenance
|
|
|
|
**
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
** Copyright 2009 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.
|
|
|
|
**---------------------------------------------------------------------------
|
|
|
|
**
|
|
|
|
*/
|
|
|
|
|
2014-05-12 12:45:41 +00:00
|
|
|
#include "templates.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/system/gl_system.h"
|
2013-09-03 16:29:39 +00:00
|
|
|
#include "gl/system/gl_interface.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#include "gl/data/gl_data.h"
|
2014-05-10 19:47:07 +00:00
|
|
|
#include "gl/data/gl_vertexbuffer.h"
|
2013-06-23 07:49:34 +00:00
|
|
|
#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"
|
|
|
|
|
2013-08-18 13:41:52 +00:00
|
|
|
void gl_SetTextureMode(int type);
|
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
FRenderState gl_RenderState;
|
|
|
|
|
|
|
|
CVAR(Bool, gl_direct_state_change, true, 0)
|
|
|
|
|
|
|
|
|
2014-07-13 18:41:20 +00:00
|
|
|
static VSMatrix identityMatrix(1);
|
2014-07-13 20:37:34 +00:00
|
|
|
TArray<VSMatrix> gl_MatrixStack;
|
2014-07-13 18:41:20 +00:00
|
|
|
|
2013-06-23 07:49:34 +00:00
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
void FRenderState::Reset()
|
|
|
|
{
|
|
|
|
mTextureEnabled = true;
|
|
|
|
mBrightmapEnabled = mFogEnabled = mGlowEnabled = mLightEnabled = false;
|
2014-06-29 09:00:21 +00:00
|
|
|
mFogColor.d = -1;
|
|
|
|
mTextureMode = -1;
|
2014-05-12 12:45:41 +00:00
|
|
|
mDesaturation = 0;
|
2013-06-23 07:49:34 +00:00
|
|
|
mSrcBlend = GL_SRC_ALPHA;
|
|
|
|
mDstBlend = GL_ONE_MINUS_SRC_ALPHA;
|
|
|
|
mAlphaThreshold = 0.5f;
|
|
|
|
mBlendEquation = GL_FUNC_ADD;
|
2014-05-11 14:06:25 +00:00
|
|
|
mObjectColor = 0xffffffff;
|
2013-06-23 07:49:34 +00:00
|
|
|
m2D = true;
|
2014-05-10 19:47:07 +00:00
|
|
|
mVertexBuffer = mCurrentVertexBuffer = NULL;
|
2014-05-11 19:47:54 +00:00
|
|
|
mColormapState = CM_DEFAULT;
|
2014-05-12 12:45:41 +00:00
|
|
|
mLightParms[3] = -1.f;
|
2014-06-29 09:00:21 +00:00
|
|
|
mSpecialEffect = EFF_NONE;
|
2014-07-13 11:25:42 +00:00
|
|
|
mClipHeightTop = 65536.f;
|
|
|
|
mClipHeightBottom = -65536.f;
|
2014-07-27 10:33:54 +00:00
|
|
|
|
|
|
|
stSrcBlend = stDstBlend = -1;
|
|
|
|
stBlendEquation = -1;
|
|
|
|
stAlphaThreshold = -1.f;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Apply shader settings
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
|
|
|
bool FRenderState::ApplyShader()
|
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
FShader *activeShader;
|
|
|
|
if (mSpecialEffect > EFF_NONE)
|
|
|
|
{
|
|
|
|
activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-07-13 10:14:12 +00:00
|
|
|
// todo: check how performance is affected by using 'discard' in a shader and if necessary create a separate set of discard-less shaders.
|
2014-06-21 13:50:32 +00:00
|
|
|
activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4);
|
|
|
|
activeShader->Bind();
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
int fogset = 0;
|
2014-07-13 10:14:12 +00:00
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
if (mFogEnabled)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
if ((mFogColor & 0xffffff) == 0)
|
2014-05-11 11:27:51 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
fogset = gl_fogmode;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-05-21 10:36:29 +00:00
|
|
|
else
|
2014-05-11 19:47:54 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
fogset = -gl_fogmode;
|
2014-05-11 19:47:54 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
}
|
2014-05-11 12:46:37 +00:00
|
|
|
|
2014-07-14 22:37:13 +00:00
|
|
|
glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
activeShader->muDesaturation.Set(mDesaturation / 255.f);
|
|
|
|
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);
|
2014-07-01 07:52:41 +00:00
|
|
|
activeShader->muDynLightColor.Set(mDynColor.vec);
|
2014-06-29 09:00:21 +00:00
|
|
|
activeShader->muInterpolationFactor.Set(mInterpolationFactor);
|
2014-07-13 11:25:42 +00:00
|
|
|
activeShader->muClipHeightTop.Set(mClipHeightTop);
|
|
|
|
activeShader->muClipHeightBottom.Set(mClipHeightBottom);
|
2014-07-26 18:56:10 +00:00
|
|
|
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
|
2014-07-17 00:37:18 +00:00
|
|
|
|
|
|
|
#ifndef CORE_PROFILE
|
|
|
|
if (!(gl.flags & RFL_COREPROFILE))
|
|
|
|
{
|
2014-07-27 10:33:54 +00:00
|
|
|
if (mAlphaThreshold != stAlphaThreshold)
|
2014-07-17 00:37:18 +00:00
|
|
|
{
|
2014-07-27 10:33:54 +00:00
|
|
|
stAlphaThreshold = mAlphaThreshold;
|
2014-07-17 00:37:18 +00:00
|
|
|
if (mAlphaThreshold < 0.f)
|
|
|
|
{
|
|
|
|
glDisable(GL_ALPHA_TEST);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
2014-07-27 10:33:54 +00:00
|
|
|
glAlphaFunc(GL_GREATER, mAlphaThreshold * mColor.vec[3]);
|
2014-07-17 00:37:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
|
|
|
|
}
|
2014-05-12 12:45:41 +00:00
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
if (mGlowEnabled)
|
|
|
|
{
|
|
|
|
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.
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
activeShader->muLightRange.Set(mNumLights);
|
|
|
|
glUniform4fv(activeShader->lights_index, mNumLights[3], mLightData);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
static const int nulint[] = { 0, 0, 0, 0 };
|
|
|
|
activeShader->muLightRange.Set(nulint);
|
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
if (mColormapState != activeShader->currentfixedcolormap)
|
|
|
|
{
|
|
|
|
float r, g, b;
|
|
|
|
activeShader->currentfixedcolormap = mColormapState;
|
|
|
|
if (mColormapState == CM_DEFAULT)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
activeShader->muFixedColormap.Set(0);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
else if (mColormapState < CM_MAXCOLORMAP)
|
2014-05-10 15:09:43 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
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 };
|
2014-05-10 15:09:43 +00:00
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
activeShader->muFixedColormap.Set(1);
|
|
|
|
activeShader->muColormapStart.Set(scm->ColorizeStart[0], scm->ColorizeStart[1], scm->ColorizeStart[2], 0.f);
|
|
|
|
activeShader->muColormapRange.Set(m);
|
2014-05-11 14:06:25 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
else if (mColormapState == CM_FOGLAYER)
|
2014-05-11 14:49:17 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
activeShader->muFixedColormap.Set(3);
|
2014-05-11 14:49:17 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
else if (mColormapState == CM_LITE)
|
2014-05-11 22:13:19 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
if (gl_enhanced_nightvision)
|
2014-05-12 12:45:41 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
r = 0.375f, g = 1.0f, b = 0.375f;
|
2014-05-12 12:45:41 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
else
|
2014-05-12 12:45:41 +00:00
|
|
|
{
|
2014-06-21 13:50:32 +00:00
|
|
|
r = g = b = 1.f;
|
2014-05-12 12:45:41 +00:00
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
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);
|
2014-05-12 12:45:41 +00:00
|
|
|
}
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
2014-07-13 18:41:20 +00:00
|
|
|
if (mTextureMatrixEnabled)
|
|
|
|
{
|
|
|
|
mTextureMatrix.matrixToGL(activeShader->texturematrix_index);
|
|
|
|
activeShader->currentTextureMatrixState = true;
|
|
|
|
}
|
|
|
|
else if (activeShader->currentTextureMatrixState)
|
|
|
|
{
|
|
|
|
activeShader->currentTextureMatrixState = false;
|
|
|
|
identityMatrix.matrixToGL(activeShader->texturematrix_index);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mModelMatrixEnabled)
|
|
|
|
{
|
|
|
|
mModelMatrix.matrixToGL(activeShader->modelmatrix_index);
|
|
|
|
activeShader->currentModelMatrixState = true;
|
|
|
|
}
|
|
|
|
else if (activeShader->currentModelMatrixState)
|
|
|
|
{
|
|
|
|
activeShader->currentModelMatrixState = false;
|
|
|
|
identityMatrix.matrixToGL(activeShader->modelmatrix_index);
|
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
return true;
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//==========================================================================
|
|
|
|
//
|
|
|
|
// Apply State
|
|
|
|
//
|
|
|
|
//==========================================================================
|
|
|
|
|
2014-06-21 13:50:32 +00:00
|
|
|
void FRenderState::Apply()
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
|
|
|
if (!gl_direct_state_change)
|
|
|
|
{
|
2014-07-27 10:33:54 +00:00
|
|
|
if (mSrcBlend != stSrcBlend || mDstBlend != stDstBlend)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-07-27 10:33:54 +00:00
|
|
|
stSrcBlend = mSrcBlend;
|
|
|
|
stDstBlend = mDstBlend;
|
2013-06-23 07:49:34 +00:00
|
|
|
glBlendFunc(mSrcBlend, mDstBlend);
|
|
|
|
}
|
2014-07-27 10:33:54 +00:00
|
|
|
if (mBlendEquation != stBlendEquation)
|
2013-06-23 07:49:34 +00:00
|
|
|
{
|
2014-07-27 10:33:54 +00:00
|
|
|
stBlendEquation = mBlendEquation;
|
|
|
|
glBlendEquation(mBlendEquation);
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-10 19:47:07 +00:00
|
|
|
if (mVertexBuffer != mCurrentVertexBuffer)
|
|
|
|
{
|
|
|
|
if (mVertexBuffer == NULL) glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
|
|
else mVertexBuffer->BindVBO();
|
|
|
|
mCurrentVertexBuffer = mVertexBuffer;
|
|
|
|
}
|
2014-06-21 13:50:32 +00:00
|
|
|
ApplyShader();
|
2013-06-23 07:49:34 +00:00
|
|
|
}
|
|
|
|
|
2014-07-13 20:37:34 +00:00
|
|
|
|
|
|
|
|
|
|
|
void FRenderState::ApplyMatrices()
|
|
|
|
{
|
2014-07-13 21:13:40 +00:00
|
|
|
if (GLRenderer->mShaderManager != NULL)
|
|
|
|
{
|
|
|
|
GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix);
|
|
|
|
}
|
2014-07-13 20:37:34 +00:00
|
|
|
}
|