refactor custom uniforms in preparation for custom material uniforms
This commit is contained in:
parent
6a2ade1988
commit
d23c727350
10 changed files with 648 additions and 278 deletions
|
|
@ -96,13 +96,14 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH
|
|||
// Extract blooming pixels from scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomExtract;
|
||||
renderstate->Uniforms.Set(extractUniforms);
|
||||
renderstate->Uniforms.Set(&extractUniforms);
|
||||
renderstate->Viewport = level0.Viewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetInputTexture(1, &hw_postprocess.exposure.CameraTexture);
|
||||
renderstate->SetOutputTexture(&level0.VTexture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
const float blurAmount = gl_bloom_amount;
|
||||
BlurUniforms blurUniforms;
|
||||
|
|
@ -120,7 +121,6 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH
|
|||
// Linear downscale:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.VTexture);
|
||||
|
|
@ -140,7 +140,6 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH
|
|||
// Linear upscale:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.VTexture);
|
||||
|
|
@ -154,7 +153,6 @@ void PPBloom::RenderBloom(PPRenderState *renderstate, int sceneWidth, int sceneH
|
|||
// Add bloom back to scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BloomCombine;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = screen->mSceneViewport;
|
||||
renderstate->SetInputTexture(0, &level0.VTexture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputCurrent();
|
||||
|
|
@ -265,12 +263,13 @@ void PPBloom::BlurStep(PPRenderState *renderstate, const BlurUniforms &blurUnifo
|
|||
{
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = vertical ? &BlurVertical : &BlurHorizontal;
|
||||
renderstate->Uniforms.Set(blurUniforms);
|
||||
renderstate->Uniforms.Set(&blurUniforms);
|
||||
renderstate->Viewport = viewport;
|
||||
renderstate->SetInputTexture(0, &input);
|
||||
renderstate->SetOutputTexture(&output);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
}
|
||||
|
||||
float PPBloom::ComputeBlurGaussian(float n, float theta) // theta = Blur Amount
|
||||
|
|
@ -344,12 +343,13 @@ void PPLensDistort::Render(PPRenderState *renderstate)
|
|||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &Lens;
|
||||
renderstate->Uniforms.Set(uniforms);
|
||||
renderstate->Uniforms.Set(&uniforms);
|
||||
renderstate->Viewport = screen->mScreenViewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetOutputNext();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
|
@ -380,9 +380,10 @@ void PPFXAA::Render(PPRenderState *renderstate)
|
|||
renderstate->Draw();
|
||||
|
||||
renderstate->Shader = &FXAA;
|
||||
renderstate->Uniforms.Set(uniforms);
|
||||
renderstate->Uniforms.Set(&uniforms);
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
|
@ -457,12 +458,13 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc
|
|||
// Extract light blevel from scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &ExposureExtract;
|
||||
renderstate->Uniforms.Set(extractUniforms);
|
||||
renderstate->Uniforms.Set(&extractUniforms);
|
||||
renderstate->Viewport = level0.Viewport;
|
||||
renderstate->SetInputCurrent(0, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&level0.Texture);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
// Find the average value:
|
||||
for (size_t i = 0; i + 1 < ExposureLevels.size(); i++)
|
||||
|
|
@ -471,7 +473,6 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc
|
|||
auto &next = ExposureLevels[i + 1];
|
||||
|
||||
renderstate->Shader = &ExposureAverage;
|
||||
renderstate->Uniforms.Clear();
|
||||
renderstate->Viewport = next.Viewport;
|
||||
renderstate->SetInputTexture(0, &blevel.Texture, PPFilterMode::Linear);
|
||||
renderstate->SetOutputTexture(&next.Texture);
|
||||
|
|
@ -481,7 +482,7 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc
|
|||
|
||||
// Combine average value with current camera exposure:
|
||||
renderstate->Shader = &ExposureCombine;
|
||||
renderstate->Uniforms.Set(combineUniforms);
|
||||
renderstate->Uniforms.Set(&combineUniforms);
|
||||
renderstate->Viewport.left = 0;
|
||||
renderstate->Viewport.top = 0;
|
||||
renderstate->Viewport.width = 1;
|
||||
|
|
@ -493,6 +494,7 @@ void PPCameraExposure::Render(PPRenderState *renderstate, int sceneWidth, int sc
|
|||
else
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
|
||||
|
|
@ -559,12 +561,13 @@ void PPColormap::Render(PPRenderState *renderstate, int fixedcm, float flash)
|
|||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &Colormap;
|
||||
renderstate->Uniforms.Set(uniforms);
|
||||
renderstate->Uniforms.Set(&uniforms);
|
||||
renderstate->Viewport = screen->mScreenViewport;
|
||||
renderstate->SetInputCurrent(0);
|
||||
renderstate->SetOutputNext();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
|
@ -664,13 +667,14 @@ void PPLinearDepth::Render(PPRenderState* renderstate, int sceneWidth, int scene
|
|||
// Calculate linear depth values
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = gl_multisample > 1 ? &LinearDepthMS : &LinearDepth;
|
||||
renderstate->Uniforms.Set(linearUniforms);
|
||||
renderstate->Uniforms.Set(&linearUniforms);
|
||||
renderstate->Viewport = viewport;
|
||||
renderstate->SetInputSceneDepth(0);
|
||||
renderstate->SetInputSceneColor(1);
|
||||
renderstate->SetOutputSceneLinearDepth();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
|
@ -818,7 +822,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW
|
|||
// Apply ambient occlusion
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = gl_multisample > 1 ? &AmbientOccludeMS : &AmbientOcclude;
|
||||
renderstate->Uniforms.Set(ssaoUniforms);
|
||||
renderstate->Uniforms.Set(&ssaoUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputSceneLinearDepth(0);
|
||||
renderstate->SetInputSceneNormal(1);
|
||||
|
|
@ -826,33 +830,36 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW
|
|||
renderstate->SetOutputTexture(&Ambient0);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
// Blur SSAO texture
|
||||
if (gl_ssao_debug < 2 && !gl_shownormals)
|
||||
{
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BlurHorizontal;
|
||||
renderstate->Uniforms.Set(blurUniforms);
|
||||
renderstate->Uniforms.Set(&blurUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputTexture(0, &Ambient0);
|
||||
renderstate->SetOutputTexture(&Ambient1);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &BlurVertical;
|
||||
renderstate->Uniforms.Set(blurUniforms);
|
||||
renderstate->Uniforms.Set(&blurUniforms);
|
||||
renderstate->Viewport = ambientViewport;
|
||||
renderstate->SetInputTexture(0, &Ambient1);
|
||||
renderstate->SetOutputTexture(&Ambient0);
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
}
|
||||
|
||||
// Add SSAO back to scene texture:
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = gl_multisample > 1 ? &CombineMS : &Combine;
|
||||
renderstate->Uniforms.Set(combineUniforms);
|
||||
renderstate->Uniforms.Set(&combineUniforms);
|
||||
renderstate->Viewport = screen->mSceneViewport;
|
||||
renderstate->SetInputTexture(0, &Ambient0, PPFilterMode::Linear);
|
||||
if (gl_ssao_debug < 4 && !gl_shownormals)
|
||||
|
|
@ -865,6 +872,7 @@ void PPAmbientOcclusion::Render(PPRenderState *renderstate, float m5, int sceneW
|
|||
else
|
||||
renderstate->SetAlphaBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
|
@ -903,12 +911,13 @@ void PPShadowMap::Update(PPRenderState* renderstate)
|
|||
|
||||
renderstate->Clear();
|
||||
renderstate->Shader = &ShadowMap;
|
||||
renderstate->Uniforms.Set(uniforms);
|
||||
renderstate->Uniforms.Set(&uniforms);
|
||||
renderstate->Viewport = { 0, 0, gl_shadowmap_quality, 1024 };
|
||||
renderstate->SetShadowMapBuffers(true);
|
||||
renderstate->SetOutputShadowMap();
|
||||
renderstate->SetNoBlend();
|
||||
renderstate->Draw();
|
||||
renderstate->Uniforms.Clear();
|
||||
|
||||
renderstate->PopGroup();
|
||||
}
|
||||
|
|
@ -948,11 +957,13 @@ void PPCustomShaders::CreateShaders()
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc)
|
||||
void UserUniforms::LoadUniforms(const TMap<FString, UserUniformValue> &Uniforms)
|
||||
{
|
||||
assert(UniformStructSize == 0);
|
||||
|
||||
// Build an uniform block to be used as input
|
||||
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
||||
TMap<FString, PostProcessUniformValue>::Pair *pair;
|
||||
TMap<FString, UserUniformValue>::ConstIterator it(Uniforms);
|
||||
TMap<FString, UserUniformValue>::ConstPair *pair;
|
||||
size_t offset = 0;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
|
|
@ -961,16 +972,21 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d
|
|||
|
||||
switch (pair->Value.Type)
|
||||
{
|
||||
case PostProcessUniformType::Float: AddUniformField(offset, name, UniformType::Float, sizeof(float)); break;
|
||||
case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break;
|
||||
case PostProcessUniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break;
|
||||
case PostProcessUniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break;
|
||||
case PostProcessUniformType::Vec4: AddUniformField(offset, name, UniformType::Vec4, sizeof(float) * 4); break;
|
||||
case UniformType::Float: AddUniformField(offset, name, UniformType::Float, sizeof(float)); break;
|
||||
case UniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); break;
|
||||
case UniformType::Vec2: AddUniformField(offset, name, UniformType::Vec2, sizeof(float) * 2); break;
|
||||
case UniformType::Vec3: AddUniformField(offset, name, UniformType::Vec3, sizeof(float) * 3, sizeof(float) * 4); break;
|
||||
case UniformType::Vec4: AddUniformField(offset, name, UniformType::Vec4, sizeof(float) * 4); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
UniformStructSize = ((int)offset + 15) / 16 * 16;
|
||||
|
||||
UniformStructSize = ((int)offset + 15) / 16 * 16;
|
||||
BuildStruct(Uniforms);
|
||||
}
|
||||
|
||||
PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(desc)
|
||||
{
|
||||
// Build the input textures
|
||||
FString uniformTextures;
|
||||
uniformTextures += "layout(binding=0) uniform sampler2D InputTexture;\n";
|
||||
|
|
@ -1000,7 +1016,7 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d
|
|||
prolog += uniformTextures;
|
||||
prolog += pipelineInOut;
|
||||
|
||||
Shader = PPShader(Desc->ShaderLumpName, prolog, Fields);
|
||||
Shader = PPShader(Desc->ShaderLumpName, prolog, Desc->Uniforms.Fields);
|
||||
}
|
||||
|
||||
void PPCustomShaderInstance::Run(PPRenderState *renderstate)
|
||||
|
|
@ -1070,75 +1086,82 @@ void PPCustomShaderInstance::SetTextures(PPRenderState *renderstate)
|
|||
|
||||
void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate)
|
||||
{
|
||||
TArray<uint8_t> uniforms;
|
||||
uniforms.Resize(UniformStructSize);
|
||||
|
||||
TMap<FString, PostProcessUniformValue>::Iterator it(Desc->Uniforms);
|
||||
TMap<FString, PostProcessUniformValue>::Pair *pair;
|
||||
while (it.NextPair(pair))
|
||||
{
|
||||
auto it2 = FieldOffset.find(pair->Key);
|
||||
if (it2 != FieldOffset.end())
|
||||
{
|
||||
uint8_t *dst = &uniforms[it2->second];
|
||||
float fValues[4];
|
||||
int iValues[4];
|
||||
switch (pair->Value.Type)
|
||||
{
|
||||
case PostProcessUniformType::Float:
|
||||
fValues[0] = (float)pair->Value.Values[0];
|
||||
memcpy(dst, fValues, sizeof(float));
|
||||
break;
|
||||
case PostProcessUniformType::Int:
|
||||
iValues[0] = (int)pair->Value.Values[0];
|
||||
memcpy(dst, iValues, sizeof(int));
|
||||
break;
|
||||
case PostProcessUniformType::Vec2:
|
||||
fValues[0] = (float)pair->Value.Values[0];
|
||||
fValues[1] = (float)pair->Value.Values[1];
|
||||
memcpy(dst, fValues, sizeof(float) * 2);
|
||||
break;
|
||||
case PostProcessUniformType::Vec3:
|
||||
fValues[0] = (float)pair->Value.Values[0];
|
||||
fValues[1] = (float)pair->Value.Values[1];
|
||||
fValues[2] = (float)pair->Value.Values[2];
|
||||
memcpy(dst, fValues, sizeof(float) * 3);
|
||||
break;
|
||||
case PostProcessUniformType::Vec4:
|
||||
fValues[0] = (float)pair->Value.Values[0];
|
||||
fValues[1] = (float)pair->Value.Values[1];
|
||||
fValues[2] = (float)pair->Value.Values[2];
|
||||
fValues[3] = (float)pair->Value.Values[3];
|
||||
memcpy(dst, fValues, sizeof(float) * 4);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderstate->Uniforms.Data = uniforms;
|
||||
Desc->Uniforms.WriteUniforms(renderstate->Uniforms);
|
||||
}
|
||||
|
||||
void PPCustomShaderInstance::AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment)
|
||||
void UserUniforms::BuildStruct(const TMap<FString, UserUniformValue> &Uniforms)
|
||||
{
|
||||
if(UniformStruct) delete[] UniformStruct;
|
||||
|
||||
UniformStruct = new uint8_t[UniformStructSize];
|
||||
|
||||
for(UniformFieldDesc &field : Fields)
|
||||
{
|
||||
uint8_t *dst = &UniformStruct[field.Offset];
|
||||
float *fValues = reinterpret_cast<float *>(dst);
|
||||
int *iValues = reinterpret_cast<int *>(dst);
|
||||
|
||||
const UserUniformValue &val = Uniforms[field.Name];
|
||||
|
||||
switch (field.Type)
|
||||
{
|
||||
case UniformType::Float:
|
||||
fValues[0] = (float)val.Values[0];
|
||||
break;
|
||||
case UniformType::Int:
|
||||
iValues[0] = (int)val.Values[0];
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
fValues[0] = (float)val.Values[0];
|
||||
fValues[1] = (float)val.Values[1];
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
fValues[0] = (float)val.Values[0];
|
||||
fValues[1] = (float)val.Values[1];
|
||||
fValues[2] = (float)val.Values[2];
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
fValues[0] = (float)val.Values[0];
|
||||
fValues[1] = (float)val.Values[1];
|
||||
fValues[2] = (float)val.Values[2];
|
||||
fValues[3] = (float)val.Values[3];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UniformField UserUniforms::GetField(const FString &name)
|
||||
{
|
||||
size_t *index = FieldNames.CheckKey(name);
|
||||
if(!index || !UniformStruct) return {};
|
||||
|
||||
auto &field = Fields[*index];
|
||||
|
||||
return {field.Type, UniformStruct + field.Offset};
|
||||
}
|
||||
|
||||
void UserUniforms::WriteUniforms(UniformStructHolder &Uniforms)
|
||||
{
|
||||
Uniforms.Clear();
|
||||
Uniforms.addr = UniformStruct;
|
||||
Uniforms.sz = UniformStructSize;
|
||||
}
|
||||
|
||||
void UserUniforms::AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment)
|
||||
{
|
||||
if (alignment == 0) alignment = fieldsize;
|
||||
offset = (offset + alignment - 1) / alignment * alignment;
|
||||
|
||||
FieldOffset[name] = offset;
|
||||
|
||||
auto name2 = std::make_unique<FString>(name);
|
||||
auto chars = name2->GetChars();
|
||||
FieldNames.push_back(std::move(name2));
|
||||
Fields.push_back({ chars, type, offset });
|
||||
FieldNames.Insert(name, Fields.size());
|
||||
Fields.push_back({ name, type, offset });
|
||||
offset += fieldsize;
|
||||
|
||||
if (fieldsize != alignment) // Workaround for buggy OpenGL drivers that does not do std140 layout correctly for vec3
|
||||
{
|
||||
name2 = std::make_unique<FString>(name + "_F39350FF12DE_padding");
|
||||
chars = name2->GetChars();
|
||||
FieldNames.push_back(std::move(name2));
|
||||
Fields.push_back({ chars, UniformType::Float, offset });
|
||||
FString name2 = name + "_F39350FF12DE_padding";
|
||||
Fields.push_back({ name2, UniformType::Float, offset });
|
||||
offset += alignment - fieldsize;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include "vectors.h"
|
||||
#include <vector>
|
||||
|
||||
#include "hw_useruniforms.h"
|
||||
|
||||
struct PostProcessShader;
|
||||
|
||||
typedef FRenderStyle PPBlendMode;
|
||||
|
|
@ -29,34 +31,6 @@ enum class ETonemapMode : uint8_t
|
|||
NumTonemapModes
|
||||
};
|
||||
|
||||
enum class UniformType
|
||||
{
|
||||
Int,
|
||||
UInt,
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3,
|
||||
Vec4,
|
||||
IVec2,
|
||||
IVec3,
|
||||
IVec4,
|
||||
UVec2,
|
||||
UVec3,
|
||||
UVec4,
|
||||
Mat4
|
||||
};
|
||||
|
||||
class UniformFieldDesc
|
||||
{
|
||||
public:
|
||||
UniformFieldDesc() = default;
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
enum class PPFilterMode { Nearest, Linear };
|
||||
enum class PPWrapMode { Clamp, Repeat };
|
||||
|
|
@ -78,47 +52,6 @@ public:
|
|||
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:
|
||||
|
|
@ -133,7 +66,7 @@ public:
|
|||
{
|
||||
Shader = nullptr;
|
||||
Textures = TArray<PPTextureInput>();
|
||||
Uniforms = PPUniforms();
|
||||
Uniforms.Clear();
|
||||
Viewport = PPViewport();
|
||||
BlendMode = PPBlendMode();
|
||||
Output = PPOutput();
|
||||
|
|
@ -265,7 +198,7 @@ public:
|
|||
|
||||
PPShader *Shader;
|
||||
TArray<PPTextureInput> Textures;
|
||||
PPUniforms Uniforms;
|
||||
UniformStructHolder Uniforms;
|
||||
PPViewport Viewport;
|
||||
PPBlendMode BlendMode;
|
||||
PPOutput Output;
|
||||
|
|
@ -371,7 +304,7 @@ public:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ExtractUniforms
|
||||
struct alignas(32) ExtractUniforms
|
||||
{
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
|
@ -386,7 +319,7 @@ struct ExtractUniforms
|
|||
}
|
||||
};
|
||||
|
||||
struct BlurUniforms
|
||||
struct alignas(32) BlurUniforms
|
||||
{
|
||||
float SampleWeights[8];
|
||||
|
||||
|
|
@ -441,7 +374,7 @@ private:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct LensUniforms
|
||||
struct alignas(32) LensUniforms
|
||||
{
|
||||
float AspectRatio;
|
||||
float Scale;
|
||||
|
|
@ -474,7 +407,7 @@ private:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct FXAAUniforms
|
||||
struct alignas(32) FXAAUniforms
|
||||
{
|
||||
FVector2 ReciprocalResolution;
|
||||
float Padding0, Padding1;
|
||||
|
|
@ -507,7 +440,7 @@ private:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ExposureExtractUniforms
|
||||
struct alignas(32) ExposureExtractUniforms
|
||||
{
|
||||
FVector2 Scale;
|
||||
FVector2 Offset;
|
||||
|
|
@ -522,7 +455,7 @@ struct ExposureExtractUniforms
|
|||
}
|
||||
};
|
||||
|
||||
struct ExposureCombineUniforms
|
||||
struct alignas(32) ExposureCombineUniforms
|
||||
{
|
||||
float ExposureBase;
|
||||
float ExposureMin;
|
||||
|
|
@ -568,7 +501,7 @@ private:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ColormapUniforms
|
||||
struct alignas(32) ColormapUniforms
|
||||
{
|
||||
FVector4 MapStart;
|
||||
FVector4 MapRange;
|
||||
|
|
@ -616,7 +549,7 @@ private:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct LinearDepthUniforms
|
||||
struct alignas(32) LinearDepthUniforms
|
||||
{
|
||||
int SampleIndex;
|
||||
float LinearizeDepthA;
|
||||
|
|
@ -657,7 +590,7 @@ private:
|
|||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct SSAOUniforms
|
||||
struct alignas(32) SSAOUniforms
|
||||
{
|
||||
FVector2 UVToViewA;
|
||||
FVector2 UVToViewB;
|
||||
|
|
@ -693,7 +626,7 @@ struct SSAOUniforms
|
|||
}
|
||||
};
|
||||
|
||||
struct DepthBlurUniforms
|
||||
struct alignas(32) DepthBlurUniforms
|
||||
{
|
||||
float BlurSharpness;
|
||||
float PowExponent;
|
||||
|
|
@ -711,7 +644,7 @@ struct DepthBlurUniforms
|
|||
}
|
||||
};
|
||||
|
||||
struct AmbientCombineUniforms
|
||||
struct alignas(32) AmbientCombineUniforms
|
||||
{
|
||||
int SampleCount;
|
||||
int DebugMode, Padding1, Padding2;
|
||||
|
|
@ -772,7 +705,7 @@ private:
|
|||
PPTexture AmbientRandomTexture[NumAmbientRandomTextures];
|
||||
};
|
||||
|
||||
struct PresentUniforms
|
||||
struct alignas(32) PresentUniforms
|
||||
{
|
||||
float InvGamma;
|
||||
float Contrast;
|
||||
|
|
@ -816,7 +749,7 @@ public:
|
|||
PPShader Row3D = { "shaders/pp/present_row3d.fp", "", PresentUniforms::Desc() };
|
||||
};
|
||||
|
||||
struct ShadowMapUniforms
|
||||
struct alignas(32) ShadowMapUniforms
|
||||
{
|
||||
float ShadowmapQuality;
|
||||
int NodesCount;
|
||||
|
|
@ -844,16 +777,11 @@ public:
|
|||
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
|
||||
|
|
|
|||
|
|
@ -43,18 +43,42 @@ DEFINE_ACTION_FUNCTION_NATIVE(_PPShader, SetEnabled, ShaderSetEnabled)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void ShaderSetUniform1f(const FString &shaderName, const FString &uniformName, double value)
|
||||
static void ShaderSetUniform1f(const FString &shaderName, const FString &uniformName, double x)
|
||||
{
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = value;
|
||||
vec4[1] = 0.0;
|
||||
vec4[2] = 0.0;
|
||||
vec4[3] = 1.0;
|
||||
auto uniform = shader.Uniforms.GetField(uniformName);
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
break;
|
||||
case UniformType::Int:
|
||||
*i = (int)x;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
*f = (float)x;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
f[0] = (float)x;
|
||||
f[1] = 0.0f;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
f[0] = (float)x;
|
||||
f[1] = 0.0f;
|
||||
f[2] = 0.0f;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
f[0] = (float)x;
|
||||
f[1] = 0.0f;
|
||||
f[2] = 0.0f;
|
||||
f[3] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -82,11 +106,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform2f)
|
|||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = x;
|
||||
vec4[1] = y;
|
||||
vec4[2] = 0.0;
|
||||
vec4[3] = 1.0;
|
||||
auto uniform = shader.Uniforms.GetField(uniformName);
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
break;
|
||||
case UniformType::Int:
|
||||
*i = (int)x;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
*f = (float)x;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
f[2] = 0.0f;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
f[2] = 0.0f;
|
||||
f[3] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -106,11 +154,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f)
|
|||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = x;
|
||||
vec4[1] = y;
|
||||
vec4[2] = z;
|
||||
vec4[3] = 1.0;
|
||||
auto uniform = shader.Uniforms.GetField(uniformName);
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
break;
|
||||
case UniformType::Int:
|
||||
*i = (int)x;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
*f = (float)x;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
f[2] = (float)z;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
f[2] = (float)z;
|
||||
f[3] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -131,11 +203,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform4f)
|
|||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = x;
|
||||
vec4[1] = y;
|
||||
vec4[2] = z;
|
||||
vec4[3] = w;
|
||||
auto uniform = shader.Uniforms.GetField(uniformName);
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
break;
|
||||
case UniformType::Int:
|
||||
*i = (int)x;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
*f = (float)x;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
f[2] = (float)z;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
f[0] = (float)x;
|
||||
f[1] = (float)y;
|
||||
f[2] = (float)z;
|
||||
f[3] = (float)w;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
@ -153,11 +249,35 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i)
|
|||
PostProcessShader &shader = PostProcessShaders[i];
|
||||
if (shader.Name == shaderName)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = (double)value;
|
||||
vec4[1] = 0.0;
|
||||
vec4[2] = 0.0;
|
||||
vec4[3] = 1.0;
|
||||
auto uniform = shader.Uniforms.GetField(uniformName);
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
break;
|
||||
case UniformType::Int:
|
||||
*i = value;
|
||||
break;
|
||||
case UniformType::Float:
|
||||
*f = (float)value;
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
f[0] = (float)value;
|
||||
f[1] = 0.0f;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
f[0] = (float)value;
|
||||
f[1] = 0.0f;
|
||||
f[2] = 0.0f;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
f[0] = (float)value;
|
||||
f[1] = 0.0f;
|
||||
f[2] = 0.0f;
|
||||
f[3] = 1.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -3,21 +3,7 @@
|
|||
#include "zstring.h"
|
||||
#include "tarray.h"
|
||||
|
||||
enum class PostProcessUniformType
|
||||
{
|
||||
Undefined,
|
||||
Int,
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3,
|
||||
Vec4
|
||||
};
|
||||
|
||||
struct PostProcessUniformValue
|
||||
{
|
||||
PostProcessUniformType Type = PostProcessUniformType::Undefined;
|
||||
double Values[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
};
|
||||
#include "hw_useruniforms.h"
|
||||
|
||||
struct PostProcessShader
|
||||
{
|
||||
|
|
@ -28,7 +14,8 @@ struct PostProcessShader
|
|||
FString Name;
|
||||
bool Enabled = false;
|
||||
|
||||
TMap<FString, PostProcessUniformValue> Uniforms;
|
||||
//TMap<FString, UserUniformValue> Uniforms;
|
||||
UserUniforms Uniforms;
|
||||
TMap<FString, FString> Textures;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,33 @@ CCMD (shaderenable)
|
|||
Printf("No shader named '%s' found\n", shaderName);
|
||||
}
|
||||
|
||||
static void PrintUniform(const char * shaderName, const char * uniformName, const UniformField &uniform)
|
||||
{
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
Printf("Shader '%s': could not find uniform '%s': %f %f %f\n", shaderName, uniformName);
|
||||
break;
|
||||
case UniformType::Int:
|
||||
Printf("Shader '%s' uniform '%s': %d\n", shaderName, uniformName, *i);
|
||||
break;
|
||||
case UniformType::Float:
|
||||
Printf("Shader '%s' uniform '%s': %f\n", shaderName, uniformName, *f);
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
Printf("Shader '%s' uniform '%s': %f %f\n", shaderName, uniformName, f[0], f[1]);
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
Printf("Shader '%s' uniform '%s': %f %f %f\n", shaderName, uniformName, f[0], f[1], f[2]);
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
Printf("Shader '%s' uniform '%s': %f %f %f %f\n", shaderName, uniformName, f[0], f[1], f[2], f[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CCMD (shaderuniform)
|
||||
{
|
||||
if (argv.argc() < 3)
|
||||
|
|
@ -74,16 +101,40 @@ CCMD (shaderuniform)
|
|||
{
|
||||
if (argv.argc() > 3)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
vec4[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0;
|
||||
vec4[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0;
|
||||
vec4[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0;
|
||||
vec4[3] = 1.0;
|
||||
auto uniform = shader.Uniforms.GetField(uniformName);
|
||||
float * f = (float *)uniform.Value;
|
||||
int * i = (int *)uniform.Value;
|
||||
switch(uniform.Type)
|
||||
{
|
||||
case UniformType::Undefined:
|
||||
Printf("Shader '%s': could not find uniform '%s': %f %f %f\n", shaderName, uniformName);
|
||||
break;
|
||||
case UniformType::Int:
|
||||
*i = atoi(argv[3]);
|
||||
break;
|
||||
case UniformType::Float:
|
||||
*f = atof(argv[3]);
|
||||
break;
|
||||
case UniformType::Vec2:
|
||||
f[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0;
|
||||
f[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0;
|
||||
break;
|
||||
case UniformType::Vec3:
|
||||
f[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0;
|
||||
f[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0;
|
||||
f[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0;
|
||||
break;
|
||||
case UniformType::Vec4:
|
||||
f[0] = argv.argc()>=4 ? atof(argv[3]) : 0.0;
|
||||
f[1] = argv.argc()>=5 ? atof(argv[4]) : 0.0;
|
||||
f[2] = argv.argc()>=6 ? atof(argv[5]) : 0.0;
|
||||
f[3] = argv.argc()>=7 ? atof(argv[6]) : 1.0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double *vec4 = shader.Uniforms[uniformName].Values;
|
||||
Printf("Shader '%s' uniform '%s': %f %f %f\n", shaderName, uniformName, vec4[0], vec4[1], vec4[2]);
|
||||
PrintUniform(shaderName, uniformName, shader.Uniforms.GetField(uniformName));
|
||||
}
|
||||
found = 1;
|
||||
}
|
||||
|
|
@ -120,14 +171,11 @@ CCMD(listuniforms)
|
|||
{
|
||||
Printf("Shader '%s' uniforms:\n", shaderName);
|
||||
|
||||
decltype(shader.Uniforms)::Iterator it(shader.Uniforms);
|
||||
decltype(shader.Uniforms)::Pair* pair;
|
||||
|
||||
while (it.NextPair(pair))
|
||||
for(auto &field : shader.Uniforms.Fields)
|
||||
{
|
||||
double *vec4 = shader.Uniforms[pair->Key].Values;
|
||||
Printf(" %s : %f %f %f\n", pair->Key.GetChars(), vec4[0], vec4[1], vec4[2]);
|
||||
PrintUniform(shaderName, field.Name.GetChars(), shader.Uniforms.GetField(field.Name));
|
||||
}
|
||||
|
||||
found = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
149
src/common/rendering/hwrenderer/postprocessing/hw_useruniforms.h
Normal file
149
src/common/rendering/hwrenderer/postprocessing/hw_useruniforms.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cstddef>
|
||||
|
||||
#include "tarray.h"
|
||||
#include "zstring.h"
|
||||
|
||||
enum class UniformType
|
||||
{
|
||||
Undefined,
|
||||
Int,
|
||||
UInt,
|
||||
Float,
|
||||
Vec2,
|
||||
Vec3,
|
||||
Vec4,
|
||||
IVec2,
|
||||
IVec3,
|
||||
IVec4,
|
||||
UVec2,
|
||||
UVec3,
|
||||
UVec4,
|
||||
Mat4
|
||||
};
|
||||
|
||||
struct UserUniformValue
|
||||
{
|
||||
UniformType Type = UniformType::Undefined;
|
||||
double Values[4] = { 0.0, 0.0, 0.0, 0.0 };
|
||||
};
|
||||
|
||||
struct UniformFieldDesc
|
||||
{
|
||||
FString Name;
|
||||
UniformType Type;
|
||||
std::size_t Offset;
|
||||
};
|
||||
|
||||
struct UniformField
|
||||
{
|
||||
UniformType Type = UniformType::Undefined;
|
||||
void * Value = nullptr;
|
||||
};
|
||||
|
||||
class UniformStructHolder
|
||||
{
|
||||
public:
|
||||
UniformStructHolder()
|
||||
{
|
||||
}
|
||||
|
||||
UniformStructHolder(const UniformStructHolder &src)
|
||||
{
|
||||
*this = src;
|
||||
}
|
||||
|
||||
~UniformStructHolder()
|
||||
{
|
||||
Clear();
|
||||
}
|
||||
|
||||
UniformStructHolder &operator=(const UniformStructHolder &src)
|
||||
{
|
||||
Clear();
|
||||
|
||||
if(src.alloc)
|
||||
{
|
||||
alloc = true;
|
||||
sz = src.sz;
|
||||
addr = new uint8_t[sz];
|
||||
memcpy((uint8_t*)addr, src.addr, sz);
|
||||
}
|
||||
else
|
||||
{
|
||||
sz = src.sz;
|
||||
addr = src.addr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if(alloc)
|
||||
{
|
||||
delete[] addr;
|
||||
}
|
||||
alloc = false;
|
||||
addr = nullptr;
|
||||
sz = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Set(const T *v)
|
||||
{
|
||||
Clear();
|
||||
|
||||
sz = sizeof(T);
|
||||
addr = reinterpret_cast<const uint8_t*>(v);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Set(const T &v, typename std::enable_if<!std::is_pointer_v<T>, bool>::type enabled = true)
|
||||
{
|
||||
static_assert(std::is_trivially_copyable_v<T>);
|
||||
|
||||
alloc = true;
|
||||
sz = sizeof(T);
|
||||
addr = new uint8_t[sizeof(T)];
|
||||
memcpy((uint8_t*)addr, &v, sizeof(T));
|
||||
}
|
||||
|
||||
bool alloc = false;
|
||||
size_t sz = 0;
|
||||
const uint8_t * addr = nullptr;
|
||||
};
|
||||
|
||||
class UserUniforms
|
||||
{
|
||||
void AddUniformField(size_t &offset, const FString &name, UniformType type, size_t fieldsize, size_t alignment = 0);
|
||||
void BuildStruct(const TMap<FString, UserUniformValue> &Uniforms);
|
||||
public:
|
||||
UserUniforms() = default;
|
||||
UserUniforms(const TMap<FString, UserUniformValue> &Uniforms)
|
||||
{
|
||||
LoadUniforms(Uniforms);
|
||||
}
|
||||
|
||||
~UserUniforms()
|
||||
{
|
||||
if(UniformStruct) delete[] UniformStruct;
|
||||
}
|
||||
|
||||
//must only be called once
|
||||
void LoadUniforms(const TMap<FString, UserUniformValue> &Uniforms);
|
||||
void WriteUniforms(UniformStructHolder &Data);
|
||||
|
||||
|
||||
int UniformStructSize = 0;
|
||||
uint8_t * UniformStruct = nullptr;
|
||||
|
||||
UniformField GetField(const FString &name);
|
||||
|
||||
std::vector<UniformFieldDesc> Fields;
|
||||
TMap<FString, size_t> FieldNames;
|
||||
};
|
||||
|
|
@ -233,7 +233,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
|||
|
||||
renderstate.Clear();
|
||||
renderstate.Shader = &hw_postprocess.present.Present;
|
||||
renderstate.Uniforms.Set(uniforms);
|
||||
renderstate.Uniforms.Set(&uniforms);
|
||||
renderstate.Viewport = box;
|
||||
renderstate.SetInputCurrent(0, ViewportLinearScale() ? PPFilterMode::Linear : PPFilterMode::Nearest);
|
||||
renderstate.SetInputTexture(1, &hw_postprocess.present.Dither, PPFilterMode::Nearest, PPWrapMode::Repeat);
|
||||
|
|
@ -243,6 +243,7 @@ void VkPostprocess::DrawPresentTexture(const IntRect &box, bool applyGamma, bool
|
|||
renderstate.SetOutputSwapChain();
|
||||
renderstate.SetNoBlend();
|
||||
renderstate.Draw();
|
||||
renderstate.Uniforms.Clear();
|
||||
}
|
||||
|
||||
void VkPostprocess::UpdateLinearDepthTexture()
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ void VkPPRenderState::Draw()
|
|||
VkPPRenderPassKey key;
|
||||
key.BlendMode = BlendMode;
|
||||
key.InputTextures = Textures.Size();
|
||||
key.Uniforms = Uniforms.Data.Size();
|
||||
key.Uniforms = Uniforms.sz;
|
||||
key.Shader = fb->GetShaderManager()->GetVkShader(Shader);
|
||||
key.SwapChain = (Output.Type == PPTextureType::SwapChain);
|
||||
key.ShadowMapBuffers = ShadowMapBuffers;
|
||||
|
|
@ -88,7 +88,7 @@ void VkPPRenderState::Draw()
|
|||
VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers);
|
||||
VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight);
|
||||
|
||||
RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest == WhichDepthStencil::Scene);
|
||||
RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.addr, Uniforms.sz, key.StencilTest == WhichDepthStencil::Scene);
|
||||
|
||||
// Advance to next PP texture if our output was sent there
|
||||
if (Output.Type == PPTextureType::NextPipelineTexture)
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@
|
|||
#include "hw_texcontainer.h"
|
||||
#include "floatrect.h"
|
||||
#include "refcounted.h"
|
||||
#include "tarray.h"
|
||||
|
||||
#include "hwrenderer/postprocessing/hw_useruniforms.h"
|
||||
|
||||
class FImageSource;
|
||||
class FGameTexture;
|
||||
|
|
@ -110,6 +113,9 @@ struct UserShaderDesc
|
|||
FString defines;
|
||||
bool disablealphatest = false;
|
||||
uint8_t shaderFlags = 0;
|
||||
|
||||
TMap<FString, UserUniformValue> Uniforms;
|
||||
UserUniforms UniformData;
|
||||
};
|
||||
|
||||
extern TArray<UserShaderDesc> usershaders;
|
||||
|
|
|
|||
|
|
@ -65,46 +65,121 @@ struct ExtraUniformCVARData
|
|||
{
|
||||
FString Shader;
|
||||
FString Uniform;
|
||||
double* vec4 = nullptr;
|
||||
void * data = nullptr;
|
||||
ExtraUniformCVARData* Next = nullptr;
|
||||
void (*OldCallback)(FBaseCVar &);
|
||||
};
|
||||
|
||||
static void do_uniform_set(DVector4 value, ExtraUniformCVARData* data)
|
||||
void pp_uniform_get_data(ExtraUniformCVARData* data)
|
||||
{
|
||||
if (!(data->vec4))
|
||||
if (!(data->data))
|
||||
{
|
||||
for (unsigned int i = 0; i < PostProcessShaders.Size(); i++)
|
||||
{
|
||||
PostProcessShader& shader = PostProcessShaders[i];
|
||||
if (strcmp(shader.Name.GetChars(), data->Shader.GetChars()) == 0)
|
||||
{
|
||||
data->vec4 = shader.Uniforms[data->Uniform].Values;
|
||||
data->data = shader.Uniforms.GetField(data->Uniform).Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
double* vec4 = data->vec4;
|
||||
if (vec4)
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set1i(int value, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
|
||||
int * i1 = (int *)data->data;
|
||||
if (i1)
|
||||
{
|
||||
vec4[0] = value.X;
|
||||
vec4[1] = value.Y;
|
||||
vec4[2] = value.Z;
|
||||
vec4[3] = value.W;
|
||||
i1[0] = value;
|
||||
}
|
||||
|
||||
if (data->Next)
|
||||
do_uniform_set(value, data->Next);
|
||||
do_pp_uniform_set1i(value, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set1f(float value, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
|
||||
float * f1 = (float *)data->data;
|
||||
if (f1)
|
||||
{
|
||||
f1[0] = value;
|
||||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set1f(value, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set2f(float x, float y, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
|
||||
float * f2 = (float *)data->data;
|
||||
if (f2)
|
||||
{
|
||||
f2[0] = x;
|
||||
f2[1] = y;
|
||||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set2f(x, y, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set3f(float x, float y, float z, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
|
||||
float * f3 = (float *)data->data;
|
||||
if (f3)
|
||||
{
|
||||
f3[0] = x;
|
||||
f3[1] = y;
|
||||
f3[2] = z;
|
||||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set3f(x, y, z, data->Next);
|
||||
}
|
||||
|
||||
static void do_pp_uniform_set4f(float x, float y, float z, float w, ExtraUniformCVARData* data)
|
||||
{
|
||||
pp_uniform_get_data(data);
|
||||
|
||||
float * f4 = (float *)data->data;
|
||||
if (f4)
|
||||
{
|
||||
f4[0] = x;
|
||||
f4[1] = y;
|
||||
f4[2] = z;
|
||||
f4[3] = w;
|
||||
}
|
||||
|
||||
if (data->Next)
|
||||
do_pp_uniform_set4f(x, y, z, w, data->Next);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void uniform_callback1(T &self)
|
||||
void pp_uniform_callback1i(T &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
||||
do_uniform_set(DVector4(*self, 0.0, 0.0, 1.0), data);
|
||||
do_pp_uniform_set1i(*self, data);
|
||||
}
|
||||
|
||||
void uniform_callback_color(FColorCVar &self)
|
||||
template<typename T>
|
||||
void pp_uniform_callback1f(T &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
||||
do_pp_uniform_set1f(*self, data);
|
||||
}
|
||||
|
||||
void pp_uniform_callback_color3f(FColorCVar &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
|
@ -112,7 +187,18 @@ void uniform_callback_color(FColorCVar &self)
|
|||
PalEntry col;
|
||||
col.d = *self;
|
||||
|
||||
do_uniform_set(DVector4(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0), data);
|
||||
do_pp_uniform_set3f(col.r / 255.0, col.g / 255.0, col.b / 255.0, data);
|
||||
}
|
||||
|
||||
void pp_uniform_callback_color4f(FColorCVar &self)
|
||||
{
|
||||
auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
|
||||
if(data->OldCallback) data->OldCallback(self);
|
||||
|
||||
PalEntry col;
|
||||
col.d = *self;
|
||||
|
||||
do_pp_uniform_set4f(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0, data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
@ -1875,6 +1961,7 @@ class GLDefsParser
|
|||
sc.MustGetString();
|
||||
|
||||
PostProcessShader shaderdesc;
|
||||
TMap<FString, UserUniformValue> Uniforms;
|
||||
shaderdesc.Target = sc.String;
|
||||
shaderdesc.Target.ToLower();
|
||||
|
||||
|
|
@ -1916,27 +2003,27 @@ class GLDefsParser
|
|||
sc.MustGetString();
|
||||
FString uniformName = sc.String;
|
||||
|
||||
PostProcessUniformType parsedType = PostProcessUniformType::Undefined;
|
||||
UniformType parsedType = UniformType::Undefined;
|
||||
|
||||
if (uniformType.Compare("int") == 0)
|
||||
{
|
||||
parsedType = PostProcessUniformType::Int;
|
||||
parsedType = UniformType::Int;
|
||||
}
|
||||
else if (uniformType.Compare("float") == 0)
|
||||
{
|
||||
parsedType = PostProcessUniformType::Float;
|
||||
parsedType = UniformType::Float;
|
||||
}
|
||||
else if (uniformType.Compare("vec2") == 0)
|
||||
{
|
||||
parsedType = PostProcessUniformType::Vec2;
|
||||
parsedType = UniformType::Vec2;
|
||||
}
|
||||
else if (uniformType.Compare("vec3") == 0)
|
||||
{
|
||||
parsedType = PostProcessUniformType::Vec3;
|
||||
parsedType = UniformType::Vec3;
|
||||
}
|
||||
else if (uniformType.Compare("vec4") == 0)
|
||||
{
|
||||
parsedType = PostProcessUniformType::Vec4;
|
||||
parsedType = UniformType::Vec4;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1954,21 +2041,21 @@ class GLDefsParser
|
|||
}
|
||||
else switch(parsedType)
|
||||
{
|
||||
case PostProcessUniformType::Int:
|
||||
case UniformType::Int:
|
||||
sc.MustGetNumber();
|
||||
Values[0] = sc.BigNumber;
|
||||
break;
|
||||
case PostProcessUniformType::Float:
|
||||
case UniformType::Float:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
break;
|
||||
case PostProcessUniformType::Vec2:
|
||||
case UniformType::Vec2:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
Values[1] = sc.Float;
|
||||
break;
|
||||
case PostProcessUniformType::Vec3:
|
||||
case UniformType::Vec3:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
|
|
@ -1976,7 +2063,7 @@ class GLDefsParser
|
|||
sc.MustGetFloat();
|
||||
Values[2] = sc.Float;
|
||||
break;
|
||||
case PostProcessUniformType::Vec4:
|
||||
case UniformType::Vec4:
|
||||
sc.MustGetFloat();
|
||||
Values[0] = sc.Float;
|
||||
sc.MustGetFloat();
|
||||
|
|
@ -1992,11 +2079,11 @@ class GLDefsParser
|
|||
|
||||
if (ok && !is_cvar)
|
||||
{
|
||||
shaderdesc.Uniforms[uniformName].Type = parsedType;
|
||||
shaderdesc.Uniforms[uniformName].Values[0] = Values[0];
|
||||
shaderdesc.Uniforms[uniformName].Values[1] = Values[1];
|
||||
shaderdesc.Uniforms[uniformName].Values[2] = Values[2];
|
||||
shaderdesc.Uniforms[uniformName].Values[3] = Values[3];
|
||||
Uniforms[uniformName].Type = parsedType;
|
||||
Uniforms[uniformName].Values[0] = Values[0];
|
||||
Uniforms[uniformName].Values[1] = Values[1];
|
||||
Uniforms[uniformName].Values[2] = Values[2];
|
||||
Uniforms[uniformName].Values[3] = Values[3];
|
||||
}
|
||||
|
||||
if (ok && is_cvar)
|
||||
|
|
@ -2027,38 +2114,53 @@ class GLDefsParser
|
|||
switch (cvar->GetRealType())
|
||||
{
|
||||
case CVAR_Int:
|
||||
if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float)
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1i<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1f<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (int) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1<FIntCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
}
|
||||
break;
|
||||
case CVAR_Float:
|
||||
if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float)
|
||||
if(parsedType == UniformType::Int)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1i<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else if(parsedType == UniformType::Float)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback1f<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (float) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))(&uniform_callback1<FFloatCVar>);
|
||||
Values[0] = cvar->GetGenericRep(CVAR_Float).Float;
|
||||
}
|
||||
break;
|
||||
case CVAR_Color:
|
||||
if(parsedType != PostProcessUniformType::Vec3 && parsedType != PostProcessUniformType::Vec4)
|
||||
if(parsedType == UniformType::Vec3)
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback_color3f);
|
||||
|
||||
PalEntry col;
|
||||
col.d = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
Values[0] = col.r / 255.0;
|
||||
Values[1] = col.g / 255.0;
|
||||
Values[2] = col.b / 255.0;
|
||||
}
|
||||
else
|
||||
else if(parsedType == UniformType::Vec4)
|
||||
{
|
||||
callback = (void (*)(FBaseCVar&))uniform_callback_color;
|
||||
callback = (void (*)(FBaseCVar&))(&pp_uniform_callback_color4f);
|
||||
|
||||
PalEntry col;
|
||||
col.d = cvar->GetGenericRep(CVAR_Int).Int;
|
||||
|
|
@ -2067,6 +2169,11 @@ class GLDefsParser
|
|||
Values[2] = col.b / 255.0;
|
||||
Values[3] = col.a / 255.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars());
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
sc.ScriptError("CVar '%s' type not supported for uniforms!", cvarname.GetChars());
|
||||
|
|
@ -2088,11 +2195,11 @@ class GLDefsParser
|
|||
cvar->SetCallback(callback);
|
||||
cvar->SetExtraDataPointer2(extra);
|
||||
|
||||
shaderdesc.Uniforms[uniformName].Type = parsedType;
|
||||
shaderdesc.Uniforms[uniformName].Values[0] = Values[0];
|
||||
shaderdesc.Uniforms[uniformName].Values[1] = Values[1];
|
||||
shaderdesc.Uniforms[uniformName].Values[2] = Values[2];
|
||||
shaderdesc.Uniforms[uniformName].Values[3] = Values[3];
|
||||
Uniforms[uniformName].Type = parsedType;
|
||||
Uniforms[uniformName].Values[0] = Values[0];
|
||||
Uniforms[uniformName].Values[1] = Values[1];
|
||||
Uniforms[uniformName].Values[2] = Values[2];
|
||||
Uniforms[uniformName].Values[3] = Values[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2116,7 +2223,8 @@ class GLDefsParser
|
|||
}
|
||||
}
|
||||
|
||||
PostProcessShaders.Push(shaderdesc);
|
||||
auto index = PostProcessShaders.Push(shaderdesc);
|
||||
PostProcessShaders[index].Uniforms.LoadUniforms(Uniforms);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue