gzdoom/src/gl/renderer/gl_renderstate.cpp
Christoph Oelckers 09f54b0940 - cleaned up the clip plane management for portals.
Unfortunately the math behind the old clip planes is utterly impenetrable and so poorly documented that I have no idea how to set that up, so it is deactivated for now. It wasn't working anyway.
2016-04-27 00:41:00 +02:00

350 lines
10 KiB
C++

/*
** 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.
**---------------------------------------------------------------------------
**
*/
#include "templates.h"
#include "gl/system/gl_system.h"
#include "gl/system/gl_interface.h"
#include "gl/data/gl_data.h"
#include "gl/data/gl_vertexbuffer.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"
#include "gl/dynlights//gl_lightbuffer.h"
void gl_SetTextureMode(int type);
FRenderState gl_RenderState;
CVAR(Bool, gl_direct_state_change, true, 0)
static VSMatrix identityMatrix(1);
TArray<VSMatrix> gl_MatrixStack;
//==========================================================================
//
//
//
//==========================================================================
void FRenderState::Reset()
{
mTextureEnabled = true;
mSplitEnabled = mBrightmapEnabled = mFogEnabled = mGlowEnabled = false;
mColorMask[0] = mColorMask[1] = mColorMask[2] = mColorMask[3] = true;
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
mFogColor.d = -1;
mTextureMode = -1;
mLightIndex = -1;
mDesaturation = 0;
mSrcBlend = GL_SRC_ALPHA;
mDstBlend = GL_ONE_MINUS_SRC_ALPHA;
mAlphaThreshold = 0.5f;
mBlendEquation = GL_FUNC_ADD;
mObjectColor = 0xffffffff;
m2D = true;
mVertexBuffer = mCurrentVertexBuffer = NULL;
mColormapState = CM_DEFAULT;
mLightParms[3] = -1.f;
mSpecialEffect = EFF_NONE;
mClipHeight = 0.f;
mClipHeightDirection = 0.f;
ClearClipSplit();
stSrcBlend = stDstBlend = -1;
stBlendEquation = -1;
stAlphaThreshold = -1.f;
mLastDepthClamp = true;
}
//==========================================================================
//
// Apply shader settings
//
//==========================================================================
bool FRenderState::ApplyShader()
{
static const float nulvec[] = { 0.f, 0.f, 0.f, 0.f };
if (mSpecialEffect > EFF_NONE)
{
activeShader = GLRenderer->mShaderManager->BindEffect(mSpecialEffect);
}
else
{
activeShader = GLRenderer->mShaderManager->Get(mTextureEnabled ? mEffectState : 4, mAlphaThreshold >= 0.f);
activeShader->Bind();
}
int fogset = 0;
if (mFogEnabled)
{
if ((mFogColor & 0xffffff) == 0)
{
fogset = gl_fogmode;
}
else
{
fogset = -gl_fogmode;
}
}
glVertexAttrib4fv(VATTR_COLOR, mColor.vec);
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);
activeShader->muDynLightColor.Set(mDynColor.vec);
activeShader->muInterpolationFactor.Set(mInterpolationFactor);
activeShader->muClipHeight.Set(mClipHeight);
activeShader->muClipHeightDirection.Set(mClipHeightDirection);
activeShader->muTimer.Set(gl_frameMS * mShaderTimer / 1000.f);
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
activeShader->muClipSplit.Set(mClipSplit);
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.
activeShader->muGlowTopColor.Set(nulvec);
activeShader->muGlowBottomColor.Set(nulvec);
activeShader->muGlowTopPlane.Set(nulvec);
activeShader->muGlowBottomPlane.Set(nulvec);
activeShader->currentglowstate = 0;
}
if (mSplitEnabled)
{
activeShader->muSplitTopPlane.Set(mSplitTopPlane.vec);
activeShader->muSplitBottomPlane.Set(mSplitBottomPlane.vec);
activeShader->currentsplitstate = 1;
}
else
{
activeShader->muSplitTopPlane.Set(nulvec);
activeShader->muSplitBottomPlane.Set(nulvec);
}
if (mColormapState != activeShader->currentfixedcolormap)
{
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);
}
}
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);
}
return true;
}
//==========================================================================
//
// Apply State
//
//==========================================================================
void FRenderState::Apply()
{
if (!gl_direct_state_change)
{
if (mSrcBlend != stSrcBlend || mDstBlend != stDstBlend)
{
stSrcBlend = mSrcBlend;
stDstBlend = mDstBlend;
glBlendFunc(mSrcBlend, mDstBlend);
}
if (mBlendEquation != stBlendEquation)
{
stBlendEquation = mBlendEquation;
glBlendEquation(mBlendEquation);
}
}
//ApplyColorMask(); I don't think this is needed.
if (mVertexBuffer != mCurrentVertexBuffer)
{
if (mVertexBuffer == NULL) glBindBuffer(GL_ARRAY_BUFFER, 0);
else mVertexBuffer->BindVBO();
mCurrentVertexBuffer = mVertexBuffer;
}
if (gl.glslversion > 0)
{
ApplyShader();
}
else
{
ApplyFixedFunction();
}
}
void FRenderState::ApplyColorMask()
{
if ((mColorMask[0] != currentColorMask[0]) ||
(mColorMask[1] != currentColorMask[1]) ||
(mColorMask[2] != currentColorMask[2]) ||
(mColorMask[3] != currentColorMask[3]))
{
glColorMask(mColorMask[0], mColorMask[1], mColorMask[2], mColorMask[3]);
currentColorMask[0] = mColorMask[0];
currentColorMask[1] = mColorMask[1];
currentColorMask[2] = mColorMask[2];
currentColorMask[3] = mColorMask[3];
}
}
void FRenderState::ApplyMatrices()
{
if (GLRenderer->mShaderManager != NULL)
{
GLRenderer->mShaderManager->ApplyMatrices(&mProjectionMatrix, &mViewMatrix);
}
}
void FRenderState::ApplyLightIndex(int index)
{
if (gl.lightmethod != LM_SOFTWARE)
{
if (index > -1 && GLRenderer->mLights->GetBufferType() == GL_UNIFORM_BUFFER)
{
index = GLRenderer->mLights->BindUBO(index);
}
activeShader->muLightIndex.Set(index);
}
}
void FRenderState::SetClipHeight(float height, float direction)
{
mClipHeight = height;
mClipHeightDirection = direction;
if (direction != 0.f)
{
if (gl.glslversion >= 1.3f) glEnable(GL_CLIP_DISTANCE0);
else
{
// This does not work. Need someone who understands how glClipPlane works...
//glEnable(GL_CLIP_PLANE0);
// Plane mirrors never are slopes.
//double d[4] = { 0, direction, 0, -direction * height };
//glClipPlane(GL_CLIP_PLANE0, d);
}
}
else
{
if (gl.glslversion >= 1.3f) glDisable(GL_CLIP_DISTANCE0);
//else glDisable(GL_CLIP_PLANE0);
}
}