mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-12-16 07:21:28 +00:00
488 lines
9 KiB
C++
488 lines
9 KiB
C++
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// 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/
|
|
//
|
|
//--------------------------------------------------------------------------
|
|
//
|
|
|
|
#ifndef __GL_RENDERSTATE_H
|
|
#define __GL_RENDERSTATE_H
|
|
|
|
#include <string.h>
|
|
#include "gl/system/gl_interface.h"
|
|
#include "gl/data/gl_data.h"
|
|
#include "gl/data/gl_matrix.h"
|
|
#include "gl/textures/gl_material.h"
|
|
#include "c_cvars.h"
|
|
#include "r_defs.h"
|
|
#include "r_data/r_translate.h"
|
|
|
|
class FVertexBuffer;
|
|
class FShader;
|
|
extern TArray<VSMatrix> gl_MatrixStack;
|
|
|
|
EXTERN_CVAR(Bool, gl_direct_state_change)
|
|
|
|
struct FStateVec4
|
|
{
|
|
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
|
|
{
|
|
EFF_NONE=-1,
|
|
EFF_FOGBOUNDARY,
|
|
EFF_SPHEREMAP,
|
|
EFF_BURN,
|
|
EFF_STENCIL,
|
|
|
|
MAX_EFFECTS
|
|
};
|
|
|
|
enum EPassType
|
|
{
|
|
NORMAL_PASS,
|
|
GBUFFER_PASS,
|
|
MAX_PASS_TYPES
|
|
};
|
|
|
|
class FRenderState
|
|
{
|
|
bool mTextureEnabled;
|
|
bool mFogEnabled;
|
|
bool mGlowEnabled;
|
|
bool mSplitEnabled;
|
|
bool mClipLineEnabled;
|
|
bool mBrightmapEnabled;
|
|
bool mColorMask[4];
|
|
bool currentColorMask[4];
|
|
int mLightIndex;
|
|
int mSpecialEffect;
|
|
int mTextureMode;
|
|
int mDesaturation;
|
|
int mSoftLight;
|
|
float mLightParms[4];
|
|
int mSrcBlend, mDstBlend;
|
|
float mAlphaThreshold;
|
|
int mBlendEquation;
|
|
bool mModelMatrixEnabled;
|
|
bool mTextureMatrixEnabled;
|
|
bool mLastDepthClamp;
|
|
float mInterpolationFactor;
|
|
float mClipHeight, mClipHeightDirection;
|
|
float mShaderTimer;
|
|
|
|
FVertexBuffer *mVertexBuffer, *mCurrentVertexBuffer;
|
|
FStateVec4 mColor;
|
|
FStateVec4 mCameraPos;
|
|
FStateVec4 mGlowTop, mGlowBottom;
|
|
FStateVec4 mGlowTopPlane, mGlowBottomPlane;
|
|
FStateVec4 mSplitTopPlane, mSplitBottomPlane;
|
|
FStateVec4 mClipLine;
|
|
PalEntry mFogColor;
|
|
PalEntry mObjectColor;
|
|
FStateVec4 mDynColor;
|
|
float mClipSplit[2];
|
|
|
|
int mEffectState;
|
|
int mColormapState;
|
|
|
|
float stAlphaThreshold;
|
|
int stSrcBlend, stDstBlend;
|
|
bool stAlphaTest;
|
|
int stBlendEquation;
|
|
|
|
FShader *activeShader;
|
|
|
|
EPassType mPassType = NORMAL_PASS;
|
|
|
|
bool ApplyShader();
|
|
|
|
public:
|
|
|
|
VSMatrix mProjectionMatrix;
|
|
VSMatrix mViewMatrix;
|
|
VSMatrix mModelMatrix;
|
|
VSMatrix mTextureMatrix;
|
|
|
|
FRenderState()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
void Reset();
|
|
|
|
void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader, bool alphatexture)
|
|
{
|
|
// textures without their own palette are a special case for use as an alpha texture:
|
|
// They use the color index directly as an alpha value instead of using the palette's red.
|
|
// To handle this case, we need to set a special translation for such textures.
|
|
// Without shaders this translation must be applied to any texture.
|
|
if (alphatexture)
|
|
{
|
|
if (mat->tex->UseBasePalette() || gl.legacyMode) translation = TRANSLATION(TRANSLATION_Standard, 8);
|
|
}
|
|
mEffectState = overrideshader >= 0? overrideshader : mat->mShaderIndex;
|
|
mShaderTimer = mat->tex->gl_info.shaderspeed;
|
|
mat->Bind(clampmode, translation);
|
|
}
|
|
|
|
void Apply();
|
|
void ApplyColorMask();
|
|
void ApplyMatrices();
|
|
void ApplyLightIndex(int index);
|
|
|
|
void SetVertexBuffer(FVertexBuffer *vb)
|
|
{
|
|
mVertexBuffer = vb;
|
|
}
|
|
|
|
void ResetVertexBuffer()
|
|
{
|
|
// forces rebinding with the next 'apply' call.
|
|
mCurrentVertexBuffer = NULL;
|
|
}
|
|
|
|
float GetClipHeight()
|
|
{
|
|
return mClipHeight;
|
|
}
|
|
|
|
float GetClipHeightDirection()
|
|
{
|
|
return mClipHeightDirection;
|
|
}
|
|
|
|
FStateVec4 &GetClipLine()
|
|
{
|
|
return mClipLine;
|
|
}
|
|
|
|
bool GetClipLineState()
|
|
{
|
|
return mClipLineEnabled;
|
|
}
|
|
|
|
void SetClipHeight(float height, float direction);
|
|
|
|
void SetColor(float r, float g, float b, float a = 1.f, int desat = 0)
|
|
{
|
|
mColor.Set(r, g, b, a);
|
|
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);
|
|
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);
|
|
mDesaturation = desat;
|
|
}
|
|
|
|
void ResetColor()
|
|
{
|
|
mColor.Set(1,1,1,1);
|
|
mDesaturation = 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
void SetTextureMode(int mode)
|
|
{
|
|
mTextureMode = mode;
|
|
}
|
|
|
|
int GetTextureMode()
|
|
{
|
|
return mTextureMode;
|
|
}
|
|
|
|
void EnableTexture(bool on)
|
|
{
|
|
mTextureEnabled = on;
|
|
}
|
|
|
|
void EnableFog(bool on)
|
|
{
|
|
mFogEnabled = on;
|
|
}
|
|
|
|
void SetEffect(int eff)
|
|
{
|
|
mSpecialEffect = eff;
|
|
}
|
|
|
|
void EnableGlow(bool on)
|
|
{
|
|
mGlowEnabled = on;
|
|
}
|
|
|
|
void EnableSplit(bool on)
|
|
{
|
|
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
|
{
|
|
mSplitEnabled = on;
|
|
if (on)
|
|
{
|
|
glEnable(GL_CLIP_DISTANCE3);
|
|
glEnable(GL_CLIP_DISTANCE4);
|
|
}
|
|
else
|
|
{
|
|
glDisable(GL_CLIP_DISTANCE3);
|
|
glDisable(GL_CLIP_DISTANCE4);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetClipLine(line_t *line)
|
|
{
|
|
mClipLine.Set(line->v1->fX(), line->v1->fY(), line->Delta().X, line->Delta().Y);
|
|
}
|
|
|
|
void EnableClipLine(bool on)
|
|
{
|
|
if (!(gl.flags & RFL_NO_CLIP_PLANES))
|
|
{
|
|
mClipLineEnabled = on;
|
|
if (on)
|
|
{
|
|
glEnable(GL_CLIP_DISTANCE0);
|
|
}
|
|
else
|
|
{
|
|
glDisable(GL_CLIP_DISTANCE0);
|
|
}
|
|
}
|
|
}
|
|
|
|
void SetLightIndex(int n)
|
|
{
|
|
mLightIndex = n;
|
|
}
|
|
|
|
void EnableBrightmap(bool on)
|
|
{
|
|
mBrightmapEnabled = on;
|
|
}
|
|
|
|
void EnableModelMatrix(bool on)
|
|
{
|
|
mModelMatrixEnabled = on;
|
|
}
|
|
|
|
void EnableTextureMatrix(bool on)
|
|
{
|
|
mTextureMatrixEnabled = on;
|
|
}
|
|
|
|
void SetCameraPos(float x, float y, float z)
|
|
{
|
|
mCameraPos.Set(x, z, y, 0);
|
|
}
|
|
|
|
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]);
|
|
}
|
|
|
|
void SetSoftLightLevel(int 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)
|
|
{
|
|
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());
|
|
}
|
|
|
|
void SetSplitPlanes(const secplane_t &top, const secplane_t &bottom)
|
|
{
|
|
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());
|
|
}
|
|
|
|
void SetDynLight(float r, float g, float b)
|
|
{
|
|
mDynColor.Set(r, g, b, 0);
|
|
}
|
|
|
|
void SetObjectColor(PalEntry pe)
|
|
{
|
|
mObjectColor = pe;
|
|
}
|
|
|
|
void SetFog(PalEntry c, float d)
|
|
{
|
|
const float LOG2E = 1.442692f; // = 1/log(2)
|
|
mFogColor = c;
|
|
if (d >= 0.0f) mLightParms[2] = d * (-LOG2E / 64000.f);
|
|
}
|
|
|
|
void SetLightParms(float f, float d)
|
|
{
|
|
mLightParms[1] = f;
|
|
mLightParms[0] = d;
|
|
}
|
|
|
|
void SetFixedColormap(int cm)
|
|
{
|
|
mColormapState = cm;
|
|
}
|
|
|
|
int GetFixedColormap()
|
|
{
|
|
return mColormapState;
|
|
}
|
|
|
|
PalEntry GetFogColor() const
|
|
{
|
|
return mFogColor;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (func == GL_GREATER) mAlphaThreshold = thresh;
|
|
else mAlphaThreshold = thresh - 0.001f;
|
|
}
|
|
|
|
void BlendEquation(int eq)
|
|
{
|
|
if (!gl_direct_state_change)
|
|
{
|
|
mBlendEquation = eq;
|
|
}
|
|
else
|
|
{
|
|
glBlendEquation(eq);
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
void SetInterpolationFactor(float fac)
|
|
{
|
|
mInterpolationFactor = fac;
|
|
}
|
|
|
|
float GetInterpolationFactor()
|
|
{
|
|
return mInterpolationFactor;
|
|
}
|
|
|
|
void SetPassType(EPassType passType)
|
|
{
|
|
mPassType = passType;
|
|
}
|
|
|
|
EPassType GetPassType()
|
|
{
|
|
return mPassType;
|
|
}
|
|
|
|
// Backwards compatibility crap follows
|
|
void ApplyFixedFunction();
|
|
void DrawColormapOverlay();
|
|
};
|
|
|
|
extern FRenderState gl_RenderState;
|
|
|
|
#endif
|