- updated common code.

Most of what got added is still unused.

# Conflicts:
#	source/build/src/palette.cpp

# Conflicts:
#	source/build/src/palette.cpp

# Conflicts:
#	source/common/engine/i_interface.h
This commit is contained in:
Christoph Oelckers 2020-04-26 00:01:04 +02:00
parent 82eb807090
commit ea08fa0a4e
20 changed files with 1494 additions and 62 deletions

View file

@ -0,0 +1,83 @@
#pragma once
#include <stddef.h>
#include <assert.h>
class FRenderState;
// The low level code needs to know which attributes exist.
// OpenGL needs to change the state of all of them per buffer binding.
// VAOs are mostly useless for this because they lump buffer and binding state together which the model code does not want.
enum
{
VATTR_VERTEX,
VATTR_TEXCOORD,
VATTR_COLOR,
VATTR_VERTEX2,
VATTR_NORMAL,
VATTR_NORMAL2,
VATTR_MAX
};
enum EVertexAttributeFormat
{
VFmt_Float4,
VFmt_Float3,
VFmt_Float2,
VFmt_Float,
VFmt_Byte4,
VFmt_Packed_A2R10G10B10,
};
struct FVertexBufferAttribute
{
int binding;
int location;
int format;
int offset;
};
class IBuffer
{
protected:
size_t buffersize = 0;
void *map = nullptr;
public:
IBuffer() = default;
IBuffer(const IBuffer &) = delete;
IBuffer &operator=(const IBuffer &) = delete;
virtual ~IBuffer() = default;
virtual void SetData(size_t size, const void *data, bool staticdata = true) = 0;
virtual void SetSubData(size_t offset, size_t size, const void *data) = 0;
virtual void *Lock(unsigned int size) = 0;
virtual void Unlock() = 0;
virtual void Resize(size_t newsize) = 0;
virtual void Map() {} // Only needed by old OpenGL but this needs to be in the interface.
virtual void Unmap() {}
void *Memory() { assert(map); return map; }
size_t Size() { return buffersize; }
};
class IVertexBuffer : virtual public IBuffer
{
public:
virtual void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) = 0;
};
// This merely exists to have a dedicated type for index buffers to inherit from.
class IIndexBuffer : virtual public IBuffer
{
// Element size is fixed to 4, thanks to OpenGL requiring this info to be coded into the glDrawElements call.
// This mostly prohibits a more flexible buffer setup but GZDoom doesn't use any other format anyway.
// Ob Vulkam, element size is a buffer property and of no concern to the drawing functions (as it should be.)
};
class IDataBuffer : virtual public IBuffer
{
// Can be either uniform or shader storage buffer, depending on its needs.
public:
virtual void BindRange(FRenderState *state, size_t start, size_t length) = 0;
};

View file

