Dynamic Bloodpool Framework - API Documentation

šŸ“Œ Introduction

The Dynamic Bloodpool Framework (DBF) is a mesh-based rendering system designed to dynamically generate fully animated blood pools using externally defined profile configurations.

Unlike Skyrim's traditional decal-based approach, which relies on static projections with limited flexibility, DBF creates real geometry-driven blood pools that expand, animate, and blend naturally with the environment. This ensures consistent visual fidelity across uneven terrain, complex surfaces, and varied environmental conditions.

Each blood pool is generated from a profile definition stored in a JSON file. These profiles control every aspect of the blood pool's behavior and appearance, including textures, expansion speed, size variation, animation curves, and shader properties.

A single blood pool animation can consist of up to two independent layers:

This layered approach enables complex and natural-looking animations while remaining extremely efficient.

All profile data is loaded and processed natively by the game engine, without relying on Papyrus scripts or runtime polling. This guarantees optimal performance, high scalability, and complete stability, even during intense gameplay scenarios.

Because profiles are defined externally and evaluated at runtime, any mod can create, extend, or override blood pool definitions without conflicts. This makes the Dynamic Bloodpool Framework a fully modular and future-proof solution for advanced blood pool rendering in Skyrim.

šŸ“Œ Prerequisites

Before starting this tutorial, and to save time, make sure you have the following skills:

If you're not comfortable with any of these skills or tools, it is recommended to acquire them before following this tutorial.

Great, now that we're all set up, let's dive into using the Dynamic Bloodpool Framework API.

šŸ“Œ Location of JSON Files

The JSON files should be placed in Data/SKSE/DynamicBloodpoolFramework. The exact organization of these files doesn't matter as long as they remain in this directory. You are free to organize them in subfolders as you see fit.

Similarly, there are no specific rules for naming the files: you are completely free to name them however you like.

In summary: as long as they are in this folder, everything is fine. The rest is up to you! āœ…

šŸ“Œ Pool Profiles Mapping

The PoolProfilesMapping array defines all available blood pool profiles. This array can contain an unlimited number of profiles, and the same structure applies to all DBF JSON files.

Each profile in the array represents a unique blood pool configuration identified by a ProfileID. If multiple profiles share the same ProfileID, the one with the highest Priority will override the others.

{
  "PoolProfilesMapping": [
    {
      "ProfileID": "MyProfile",
      "Priority": 0,
      "Variants": [ ... ]
    },
    {
      "ProfileID": "AnotherProfile",
      "Priority": 0,
      "Variants": [ ... ]
    },
    {
      "ProfileID": "AnotherProfile",
      "Priority": 10,
      "Override": true,
      "Variants": [ ... ]
    }
  ]
}

Each entry in PoolProfilesMapping contains the following parameters:

Parameter Description Notes / Possible Values
ProfileID Unique identifier for the profile. Mods use this ID to request a specific blood pool. String. Must be unique within the array. If duplicates exist, the profile with the highest Priority takes effect.
Priority Determines which profile takes precedence when multiple profiles share the same ProfileID. Integer. Higher values override lower values. Defaults to 0 if not specified.
Override If enabled, existing variants will not be completely replaced. Instead, their properties will be merged with the new ones. Boolean. Default = False
Variants An array of possible blood pool variants. When the profile is called, only one variant is randomly selected and played. Array of variant objects. Each variant defines textures, pivot, size, duration, shaders, and optionally an extended layer for more complex animation.

Notes:

šŸ“Œ Variants

Each Variants entry defines a set of blood pool behaviors and visual properties. When a profile is invoked, only one variant is randomly selected and played. A variant can have up to two layers: the Primary layer and an optional Extended layer, plus shader configuration.

šŸ”¹ Primary Layer

Parameter Description and Possible Values
TextureSet

Description: Defines the textures used for the primary layer.
You can provide either the FormID of a Texture Set or directly link the textures using an object.

