implement actor uniforms

This commit is contained in:
Ricardo Luís Vaz Silva 2025-01-10 19:55:10 -03:00 committed by Magnus Norddahl
commit fcf4c9d07e
5 changed files with 177 additions and 0 deletions

View file

@ -105,6 +105,8 @@ enum
SFlag_Global = 1,
};
class AActor;
struct UserShaderDesc
{
FString shader;
@ -117,6 +119,8 @@ struct UserShaderDesc
std::vector<VaryingFieldDesc> Varyings;
UserUniforms Uniforms;
TMap<FString, FString> ActorFieldBindings;
void BindActorFields(AActor * act);
};
extern TArray<UserShaderDesc> usershaders;

View file

@ -50,6 +50,7 @@
#include "texturemanager.h"
#include "gameconfigfile.h"
#include "m_argv.h"
#include "types.h"
void AddLightDefaults(FLightDefaults *defaults, double attnFactor);
void AddLightAssociation(const char *actor, const char *frame, const char *light);
@ -299,6 +300,154 @@ void uniform_callback_color4f(FColorCVar &self)
do_uniform_set4f(col.r / 255.0, col.g / 255.0, col.b / 255.0, col.a / 255.0, data);
}
void setUniformI(UniformField field, int val)
{
switch(field.Type)
{
case UniformType::Int:
((int *)field.Value)[0] = val;
break;
case UniformType::Vec4:
((float *)field.Value)[3] = 1.0f;
case UniformType::Vec3:
((float *)field.Value)[2] = 0.0f;
case UniformType::Vec2:
((float *)field.Value)[1] = 0.0f;
case UniformType::Float:
((float *)field.Value)[0] = val;
break;
}
}
void setUniformF(UniformField field, float val)
{
switch(field.Type)
{
case UniformType::Int:
((int *)field.Value)[0] = val;
break;
case UniformType::Vec4:
((float *)field.Value)[3] = 1.0f;
case UniformType::Vec3:
((float *)field.Value)[2] = 0.0f;
case UniformType::Vec2:
((float *)field.Value)[1] = 0.0f;
case UniformType::Float:
((float *)field.Value)[0] = val;
break;
}
}
void setUniformF(UniformField field, const FVector2 &val)
{
switch(field.Type)
{
case UniformType::Int:
((int *)field.Value)[0] = val.X;
break;
case UniformType::Vec4:
((float *)field.Value)[3] = 1.0f;
case UniformType::Vec3:
((float *)field.Value)[2] = 0.0f;
case UniformType::Vec2:
((float *)field.Value)[1] = val.Y;
case UniformType::Float:
((float *)field.Value)[0] = val.X;
break;
}
}
void setUniformF(UniformField field, const FVector3 &val)
{
switch(field.Type)
{
case UniformType::Int:
((int *)field.Value)[0] = val.X;
break;
case UniformType::Vec4:
((float *)field.Value)[3] = 1.0f;
case UniformType::Vec3:
((float *)field.Value)[2] = val.Z;
case UniformType::Vec2:
((float *)field.Value)[1] = val.Y;
case UniformType::Float:
((float *)field.Value)[0] = val.X;
break;
}
}
void setUniformF(UniformField field, const FVector4 &val)
{
switch(field.Type)
{
case UniformType::Int:
((int *)field.Value)[0] = val.X;
break;
case UniformType::Vec4:
((float *)field.Value)[3] = val.W;
case UniformType::Vec3:
((float *)field.Value)[2] = val.Z;
case UniformType::Vec2:
((float *)field.Value)[1] = val.Y;
case UniformType::Float:
((float *)field.Value)[0] = val.X;
break;
}
}
void UserShaderDesc::BindActorFields(AActor * act)
{
TMapIterator<FString, FString> it(ActorFieldBindings);
TMap<FString, FString>::Pair * p;
while(it.NextPair(p))
{
UniformField uniformField = Uniforms.GetField(p->Key);
PField * actorField = dyn_cast<PField>(act->GetClass()->FindSymbol(p->Value, true));
if(actorField && uniformField.Type != UniformType::Undefined)
{
void * addr = reinterpret_cast<uint8_t*>(act) + actorField->Offset;
PType * t = actorField->Type;
if(t == TypeUInt32 || t == TypeSInt32)
{
setUniformI(uniformField, *(int*)addr);
}
else if(t == TypeFloat32)
{
setUniformF(uniformField, *(float*)addr);
}
else if(t == TypeFloat64)
{
setUniformF(uniformField, (float)*(double*)addr);
}
else if(t == TypeFVector2)
{
setUniformF(uniformField, *(FVector2*)addr);
}
else if(t == TypeVector2)
{
setUniformF(uniformField, FVector2(*(DVector2*)addr));
}
else if(t == TypeFVector3)
{
setUniformF(uniformField, *(FVector3*)addr);
}
else if(t == TypeVector3)
{
setUniformF(uniformField, FVector3(*(DVector3*)addr));
}
else if(t == TypeFVector4 || t == TypeQuaternion)
{
setUniformF(uniformField, *(FVector4*)addr);
}
else if(t == TypeVector4 || t == TypeFQuaternion)
{
setUniformF(uniformField, FVector4(*(DVector4*)addr));
}
}
}
}
//-----------------------------------------------------------------------------
//
// ParseVavoomSkybox

View file

@ -137,6 +137,17 @@ void FHWModelRenderer::SetInterpolation(double inter)
void FHWModelRenderer::SetMaterial(FGameTexture *skin, bool clampNoFilter, FTranslationID translation, AActor * act)
{
state.SetMaterial(skin, UF_Skin, 0, clampNoFilter ? CLAMP_NOFILTER : CLAMP_NONE, translation, -1, act ? act->GetClass() : nullptr);
int shader = state.getShaderIndex();
if(shader >= FIRST_USER_SHADER && act && (act != lastAct || shader != lastShader))
{ // only re-bind uniforms if the actor or the shader have changed
usershaders[shader - FIRST_USER_SHADER].BindActorFields(act);
}
lastAct = act;
lastShader = shader;
state.SetLightIndex(modellightindex);
}

View file

@ -42,6 +42,9 @@ class FHWModelRenderer : public FModelRenderer
int boneIndexBase = -1;
HWDrawInfo *di;
FRenderState &state;
AActor * lastAct = nullptr;
int lastShader = 0;
public:
FHWModelRenderer(HWDrawInfo *d, FRenderState &st, int mli) : modellightindex(mli), di(d), state(st)
{}

View file

@ -241,6 +241,16 @@ void HWSprite::DrawSprite(HWDrawInfo *di, FRenderState &state, bool translucent)
if (texture) state.SetMaterial(texture, UF_Sprite, (spritetype == RF_FACESPRITE) ? CTF_Expand : 0, clampmode, translation, OverrideShader, actor ? actor->GetClass() : nullptr);
else if (!modelframe) state.EnableTexture(false);
if (actor && texture)
{
int binding = state.getShaderIndex();
if(binding >= FIRST_USER_SHADER)
{
usershaders[binding - FIRST_USER_SHADER].BindActorFields(actor);
}
}
//SetColor(lightlevel, rel, Colormap, trans);
unsigned int iter = lightlist ? lightlist->Size() : 1;