2016-09-14 18:01:13 +00:00
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2009-2016 Christoph Oelckers
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
2013-06-23 07:49:34 +00:00
# ifndef __GL_RENDERSTATE_H
# define __GL_RENDERSTATE_H
# include <string.h>
2014-05-11 17:44:19 +00:00
# include "gl/system/gl_interface.h"
2014-05-12 12:45:41 +00:00
# include "gl/data/gl_data.h"
2017-11-25 12:51:09 +00:00
# include "r_data/matrix.h"
2014-09-09 10:00:42 +00:00
# include "gl/textures/gl_material.h"
2013-06-23 07:49:34 +00:00
# include "c_cvars.h"
2014-05-10 15:09:43 +00:00
# include "r_defs.h"
2014-09-09 11:21:36 +00:00
# include "r_data/r_translate.h"
2013-06-23 07:49:34 +00:00
2014-05-10 19:47:07 +00:00
class FVertexBuffer ;
2014-08-01 18:59:39 +00:00
class FShader ;
2014-07-13 20:37:34 +00:00
extern TArray < VSMatrix > gl_MatrixStack ;
2014-05-10 19:47:07 +00:00
2013-06-23 07:49:34 +00:00
EXTERN_CVAR ( Bool , gl_direct_state_change )
2014-05-12 12:45:41 +00:00
struct FStateVec4
2013-06-23 07:49:34 +00:00
{
float vec [ 4 ] ;
void Set ( float r , float g , float b , float a )
{
vec [ 0 ] = r ;
vec [ 1 ] = g ;
vec [ 2 ] = b ;
vec [ 3 ] = a ;
}
} ;
enum EEffect
{
2014-05-12 12:45:41 +00:00
EFF_NONE = - 1 ,
2013-06-23 07:49:34 +00:00
EFF_FOGBOUNDARY ,
EFF_SPHEREMAP ,
2014-05-12 12:45:41 +00:00
EFF_BURN ,
EFF_STENCIL ,
MAX_EFFECTS
2013-06-23 07:49:34 +00:00
} ;
2016-09-20 00:57:57 +00:00
enum EPassType
{
NORMAL_PASS ,
GBUFFER_PASS ,
MAX_PASS_TYPES
} ;
2013-06-23 07:49:34 +00:00
class FRenderState
{
bool mTextureEnabled ;
bool mFogEnabled ;
bool mGlowEnabled ;
2016-01-30 22:01:11 +00:00
bool mSplitEnabled ;
2016-04-28 23:48:06 +00:00
bool mClipLineEnabled ;
2013-06-23 07:49:34 +00:00
bool mBrightmapEnabled ;
2015-12-31 16:57:21 +00:00
bool mColorMask [ 4 ] ;
bool currentColorMask [ 4 ] ;
2014-08-01 18:59:39 +00:00
int mLightIndex ;
2013-06-23 07:49:34 +00:00
int mSpecialEffect ;
int mTextureMode ;
2014-05-12 12:45:41 +00:00
int mDesaturation ;
2014-05-11 22:13:19 +00:00
int mSoftLight ;
2014-05-12 12:45:41 +00:00
float mLightParms [ 4 ] ;
2013-06-23 07:49:34 +00:00
int mSrcBlend , mDstBlend ;
float mAlphaThreshold ;
int mBlendEquation ;
2014-07-13 18:41:20 +00:00
bool mModelMatrixEnabled ;
bool mTextureMatrixEnabled ;
2016-08-14 07:14:26 +00:00
bool mLastDepthClamp ;
2014-08-01 18:59:39 +00:00
float mInterpolationFactor ;
2016-04-26 22:41:00 +00:00
float mClipHeight , mClipHeightDirection ;
2018-01-25 18:53:55 +00:00
float mGlossiness , mSpecularLevel ;
2014-07-26 18:56:10 +00:00
float mShaderTimer ;
2013-06-23 07:49:34 +00:00
2014-05-10 19:47:07 +00:00
FVertexBuffer * mVertexBuffer , * mCurrentVertexBuffer ;
2016-10-03 14:09:32 +00:00
FStateVec4 mNormal ;
2014-05-11 14:06:25 +00:00
FStateVec4 mColor ;
2014-05-12 12:45:41 +00:00
FStateVec4 mCameraPos ;
2013-06-23 07:49:34 +00:00
FStateVec4 mGlowTop , mGlowBottom ;
2014-05-10 15:09:43 +00:00
FStateVec4 mGlowTopPlane , mGlowBottomPlane ;
2016-01-30 22:01:11 +00:00
FStateVec4 mSplitTopPlane , mSplitBottomPlane ;
2016-04-28 23:48:06 +00:00
FStateVec4 mClipLine ;
2013-06-23 07:49:34 +00:00
PalEntry mFogColor ;
2014-05-11 14:06:25 +00:00
PalEntry mObjectColor ;
2017-01-28 17:19:58 +00:00
PalEntry mObjectColor2 ;
2018-03-29 14:21:21 +00:00
PalEntry m2DColors [ 2 ] ; // in the shader these will reuse the colormap ramp uniforms.
2014-07-01 07:52:41 +00:00
FStateVec4 mDynColor ;
2015-04-05 16:55:21 +00:00
float mClipSplit [ 2 ] ;
2013-06-23 07:49:34 +00:00
int mEffectState ;
int mColormapState ;
2018-03-01 12:52:23 +00:00
int mTempTM = TM_MODULATE ;
2013-06-23 07:49:34 +00:00
2014-07-27 10:33:54 +00:00
float stAlphaThreshold ;
int stSrcBlend , stDstBlend ;
bool stAlphaTest ;
int stBlendEquation ;
2013-06-23 07:49:34 +00:00
2014-08-01 18:59:39 +00:00
FShader * activeShader ;
2016-09-20 00:57:57 +00:00
EPassType mPassType = NORMAL_PASS ;
2016-10-21 22:09:06 +00:00
int mNumDrawBuffers = 1 ;
2016-09-20 00:57:57 +00:00
2013-06-23 07:49:34 +00:00
bool ApplyShader ( ) ;
public :
2014-07-13 18:41:20 +00:00
VSMatrix mProjectionMatrix ;
VSMatrix mViewMatrix ;
VSMatrix mModelMatrix ;
VSMatrix mTextureMatrix ;
2016-10-03 14:09:32 +00:00
VSMatrix mNormalViewMatrix ;
2014-07-13 18:41:20 +00:00
2013-06-23 07:49:34 +00:00
FRenderState ( )
{
Reset ( ) ;
}
void Reset ( ) ;
2014-09-09 10:00:42 +00:00
void SetMaterial ( FMaterial * mat , int clampmode , int translation , int overrideshader , bool alphatexture )
2014-07-26 18:56:10 +00:00
{
2018-03-30 16:14:42 +00:00
// alpha textures need special treatment in the legacy renderer because without shaders they need a different texture. This will also override all other translations.
2018-04-01 12:38:48 +00:00
if ( alphatexture & & gl . legacyMode ) translation = - STRange_AlphaTexture ;
2018-03-22 19:42:17 +00:00
2018-03-01 12:52:23 +00:00
if ( mat - > tex - > bHasCanvas )
{
mTempTM = TM_OPAQUE ;
}
else
{
mTempTM = TM_MODULATE ;
}
2014-09-09 10:00:42 +00:00
mEffectState = overrideshader > = 0 ? overrideshader : mat - > mShaderIndex ;
mShaderTimer = mat - > tex - > gl_info . shaderspeed ;
2018-01-25 18:53:55 +00:00
SetSpecular ( mat - > tex - > gl_info . Glossiness , mat - > tex - > gl_info . SpecularLevel ) ;
2014-09-09 11:21:36 +00:00
mat - > Bind ( clampmode , translation ) ;
2014-07-26 18:56:10 +00:00
}
2014-06-21 13:50:32 +00:00
void Apply ( ) ;
2015-12-31 16:57:21 +00:00
void ApplyColorMask ( ) ;
2014-07-13 18:41:20 +00:00
void ApplyMatrices ( ) ;
2014-08-01 18:59:39 +00:00
void ApplyLightIndex ( int index ) ;
2013-06-23 07:49:34 +00:00
2014-05-10 19:47:07 +00:00
void SetVertexBuffer ( FVertexBuffer * vb )
{
mVertexBuffer = vb ;
}
2014-06-13 23:24:28 +00:00
void ResetVertexBuffer ( )
{
// forces rebinding with the next 'apply' call.
mCurrentVertexBuffer = NULL ;
}
2016-04-26 22:41:00 +00:00
float GetClipHeight ( )
2014-07-13 10:14:12 +00:00
{
2016-04-26 22:41:00 +00:00
return mClipHeight ;
2014-07-13 10:14:12 +00:00
}
2016-04-26 22:41:00 +00:00
float GetClipHeightDirection ( )
2014-07-13 10:14:12 +00:00
{
2016-04-26 22:41:00 +00:00
return mClipHeightDirection ;
2014-07-13 11:25:42 +00:00
}
2016-04-28 23:48:06 +00:00
FStateVec4 & GetClipLine ( )
{
return mClipLine ;
}
bool GetClipLineState ( )
{
return mClipLineEnabled ;
}
2016-04-26 22:41:00 +00:00
void SetClipHeight ( float height , float direction ) ;
2014-07-13 10:14:12 +00:00
2016-10-03 14:09:32 +00:00
void SetNormal ( FVector3 norm )
{
mNormal . Set ( norm . X , norm . Y , norm . Z , 0.f ) ;
}
void SetNormal ( float x , float y , float z )
{
mNormal . Set ( x , y , z , 0.f ) ;
}
2014-05-11 14:06:25 +00:00
void SetColor ( float r , float g , float b , float a = 1.f , int desat = 0 )
{
mColor . Set ( r , g , b , a ) ;
2014-05-12 12:45:41 +00:00
mDesaturation = desat ;
2014-05-11 14:06:25 +00:00
}
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 ) ;
2014-05-12 12:45:41 +00:00
mDesaturation = desat ;
2014-05-11 14:06:25 +00:00
}
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 ) ;
2014-05-12 12:45:41 +00:00
mDesaturation = desat ;
2014-05-11 14:06:25 +00:00
}
void ResetColor ( )
{
mColor . Set ( 1 , 1 , 1 , 1 ) ;
2014-05-12 12:45:41 +00:00
mDesaturation = 0 ;
2014-05-11 14:06:25 +00:00
}
2015-12-31 16:57:21 +00:00
void GetColorMask ( bool & r , bool & g , bool & b , bool & a ) const
{
r = mColorMask [ 0 ] ;
g = mColorMask [ 1 ] ;
b = mColorMask [ 2 ] ;
a = mColorMask [ 3 ] ;
}
void SetColorMask ( bool r , bool g , bool b , bool a )
{
mColorMask [ 0 ] = r ;
mColorMask [ 1 ] = g ;
mColorMask [ 2 ] = b ;
mColorMask [ 3 ] = a ;
}
void ResetColorMask ( )
{
for ( int i = 0 ; i < 4 ; + + i )
mColorMask [ i ] = true ;
}
2013-06-23 07:49:34 +00:00
void SetTextureMode ( int mode )
{
mTextureMode = mode ;
}
2014-09-21 09:08:17 +00:00
int GetTextureMode ( )
{
return mTextureMode ;
}
2013-06-23 07:49:34 +00:00
void EnableTexture ( bool on )
{
mTextureEnabled = on ;
}
void EnableFog ( bool on )
{
mFogEnabled = on ;
}
void SetEffect ( int eff )
{
mSpecialEffect = eff ;
}
void EnableGlow ( bool on )
{
mGlowEnabled = on ;
}
2016-01-30 22:01:11 +00:00
void EnableSplit ( bool on )
{
2016-08-08 10:55:09 +00:00
if ( ! ( gl . flags & RFL_NO_CLIP_PLANES ) )
2016-04-26 19:55:17 +00:00
{
mSplitEnabled = on ;
if ( on )
{
glEnable ( GL_CLIP_DISTANCE3 ) ;
glEnable ( GL_CLIP_DISTANCE4 ) ;
}
else
{
glDisable ( GL_CLIP_DISTANCE3 ) ;
glDisable ( GL_CLIP_DISTANCE4 ) ;
}
}
2016-01-30 22:01:11 +00:00
}
2016-04-28 23:48:06 +00:00
void SetClipLine ( line_t * line )
{
mClipLine . Set ( line - > v1 - > fX ( ) , line - > v1 - > fY ( ) , line - > Delta ( ) . X , line - > Delta ( ) . Y ) ;
}
void EnableClipLine ( bool on )
{
2016-08-08 10:55:09 +00:00
if ( ! ( gl . flags & RFL_NO_CLIP_PLANES ) )
2016-04-28 23:48:06 +00:00
{
mClipLineEnabled = on ;
if ( on )
{
glEnable ( GL_CLIP_DISTANCE0 ) ;
}
else
{
glDisable ( GL_CLIP_DISTANCE0 ) ;
}
}
}
2014-08-01 18:59:39 +00:00
void SetLightIndex ( int n )
2013-06-23 07:49:34 +00:00
{
2014-08-01 18:59:39 +00:00
mLightIndex = n ;
2013-06-23 07:49:34 +00:00
}
void EnableBrightmap ( bool on )
{
mBrightmapEnabled = on ;
}
2014-07-13 18:41:20 +00:00
void EnableModelMatrix ( bool on )
{
mModelMatrixEnabled = on ;
}
void EnableTextureMatrix ( bool on )
{
mTextureMatrixEnabled = on ;
}
2013-06-23 07:49:34 +00:00
void SetCameraPos ( float x , float y , float z )
{
2014-05-12 12:45:41 +00:00
mCameraPos . Set ( x , z , y , 0 ) ;
2013-06-23 07:49:34 +00:00
}
void SetGlowParams ( float * t , float * b )
{
mGlowTop . Set ( t [ 0 ] , t [ 1 ] , t [ 2 ] , t [ 3 ] ) ;
mGlowBottom . Set ( b [ 0 ] , b [ 1 ] , b [ 2 ] , b [ 3 ] ) ;
}
2014-05-11 22:13:19 +00:00
void SetSoftLightLevel ( int level )
{
2014-05-12 12:45:41 +00:00
if ( glset . lightmode = = 8 ) mLightParms [ 3 ] = level / 255.f ;
else mLightParms [ 3 ] = - 1.f ;
2014-05-11 22:13:19 +00:00
}
2014-05-10 15:09:43 +00:00
void SetGlowPlanes ( const secplane_t & top , const secplane_t & bottom )
{
2016-04-04 10:22:47 +00:00
DVector3 tn = top . Normal ( ) ;
DVector3 bn = bottom . Normal ( ) ;
mGlowTopPlane . Set ( tn . X , tn . Y , 1. / tn . Z , top . fD ( ) ) ;
mGlowBottomPlane . Set ( bn . X , bn . Y , 1. / bn . Z , bottom . fD ( ) ) ;
2014-05-10 15:09:43 +00:00
}
2016-01-30 22:01:11 +00:00
void SetSplitPlanes ( const secplane_t & top , const secplane_t & bottom )
{
2016-04-04 10:22:47 +00:00
DVector3 tn = top . Normal ( ) ;
DVector3 bn = bottom . Normal ( ) ;
mSplitTopPlane . Set ( tn . X , tn . Y , 1. / tn . Z , top . fD ( ) ) ;
mSplitBottomPlane . Set ( bn . X , bn . Y , 1. / bn . Z , bottom . fD ( ) ) ;
2016-01-30 22:01:11 +00:00
}
2014-05-10 15:09:43 +00:00
void SetDynLight ( float r , float g , float b )
2013-06-23 07:49:34 +00:00
{
2014-07-01 07:52:41 +00:00
mDynColor . Set ( r , g , b , 0 ) ;
2013-06-23 07:49:34 +00:00
}
2014-05-11 14:54:11 +00:00
void SetObjectColor ( PalEntry pe )
{
mObjectColor = pe ;
}
2017-01-28 17:19:58 +00:00
void SetObjectColor2 ( PalEntry pe )
{
mObjectColor2 = pe ;
}
2018-03-30 16:14:42 +00:00
void Set2DOverlayColor ( PalEntry pe )
2018-03-29 14:21:21 +00:00
{
m2DColors [ 0 ] = pe ;
}
2018-01-25 18:53:55 +00:00
void SetSpecular ( float glossiness , float specularLevel )
{
mGlossiness = glossiness ;
mSpecularLevel = specularLevel ;
}
2013-06-23 07:49:34 +00:00
void SetFog ( PalEntry c , float d )
{
2014-05-12 12:45:41 +00:00
const float LOG2E = 1.442692f ; // = 1/log(2)
2013-06-23 07:49:34 +00:00
mFogColor = c ;
2014-05-12 12:45:41 +00:00
if ( d > = 0.0f ) mLightParms [ 2 ] = d * ( - LOG2E / 64000.f ) ;
2013-06-23 07:49:34 +00:00
}
void SetLightParms ( float f , float d )
{
2014-05-12 12:45:41 +00:00
mLightParms [ 1 ] = f ;
mLightParms [ 0 ] = d ;
2013-06-23 07:49:34 +00:00
}
2013-12-05 14:06:10 +00:00
void SetFixedColormap ( int cm )
{
mColormapState = cm ;
}
2016-04-26 18:02:57 +00:00
int GetFixedColormap ( )
{
return mColormapState ;
}
2013-06-23 07:49:34 +00:00
PalEntry GetFogColor ( ) const
{
return mFogColor ;
}
2015-04-05 16:55:21 +00:00
void SetClipSplit ( float bottom , float top )
{
mClipSplit [ 0 ] = bottom ;
mClipSplit [ 1 ] = top ;
}
void SetClipSplit ( float * vals )
{
memcpy ( mClipSplit , vals , 2 * sizeof ( float ) ) ;
}
void GetClipSplit ( float * out )
{
memcpy ( out , mClipSplit , 2 * sizeof ( float ) ) ;
}
void ClearClipSplit ( )
{
mClipSplit [ 0 ] = - 1000000.f ;
mClipSplit [ 1 ] = 1000000.f ;
}
2013-06-23 07:49:34 +00:00
void BlendFunc ( int src , int dst )
{
if ( ! gl_direct_state_change )
{
mSrcBlend = src ;
mDstBlend = dst ;
}
else
{
glBlendFunc ( src , dst ) ;
}
}
void AlphaFunc ( int func , float thresh )
{
2014-07-14 19:14:43 +00:00
if ( func = = GL_GREATER ) mAlphaThreshold = thresh ;
else mAlphaThreshold = thresh - 0.001f ;
2013-06-23 07:49:34 +00:00
}
void BlendEquation ( int eq )
{
if ( ! gl_direct_state_change )
{
mBlendEquation = eq ;
}
else
{
2014-07-27 10:33:54 +00:00
glBlendEquation ( eq ) ;
2013-06-23 07:49:34 +00:00
}
}
2014-11-27 11:26:52 +00:00
// This wraps the depth clamp setting because we frequently need to read it which OpenGL is not particularly performant at...
bool SetDepthClamp ( bool on )
{
bool res = mLastDepthClamp ;
if ( ! on ) glDisable ( GL_DEPTH_CLAMP ) ;
else glEnable ( GL_DEPTH_CLAMP ) ;
mLastDepthClamp = on ;
return res ;
}
2014-06-29 09:00:21 +00:00
void SetInterpolationFactor ( float fac )
{
mInterpolationFactor = fac ;
}
2016-04-26 16:24:02 +00:00
2016-05-03 11:10:00 +00:00
float GetInterpolationFactor ( )
{
return mInterpolationFactor ;
}
2016-09-20 00:57:57 +00:00
void SetPassType ( EPassType passType )
{
mPassType = passType ;
}
EPassType GetPassType ( )
{
return mPassType ;
}
2016-10-21 22:09:06 +00:00
void EnableDrawBuffers ( int count )
{
count = MIN ( count , 3 ) ;
if ( mNumDrawBuffers ! = count )
{
static GLenum buffers [ ] = { GL_COLOR_ATTACHMENT0 , GL_COLOR_ATTACHMENT1 , GL_COLOR_ATTACHMENT2 } ;
glDrawBuffers ( count , buffers ) ;
mNumDrawBuffers = count ;
}
}
int GetPassDrawBufferCount ( )
{
return mPassType = = GBUFFER_PASS ? 3 : 1 ;
}
2016-04-26 16:24:02 +00:00
// Backwards compatibility crap follows
void ApplyFixedFunction ( ) ;
2016-04-26 18:02:57 +00:00
void DrawColormapOverlay ( ) ;
2013-06-23 07:49:34 +00:00
} ;
extern FRenderState gl_RenderState ;
# endif