Vertex packing for Runtime SDK files
Customize data packing for SpeedTree Runtime SDK mesh export (STSDK format), using the "Vertex packing" feature.
Overall process
To define and apply custom data packing to STSDK export:
Create a description XML file and save it in the
<app install>/vertex_packing
folder.Write a packing script in Lua language and save the file at the path specified in the XML file.
In Game export options, under the Format-specific section, select the Vertex packing option that corresponds to your custom packer.
Description XML
This XML file defines the vertex packer, which includes mostly:
- The path to the packing script to run for each vertex, and
- A description of the vertex attributes, organized in vertex streams.
Vertex streams represent separate buffers of data that can be bound to the vertex shader separately (though most common use is to just use one). Each stream can contain multiple vertex attributes.
Note
To be able to select your custom vertex packer from the Modeler at export, you must place the XML file in the <app install>/vertex_packing
folder.
XML file format
<?xml version="1.0" encoding="UTF-8"?>
<SpeedTreeVertexPacker
Program="[filename of the lua script to run for this packer,
often named the same but with the .lua extension]"
Force32bitIndices="[true/false to always use 32bit indices, or allow the indices
to fall back to 16bit if there are fewer than 65k vertices]"
>
<Stream
Name="[name of this stream]"
>
<Attribute
Type="[type of variable used for this attribute:
byte, ubyte, short, ushort, int, uint, half, float, or double]"
Count="[integer for how many elements in this attribute, 1-4]"
Normalize="[doesn't affect the packing, but does tell the runtime to normalize
this attribute, for instance a 0-255 ubyte will come into the shader
as 0.0-1.0]"
Description="[description of this stream, if needed]"
>
...
</Stream>
...
</SpeedTreeVertexPacker>
Example: Standard packer
Content of the Standard packer description XML file provided by default with the Modeler:
<?xml version="1.0" encoding="UTF-8"?>
<SpeedTreeVertexPacker
Program="Standard.lua"
Force32bitIndices="false"
>
<Stream Name="Main">
<Attribute Type="half" Count="4"
Description="position(3)/texcoord_u(1)"/>
<Attribute Type="half" Count="4"
Description="lod_position(3)/texcoord_v(1)"/>
<Attribute Type="ubyte" Count="4" Normalize="false"
Description="normal(1)/binormal(1)/tangent(1)/wind_branch_dir(1)"/>
<Attribute Type="ubyte" Count="4" Normalize="true"
Description="wind_weight(1)/wind_ripple(1)/wind_branch_offset(1)/ao_blend_and_2sided_packed(1)"/>
</Stream>
</SpeedTreeVertexPacker>
Packing script (in Lua)
This script packs the model input data into the vertices of the exported file. During export, the Modeler runs the script for each vertex.
Note
To allow the Modeler to run this script, you must name and place it according to the path you specified in the description XML file.
Script language and capabilities
You have to write the packing script in Lua language. For more information and examples about this language, refer to www.lua.org and Lua Tutorials.
The base purpose of the script is to get data from the model and pack it to the exported mesh, but you can also use any built-in Lua functions to pre-process and transform that data before packing it, if you need to. Various additional functions are also available to control batch geometry, delete vertices, or print information for debug.
Tip
- Get the list of all input data and SpeedTree specific functions available to write the script.
- Look at the
Standard.lua
file provided by default in the<app install>/vertex_packing
folder.
Vertex data packing
The input data available to use in the script covers all of the data available for a vertex.
To place any of that data into the final vertex attributes in the export file, use the set_attribute
function, or the set_attribute_integer
function when strict adherence to integers is wanted.
The value you pass to these functions gets converted to the final data type as close as possible. For example, you don't have to worry about packing a float into a half float or even a byte, as the set_attribute functions will attempt to do this for you.
Geometry batching control
The geometry in the tree is as batched as possible, just like in other file formats. Without any further input, the exported tree is batched into as few draw calls as possible, depending on the number of separate materials produced after atlassing.
However, you have some control over this from the packing script. The set_batch_type
function can pull geometry out into a separate draw call. For example, you might want to pull anything with a blend/alpha value other than 1.0 out into a separate draw call to avoid rendering the whole tree with alpha blending on.
To do this, you can set any integer you wish to set_batch_type
. The default is 0. Any unique integer passed causes a new draw call filled with all of the geometry set to that integer. The batch type value is available in the file and through the SpeedTree SDK to do with as you wish at runtime. You can encode all sorts of things into the batch type, and cause different rendering states or shaders to be used at runtime on that piece of geometry.
Polygons are made up of multiple vertices, and they may have different values for the code used in set_batch_type
. You may want to make sure that a certain vertex value takes priority over the other vertices in that polygon. To do this, use set_batch_priority
. With the previous example of pulling out polygons needing alpha blending, you would set the priority to 1 if blend/alpha is less than 1.0 and 0 otherwise. This ensures that any polygon needing to be put into the batch type of 1 gets that value.
Lua batching examples
-- batch by geometry type
set_batch_type(in_geometry_type)
-- batch by two-sided or not
if in_two_sided then
set_batch_type(1)
else
set_batch_type(0)
end
-- batch by needing blending
if (in_vertex_alpha < 1.0) then
set_batch_type(1)
set_batch_priority(1.0)
else
set_batch_type(0)
set_batch_priority(0.0)
end
-- batch by geometry type AND two-sided
if in_two_sided then
set_batch_type(in_geometry_type + 5)
else
set_batch_type(in_geometry_type)
end
Reference
Available input data
List of all vertex data available as input for data packing customization.
Variable | Type/format | Description |
---|---|---|
in_anchor | 3 float array | Anchor position for node. |
in_offset | 3 float array | Offset from anchor. |
in_lod_offset | 3 float array | LOD offset from anchor. |
in_texcoord | 2 float array | Main UV. |
in_lightmap_texcoord | 2 float array | Lightmap UV, if available. |
in_normal | 3 float array | Vertex normal. |
in_binormal | 3 float array | Vertex binormal. |
in_tangent | 3 float array | Vertex tangent. |
in_vertex_color | 3 float array | Vertex color. |
in_vertex_alpha | float | Vertex blend value. |
in_ambient_occlusion | float | Ambient occlusion value. |
in_wind_branch1_position | 3 float array | Branch tip position for level-1 branch in wind. |
in_wind_branch1_origin | 3 float array | Pivot point position for level-1 branch in wind. |
in_wind_branch1_direction | 3 float array | Growth direction for level-1 branch in wind. |
in_wind_branch1_weight | float | Weight/amount for level-1 branch wind motion. |
in_wind_branch2_position | 3 float array | Branch tip position for level-2 branch in wind. |
in_wind_branch2_origin | 3 float array | Pivot point position for level-2 branch in wind. |
in_wind_branch2_direction | 3 float array | Growth direction for level-2 branch in wind. |
in_wind_branch2_weight | float | Weight/amount for level-2 branch wind motion. |
in_wind_ripple | float | Wind ripple scalar. |
in_bone_id | integer | ID of the bone attached to this vertex. |
in_two_sided | boolean | Represents the two-sided flag on the material used on this vertex. |
in_geometry_type | integer | Geometry type: Branch=0, Frond, Leaf, FacingLeaf, Billboard. |
in_original_geometry_type | integer | Original geometry type before batching: Branch=0, SubDivBranch, Cap, Frond, Leaf, FacingLeaf, Mesh. |
in_tree_extents | 6 float array | Tree extents: min xyz, max xyz. |
Available functions
List of all SpeedTree specific functions you can call in the script, in addition to built-in Lua calls.
Function | Parameters | Description |
---|---|---|
set_attribute | <attribute index>, <component/swizzle index>, <double/float value> | Save data to the vertex attributes. |
set_attribute_integer | <attribute index>, <component/swizzle index>, <integer value> | Save integer data to the vertex attributes. |
set_batch_type | <integer> | Set the batch type for this vertex. Refer to batching control. |
set_batch_priority | <float> | Set the batch priority for this vertex. Refer to batching control. |
kill | Completely remove this vertex (and the associated polygon) from the exported mesh. | |
<string> | Output information to the SpeedTree Modeler Console. Use it for debugging, but carefully, since it prints for every vertex. |