refactor custom uniforms in preparation for custom material uniforms

This commit is contained in:
Ricardo Luís Vaz Silva 2025-01-07 16:25:24 -03:00 committed by Nash Muhandes
commit d23c727350
10 changed files with 648 additions and 278 deletions

View file

@ -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;
}
}

View file

@ -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

View file

@ -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;

View file

@ -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;
};

View file

@ -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;
}
}

View 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;
};

View file

@ -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()

View file

@ -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)

View file

@ -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;

View file

@ -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
{