Skip to main content
Version: 26.1+

Dynamic Textures

A dynamic texture is a texture that is decided while the game runs instead of being a fixed file. It can switch between files based on what the player is doing, use the player's own skin, or be built from several images that Palladium combines for you. Typical uses are a suit that changes its look with an ability, a helmet that dissolves frame by frame during a transformation, or glowing eyes drawn exactly where the player placed them.

Dynamic textures work anywhere Palladium accepts a texture reference: render layers, power renderer models, icons, GUI widgets and backgrounds, textured beams and the ability bar.

Two Ways to Use Them​

As a standalone file​

Dynamic texture files are client-side assets:

assets/<namespace>/palladium/dynamic_textures/<filename>.json

They are referenced with a # in front of the ID. The file assets/mypack/palladium/dynamic_textures/hero_suit.json becomes #mypack:hero_suit:

assets/mypack/palladium/render_layers/hero_suit.json
{
"texture": "#mypack:hero_suit"
}

Without the # the same string would be read as a normal texture path. Standalone files are the way to go when several render layers, icons or widgets share the same dynamic texture.

Inline in a render layer​

Render layers also accept the dynamic texture object directly in their texture field, so you do not need an extra file for a texture that is only used once:

assets/mypack/palladium/render_layers/hero_suit.json
{
"texture": {
"base": "mypack:textures/entity/hero_suit_#MODE.png",
"variables": {
"MODE": {
"type": "palladium:crouching",
"on_true": "stealth",
"on_false": "normal"
}
}
}
}

Inline objects only work in render layers. Every other texture field takes a texture reference, which means a plain path or a # reference to a standalone file.

Texture Types​

The type field selects how the texture is produced. If it is left out, the Configured Texture is used, which is why the examples above have no type.

Configured Texture​

ID: palladium:configured
The texture type used when no type is given. With only variables it swaps between existing texture files, with transformers it builds a new texture in memory from the base image.
KeyTypeDescriptionRequiredFallback
baseIdentifierThe base texture, as a full texture path including "textures/" and ".png". Can use variables./
variablesMap<String, Path Variable>A map of variables that can be used in the texture path./
transformersTexture Transformer,
Texture Transformer[]
Texture transformers applied to the base image, in the order they are listed./
outputIdentifierPath the generated texture is registered under. Supports variables. If not specified, it is derived from the base path and the used variables./

Entity Texture​

ID: palladium:entity
Starts from the texture the entity is currently rendered with. For players that is their skin, including skins set by abilities or customizations. On its own it is rarely useful; it exists to run transformers on the skin, for example to paint a suit pattern onto it.
KeyTypeDescriptionRequiredFallback
variablesMap<String, Path Variable>A map of variables that can be used in the output path and transformer paths./
transformersTexture Transformer,
Texture Transformer[]
Texture transformers applied to the entity texture, in the order they are listed./
outputIdentifierPath the generated texture is registered under. Supports variables. If not specified, it is derived from the entity texture path and the used variables./

Eye Selection Texture​

ID: palladium:eye_selection
Draws the pixels the player picked in the eye selection screen of the customization menu onto an empty 64x64 skin-sized texture, in the given color. On a render layer with "light_emission" set to 15 this gives the player glowing eyes exactly where they chose. The eye selection screen requires the "palladium:customization/eye_selection" feature flag.
KeyTypeDescriptionRequiredFallback
colorColorThe color the selected pixels are drawn in./

Static Texture​

ID: palladium:static
Always returns the same texture file. Exists so that places expecting a dynamic texture can still be given a plain one.
KeyTypeDescriptionRequiredFallback
textureIdentifierThe texture to use./

Variables​

Variables replace parts of a path with something that is calculated every frame. Each entry in variables has a name and a value. Everywhere the name appears with a # in front of it, it is replaced with the value:

"base": "mypack:textures/entity/hero_#STAGE.png",
"variables": {
"STAGE": {
"type": "palladium:ability_animation_timer_value",
"ability": "mypack:hero#transform"
}
}

While the ability's animation timer counts from 0 to 10, this texture goes through hero_0.png, hero_1.png up to hero_10.png.

Variables are replaced in base, in output and in the texture paths of transformers (overlay, mask).

A few things to keep in mind:

  • The value is inserted as text. Decimal numbers come out as 1.0, 2.5 and so on, so use integer values or wrap a decimal value in palladium:convert_to_integer when the result is part of a file name.
  • Boolean values like palladium:crouching need on_true and on_false strings, which are inserted as they are.
  • Most number values have a modify field that takes a MoLang expression with this as the value. "modify": "math.mod(this / 20, 3) + 1" on palladium:entity_tick_count cycles through 1, 2 and 3, switching every second.
  • Replacement is plain text search. If one variable name is part of another one, like #A and #AB, they get in each other's way. Use names that do not overlap. Upper case names are a good habit because they stand out from the rest of the path.

Texture Transformers​

Transformers are steps that edit the base image, applied in the order they are listed. They work on the Configured and Entity types. The transformers field takes a single transformer or a list.

Alpha Mask​

ID: palladium:alpha_mask
Makes parts of the base image see-through based on the brightness of the mask image. Black mask pixels keep the base fully visible, white pixels hide it completely, grays fade it partially and fully transparent mask pixels hide it as well. The mask is read pixel by pixel at the same coordinates as the base, so it should have the same size as the base texture. A set of masks with a growing white area, combined with a variable, gives a dissolve or build-up effect.
KeyTypeDescriptionRequiredFallback
maskIdentifierThe location of the mask texture. Can use variables./

Overlay​

ID: palladium:overlay
Draws a second image on top of the base image, respecting its transparency, like stacking two layers in an image editor. The overlay is read pixel by pixel at the same coordinates as the base, so it should have the same size as the base texture.
KeyTypeDescriptionRequiredFallback
overlayIdentifierThe location of the overlay texture. Can use variables./
ignore_blankBooleanIf true, the overlay is only applied where the base already has pixels, so it can never add pixels outside the existing shape.false

Tint​

ID: palladium:tint
Multiplies the colors of the base image with a color, keeping its transparency, so one grayscale or neutral texture can be recolored. Both settings can use variables, which makes the color and strength follow a data attachment. Note that variable values also end up in the generated texture's path, so a color variable should be lowercase hex without a leading #, and a strength variable should take only a few different values (for example integer percentages mapped in a Value), because every distinct value creates its own texture.
KeyTypeDescriptionRequiredFallback
colorStringThe tint color as hex, like "ffd24a" or "#ffd24a". Can use variables./
opacityStringHow strongly the tint is applied, from 0 (no change) to 1 (full tint). Can use variables.1
filterStringOnly pixels with exactly this color (as hex, like "ff0000") are tinted, every other pixel stays untouched. Useful to recolor just one part of a texture. Can use variables./

Generated textures​

A dynamic texture with transformers creates a real texture in memory. It is registered under the output path, or under a path derived from the base and the variable names when output is not set. Every distinct result of the variables produces its own texture, which is then reused until resources are reloaded (F3+T clears them all).

This keeps rendering cheap, but it means a variable with many possible results also creates many textures. A transformation with 17 frames is fine. A raw tick count that never repeats is not, so limit such values with modify or a conditional value first. Textures without transformers only switch between existing files and create nothing new.

Examples​

Different suit while crouching​

A render layer that swaps between two existing files, without a separate dynamic texture file:

assets/mypack/palladium/render_layers/stealth_suit.json
{
"texture": {
"base": "mypack:textures/entity/suit_#STATE.png",
"variables": {
"STATE": {
"type": "palladium:crouching",
"on_true": "stealth",
"on_false": "default"
}
}
}
}

The pack needs suit_stealth.png and suit_default.png next to each other.

Blinking lights shared by several layers​

A standalone file so the helmet and the chestplate layers can use the same animation. It shows lights_1.png, lights_2.png and lights_3.png, one per second:

assets/mypack/palladium/dynamic_textures/suit_lights.json
{
"base": "mypack:textures/entity/lights_#FRAME.png",
"variables": {
"FRAME": {
"type": "palladium:entity_tick_count",
"modify": "math.mod(this / 20, 3) + 1"
}
}
}
assets/mypack/palladium/render_layers/suit_lights.json
{
"texture": "#mypack:suit_lights",
"render_type": "palladium:glow"
}

Glowing eyes​

Red eyes at the spots the player selected:

assets/mypack/palladium/render_layers/glowing_eyes.json
{
"texture": {
"type": "palladium:eye_selection",
"color": "#ff0000"
},
"light_emission": 15
}

Suit dissolving with an ability​

The suit fades in frame by frame while the ability's animation timer runs. The pack provides 17 masks, transformation_0.png (all white) to transformation_16.png (all black), which uncover the suit step by step. The reactor lights are a second layer that is always visible:

data/mypack/palladium/power/armor.json (excerpt)
"abilities": {
"suit_up": {
"type": "palladium:dummy",
"properties": {
"animation_timer": 16
},
"state": {
"enabling": {
"type": "palladium:key_bind",
"behaviour": "toggle"
}
}
}
}
assets/mypack/palladium/render_layers/armor.json
{
"type": "palladium:compound",
"layers": [
{
"texture": {
"base": "mypack:textures/entity/armor.png",
"transformers": {
"type": "palladium:alpha_mask",
"mask": "mypack:textures/entity/armor_masks/transformation_#TIMER.png"
},
"variables": {
"TIMER": {
"type": "palladium:ability_animation_timer_value",
"ability": "mypack:armor#suit_up"
}
}
}
},
{
"texture": "mypack:textures/entity/armor_lights.png",
"light_emission": 15
}
]
}

Suit painted onto the player's skin​

Takes the player's skin and draws a suit pattern over it. With ignore_blank the pattern only lands where the skin has pixels, so slim and wide skins both stay clean. Since every skin is different, Palladium generates one texture per skin automatically:

assets/mypack/palladium/dynamic_textures/skin_suit.json
{
"type": "palladium:entity",
"transformers": [
{
"type": "palladium:overlay",
"overlay": "mypack:textures/entity/suit_pattern.png",
"ignore_blank": true
}
]
}
assets/mypack/palladium/render_layers/skin_suit.json
{
"texture": "#mypack:skin_suit"
}

Overlay that follows a choice​

Combines a variable and a transformer: the emblem drawn onto the suit depends on an integer data attachment, so commands or abilities can switch it. output is set to a short, readable path for the generated textures:

assets/mypack/palladium/dynamic_textures/emblem_suit.json
{
"base": "mypack:textures/entity/suit.png",
"output": "mypack:generated/emblem_suit_#EMBLEM",
"transformers": [
{
"type": "palladium:overlay",
"overlay": "mypack:textures/entity/emblems/emblem_#EMBLEM.png"
}
],
"variables": {
"EMBLEM": {
"type": "palladium:integer_data_attachment",
"attachment": "mypack:emblem",
"fallback": 0
}
}
}