āš ļø Note that in the second case, the texture paths are always relative to the "Data\Textures" folder.

Possible Values:

  • Object with texture slots:
    Diffuse, Normal, Glow, Height, Environment, Specular
  • FormID (TextureSet)

Example N°1:

"TextureSet": {
	  "Diffuse": "MyMod\\Bloodpools\\BloodPool_01_P1.dds",
	  "Normal": "MyMod\\Bloodpools\\BloodPool_01_P1_n.dds"
	}

Example N°2:

"TextureSet": "Plugin.esp:0x800"

Pivot

Description: Defines the anchor point of the blood pool within the local space of the mesh.

The X and Y coordinates determine where the pool originates relative to the mesh, with 0.0 representing the bottom-left corner and 1.0 representing the top-right corner.

Possible Values: Array of 2 floats [0.0 - 1.0]

Example: [0.9, 0.22] (close to the right edge, slightly above the bottom)

SizeRange

Description: Min and max size for the blood pool.

The actual size is randomly chosen within this range.

Possible Values: Array of 2 floats

Example: [50.0, 75.0]

Duration

Description: Time in seconds for the primary layer to fully animate.

Possible Values: Float

Example: 3.0

DurationMultRange
(optional)

Description: Random multiplier range for the whole duration.

Possible Values: Array of 2 floats

Example: [1.0, 2.0]

EasePower
(optional)

Description: Controls the animation curve power (ease-in/out).

Possible Values: Float > 0

Example: 2.5

FadeOutRange
(optional)

Description: Defines the start and end of fade-out as a fraction of the duration.

Possible Values: Array of 2 floats [0.0 - 1.0]

Example: [0.7, 0.9]

šŸ”¹ Extended Layer (optional)

The Extended Layer is an optional secondary layer that plays either alongside or after the primary layer, depending on the blending settings. It adds extra visual detail, like organic expansion or irregular shapes.

Its final position is always centered on the primary layer, ensuring the animation stays aligned and natural-looking.

Parameter Description and Possible Values
TextureSet

Description: Defines the textures for the extended layer, which expands outward from the primary layer. You can provide either the FormID of a Texture Set or directly link the textures using an object.

āš ļø Note that in the second case, the texture paths are always relative to the "Data\Textures" folder.

Possible Values:

  • Object with texture slots: Diffuse, Normal, Glow, Height, Environment, Specular
  • FormID (TextureSet)

Example:

"TextureSet": {
	  "Diffuse": "MyMod\\Bloodpools\\BloodPool_01_P2.dds",
	  "Normal": "MyMod\\Bloodpools\\BloodPool_01_P2_n.dds"
	}

Example N°2:

"TextureSet": "Plugin.esp:0x801"

Pivot

Description: Anchor point of the extended layer within the mesh local space.

Coordinates 0.0 represent the bottom-left corner, 1.0 the top-right corner.

Possible Values: Array of 2 floats [0.0 - 1.0]

Example: [0.58, 0.39]

SizeMultRange

Description: Multiplier range applied to the primary layer's size for random variation.

Possible Values: Array of 2 floats

Example: [1.0, 1.1]

Duration

Description: Duration in seconds for the extended layer to fully animate.

Possible Values: Float

Example: 4.0

EasePower
(optional)

Description: Animation curve power for ease-in/out of the extended layer.

Possible Values: Float > 0

Example: 3.0

BlendFactor
(optional)

Description: Blending strength between primary and extended layers.

Possible Values: Float [0.0 - 1.0]

Example: 0.35

FadeInRange
(optional)

Description: Fraction of duration over which the extended layer fades in.

Possible Values: Array of 2 floats [0.0 - 1.0]

Example: [0.0, 0.5]

OnTop
(optional)

Description: Determines whether the extended layer is rendered on top of the primary layer. Default is false.

Possible Values: true, false

Example: false

šŸ”¹ Shaders

