mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-01-06 01:30:54 +00:00
8b6e09ca09
This was done to clean up the license and to ensure that any commercial fork of the engine has to obey the far stricter requirements concerning source distribution. The old license was compatible with GPLv2 whereas combining GPLv2 and LGPLv3 force a license upgrade to GPLv3. The license of code that originates from ZDoomGL has not been changed.
389 lines
7.9 KiB
C++
389 lines
7.9 KiB
C++
//
|
|
//---------------------------------------------------------------------------
|
|
//
|
|
// Copyright(C) 2004-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_SHADERS_H__
|
|
#define __GL_SHADERS_H__
|
|
|
|
#include "gl/renderer/gl_renderstate.h"
|
|
#include "name.h"
|
|
|
|
extern bool gl_shaderactive;
|
|
|
|
enum
|
|
{
|
|
VATTR_VERTEX = 0,
|
|
VATTR_TEXCOORD = 1,
|
|
VATTR_COLOR = 2,
|
|
VATTR_VERTEX2 = 3,
|
|
VATTR_NORMAL = 4
|
|
};
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
//
|
|
//==========================================================================
|
|
|
|
class FUniform1i
|
|
{
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
}
|
|
|
|
void Set(int newvalue)
|
|
{
|
|
glUniform1i(mIndex, newvalue);
|
|
}
|
|
};
|
|
|
|
class FBufferedUniform1i
|
|
{
|
|
int mBuffer;
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
mBuffer = 0;
|
|
}
|
|
|
|
void Set(int newvalue)
|
|
{
|
|
if (newvalue != mBuffer)
|
|
{
|
|
mBuffer = newvalue;
|
|
glUniform1i(mIndex, newvalue);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FBufferedUniform4i
|
|
{
|
|
int mBuffer[4];
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
memset(mBuffer, 0, sizeof(mBuffer));
|
|
}
|
|
|
|
void Set(const int *newvalue)
|
|
{
|
|
if (memcmp(newvalue, mBuffer, sizeof(mBuffer)))
|
|
{
|
|
memcpy(mBuffer, newvalue, sizeof(mBuffer));
|
|
glUniform4iv(mIndex, 1, newvalue);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FBufferedUniform1f
|
|
{
|
|
float mBuffer;
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
mBuffer = 0;
|
|
}
|
|
|
|
void Set(float newvalue)
|
|
{
|
|
if (newvalue != mBuffer)
|
|
{
|
|
mBuffer = newvalue;
|
|
glUniform1f(mIndex, newvalue);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FBufferedUniform2f
|
|
{
|
|
float mBuffer[2];
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
memset(mBuffer, 0, sizeof(mBuffer));
|
|
}
|
|
|
|
void Set(const float *newvalue)
|
|
{
|
|
if (memcmp(newvalue, mBuffer, sizeof(mBuffer)))
|
|
{
|
|
memcpy(mBuffer, newvalue, sizeof(mBuffer));
|
|
glUniform2fv(mIndex, 1, newvalue);
|
|
}
|
|
}
|
|
|
|
void Set(float f1, float f2)
|
|
{
|
|
if (mBuffer[0] != f1 || mBuffer[1] != f2)
|
|
{
|
|
mBuffer[0] = f1;
|
|
mBuffer[1] = f2;
|
|
glUniform2fv(mIndex, 1, mBuffer);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
class FBufferedUniform4f
|
|
{
|
|
float mBuffer[4];
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
memset(mBuffer, 0, sizeof(mBuffer));
|
|
}
|
|
|
|
void Set(const float *newvalue)
|
|
{
|
|
if (memcmp(newvalue, mBuffer, sizeof(mBuffer)))
|
|
{
|
|
memcpy(mBuffer, newvalue, sizeof(mBuffer));
|
|
glUniform4fv(mIndex, 1, newvalue);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FUniform4f
|
|
{
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
}
|
|
|
|
void Set(const float *newvalue)
|
|
{
|
|
glUniform4fv(mIndex, 1, newvalue);
|
|
}
|
|
|
|
void Set(float a, float b, float c, float d)
|
|
{
|
|
glUniform4f(mIndex, a, b, c, d);
|
|
}
|
|
};
|
|
|
|
class FBufferedUniformPE
|
|
{
|
|
PalEntry mBuffer;
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
mBuffer = 0;
|
|
}
|
|
|
|
void Set(PalEntry newvalue)
|
|
{
|
|
if (newvalue != mBuffer)
|
|
{
|
|
mBuffer = newvalue;
|
|
glUniform4f(mIndex, newvalue.r/255.f, newvalue.g/255.f, newvalue.b/255.f, newvalue.a/255.f);
|
|
}
|
|
}
|
|
};
|
|
|
|
class FBufferedUniformSampler
|
|
{
|
|
int mBuffer;
|
|
int mIndex;
|
|
|
|
public:
|
|
void Init(GLuint hShader, const GLchar *name)
|
|
{
|
|
mIndex = glGetUniformLocation(hShader, name);
|
|
mBuffer = -1;
|
|
}
|
|
|
|
void Set(int newvalue)
|
|
{
|
|
if (newvalue != mBuffer)
|
|
{
|
|
mBuffer = newvalue;
|
|
glUniform1i(mIndex, newvalue);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
class FShader
|
|
{
|
|
friend class FShaderManager;
|
|
friend class FRenderState;
|
|
|
|
unsigned int hShader;
|
|
unsigned int hVertProg;
|
|
unsigned int hFragProg;
|
|
FName mName;
|
|
|
|
FBufferedUniform1f muDesaturation;
|
|
FBufferedUniform1i muFogEnabled;
|
|
FBufferedUniform1i muTextureMode;
|
|
FBufferedUniform4f muCameraPos;
|
|
FBufferedUniform4f muLightParms;
|
|
FBufferedUniform2f muClipSplit;
|
|
FUniform1i muFixedColormap;
|
|
FUniform4f muColormapStart;
|
|
FUniform4f muColormapRange;
|
|
FBufferedUniform1i muLightIndex;
|
|
FBufferedUniformPE muFogColor;
|
|
FBufferedUniform4f muDynLightColor;
|
|
FBufferedUniformPE muObjectColor;
|
|
FUniform4f muGlowBottomColor;
|
|
FUniform4f muGlowTopColor;
|
|
FUniform4f muGlowBottomPlane;
|
|
FUniform4f muGlowTopPlane;
|
|
FUniform4f muSplitBottomPlane;
|
|
FUniform4f muSplitTopPlane;
|
|
FUniform4f muClipLine;
|
|
FBufferedUniform1f muInterpolationFactor;
|
|
FBufferedUniform1f muClipHeight;
|
|
FBufferedUniform1f muClipHeightDirection;
|
|
FBufferedUniform1f muAlphaThreshold;
|
|
FBufferedUniform1f muTimer;
|
|
|
|
int lights_index;
|
|
int projectionmatrix_index;
|
|
int viewmatrix_index;
|
|
int modelmatrix_index;
|
|
int texturematrix_index;
|
|
public:
|
|
int vertexmatrix_index;
|
|
int texcoordmatrix_index;
|
|
int quadmode_index;
|
|
int fakevb_index;
|
|
private:
|
|
int currentglowstate = 0;
|
|
int currentsplitstate = 0;
|
|
int currentcliplinestate = 0;
|
|
int currentfixedcolormap = 0;
|
|
bool currentTextureMatrixState = true;// by setting the matrix state to 'true' it is guaranteed to be set the first time the render state gets applied.
|
|
bool currentModelMatrixState = true;
|
|
|
|
public:
|
|
FShader(const char *name)
|
|
: mName(name)
|
|
{
|
|
hShader = hVertProg = hFragProg = 0;
|
|
}
|
|
|
|
~FShader();
|
|
|
|
bool Load(const char * name, const char * vert_prog_lump, const char * fragprog, const char * fragprog2, const char *defines);
|
|
|
|
void SetColormapColor(float r, float g, float b, float r1, float g1, float b1);
|
|
void SetGlowParams(float *topcolors, float topheight, float *bottomcolors, float bottomheight);
|
|
void SetLightRange(int start, int end, int forceadd);
|
|
|
|
bool Bind();
|
|
unsigned int GetHandle() const { return hShader; }
|
|
|
|
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
|
|
|
};
|
|
|
|
|
|
//==========================================================================
|
|
//
|
|
// The global shader manager
|
|
//
|
|
//==========================================================================
|
|
class FShaderManager
|
|
{
|
|
TArray<FShader*> mTextureEffects;
|
|
TArray<FShader*> mTextureEffectsNAT;
|
|
FShader *mActiveShader;
|
|
FShader *mEffectShaders[MAX_EFFECTS];
|
|
|
|
void Clean();
|
|
void CompileShaders();
|
|
|
|
public:
|
|
FShaderManager();
|
|
~FShaderManager();
|
|
FShader *Compile(const char *ShaderName, const char *ShaderPath, bool usediscard);
|
|
int Find(const char *mame);
|
|
FShader *BindEffect(int effect);
|
|
void SetActiveShader(FShader *sh);
|
|
void ApplyMatrices(VSMatrix *proj, VSMatrix *view);
|
|
FShader *GetActiveShader() const
|
|
{
|
|
return mActiveShader;
|
|
}
|
|
|
|
void ResetFixedColormap()
|
|
{
|
|
for (unsigned i = 0; i < mTextureEffects.Size(); i++)
|
|
{
|
|
mTextureEffects[i]->currentfixedcolormap = -1;
|
|
}
|
|
for (unsigned i = 0; i < mTextureEffectsNAT.Size(); i++)
|
|
{
|
|
mTextureEffectsNAT[i]->currentfixedcolormap = -1;
|
|
}
|
|
}
|
|
|
|
FShader *Get(unsigned int eff, bool alphateston)
|
|
{
|
|
// indices 0-2 match the warping modes, 3 is brightmap, 4 no texture, the following are custom
|
|
if (!alphateston && eff <= 3)
|
|
{
|
|
return mTextureEffectsNAT[eff]; // Non-alphatest shaders are only created for default, warp1+2 and brightmap. The rest won't get used anyway
|
|
}
|
|
if (eff < mTextureEffects.Size())
|
|
{
|
|
return mTextureEffects[eff];
|
|
}
|
|
return NULL;
|
|
}
|
|
};
|
|
|
|
#define FIRST_USER_SHADER 12
|
|
|
|
enum
|
|
{
|
|
LIGHTBUF_BINDINGPOINT = 1
|
|
};
|
|
|
|
#endif
|
|
|