add default values, vec4 uniforms, and cvar uniforms to post-process uniforms

This commit is contained in:
Ricardo Luís Vaz Silva 2025-01-06 09:54:08 -03:00 committed by Rachael Alexanderson
parent 22690bbb76
commit e12d51c5a2
7 changed files with 229 additions and 95 deletions

View file

@ -240,6 +240,16 @@ void* FBaseCVar::GetExtraDataPointer()
return m_ExtraDataPointer; return m_ExtraDataPointer;
} }
void FBaseCVar::SetExtraDataPointer2(void *pointer)
{
m_ExtraDataPointer2 = pointer;
}
void* FBaseCVar::GetExtraDataPointer2()
{
return m_ExtraDataPointer2;
}
const char *FBaseCVar::GetHumanString(int precision) const const char *FBaseCVar::GetHumanString(int precision) const
{ {
return GetGenericRep(CVAR_String).String; return GetGenericRep(CVAR_String).String;

View file

@ -222,8 +222,10 @@ public:
void ClearCallback(); void ClearCallback();
void SetExtraDataPointer(void *pointer); void SetExtraDataPointer(void *pointer);
void SetExtraDataPointer2(void *pointer);
void* GetExtraDataPointer(); void* GetExtraDataPointer();
void* GetExtraDataPointer2();
int pnum = -1; int pnum = -1;
FName userinfoName; FName userinfoName;
@ -259,7 +261,8 @@ private:
static inline bool m_UseCallback = false; static inline bool m_UseCallback = false;
static inline bool m_DoNoSet = false; static inline bool m_DoNoSet = false;
void *m_ExtraDataPointer; void *m_ExtraDataPointer = nullptr;
void *m_ExtraDataPointer2 = nullptr;
// These need to go away! // These need to go away!
friend FString C_GetMassCVarString (uint32_t filter, bool compact); friend FString C_GetMassCVarString (uint32_t filter, bool compact);
@ -275,6 +278,8 @@ private:
friend void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32_t filter); friend void FilterCompactCVars (TArray<FBaseCVar *> &cvars, uint32_t filter);
friend void C_DeinitConsole(); friend void C_DeinitConsole();
friend void C_ListCVarsWithoutDescription(); friend void C_ListCVarsWithoutDescription();
friend class GLDefsParser;
}; };
// Returns a string with all cvars whose flags match filter. In compact mode, // Returns a string with all cvars whose flags match filter. In compact mode,

View file

@ -947,6 +947,7 @@ PPCustomShaderInstance::PPCustomShaderInstance(PostProcessShader *desc) : Desc(d
case PostProcessUniformType::Int: AddUniformField(offset, name, UniformType::Int, sizeof(int)); 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::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::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;
default: break; default: break;
} }
} }
@ -1085,6 +1086,13 @@ void PPCustomShaderInstance::SetUniforms(PPRenderState *renderstate)
fValues[2] = (float)pair->Value.Values[2]; fValues[2] = (float)pair->Value.Values[2];
memcpy(dst, fValues, sizeof(float) * 3); memcpy(dst, fValues, sizeof(float) * 3);
break; 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: default:
break; break;
} }

View file

@ -116,6 +116,31 @@ DEFINE_ACTION_FUNCTION(_PPShader, SetUniform3f)
return 0; return 0;
} }
DEFINE_ACTION_FUNCTION(_PPShader, SetUniform4f)
{
PARAM_PROLOGUE;
PARAM_STRING(shaderName);
PARAM_STRING(uniformName);
PARAM_FLOAT(x);
PARAM_FLOAT(y);
PARAM_FLOAT(z);
PARAM_FLOAT(w);
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] = x;
vec4[1] = y;
vec4[2] = z;
vec4[3] = w;
}
}
return 0;
}
DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i) DEFINE_ACTION_FUNCTION(_PPShader, SetUniform1i)
{ {
PARAM_PROLOGUE; PARAM_PROLOGUE;

View file

@ -9,7 +9,8 @@ enum class PostProcessUniformType
Int, Int,
Float, Float,
Vec2, Vec2,
Vec3 Vec3,
Vec4
}; };
struct PostProcessUniformValue struct PostProcessUniformValue