The Shaders section defines how the blood pool interacts with light and surfaces. It controls properties like specularity, glossiness, emissive color, and transparency, allowing each layer to have a unique visual style while blending naturally with the environment.

Parameter Description and Possible Values
Type
(optional)

Description: Shader type used for the blood pool.

If Greyscale, the Tint element must also be defined.

Possible Values: Default, Greyscale, PBR

Tint
(optional)

Description: Required only for Greyscale shaders. Defines the color tint to apply.

Possible Values: Hex #RRGGBB

Example: #FF0000

EmissiveColor
(optional)

Description: Hex color for emissive effect.

Possible Values: #RRGGBB

Example: #000000

EmissiveMultiple
(optional)

Description: Multiplier for emissive intensity.

Possible Values: Float

Example: 1.0

SpecularColor
(optional)

Description: Hex color for specular reflection.

Possible Values: #RRGGBB

Example: #2A2A2A

SpecularStrength
(optional)

Description: Intensity of specular reflection.

Possible Values: Float

Example: 1.1

Glossiness
(optional)

Description: Glossiness coefficient for surface reflection.

Possible Values: Float

Example: 120.0

RefractionStrength
(optional)

Description: Refraction effect strength.

Possible Values: Float

Example: 0.0

SubSurfaceLightRolloff
(optional)

Description: Intensity of subsurface light falloff.

Possible Values: Float

Example: 2.0

RimLightPower
(optional)

Description: Strength of rim lighting effect around the edges of the surface.

Possible Values: Float

Example: 0.5

Alpha
(optional)

Description: Transparency multiplier.

Possible Values: Float [0.0 - 1.0]

Example: 1.0

šŸ“Œ Complete Example

{
  "PoolProfilesMapping": [
    {
      "ProfileID": "ExampleProfile",
      "Priority": 0,
      "Variants": [
        {
          "TextureSet": {
              "Diffuse": "MyMod\\Bloodpools\\BloodPool_01_P1.dds",
              "Normal": "MyMod\\Bloodpools\\BloodPool_01_P1_n.dds"
          },
          "Pivot": [0.25, 0.75],
          "SizeRange": [50.0, 75.0],
          "Duration": 3.0,
          "DurationMultRange": [1.0, 2.0],
          "EasePower": 2.5,
          "FadeOutRange": [0.7, 1.0],
          "Extended": {
            "TextureSet": {
              "Diffuse": "MyMod\\Bloodpools\\BloodPool_01_P2.dds",
              "Normal": "MyMod\\Bloodpools\\BloodPool_01_P2_n.dds"
            },
            "Pivot": [0.5, 0.5],
            "SizeMultRange": [1.0, 1.1],
            "Duration": 2.0,
            "EasePower": 3,
            "BlendFactor": 0.35,
            "FadeInRange": [0.0, 0.3],
            "OnTop": true
          },
          "Shaders": {
            "Type": "Default",
            "EmissiveColor": "#110000",
            "EmissiveMultiple": 1.0,
            "SpecularColor": "#FFDDDD",
            "SpecularStrength": 1.1,
            "Glossiness": 120.0,
            "RefractionStrength": 0.0,
            "SubSurfaceLightRolloff": 2.0,
            "RimLightPower": 0.5,
            "Alpha": 1.0
          }
        }
      ]
    }
  ]
}

šŸ“Œ Testing in the Game

After configuring your JSON files, it is crucial to test your changes in the game to ensure they work as intended. If you encounter a crash when launching the game, it likely means that the structure of one of your JSON files is malformed (possibly an extra comma). Feel free to use tools like JSON Formatter to validate your JSON files or find potential errors.

Once the game is running, be sure to check the DynamicBloodpoolFramework.log file (located in Documents\My Games\Skyrim Special Edition\SKSE) for any errors or issues with your JSON files. Regularly check this file during your testing to identify and quickly correct errors. This will help you refine your configuration and ensure smooth integration into the game.