Dynamic Bloodpool Framework - API Documentation
- Introduction
- Prerequisites
- JSON File Location
- Pool Profiles Mapping
- Variants
- Complete Example
- Testing in the Game
š 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:
- Primary layer: Defines the initial formation and core structure of the blood pool.
- Extended layer (optional): Expands outward from the primary layer, allowing for more organic, irregular, and realistic growth patterns.
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:
- Basic knowledge of Creation Kit: You should understand the basics of Creation Kit, including creating and modifying elements within this environment.
- Basic knowledge of JSON: An understanding of JSON files and their structure is essential for correctly creating and modifying the files needed for the Dynamic Bloodpool Framework (DBF).
- Understanding of impacts in Skyrim: While not essential, a general knowledge of impact systems in Skyrim will help you better understand how the DBF interacts with the game.
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:
- Every JSON file using the DBF system follows this same model: a top-level array containing multiple profile objects.
- The
ProfileIDserves as the reference key; other mods or scripts will request blood pools using this identifier. - If a profile with the same
ProfileIDexists in multiple JSON files, the profile with the highestPrioritywins, effectively allowing overriding and modular additions. - The
Variantsarray allows for visual and behavioral diversity: only one variant is chosen randomly per blood pool instance, giving natural variation in the game.
š 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. ā ļø Note that in the second case, the texture paths are always relative to the "Data\Textures" folder. Possible Values:
Example N°1:
Example N°2:
|
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 Possible Values: Array of 2 floats [0.0 - 1.0] Example: |
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: |
Duration |
Description: Time in seconds for the primary layer to fully animate. Possible Values: Float Example: |
DurationMultRange(optional) |
Description: Random multiplier range for the whole duration. Possible Values: Array of 2 floats Example: |
EasePower(optional) |
Description: Controls the animation curve power (ease-in/out). Possible Values: Float > 0 Example: |
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: |
š¹ 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:
Example:
Example N°2:
|
Pivot |
Description: Anchor point of the extended layer within the mesh local space. Coordinates Possible Values: Array of 2 floats [0.0 - 1.0] Example: |
SizeMultRange |
Description: Multiplier range applied to the primary layer's size for random variation. Possible Values: Array of 2 floats Example: |
Duration |
Description: Duration in seconds for the extended layer to fully animate. Possible Values: Float Example: |
EasePower(optional) |
Description: Animation curve power for ease-in/out of the extended layer. Possible Values: Float > 0 Example: |
BlendFactor(optional) |
Description: Blending strength between primary and extended layers. Possible Values: Float [0.0 - 1.0] Example: |
FadeInRange(optional) |
Description: Fraction of duration over which the extended layer fades in. Possible Values: Array of 2 floats [0.0 - 1.0] Example: |
OnTop(optional) |
Description: Determines whether the extended layer is rendered on top of the primary layer. Default is Possible Values: Example: |
š¹ 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 Possible Values: |
Tint(optional) |
Description: Required only for Possible Values: Hex Example: |
EmissiveColor(optional) |
Description: Hex color for emissive effect. Possible Values: Example: |
EmissiveMultiple(optional) |
Description: Multiplier for emissive intensity. Possible Values: Float Example: |
SpecularColor(optional) |
Description: Hex color for specular reflection. Possible Values: Example: |
SpecularStrength(optional) |
Description: Intensity of specular reflection. Possible Values: Float Example: |
Glossiness(optional) |
Description: Glossiness coefficient for surface reflection. Possible Values: Float Example: |
RefractionStrength(optional) |
Description: Refraction effect strength. Possible Values: Float Example: |
SubSurfaceLightRolloff(optional) |
Description: Intensity of subsurface light falloff. Possible Values: Float Example: |
RimLightPower(optional) |
Description: Strength of rim lighting effect around the edges of the surface. Possible Values: Float Example: |
Alpha(optional) |
Description: Transparency multiplier. Possible Values: Float [0.0 - 1.0] Example: |
š 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.