Making an art pack
Provenance: design. Art packs are this client's own addition, not the original's; every statement here is what Dereth's client, its launcher and its tools do with one.
An art pack is a set of models and pictures that Dereth's remaster draws in place of the world's own: a tree made again, a house's walls painted again, grass laid where retail lays its grass picture. A pack changes only what is drawn. Every object keeps its collision, its physics and everything the server sees, so a pack never changes how the game plays, and two players with different packs play the same world.
A pack replaces things by their ids in the game's data: an object, a retail picture, a terrain type. That is all it knows of the world, so a pack draws on any world whose data has those ids: the end-of-retail data and the 1999 data alike. A pack made from the 1999 data can be a remaster of 1999.
This page covers what a pack holds and how to make one. sources.md covers how packs are listed, installed and updated, and how to publish your own.
What a pack is
A pack is a folder with manifest.toml at its top, beside the glTF 2.0 models and PNG pictures it names:
holtburg-houses/
manifest.toml
cottage/lod0.gltf
cottage/lod0.bin
cottage/walls.png
ground/grass_albedo.png
...
Every file is named by a path relative to the folder, with / between its parts and nothing that climbs out of the folder (.. or an absolute path is refused). So the manifest says nothing about where the folder is, and the folder can be packed into one file: each file becomes a record keyed by its path, beside every picture already made the way the client makes it, so the packed file opens without decoding or compressing a picture. Packed is how packs are shared; the folder is how they are made.
The client opens either: --art-pack <folder or file> on its command line, DERETH_ART_PACK in its environment, or [Fidelity] ArtPack in a profile. The launcher starts the client with the packs the player has turned on in the Library. A pack offered changes nothing until the player turns on the remaster's art pack box and the switches for what it covers (trees, plants, rocks, growth in the water, buildings' materials, the ground).
The manifest
[pack]
name = "Holtburg houses"
format = 1
id = "com.example.holtburg-houses"
version = "1.0.0"
description = "Holtburg's cottages and their roofs, made again."
authors = ["Someone"]
license = "CC-BY-4.0"
homepage = "https://example.com/holtburg-houses"
made_for = ["end-of-retail", "1999"]
| key | what it is | |
|---|---|---|
name | the pack's name, as reports and the launcher show it | |
format | required | the manifest's format, 1; a manifest of another format is refused |
id | to be listed | what a source lists the pack by: lowercase words of letters, digits and -, joined by dots, your own domain reversed and a name |
version | to be listed | MAJOR.MINOR.PATCH; a source updates a pack only to a higher one |
description | a sentence or two for the player | |
authors | who made the pack, a name or a list of them | |
license | the license the pack as a whole is under; each model's own credit says its own | |
homepage | where to read more | |
made_for | the data its ids are chosen from: end-of-retail, 1999, or both |
A pack opened from its folder or its file needs only format. The listing keys are for a source (sources.md); a source may give the ones a pack packed before it named them leaves out.
The rest of the manifest is lists of what the pack replaces: models ([[model]]), ground materials ([[terrain]] and [[steep]]), materials for retail pictures ([[material]]), and how the pack wants to be lit ([lighting]). A manifest that contradicts itself (an id listed twice, a ground or a picture two materials claim, a level of detail out of order, a credit left out) is refused whole, with the reason.
Models
[[model]]
id = "0x02000258" # a setup (0x02...) or a graphics object (0x01...)
foliage = true # its cut-out materials are growth: two-sided, lit through
category = "tree" # "tree", "plant", "rock" or "water"
author = "Someone"
tool = "Blender 4.2"
license = "CC-BY-4.0"
[[model.lod]]
file = "tree/lod0.gltf"
distance = 40.0 # drawn out to this many meters from the eye
[[model.lod]]
file = "tree/lod1.gltf" # the last level is drawn at any distance unless it names one
[[model.lod]]
file = "tree/far.gltf" # pictures of the model seen from round it (see "Views")
views = 16
columns = 8
Which object a model replaces. id is the object the world places: a setup (0x02...) is replaced whole, every part of it, wherever the world places it; a graphics object (0x01...) is replaced wherever the world places it by itself, as much of the scenery is. The model is drawn at the placement's own position, turn and scale, so build it in the object's own frame: meters, its origin where the object's is, up the object's up. Find an object's id and what it looks like with dereth-art survey (below).
A model is drawn in place of the whole object. Where a pack has a model for an object, its materials for retail pictures (below) do not reach that object.
glTF. Each level is a glTF 2.0 file (.gltf with its .bin and pictures beside it), read as the client reads it: triangles with positions, normals, texture coordinates and, where it has them, tangents and vertex colors; metallic-roughness materials with a base color picture and factor, a normal picture and its scale, a metallic-roughness picture and an occlusion picture. Pictures are PNG.
Levels of detail. A model has one level or more, nearest first. Each level but the last names the distance (meters from the eye) it is drawn out to, and the distances must grow; the last is drawn at any distance unless it names one. A level that names shadows_only = true is drawn into the sun's shadows alone, where they ask for a coarser level than the view does, and never into the view, which goes from the level before it straight to the level after it; its distance may be left out. The first and the last level are always drawn into the view.
Views. A level that names views is pictures of the model rather than its shape, for far away: its glTF holds an upright quad across the model's axis (its first axis across, its height up), turned to face the eye about the model's upright axis. Its base color picture holds views pictures of the model laid in tiles, columns to a row (all in one row when it names none), left to right and then down. View k is the model seen level from 360 k / views degrees round its axis, from its first axis toward its second, looking at the axis. Its normal picture holds, for each view, the model's own normal in its color (each part -1..1 as 0..1) and, in its alpha, how far the surface stands along the view from the plane through the axis (0.5 on the plane, 0 and 1 half the quad's width nearer and farther).
Cut-outs and two-sided surfaces. A material with an alpha cutoff (glTF's MASK mode) is cut out: texels below the cutoff are not drawn. Before its levels are made, every texel the cut leaves out takes the color of the nearest texel it keeps, so filtering brings no stray color into its edge; leave the cut-away texels any color you like. A material glTF marks doubleSided is drawn from both sides. A model marked foliage = true is growth: its cut-out materials are drawn two-sided and lit through, as leaves are.
Categories. category says which of the player's switches turns a model on: tree, plant, rock or water (growth in and by the water: lily pads, reeds). A model that names none is a tree when it has a level of views, a plant when it is foliage, and a rock otherwise; a model is a water model only when it says so.
Credits. Every model names its author, the tool it was made with and its license. A model without all three is refused. Credit the tools honestly, generators included.
Ground
A pack may lay the ground: a material for each retail terrain type it covers, drawn in place of that type's ground picture wherever retail lays it, through retail's own blend masks. A type the pack names no material for keeps retail's picture.
[[terrain]]
ground = [1, 9] # the retail terrain types (0 to 31) it is drawn for, or "road"
base_color = "ground/grass_albedo.png"
normal = "ground/grass_normal.png" # tangent space: red east, green north
height = "ground/grass_height.png" # red; where layers meet, the higher one shows
roughness = "ground/grass_roughness.png" # red
occlusion = "ground/grass_occlusion.png" # red
size = 4.0 # meters one repeat of the pictures covers
author = "Someone"
tool = "Substance Designer"
license = "CC0-1.0"
Only base_color, size and the credit are required. The pictures of every ground material are square and repeat seamlessly, seen from straight above with north up.
A [[steep]] material, with the same keys, is laid on the steep slopes of the terrain types it names, in place of the scree and rock the remaster lays on steep ground of a type with none: an obsidian cliff, a sandstone face. A type may have one of each kind.
Retail pictures
A pack may draw a picture of its own in place of a retail picture, wherever a retail object or room is drawn with it: buildings, statics, rooms, dungeon pieces and what the server places alike.
[[material]]
texture = "0x0500287C" # the retail picture, or a list of them
base_color = "materials/0x0500287C_albedo.png" # with the retail picture's alpha
normal = "materials/0x0500287C_normal.png" # tangent space: red along the picture's
# width, green up it
roughness = "materials/0x0500287C_roughness.png" # red
occlusion = "materials/0x0500287C_occlusion.png" # red
normal_scale = 1.0 # how strongly the normal picture bends the normal
author = "Someone"
tool = "Krita"
license = "CC-BY-4.0"
Only texture, base_color and the credit are required. Each material names the retail pictures (texture records, 0x05...) it stands for. The retail surface's coordinates, its flags (cut out, translucent, additive, luminous) and its collision are kept, so the picture keeps the retail one's layout: a model's coordinates point into it as they point into the retail picture. Paint over the retail picture, keep its alpha, and the walls stay where they were.
Lighting
A pack may say how its art wants to be lit, with the keys and the tables of a player's look file, each kind of day a table of its own within it:
[lighting]
sun = 1.1 # a number, or [[time of day, value], ...] round the day
tint = 0.8
[lighting.rainy]
fog_density = 1.5
The keys are a look's: sun (the sun's strength, a factor), sky (both ambients' strength), tint (the evening and night tint, 1 keeping retail's and 0 taking it to gray), fog_density, fog_color, night_floor (the least the ambient may be), exposure (stops, for high dynamic range), and foliage_hue and foliage_pull (the hue the pack's leaves are pulled toward, in degrees, and how far, 0 to 1). Each may be given again for one kind of day: sunny, rainy, clear or cloudy.
The pack's lighting is laid over retail's light value by value, and a world's own light and the player's look file are laid over the pack's: a value they give wins.
Several packs at once
A player may turn on several packs, in an order: the client is given them lowest first (--art-pack once each), and the launcher's Library lists them with the winner at the top. A later pack wins, key by key:
- an object's model, by its id;
- a ground material, by terrain type (and the road), flat and steep apart;
- a material, by retail picture;
- the lighting, by key, each kind of day's table too.
Everything else of an earlier pack is still drawn, and what no pack has is drawn as before: so a pack of only Holtburg's houses, or of one kind of bush, stacks over a pack of the whole world. The client reads only what wins, so a small pack over a large one costs no more than the small pack's own.
A packed file holds at most 2 GiB. A larger pack is split into several, stacked.
The tools
dereth-art is in the repository's tools/art. Build it with cargo build --release -p dereth-art.
dereth-art pack <folder> [--out <file>] [--check]
packs the pack in <folder> into one file, --out or <folder>.dat beside the folder. It opens the folder exactly as the client does, so what it could not read or make is said, and left out of the file as the client leaves it out of the folder. With --check it writes nothing, and says whether the file is what the folder packs into now, and which records are not.
dereth-art survey [--dat-dir <dir>] [--out <dir>] [--landblocks <XXYY,...>] [--no-thumbnails]
surveys the models the world is built from, in the game's data at --dat-dir: where each one is used, how often, what it is made of, and a picture of it, as a page in --out. It is where to find the ids of the objects to make again.
To try a pack, start the client with it: --art-pack <folder> while making it (a folder is read afresh at each start, its pictures made as it opens), --art-pack <file.dat> once packed. The client's log says what the pack held and what it could not read.
Licensing and credits
A pack is its authors' work, and the client shows who made what. Give every model and material its own author, tool and license, and the pack its authors and license. Use a license that lets players download and use the pack (CC0, CC-BY, CC-BY-SA, or your own terms stated at homepage). Only put in a pack what you made or may share: a pack holds new art, never the game's own pictures or models.