@ -0,0 +1,665 @@
#pragma once
#include "v_palette.h"
#include "vectors.h"
#include "matrix.h"
#include "hw_material.h"
#include "texmanip.h"
struct FColormap;
class IVertexBuffer;
class IIndexBuffer;
enum EClearTarget
{
CT_Depth = 1,
CT_Stencil = 2,
CT_Color = 4
};
enum ERenderEffect
{
EFF_NONE = -1,
EFF_FOGBOUNDARY,
EFF_SPHEREMAP,
EFF_BURN,
EFF_STENCIL,
MAX_EFFECTS
};
enum EAlphaFunc
{
Alpha_GEqual = 0,
Alpha_Greater = 1
};
enum EDrawType
{
DT_Points = 0,
DT_Lines = 1,
DT_Triangles = 2,
DT_TriangleFan = 3,
DT_TriangleStrip = 4
};
enum EDepthFunc
{
DF_Less,
DF_LEqual,
DF_Always
};
enum EStencilFlags
{
SF_AllOn = 0,
SF_ColorMaskOff = 1,
SF_DepthMaskOff = 2,
};
enum EStencilOp
{
SOP_Keep = 0,
SOP_Increment = 1,
SOP_Decrement = 2
};
enum ECull
{
Cull_None,
Cull_CCW,
Cull_CW
};
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;
}
};
struct FMaterialState
{
FMaterial *mMaterial;
int mClampMode;
int mTranslation;
int mOverrideShader;
bool mChanged;
void Reset()
{
mMaterial = nullptr;
mTranslation = 0;
mClampMode = CLAMP_NONE;
mOverrideShader = -1;
mChanged = false;
}
};
struct FDepthBiasState
{
float mFactor;
float mUnits;
bool mChanged;
void Reset()
{
mFactor = 0;
mUnits = 0;
mChanged = false;
}
};
enum EPassType
{
NORMAL_PASS,
GBUFFER_PASS,
MAX_PASS_TYPES
};
struct FVector4PalEntry
{
float r, g, b, a;
bool operator==(const FVector4PalEntry &other) const
{
return r == other.r && g == other.g && b == other.b && a == other.a;
}
bool operator!=(const FVector4PalEntry &other) const
{
return r != other.r || g != other.g || b != other.b || a != other.a;
}
FVector4PalEntry &operator=(PalEntry newvalue)
{
const float normScale = 1.0f / 255.0f;
r = newvalue.r * normScale;
g = newvalue.g * normScale;
b = newvalue.b * normScale;
a = newvalue.a * normScale;
return *this;
}
FVector4PalEntry& SetIA(PalEntry newvalue)
{
const float normScale = 1.0f / 255.0f;
r = newvalue.r * normScale;
g = newvalue.g * normScale;
b = newvalue.b * normScale;
a = 1;
return *this;
}
FVector4PalEntry& SetFlt(float v1, float v2, float v3, float v4)
{
r = v1;
g = v2;
b = v3;
a = v4;
return *this;
}
};
struct StreamData
{
FVector4PalEntry uObjectColor;
FVector4PalEntry uObjectColor2;
FVector4 uDynLightColor;
FVector4PalEntry uAddColor;
FVector4PalEntry uTextureAddColor;
FVector4PalEntry uTextureModulateColor;
FVector4PalEntry uTextureBlendColor;
FVector4PalEntry uFogColor;
float uDesaturationFactor;
float uInterpolationFactor;
float timer;
int useVertexData;
FVector4 uVertexColor;
FVector4 uVertexNormal;
FVector4 uGlowTopPlane;
FVector4 uGlowTopColor;
FVector4 uGlowBottomPlane;
FVector4 uGlowBottomColor;
FVector4 uGradientTopPlane;
FVector4 uGradientBottomPlane;
FVector4 uSplitTopPlane;
FVector4 uSplitBottomPlane;
FVector4 uDetailParms;
};
class FRenderState
{
protected:
uint8_t mFogEnabled;
uint8_t mTextureEnabled:1;
uint8_t mGlowEnabled : 1;
uint8_t mGradientEnabled : 1;
uint8_t mModelMatrixEnabled : 1;
uint8_t mTextureMatrixEnabled : 1;
uint8_t mSplitEnabled : 1;
uint8_t mBrightmapEnabled : 1;
int mLightIndex;
int mSpecialEffect;
int mTextureMode;
int mTextureModeFlags;
int mSoftLight;
float mLightParms[4];
float mAlphaThreshold;
float mClipSplit[2];
StreamData mStreamData = {};
PalEntry mFogColor;
FRenderStyle mRenderStyle;
FMaterialState mMaterial;
FDepthBiasState mBias;
IVertexBuffer *mVertexBuffer;
int mVertexOffsets[2]; // one per binding point
IIndexBuffer *mIndexBuffer;
EPassType mPassType = NORMAL_PASS;
public:
uint64_t firstFrame = 0;
VSMatrix mModelMatrix;
VSMatrix mTextureMatrix;
public:
void Reset()
{
mTextureEnabled = true;
mBrightmapEnabled = mGradientEnabled = mFogEnabled = mGlowEnabled = false;
mFogColor = 0xffffffff;
mStreamData.uFogColor = mFogColor;
mTextureMode = -1;
mTextureModeFlags = 0;
mStreamData.uDesaturationFactor = 0.0f;
mAlphaThreshold = 0.5f;
mModelMatrixEnabled = false;
mTextureMatrixEnabled = false;
mSplitEnabled = false;
mStreamData.uAddColor = 0;
mStreamData.uObjectColor = 0xffffffff;
mStreamData.uObjectColor2 = 0;
mStreamData.uTextureBlendColor = 0;
mStreamData.uTextureAddColor = 0;
mStreamData.uTextureModulateColor = 0;
mSoftLight = 0;
mLightParms[0] = mLightParms[1] = mLightParms[2] = 0.0f;
mLightParms[3] = -1.f;
mSpecialEffect = EFF_NONE;
mLightIndex = -1;
mStreamData.uInterpolationFactor = 0;
mRenderStyle = DefaultRenderStyle();
mMaterial.Reset();
mBias.Reset();
mPassType = NORMAL_PASS;
mVertexBuffer = nullptr;
mVertexOffsets[0] = mVertexOffsets[1] = 0;
mIndexBuffer = nullptr;
mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f };
mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uGlowTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uGlowBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uGradientTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uGradientBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uDynLightColor = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uDetailParms = { 0.0f, 0.0f, 0.0f, 0.0f };
mModelMatrix.loadIdentity();
mTextureMatrix.loadIdentity();
ClearClipSplit();
}
void SetNormal(FVector3 norm)
{
mStreamData.uVertexNormal = { norm.X, norm.Y, norm.Z, 0.f };
}
void SetNormal(float x, float y, float z)
{
mStreamData.uVertexNormal = { x, y, z, 0.f };
}
void SetColor(float r, float g, float b, float a = 1.f, int desat = 0)
{
mStreamData.uVertexColor = { r, g, b, a };
mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f);
}
void SetColor(PalEntry pe, int desat = 0)
{
const float scale = 1.0f / 255.0f;
mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, pe.a * scale };
mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f);
}
void SetColorAlpha(PalEntry pe, float alpha = 1.f, int desat = 0)
{
const float scale = 1.0f / 255.0f;
mStreamData.uVertexColor = { pe.r * scale, pe.g * scale, pe.b * scale, alpha };
mStreamData.uDesaturationFactor = desat * (1.0f / 255.0f);
}
void ResetColor()
{
mStreamData.uVertexColor = { 1.0f, 1.0f, 1.0f, 1.0f };
mStreamData.uDesaturationFactor = 0.0f;
}
void SetTextureMode(int mode)
{
mTextureMode = mode;
}
void SetTextureMode(FRenderStyle style)
{
if (style.Flags & STYLEF_RedIsAlpha)
{
SetTextureMode(TM_ALPHATEXTURE);
}
else if (style.Flags & STYLEF_ColorIsFixed)
{
SetTextureMode(TM_STENCIL);
}
else if (style.Flags & STYLEF_InvertSource)
{
SetTextureMode(TM_INVERSE);
}
}
int GetTextureMode()
{
return mTextureMode;
}
void EnableTexture(bool on)
{
mTextureEnabled = on;
}
void EnableFog(uint8_t on)
{
mFogEnabled = on;
}
void SetEffect(int eff)
{
mSpecialEffect = eff;
}
void EnableGlow(bool on)
{
if (mGlowEnabled && !on)
{
mStreamData.uGlowTopColor = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uGlowBottomColor = { 0.0f, 0.0f, 0.0f, 0.0f };
}
mGlowEnabled = on;
}
void EnableGradient(bool on)
{
mGradientEnabled = on;
}
void EnableBrightmap(bool on)
{
mBrightmapEnabled = on;
}
void EnableSplit(bool on)
{
if (mSplitEnabled && !on)
{
mStreamData.uSplitTopPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
mStreamData.uSplitBottomPlane = { 0.0f, 0.0f, 0.0f, 0.0f };
}
mSplitEnabled = on;
}
void EnableModelMatrix(bool on)
{
mModelMatrixEnabled = on;
}
void EnableTextureMatrix(bool on)
{
mTextureMatrixEnabled = on;
}
void SetGlowParams(float *t, float *b)
{
mStreamData.uGlowTopColor = { t[0], t[1], t[2], t[3] };
mStreamData.uGlowBottomColor = { b[0], b[1], b[2], b[3] };
}
void SetSoftLightLevel(int llevel, int blendfactor = 0)
{
if (blendfactor == 0) mLightParms[3] = llevel / 255.f;
else mLightParms[3] = -1.f;
}
void SetNoSoftLightLevel()
{
mLightParms[3] = -1.f;
}
void SetGlowPlanes(const FVector4 &tp, const FVector4& bp)
{
mStreamData.uGlowTopPlane = tp;
mStreamData.uGlowBottomPlane = bp;
}
void SetGradientPlanes(const FVector4& tp, const FVector4& bp)
{
mStreamData.uGradientTopPlane = tp;
mStreamData.uGradientBottomPlane = bp;
}
void SetSplitPlanes(const FVector4& tp, const FVector4& bp)
{
mStreamData.uSplitTopPlane = tp;
mStreamData.uSplitBottomPlane = bp;
}
void SetDetailParms(float xscale, float yscale, float bias)
{
mStreamData.uDetailParms = { xscale, yscale, bias, 0 };
}
void SetDynLight(float r, float g, float b)
{
mStreamData.uDynLightColor = { r, g, b, 0.0f };
}
void SetObjectColor(PalEntry pe)
{
mStreamData.uObjectColor = pe;
}
void SetObjectColor2(PalEntry pe)
{
mStreamData.uObjectColor2 = pe;
}
void SetAddColor(PalEntry pe)
{
mStreamData.uAddColor = pe;
}
void ApplyTextureManipulation(TextureManipulation* texfx)
{
if (!texfx || texfx->AddColor.a == 0)
{
mStreamData.uTextureAddColor.a = 0; // we only need to set the flags to 0
}
else
{
// set up the whole thing
mStreamData.uTextureAddColor.SetIA(texfx->AddColor);
auto pe = texfx->ModulateColor;
mStreamData.uTextureModulateColor.SetFlt(pe.r * pe.a / 255.f, pe.g * pe.a / 255.f, pe.b * pe.a / 255.f, texfx->DesaturationFactor);
mStreamData.uTextureBlendColor = texfx->BlendColor;
}
}
void SetFog(PalEntry c, float d)
{
const float LOG2E = 1.442692f; // = 1/log(2)
mFogColor = c;
mStreamData.uFogColor = mFogColor;
if (d >= 0.0f) mLightParms[2] = d * (-LOG2E / 64000.f);
}
void SetLightParms(float f, float d)
{
mLightParms[1] = f;
mLightParms[0] = d;
}
PalEntry GetFogColor() const
{
return mFogColor;
}
void AlphaFunc(int func, float thresh)
{
if (func == Alpha_Greater) mAlphaThreshold = thresh;
else mAlphaThreshold = thresh - 0.001f;
}
void SetLightIndex(int index)
{
mLightIndex = index;
}
void SetRenderStyle(FRenderStyle rs)
{
mRenderStyle = rs;
}
void SetRenderStyle(ERenderStyle rs)
{
mRenderStyle = rs;
}
void SetDepthBias(float a, float b)
{
mBias.mFactor = a;
mBias.mUnits = b;
mBias.mChanged = true;
}
void ClearDepthBias()
{
mBias.mFactor = 0;
mBias.mUnits = 0;
mBias.mChanged = true;
}
void SetMaterial(FMaterial *mat, int clampmode, int translation, int overrideshader)
{
mMaterial.mMaterial = mat;
mMaterial.mClampMode = clampmode;
mMaterial.mTranslation = translation;
mMaterial.mOverrideShader = overrideshader;
mMaterial.mChanged = true;
mTextureModeFlags = mat->GetLayerFlags();
}
void SetMaterial(FGameTexture* tex, EUpscaleFlags upscalemask, int scaleflags, int clampmode, int translation, int overrideshader)
{
if (shouldUpscale(tex, upscalemask)) scaleflags |= CTF_Upscale;
SetMaterial(FMaterial::ValidateTexture(tex, scaleflags), clampmode, translation, overrideshader);
}
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 SetVertexBuffer(IVertexBuffer *vb, int offset0, int offset1)
{
assert(vb);
mVertexBuffer = vb;
mVertexOffsets[0] = offset0;
mVertexOffsets[1] = offset1;
}
void SetIndexBuffer(IIndexBuffer *ib)
{
mIndexBuffer = ib;
}
template <class T> void SetVertexBuffer(T *buffer)
{
auto ptrs = buffer->GetBufferObjects();
SetVertexBuffer(ptrs.first, 0, 0);
SetIndexBuffer(ptrs.second);
}
void SetInterpolationFactor(float fac)
{
mStreamData.uInterpolationFactor = fac;
}
float GetInterpolationFactor()
{
return mStreamData.uInterpolationFactor;
}
void EnableDrawBufferAttachments(bool on) // Used by fog boundary drawer
{
EnableDrawBuffers(on ? GetPassDrawBufferCount() : 1);
}
int GetPassDrawBufferCount()
{
return mPassType == GBUFFER_PASS ? 3 : 1;
}
void SetPassType(EPassType passType)
{
mPassType = passType;
}
EPassType GetPassType()
{
return mPassType;
}
// API-dependent render interface
// Draw commands
virtual void ClearScreen() = 0;
virtual void Draw(int dt, int index, int count, bool apply = true) = 0;
virtual void DrawIndexed(int dt, int index, int count, bool apply = true) = 0;
// Immediate render state change commands. These only change infrequently and should not clutter the render state.
virtual bool SetDepthClamp(bool on) = 0; // Deactivated only by skyboxes.
virtual void SetDepthMask(bool on) = 0; // Used by decals and indirectly by portal setup.
virtual void SetDepthFunc(int func) = 0; // Used by models, portals and mirror surfaces.
virtual void SetDepthRange(float min, float max) = 0; // Used by portal setup.
virtual void SetColorMask(bool r, bool g, bool b, bool a) = 0; // Used by portals.
virtual void SetStencil(int offs, int op, int flags=-1) = 0; // Used by portal setup and render hacks.
virtual void SetCulling(int mode) = 0; // Used by model drawer only.
virtual void EnableClipDistance(int num, bool state) = 0; // Use by sprite sorter for vertical splits.
virtual void Clear(int targets) = 0; // not used during normal rendering
virtual void EnableStencil(bool on) = 0; // always on for 3D, always off for 2D
virtual void SetScissor(int x, int y, int w, int h) = 0; // constant for 3D, changes for 2D
virtual void SetViewport(int x, int y, int w, int h) = 0; // constant for all 3D and all 2D
virtual void EnableDepthTest(bool on) = 0; // used by 2D, portals and render hacks.
virtual void EnableMultisampling(bool on) = 0; // only active for 2D
virtual void EnableLineSmooth(bool on) = 0; // constant setting for each 2D drawer operation
virtual void EnableDrawBuffers(int count, bool apply = false) = 0; // Used by SSAO and EnableDrawBufferAttachments
void SetColorMask(bool on)
{
SetColorMask(on, on, on, on);
}
};