View file

@ -59,17 +59,16 @@ void ParseColorization(FScanner& sc);
extern TDeletingArray<FLightDefaults *> LightDefaults; extern TDeletingArray<FLightDefaults *> LightDefaults;
extern int AttenuationIsSet; extern int AttenuationIsSet;
bool addedcvars = false;
struct ExtraUniformCVARData struct ExtraUniformCVARData
{ {
FString Shader; FString Shader;
FString Uniform; FString Uniform;
double* vec4 = nullptr; double* vec4 = nullptr;
ExtraUniformCVARData* Next = nullptr; ExtraUniformCVARData* Next = nullptr;
void (*OldCallback)(FBaseCVar &);
}; };
static void do_uniform_set(float value, ExtraUniformCVARData* data) static void do_uniform_set(DVector4 value, ExtraUniformCVARData* data)
{ {
if (!(data->vec4)) if (!(data->vec4))
{ {
@ -85,23 +84,33 @@ static void do_uniform_set(float value, ExtraUniformCVARData* data)
double* vec4 = data->vec4; double* vec4 = data->vec4;
if (vec4) if (vec4)
{ {
vec4[0] = value; vec4[0] = value.X;
vec4[1] = 0.0; vec4[1] = value.Y;
vec4[2] = 0.0; vec4[2] = value.Z;
vec4[3] = 1.0; vec4[3] = value.W;
} }
if (data->Next) if (data->Next)
do_uniform_set(value, data->Next); do_uniform_set(value, data->Next);
} }
void uniform_callback_int(FIntCVar &self) template<typename T>
void uniform_callback1(T &self)
{ {
do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer()); auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
if(data->OldCallback) data->OldCallback(self);
do_uniform_set(DVector4(*self, 0.0, 0.0, 1.0), data);
} }
void uniform_callback_float(FFloatCVar &self) void uniform_callback_color(FColorCVar &self)
{ {
do_uniform_set ((float)self, (ExtraUniformCVARData*)self.GetExtraDataPointer()); auto data = (ExtraUniformCVARData*)self.GetExtraDataPointer2();
if(data->OldCallback) data->OldCallback(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);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -1539,9 +1548,10 @@ class GLDefsParser
sc.MustGetString(); sc.MustGetString();
shaderdesc.Name = sc.String; shaderdesc.Name = sc.String;
} }
else if (sc.Compare("uniform") || sc.Compare("cvar_uniform")) else if (sc.Compare("uniform"))
{ {
bool is_cvar = sc.Compare("cvar_uniform"); bool is_cvar = false;
bool ok = true;
sc.MustGetString(); sc.MustGetString();
FString uniformType = sc.String; FString uniformType = sc.String;
@ -1553,104 +1563,180 @@ class GLDefsParser
PostProcessUniformType parsedType = PostProcessUniformType::Undefined; PostProcessUniformType parsedType = PostProcessUniformType::Undefined;
if (uniformType.Compare("int") == 0) if (uniformType.Compare("int") == 0)
parsedType = PostProcessUniformType::Int;
else if (uniformType.Compare("float") == 0)
parsedType = PostProcessUniformType::Float;
else if (uniformType.Compare("vec2") == 0)
parsedType = PostProcessUniformType::Vec2;
else if (uniformType.Compare("vec3") == 0)
parsedType = PostProcessUniformType::Vec3;
else
sc.ScriptError("Unrecognized uniform type '%s'", sc.String);
auto strUniformType = sc.String;
if (parsedType != PostProcessUniformType::Undefined)
shaderdesc.Uniforms[uniformName].Type = parsedType;
if (is_cvar)
{ {
addedcvars = true; parsedType = PostProcessUniformType::Int;
}
else if (uniformType.Compare("float") == 0)
{
parsedType = PostProcessUniformType::Float;
}
else if (uniformType.Compare("vec2") == 0)
{
parsedType = PostProcessUniformType::Vec2;
}
else if (uniformType.Compare("vec3") == 0)
{
parsedType = PostProcessUniformType::Vec3;
}
else if (uniformType.Compare("vec4") == 0)
{
parsedType = PostProcessUniformType::Vec4;
}
else
{
sc.ScriptError("Unrecognized uniform type '%s'", sc.String);
ok = false;
}
double Values[4] = {0.0, 0.0, 0.0, 1.0};
if(ok && sc.CheckToken('='))
{
if(sc.CheckString("cvar"))
{
is_cvar = true;
}
else switch(parsedType)
{
case PostProcessUniformType::Int:
sc.MustGetNumber();
Values[0] = sc.BigNumber;
break;
case PostProcessUniformType::Float:
sc.MustGetFloat();
Values[0] = sc.Float;
break;
case PostProcessUniformType::Vec2:
sc.MustGetFloat();
Values[0] = sc.Float;
sc.MustGetFloat();
Values[1] = sc.Float;
break;
case PostProcessUniformType::Vec3:
sc.MustGetFloat();
Values[0] = sc.Float;
sc.MustGetFloat();
Values[1] = sc.Float;
sc.MustGetFloat();
Values[2] = sc.Float;
break;
case PostProcessUniformType::Vec4:
sc.MustGetFloat();
Values[0] = sc.Float;
sc.MustGetFloat();
Values[1] = sc.Float;
sc.MustGetFloat();
Values[2] = sc.Float;
sc.MustGetFloat();
Values[3] = sc.Float;
break;
}
}
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];
}
if (ok && is_cvar)
{
if (shaderdesc.Name.IsEmpty()) if (shaderdesc.Name.IsEmpty())
sc.ScriptError("Shader must have a name to use cvar uniforms"); sc.ScriptError("Shader must have a name to use cvar uniforms");
ECVarType cvartype = CVAR_Dummy;
int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL; int cvarflags = CVAR_MOD|CVAR_ARCHIVE|CVAR_VIRTUAL;
FBaseCVar *cvar; FBaseCVar *cvar;
void (*callback)(FBaseCVar&) = NULL;
FString cvarname; FString cvarname;
switch (parsedType) void (*callback)(FBaseCVar&) = nullptr;
if(ok)
{ {
case PostProcessUniformType::Int:
cvartype = CVAR_Int;
callback = (void (*)(FBaseCVar&))uniform_callback_int;
break;
case PostProcessUniformType::Float:
cvartype = CVAR_Float;
callback = (void (*)(FBaseCVar&))uniform_callback_float;
break;
default:
sc.ScriptError("'%s' not supported for CVAR uniforms!", strUniformType);
break;
}
sc.MustGetString(); sc.MustGetString();
cvarname = sc.String; cvarname = sc.String;
cvar = FindCVar(cvarname.GetChars(), NULL); cvar = FindCVar(cvarname.GetChars(), NULL);
UCVarValue oldval; if (!cvar)
UCVarValue val;
ExtraUniformCVARData* oldextra = nullptr;
sc.MustGetFloat();
val.Float = oldval.Float = (float)sc.Float;
if (!Args->CheckParm ("-shaderuniformtest"))
{ {
// these aren't really release-ready, so lock them behind a command-line argument for now. sc.ScriptMessage("Unknown cvar passed to cvar_uniform");
sc.ScriptMessage("Warning - Use -shaderuniformtest to enable shader uniforms!"); ok = false;
}
}
if(ok)
{
switch (cvar->GetRealType())
{
case CVAR_Int:
if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float)
{
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 else
{ {
if (!cvar) callback = (void (*)(FBaseCVar&))(&uniform_callback1<FIntCVar>);
{ Values[0] = cvar->GetGenericRep(CVAR_Int).Int;
cvar = C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags);
} }
else if (cvar && (((cvar->GetFlags()) & CVAR_MOD) == CVAR_MOD)) break;
case CVAR_Float:
if(parsedType != PostProcessUniformType::Int && parsedType != PostProcessUniformType::Float)
{ {
// this value may have been previously loaded sc.ScriptError("CVar '%s' type (float) is not convertible to uniform type (%s), must be int or float", cvarname.GetChars(), uniformType.GetChars());
oldval.Float = cvar->GetGenericRep(CVAR_Float).Float; ok = false;
oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer(); }
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)
{
sc.ScriptError("CVar '%s' type (color) is not convertible to uniform type (%s), must be vec3 or vec4", cvarname.GetChars(), uniformType.GetChars());
ok = false;
}
else
{
callback = (void (*)(FBaseCVar&))uniform_callback_color;
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;
Values[3] = col.a / 255.0;
}
break;
default:
sc.ScriptError("CVar '%s' type not supported for uniforms!", cvarname.GetChars());
ok = false;
break;
}
} }
if (!(cvar->GetFlags() & CVAR_MOD)) if(ok)
{ {
if (!((cvar->GetFlags() & (CVAR_AUTO | CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE))) ExtraUniformCVARData* oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer2();
sc.ScriptError("CVAR '%s' already in use!", cvarname.GetChars());
}
// must've picked this up from an autoexec.cfg, handle accordingly
if (cvar && ((cvar->GetFlags() & (CVAR_MOD|CVAR_AUTO|CVAR_UNSETTABLE)) == (CVAR_AUTO | CVAR_UNSETTABLE)))
{
oldval.Float = cvar->GetGenericRep(CVAR_Float).Float;
delete cvar;
cvar = C_CreateCVar(cvarname.GetChars(), cvartype, cvarflags);
oldextra = (ExtraUniformCVARData*)cvar->GetExtraDataPointer();
}
shaderdesc.Uniforms[uniformName].Values[0] = oldval.Float;
cvar->SetGenericRepDefault(val, CVAR_Float);
if (val.Float != oldval.Float) // it's not default anymore
cvar->SetGenericRep(oldval.Float, CVAR_Float);
if (callback)
cvar->SetCallback(callback);
ExtraUniformCVARData* extra = new ExtraUniformCVARData; ExtraUniformCVARData* extra = new ExtraUniformCVARData;
extra->Shader = shaderdesc.Name.GetChars(); extra->Shader = shaderdesc.Name.GetChars();
extra->Uniform = uniformName.GetChars(); extra->Uniform = uniformName.GetChars();
extra->OldCallback = oldextra ? oldextra->OldCallback : cvar->m_Callback;
extra->Next = oldextra; extra->Next = oldextra;
cvar->SetExtraDataPointer(extra);
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];
} }
} }
} }
@ -1917,8 +2003,6 @@ public:
sc.SavePos(); sc.SavePos();
if (!sc.GetToken ()) if (!sc.GetToken ())
{ {
if (addedcvars)
GameConfig->DoModSetup (gameinfo.ConfigName.GetChars());
return; return;
} }
type = sc.MatchString(CoreKeywords); type = sc.MatchString(CoreKeywords);

View file

@ -4,5 +4,6 @@ struct PPShader native
native clearscope static void SetUniform1f(string shaderName, string uniformName, float value); native clearscope static void SetUniform1f(string shaderName, string uniformName, float value);
native clearscope static void SetUniform2f(string shaderName, string uniformName, vector2 value); native clearscope static void SetUniform2f(string shaderName, string uniformName, vector2 value);
native clearscope static void SetUniform3f(string shaderName, string uniformName, vector3 value); native clearscope static void SetUniform3f(string shaderName, string uniformName, vector3 value);
native clearscope static void SetUniform4f(string shaderName, string uniformName, vector4 value);
native clearscope static void SetUniform1i(string shaderName, string uniformName, int value); native clearscope static void SetUniform1i(string shaderName, string uniformName, int value);
} }