View file

@ -0,0 +1,33 @@
#pragma once
#include <stdint.h>
#include "tflags.h"
// A render queue is what contains all render commands.
// On Vulkan there can be several of them so this interface is needed to allow for the needed parallelism.
// On OpenGL the render state is global so all this will do is to translate the system independent calls into OpenGL API calls.
enum class ColormaskBits
{
RED = 1,
GREEN = 2,
BLUE = 4,
ALPHA = 8
};
typedef TFlags<ColormaskBits, uint8_t> Colormask;
class IRenderQueue
{
Colormask mColorMask;
Colormask GetColorMask() const
{
return mColorMask;
}
virtual void SetColorMask(Colormask mask) = 0;
};

View file

@ -0,0 +1,154 @@
#pragma once
#include <vector>
#include "hwrenderer/data/buffers.h"
#include "v_video.h"
enum
{
LIGHTBUF_BINDINGPOINT = 1,
POSTPROCESS_BINDINGPOINT = 2,
VIEWPOINT_BINDINGPOINT = 3,
LIGHTNODES_BINDINGPOINT = 4,
LIGHTLINES_BINDINGPOINT = 5,
LIGHTLIST_BINDINGPOINT = 6
};
enum class UniformType
{
Int,
UInt,
Float,
Vec2,
Vec3,
Vec4,
IVec2,
IVec3,
IVec4,
UVec2,
UVec3,
UVec4,
Mat4
};
class UniformFieldDesc
{
public:
UniformFieldDesc() { }
UniformFieldDesc(const char *name, UniformType type, std::size_t offset) : Name(name), Type(type), Offset(offset) { }
const char *Name;
UniformType Type;
std::size_t Offset;
};
class UniformBlockDecl
{
public:
static FString Create(const char *name, const std::vector<UniformFieldDesc> &fields, int bindingpoint)
{
FString decl;
FString layout;
if (bindingpoint == -1)
{
layout = "push_constant";
}
else if (screen->glslversion < 4.20)
{
layout = "std140";
}
else
{
layout.Format("std140, binding = %d", bindingpoint);
}
decl.Format("layout(%s) uniform %s\n{\n", layout.GetChars(), name);
for (size_t i = 0; i < fields.size(); i++)
{
decl.AppendFormat("\t%s %s;\n", GetTypeStr(fields[i].Type), fields[i].Name);
}
decl += "};\n";
return decl;
}
private:
static const char *GetTypeStr(UniformType type)
{
switch (type)
{
default:
case UniformType::Int: return "int";
case UniformType::UInt: return "uint";
case UniformType::Float: return "float";
case UniformType::Vec2: return "vec2";
case UniformType::Vec3: return "vec3";
case UniformType::Vec4: return "vec4";
case UniformType::IVec2: return "ivec2";
case UniformType::IVec3: return "ivec3";
case UniformType::IVec4: return "ivec4";
case UniformType::UVec2: return "uvec2";
case UniformType::UVec3: return "uvec3";
case UniformType::UVec4: return "uvec4";
case UniformType::Mat4: return "mat4";
}
}
};
template<typename T, int bindingpoint>
class ShaderUniforms
{
public:
ShaderUniforms()
{
memset(&Values, 0, sizeof(Values));
}
~ShaderUniforms()
{
if (mBuffer != nullptr)
delete mBuffer;
}
int BindingPoint() const
{
return bindingpoint;
}
FString CreateDeclaration(const char *name, const std::vector<UniformFieldDesc> &fields)
{
mFields = fields;
return UniformBlockDecl::Create(name, fields, bindingpoint);
}
void Init()
{
if (mBuffer == nullptr)
mBuffer = screen->CreateDataBuffer(bindingpoint, false, false);
}
void SetData()
{
if (mBuffer != nullptr)
mBuffer->SetData(sizeof(T), &Values);
}
IDataBuffer* GetBuffer() const
{
// OpenGL needs to mess around with this in ways that should not be part of the interface.
return mBuffer;
}
T *operator->() { return &Values; }
const T *operator->() const { return &Values; }
T Values;
private:
ShaderUniforms(const ShaderUniforms &) = delete;
ShaderUniforms &operator=(const ShaderUniforms &) = delete;
IDataBuffer *mBuffer = nullptr;
std::vector<UniformFieldDesc> mFields;
};

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,843 @@
#pragma once
#include "hwrenderer/data/shaderuniforms.h"
#include <memory>
#include <map>
struct PostProcessShader;
typedef FRenderStyle PPBlendMode;
typedef IntRect PPViewport;
class PPTexture;
class PPShader;
enum class PPFilterMode { Nearest, Linear };
enum class PPWrapMode { Clamp, Repeat };
enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap };
class PPTextureInput
{
public:
PPFilterMode Filter = PPFilterMode::Nearest;
PPWrapMode Wrap = PPWrapMode::Clamp;
PPTextureType Type = PPTextureType::CurrentPipelineTexture;
PPTexture *Texture = nullptr;
};
class PPOutput
{
public:
PPTextureType Type = PPTextureType::NextPipelineTexture;
PPTexture *Texture = nullptr;
};
class PPUniforms
{
public:
PPUniforms()
{
}
PPUniforms(const PPUniforms &src)
{
Data = src.Data;
}
~PPUniforms()
{
Clear();
}
PPUniforms &operator=(const PPUniforms &src)
{
Data = src.Data;
return *this;
}
void Clear()
{
Data.Clear();
}
template<typename T>
void Set(const T &v)
{
if (Data.Size() != (int)sizeof(T))
{
Data.Resize(sizeof(T));
memcpy(Data.Data(), &v, Data.Size());
}
}
TArray<uint8_t> Data;
};
class PPRenderState
{
public:
virtual ~PPRenderState() = default;
virtual void PushGroup(const FString &name) = 0;
virtual void PopGroup() = 0;
virtual void Draw() = 0;
void Clear()
{
Shader = nullptr;
Textures = TArray<PPTextureInput>();
Uniforms = PPUniforms();
Viewport = PPViewport();
BlendMode = PPBlendMode();
Output = PPOutput();
ShadowMapBuffers = false;
}
void SetInputTexture(int index, PPTexture *texture, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
if ((int)Textures.Size() < index + 1)
Textures.Resize(index + 1);
auto &tex = Textures[index];
tex.Filter = filter;
tex.Wrap = wrap;
tex.Type = PPTextureType::PPTexture;
tex.Texture = texture;
}
void SetInputCurrent(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
SetInputSpecialType(index, PPTextureType::CurrentPipelineTexture, filter, wrap);
}
void SetInputSceneColor(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
SetInputSpecialType(index, PPTextureType::SceneColor, filter, wrap);
}
void SetInputSceneFog(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
SetInputSpecialType(index, PPTextureType::SceneFog, filter, wrap);
}
void SetInputSceneNormal(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
SetInputSpecialType(index, PPTextureType::SceneNormal, filter, wrap);
}
void SetInputSceneDepth(int index, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
SetInputSpecialType(index, PPTextureType::SceneDepth, filter, wrap);
}
void SetInputSpecialType(int index, PPTextureType type, PPFilterMode filter = PPFilterMode::Nearest, PPWrapMode wrap = PPWrapMode::Clamp)
{
if ((int)Textures.Size() < index + 1)
Textures.Resize(index + 1);
auto &tex = Textures[index];
tex.Filter = filter;
tex.Wrap = wrap;
tex.Type = type;
tex.Texture = nullptr;
}
void SetShadowMapBuffers(bool enable)
{
ShadowMapBuffers = enable;
}
void SetOutputTexture(PPTexture *texture)
{
Output.Type = PPTextureType::PPTexture;
Output.Texture = texture;
}
void SetOutputCurrent()
{
Output.Type = PPTextureType::CurrentPipelineTexture;
Output.Texture = nullptr;
}
void SetOutputNext()
{
Output.Type = PPTextureType::NextPipelineTexture;
Output.Texture = nullptr;
}
void SetOutputSceneColor()
{
Output.Type = PPTextureType::SceneColor;
Output.Texture = nullptr;
}
void SetOutputSwapChain()
{
Output.Type = PPTextureType::SwapChain;
Output.Texture = nullptr;
}
void SetOutputShadowMap()
{
Output.Type = PPTextureType::ShadowMap;
Output.Texture = nullptr;
}
void SetNoBlend()
{
BlendMode.BlendOp = STYLEOP_Add;
BlendMode.SrcAlpha = STYLEALPHA_One;
BlendMode.DestAlpha = STYLEALPHA_Zero;
BlendMode.Flags = 0;
}
void SetAdditiveBlend()
{
BlendMode.BlendOp = STYLEOP_Add;
BlendMode.SrcAlpha = STYLEALPHA_One;
BlendMode.DestAlpha = STYLEALPHA_One;
BlendMode.Flags = 0;
}
void SetAlphaBlend()
{
BlendMode.BlendOp = STYLEOP_Add;
BlendMode.SrcAlpha = STYLEALPHA_Src;
BlendMode.DestAlpha = STYLEALPHA_InvSrc;
BlendMode.Flags = 0;
}
PPShader *Shader;
TArray<PPTextureInput> Textures;
PPUniforms Uniforms;
PPViewport Viewport;
PPBlendMode BlendMode;
PPOutput Output;
bool ShadowMapBuffers = false;
};
enum class PixelFormat
{
Rgba8,
Rgba16f,
R32f,
Rg16f,
Rgba16_snorm
};
class PPResource
{
public:
PPResource()
{
Next = First;
First = this;
if (Next) Next->Prev = this;
}
PPResource(const PPResource &)
{
Next = First;
First = this;
if (Next) Next->Prev = this;
}
virtual ~PPResource()
{
if (Next) Next->Prev = Prev;
if (Prev) Prev->Next = Next;
else First = Next;
}
PPResource &operator=(const PPResource &other)
{
return *this;
}
static void ResetAll()
{
for (PPResource *cur = First; cur; cur = cur->Next)
cur->ResetBackend();
}
virtual void ResetBackend() = 0;
private:
static PPResource *First;
PPResource *Prev = nullptr;
PPResource *Next = nullptr;
};
class PPTextureBackend
{
public:
virtual ~PPTextureBackend() = default;
};
class PPTexture : public PPResource
{
public:
PPTexture() = default;
PPTexture(int width, int height, PixelFormat format, std::shared_ptr<void> data = {}) : Width(width), Height(height), Format(format), Data(data) { }
void ResetBackend() override { Backend.reset(); }
int Width;
int Height;
PixelFormat Format;
std::shared_ptr<void> Data;
std::unique_ptr<PPTextureBackend> Backend;
};
class PPShaderBackend
{
public:
virtual ~PPShaderBackend() = default;
};
class PPShader : public PPResource
{
public:
PPShader() = default;
PPShader(const FString &fragment, const FString &defines, const std::vector<UniformFieldDesc> &uniforms, int version = 330) : FragmentShader(fragment), Defines(defines), Uniforms(uniforms), Version(version) { }
void ResetBackend() override { Backend.reset(); }
FString VertexShader = "shaders/glsl/screenquad.vp";
FString FragmentShader;
FString Defines;
std::vector<UniformFieldDesc> Uniforms;
int Version = 330;
std::unique_ptr<PPShaderBackend> Backend;
};
/////////////////////////////////////////////////////////////////////////////
struct ExtractUniforms
{
FVector2 Scale;
FVector2 Offset;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "Scale", UniformType::Vec2, offsetof(ExtractUniforms, Scale) },
{ "Offset", UniformType::Vec2, offsetof(ExtractUniforms, Offset) }
};
}
};
struct BlurUniforms
{
float SampleWeights[8];
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "SampleWeights0", UniformType::Float, offsetof(BlurUniforms, SampleWeights[0]) },
{ "SampleWeights1", UniformType::Float, offsetof(BlurUniforms, SampleWeights[1]) },
{ "SampleWeights2", UniformType::Float, offsetof(BlurUniforms, SampleWeights[2]) },
{ "SampleWeights3", UniformType::Float, offsetof(BlurUniforms, SampleWeights[3]) },
{ "SampleWeights4", UniformType::Float, offsetof(BlurUniforms, SampleWeights[4]) },
{ "SampleWeights5", UniformType::Float, offsetof(BlurUniforms, SampleWeights[5]) },
{ "SampleWeights6", UniformType::Float, offsetof(BlurUniforms, SampleWeights[6]) },
{ "SampleWeights7", UniformType::Float, offsetof(BlurUniforms, SampleWeights[7]) },
};
}
};
enum { NumBloomLevels = 4 };
class PPBlurLevel
{
public:
PPViewport Viewport;
PPTexture VTexture;
PPTexture HTexture;
};
class PPBloom
{
public:
void RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneHeight, int fixedcm);
void RenderBlur(PPRenderState *renderstate, int sceneWidth, int sceneHeight, float gameinfobluramount);
private:
void BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUniforms, PPTexture &input, PPTexture &output, PPViewport viewport, bool vertical);
void UpdateTextures(int width, int height);
static float ComputeBlurGaussian(float n, float theta);
static void ComputeBlurSamples(int sampleCount, float blurAmount, float *sampleWeights);
PPBlurLevel levels[NumBloomLevels];
int lastWidth = 0;
int lastHeight = 0;
PPShader BloomCombine = { "shaders/glsl/bloomcombine.fp", "", {} };
PPShader BloomExtract = { "shaders/glsl/bloomextract.fp", "", ExtractUniforms::Desc() };
PPShader BlurVertical = { "shaders/glsl/blur.fp", "#define BLUR_VERTICAL\n", BlurUniforms::Desc() };
PPShader BlurHorizontal = { "shaders/glsl/blur.fp", "#define BLUR_HORIZONTAL\n", BlurUniforms::Desc() };
};
/////////////////////////////////////////////////////////////////////////////
struct LensUniforms
{
float AspectRatio;
float Scale;
float Padding0, Padding1;
FVector4 LensDistortionCoefficient;
FVector4 CubicDistortionValue;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "Aspect", UniformType::Float, offsetof(LensUniforms, AspectRatio) },
{ "Scale", UniformType::Float, offsetof(LensUniforms, Scale) },
{ "Padding0", UniformType::Float, offsetof(LensUniforms, Padding0) },
{ "Padding1", UniformType::Float, offsetof(LensUniforms, Padding1) },
{ "k", UniformType::Vec4, offsetof(LensUniforms, LensDistortionCoefficient) },
{ "kcube", UniformType::Vec4, offsetof(LensUniforms, CubicDistortionValue) }
};
}
};
class PPLensDistort
{
public:
void Render(PPRenderState *renderstate);
private:
PPShader Lens = { "shaders/glsl/lensdistortion.fp", "", LensUniforms::Desc() };
};
/////////////////////////////////////////////////////////////////////////////
struct FXAAUniforms
{
FVector2 ReciprocalResolution;
float Padding0, Padding1;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "ReciprocalResolution", UniformType::Vec2, offsetof(FXAAUniforms, ReciprocalResolution) },
{ "Padding0", UniformType::Float, offsetof(FXAAUniforms, Padding0) },
{ "Padding1", UniformType::Float, offsetof(FXAAUniforms, Padding1) }
};
}
};
class PPFXAA
{
public:
void Render(PPRenderState *renderstate);
private:
void CreateShaders();
int GetMaxVersion();
FString GetDefines();
PPShader FXAALuma;
PPShader FXAA;
int LastQuality = -1;
};
/////////////////////////////////////////////////////////////////////////////
struct ExposureExtractUniforms
{
FVector2 Scale;
FVector2 Offset;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "Scale", UniformType::Vec2, offsetof(ExposureExtractUniforms, Scale) },
{ "Offset", UniformType::Vec2, offsetof(ExposureExtractUniforms, Offset) }
};
}
};
struct ExposureCombineUniforms
{
float ExposureBase;
float ExposureMin;
float ExposureScale;
float ExposureSpeed;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "ExposureBase", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureBase) },
{ "ExposureMin", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureMin) },
{ "ExposureScale", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureScale) },
{ "ExposureSpeed", UniformType::Float, offsetof(ExposureCombineUniforms, ExposureSpeed) }
};
}
};
class PPExposureLevel
{
public:
PPViewport Viewport;
PPTexture Texture;
};
class PPCameraExposure
{
public:
void Render(PPRenderState *renderstate, int sceneWidth, int sceneHeight);
PPTexture CameraTexture = { 1, 1, PixelFormat::R32f };
private:
void UpdateTextures(int width, int height);
std::vector<PPExposureLevel> ExposureLevels;
bool FirstExposureFrame = true;
PPShader ExposureExtract = { "shaders/glsl/exposureextract.fp", "", ExposureExtractUniforms::Desc() };
PPShader ExposureAverage = { "shaders/glsl/exposureaverage.fp", "", {}, 400 };
PPShader ExposureCombine = { "shaders/glsl/exposurecombine.fp", "", ExposureCombineUniforms::Desc() };
};
/////////////////////////////////////////////////////////////////////////////
struct ColormapUniforms
{
FVector4 MapStart;
FVector4 MapRange;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "uFixedColormapStart", UniformType::Vec4, offsetof(ColormapUniforms, MapStart) },
{ "uFixedColormapRange", UniformType::Vec4, offsetof(ColormapUniforms, MapRange) },
};
}
};
class PPColormap
{
public:
void Render(PPRenderState *renderstate, int fixedcm);
private:
PPShader Colormap = { "shaders/glsl/colormap.fp", "", ColormapUniforms::Desc() };
};
/////////////////////////////////////////////////////////////////////////////
class PPTonemap
{
public:
void Render(PPRenderState *renderstate);
void ClearTonemapPalette() { PaletteTexture = {}; }
private:
void UpdateTextures();
PPTexture PaletteTexture;
PPShader LinearShader = { "shaders/glsl/tonemap.fp", "#define LINEAR\n", {} };
PPShader ReinhardShader = { "shaders/glsl/tonemap.fp", "#define REINHARD\n", {} };
PPShader HejlDawsonShader = { "shaders/glsl/tonemap.fp", "#define HEJLDAWSON\n", {} };
PPShader Uncharted2Shader = { "shaders/glsl/tonemap.fp", "#define UNCHARTED2\n", {} };
PPShader PaletteShader = { "shaders/glsl/tonemap.fp", "#define PALETTE\n", {} };
enum TonemapMode
{
None,
Uncharted2,
HejlDawson,
Reinhard,
Linear,
Palette,
NumTonemapModes
};
};
/////////////////////////////////////////////////////////////////////////////
struct LinearDepthUniforms
{
int SampleIndex;
float LinearizeDepthA;
float LinearizeDepthB;
float InverseDepthRangeA;
float InverseDepthRangeB;
float Padding0, Padding1, Padding2;
FVector2 Scale;
FVector2 Offset;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "SampleIndex", UniformType::Int, offsetof(LinearDepthUniforms, SampleIndex) },
{ "LinearizeDepthA", UniformType::Float, offsetof(LinearDepthUniforms, LinearizeDepthA) },
{ "LinearizeDepthB", UniformType::Float, offsetof(LinearDepthUniforms, LinearizeDepthB) },
{ "InverseDepthRangeA", UniformType::Float, offsetof(LinearDepthUniforms, InverseDepthRangeA) },
{ "InverseDepthRangeB", UniformType::Float, offsetof(LinearDepthUniforms, InverseDepthRangeB) },
{ "Padding0", UniformType::Float, offsetof(LinearDepthUniforms, Padding0) },
{ "Padding1", UniformType::Float, offsetof(LinearDepthUniforms, Padding1) },
{ "Padding2", UniformType::Float, offsetof(LinearDepthUniforms, Padding2) },
{ "Scale", UniformType::Vec2, offsetof(LinearDepthUniforms, Scale) },
{ "Offset", UniformType::Vec2, offsetof(LinearDepthUniforms, Offset) }
};
}
};
struct SSAOUniforms
{
FVector2 UVToViewA;
FVector2 UVToViewB;
FVector2 InvFullResolution;
float NDotVBias;
float NegInvR2;
float RadiusToScreen;
float AOMultiplier;
float AOStrength;
int SampleIndex;
float Padding0, Padding1;
FVector2 Scale;
FVector2 Offset;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "UVToViewA", UniformType::Vec2, offsetof(SSAOUniforms, UVToViewA) },
{ "UVToViewB", UniformType::Vec2, offsetof(SSAOUniforms, UVToViewB) },
{ "InvFullResolution", UniformType::Vec2, offsetof(SSAOUniforms, InvFullResolution) },
{ "NDotVBias", UniformType::Float, offsetof(SSAOUniforms, NDotVBias) },
{ "NegInvR2", UniformType::Float, offsetof(SSAOUniforms, NegInvR2) },
{ "RadiusToScreen", UniformType::Float, offsetof(SSAOUniforms, RadiusToScreen) },
{ "AOMultiplier", UniformType::Float, offsetof(SSAOUniforms, AOMultiplier) },
{ "AOStrength", UniformType::Float, offsetof(SSAOUniforms, AOStrength) },
{ "SampleIndex", UniformType::Int, offsetof(SSAOUniforms, SampleIndex) },
{ "Padding0", UniformType::Float, offsetof(SSAOUniforms, Padding0) },
{ "Padding1", UniformType::Float, offsetof(SSAOUniforms, Padding1) },
{ "Scale", UniformType::Vec2, offsetof(SSAOUniforms, Scale) },
{ "Offset", UniformType::Vec2, offsetof(SSAOUniforms, Offset) },
};
}
};
struct DepthBlurUniforms
{
float BlurSharpness;
float PowExponent;
float Padding0, Padding1;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "BlurSharpness", UniformType::Float, offsetof(DepthBlurUniforms, BlurSharpness) },
{ "PowExponent", UniformType::Float, offsetof(DepthBlurUniforms, PowExponent) },
{ "Padding0", UniformType::Float, offsetof(DepthBlurUniforms, Padding0) },
{ "Padding1", UniformType::Float, offsetof(DepthBlurUniforms, Padding1) }
};
}
};
struct AmbientCombineUniforms
{
int SampleCount;
int DebugMode, Padding1, Padding2;
FVector2 Scale;
FVector2 Offset;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "SampleCount", UniformType::Int, offsetof(AmbientCombineUniforms, SampleCount) },
{ "DebugMode", UniformType::Int, offsetof(AmbientCombineUniforms, DebugMode) },
{ "Padding1", UniformType::Int, offsetof(AmbientCombineUniforms, Padding1) },
{ "Padding2", UniformType::Int, offsetof(AmbientCombineUniforms, Padding2) },
{ "Scale", UniformType::Vec2, offsetof(AmbientCombineUniforms, Scale) },
{ "Offset", UniformType::Vec2, offsetof(AmbientCombineUniforms, Offset) }
};
}
};
class PPAmbientOcclusion
{
public:
PPAmbientOcclusion();
void Render(PPRenderState *renderstate, float m5, int sceneWidth, int sceneHeight);
private:
void CreateShaders();
void UpdateTextures(int width, int height);
enum Quality
{
Off,
LowQuality,
MediumQuality,
HighQuality,
NumQualityModes
};
int AmbientWidth = 0;
int AmbientHeight = 0;
int LastQuality = -1;
int LastWidth = 0;
int LastHeight = 0;
PPShader LinearDepth;
PPShader LinearDepthMS;
PPShader AmbientOcclude;
PPShader AmbientOccludeMS;
PPShader BlurVertical;
PPShader BlurHorizontal;
PPShader Combine;
PPShader CombineMS;
PPTexture LinearDepthTexture;
PPTexture Ambient0;
PPTexture Ambient1;
enum { NumAmbientRandomTextures = 3 };
PPTexture AmbientRandomTexture[NumAmbientRandomTextures];
};
struct PresentUniforms
{
float InvGamma;
float Contrast;
float Brightness;
float Saturation;
int GrayFormula;
int WindowPositionParity; // top-of-window might not be top-of-screen
FVector2 Scale;
FVector2 Offset;
float ColorScale;
int HdrMode;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "InvGamma", UniformType::Float, offsetof(PresentUniforms, InvGamma) },
{ "Contrast", UniformType::Float, offsetof(PresentUniforms, Contrast) },
{ "Brightness", UniformType::Float, offsetof(PresentUniforms, Brightness) },
{ "Saturation", UniformType::Float, offsetof(PresentUniforms, Saturation) },
{ "GrayFormula", UniformType::Int, offsetof(PresentUniforms, GrayFormula) },
{ "WindowPositionParity", UniformType::Int, offsetof(PresentUniforms, WindowPositionParity) },
{ "UVScale", UniformType::Vec2, offsetof(PresentUniforms, Scale) },
{ "UVOffset", UniformType::Vec2, offsetof(PresentUniforms, Offset) },
{ "ColorScale", UniformType::Float, offsetof(PresentUniforms, ColorScale) },
{ "HdrMode", UniformType::Int, offsetof(PresentUniforms, HdrMode) }
};
}
};
class PPPresent
{
public:
PPPresent();
PPTexture Dither;
PPShader Present = { "shaders/glsl/present.fp", "", PresentUniforms::Desc() };
PPShader Checker3D = { "shaders/glsl/present_checker3d.fp", "", PresentUniforms::Desc() };
PPShader Column3D = { "shaders/glsl/present_column3d.fp", "", PresentUniforms::Desc() };
PPShader Row3D = { "shaders/glsl/present_row3d.fp", "", PresentUniforms::Desc() };
};
struct ShadowMapUniforms
{
float ShadowmapQuality;
int NodesCount;
float Padding0, Padding1;
static std::vector<UniformFieldDesc> Desc()
{
return
{
{ "ShadowmapQuality", UniformType::Float, offsetof(ShadowMapUniforms, ShadowmapQuality) },
{ "NodesCount", UniformType::Int, offsetof(ShadowMapUniforms, NodesCount) },
{ "Padding0", UniformType::Float, offsetof(ShadowMapUniforms, Padding0) },
{ "Padding1", UniformType::Float, offsetof(ShadowMapUniforms, Padding1) },
};
}
};
class PPShadowMap
{
public:
void Update(PPRenderState *renderstate);
private:
PPShader ShadowMap = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() };
};
class PPCustomShaderInstance
{
public:
PPCustomShaderInstance(PostProcessShader *desc);
void Run(PPRenderState *renderstate);
PostProcessShader *Desc = nullptr;
private:
void AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment = 0);
void SetTextures(PPRenderState *renderstate);
void SetUniforms(PPRenderState *renderstate);
PPShader Shader;
int UniformStructSize = 0;
std::vector<UniformFieldDesc> Fields;
std::vector<std::unique_ptr<FString>> FieldNames;
std::map<FTexture*, std::unique_ptr<PPTexture>> Textures;
std::map<FString, size_t> FieldOffset;
};
class PPCustomShaders
{
public:
void Run(PPRenderState *renderstate, FString target);
private:
void CreateShaders();
std::vector<std::unique_ptr<PPCustomShaderInstance>> mShaders;
};
/////////////////////////////////////////////////////////////////////////////
class Postprocess
{
public:
PPBloom bloom;
PPLensDistort lens;
PPFXAA fxaa;
PPCameraExposure exposure;
PPColormap colormap;
PPTonemap tonemap;
PPAmbientOcclusion ssao;
PPPresent present;
PPShadowMap shadowmap;
PPCustomShaders customShaders;
void Pass1(PPRenderState *state, int fixedcm, int sceneWidth, int sceneHeight);
void Pass2(PPRenderState* state, int fixedcm, int sceneWidth, int sceneHeight);
};
extern Postprocess hw_postprocess;

View file

@ -0,0 +1,98 @@
/*
** Postprocessing framework
** Copyright (c) 2016-2020 Magnus Norddahl
**
** This software is provided 'as-is', without any express or implied
** warranty. In no event will the authors be held liable for any damages
** arising from the use of this software.
**
** Permission is granted to anyone to use this software for any purpose,
** including commercial applications, and to alter it and redistribute it
** freely, subject to the following restrictions:
**
** 1. The origin of this software must not be misrepresented; you must not
** claim that you wrote the original software. If you use this software
** in a product, an acknowledgment in the product documentation would be
** appreciated but is not required.
** 2. Altered source versions must be plainly marked as such, and must not be
** misrepresented as being the original software.
** 3. This notice may not be removed or altered from any source distribution.
*/
#include "hw_postprocess_cvars.h"
#include "v_video.h"
//==========================================================================
//
// CVARs
//
//==========================================================================
CVAR(Bool, gl_bloom, false, CVAR_ARCHIVE);
CUSTOM_CVAR(Float, gl_bloom_amount, 1.4f, CVAR_ARCHIVE)
{
if (self < 0.1f) self = 0.1f;
}
CVAR(Float, gl_exposure_scale, 1.3f, CVAR_ARCHIVE)
CVAR(Float, gl_exposure_min, 0.35f, CVAR_ARCHIVE)
CVAR(Float, gl_exposure_base, 0.35f, CVAR_ARCHIVE)
CVAR(Float, gl_exposure_speed, 0.05f, CVAR_ARCHIVE)
CUSTOM_CVAR(Int, gl_tonemap, 0, CVAR_ARCHIVE)
{
if (self < 0 || self > 5)
self = 0;
}
CVAR(Bool, gl_lens, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_lens_k, -0.12f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_lens_kcube, 0.1f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Float, gl_lens_chromatic, 1.12f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Int, gl_fxaa, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self >= IFXAAShader::Count)
{
self = 0;
}
}
CUSTOM_CVAR(Int, gl_ssao, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0 || self > 3)
self = 0;
}
CUSTOM_CVAR(Int, gl_ssao_portals, 1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < 0)
self = 0;
}
CVAR(Float, gl_ssao_strength, 0.7f, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, gl_ssao_debug, 0, 0)
CVAR(Float, gl_ssao_bias, 0.2f, 0)
CVAR(Float, gl_ssao_radius, 80.0f, 0)
CUSTOM_CVAR(Float, gl_ssao_blur, 16.0f, 0)
{
if (self < 0.1f) self = 0.1f;
}
CUSTOM_CVAR(Float, gl_ssao_exponent, 1.8f, 0)
{
if (self < 0.1f) self = 0.1f;
}
CUSTOM_CVAR(Float, gl_paltonemap_powtable, 2.0f, CVAR_ARCHIVE | CVAR_NOINITCALL)
{
screen->UpdatePalette();
}
CUSTOM_CVAR(Bool, gl_paltonemap_reverselookup, true, CVAR_ARCHIVE | CVAR_NOINITCALL)
{
screen->UpdatePalette();
}
CVAR(Float, gl_menu_blur, -1.0f, CVAR_ARCHIVE)

View file

@ -0,0 +1,54 @@
#pragma once
#include "c_cvars.h"
class IFXAAShader
{
public:
enum Quality
{
None,
Low,
Medium,
High,
Extreme,
Count
};
};
//==========================================================================
//
// CVARs
//
//==========================================================================
EXTERN_CVAR(Bool, gl_bloom)
EXTERN_CVAR(Float, gl_bloom_amount)
EXTERN_CVAR(Float, gl_exposure_scale)
EXTERN_CVAR(Float, gl_exposure_min)
EXTERN_CVAR(Float, gl_exposure_base)
EXTERN_CVAR(Float, gl_exposure_speed)
EXTERN_CVAR(Int, gl_tonemap)
EXTERN_CVAR(Int, gl_bloom_kernel_size)
EXTERN_CVAR(Bool, gl_lens)
EXTERN_CVAR(Float, gl_lens_k)
EXTERN_CVAR(Float, gl_lens_kcube)
EXTERN_CVAR(Float, gl_lens_chromatic)
EXTERN_CVAR(Int, gl_fxaa)
EXTERN_CVAR(Int, gl_ssao)
EXTERN_CVAR(Int, gl_ssao_portals)
EXTERN_CVAR(Float, gl_ssao_strength)
EXTERN_CVAR(Int, gl_ssao_debug)
EXTERN_CVAR(Float, gl_ssao_bias)
EXTERN_CVAR(Float, gl_ssao_radius)
EXTERN_CVAR(Float, gl_ssao_blur)
EXTERN_CVAR(Float, gl_ssao_exponent)
EXTERN_CVAR(Float, gl_paltonemap_powtable)
EXTERN_CVAR(Bool, gl_paltonemap_reverselookup)
EXTERN_CVAR(Float, gl_menu_blur)
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Float, vid_saturation)
EXTERN_CVAR(Int, gl_satformula)

View file

@ -0,0 +1,32 @@
#pragma once
enum class PostProcessUniformType
{
Undefined,
Int,
Float,
Vec2,
Vec3
};
struct PostProcessUniformValue
{
PostProcessUniformType Type = PostProcessUniformType::Undefined;
double Values[4] = { 0.0, 0.0, 0.0, 0.0 };
};
struct PostProcessShader
{
FString Target;
FString ShaderLumpName;
int ShaderVersion = 0;
FString Name;
bool Enabled = false;
TMap<FString, PostProcessUniformValue> Uniforms;
TMap<FString, FString> Textures;
};
extern TArray<PostProcessShader> PostProcessShaders;