How to use LODService

This is a tutorial on using the LODService Plugin and Module

Keep in mind you will have to put the .rbxmx file into your local plugins folder otherwise you will NOT be able to generate templates!
You can do this by:

  1. Downloading the .rbxmx file from the devforum post
  2. Right clicking on ServerStorage → Insert → Import Roblox Model and selecting the LODServicePlugin.rbxmx file you just downloaded
  3. Right clicking on the folder called ‘LODServicePlugin’ that you just imported → Save / Export → Save as Local Plugin

After this you can delete the LODServicePlugin folder if you wish to

PROCESSING TOOLBOX MODELS

Roblox blocks CreateEditableMeshAsync/CreateEditableImageAsync for assets not owned by you, even if they are free toolbox models, and assetdelivery doesn’t work (for me atleast) in edit mode, so you will need to use an application to get past this.
You can follow the instructions and download the application used for this here: GitHub - TylerAtStarboard/RobloxAssetDeliveryProxy: Used for MeshVox and other things I need AssetDeliveryFor, because Roblox requires cookie authentication now and I don't want to send my cookie to roproxy.
You will need to have this open and running while using the plugin in order for assetdelivery to work.

ALGORITHM EXPLANATION (this is important to understand the plugin settings)

In short the simplification algorithm takes a mesh and merges the vertices into little cells based on how important they are to the geometry. This is how the original, unimproved version of vertex clustering works:


Aside from improving how the vertices are clustered, this implementation fixes the issue where triangles that have 2 vertices in the same cell just get deleted, removing too much geometry. This issue is resolved by creating a rectangle between the two cells, these are called pixel lines (this is how they will be referred to in the settings).

As for the billboards, they are constructed by a given amount of planes which are placed vertically, and 2 extra planes placed horizontally, where each plane is an orthographic projection of a given side. These planes are then blended based on view angle.

Lastly the rendering constant which is called X in the original paper. This is the pixel to cell size ratio of the lod selection, meaning the higher it is, the lower the selected lod quality will be. This is the equation for the selected cell size, we can see how X is just a multiplier for how low the selected quality will be:
image
I recommend keeping this between 3-7 with 3 translating to higher lod quality and 7 to a lower one, but you can experiment with your own values.

THE PLUGIN

Main Section
  • Insert LOD Folder - This button inserts the folder with the Module into ReplicatedStorage for in-game use
  • Model Template - This is the model that you want to turn into an LOD Template, please reselect the model if you change main settings because it will need reprocessing
  • Mesh Simplification Timeout - The timeout for the vertex clustering algorithm (this setting is pretty redundant because the algorithm is really fast, but if your computer is really old I recommend lowering this a bit)
  • Mesh Generation Timeout - Same as the previous, but for turning the simplified vertex data to a mesh
  • Billboard Generation Timeout - Same as the previous 2, but for rendering billboards (I recommend setting this a lot lower if your computer is old, as billboard generation is an expensive process)
  • Use Box Parts - Whether to process every part as blocks
  • Generate Transparent Mesh - Whether to generate a transparent mesh, turn this on if your model has parts that aren’t 1 or 0 transparency and are large enough to be seen
  • Mesh Blockiness - How much the simplified mesh’s normals should be interpolated towards the blocky normal (I recommend leaving this at 0 unless you know what you’re doing)
  • Ignore Unprocessable Parts - When this setting is on Unions and DataModelMeshes (FileMeshes, BlockMeshes, etc.) will be ignored, when off they will be treated as block parts
  • Generate Dynamic Normals - Whether to generate pixel lines
  • Maximum Pixel Lines - How many pixel lines the algorithm can generate at maximum
  • Texture Sampling Radius - How large the sampling radius should be when sampling from a texture - setting this high will make textures appear blurry, but I do not recommend changing this from 0 unless you know what you’re doing
  • Texture Sampling Iterations - How many pixels the texture sampling should sample, this is related to the previous setting, also don’t recommend changing this
  • Cell Color Averaging Bias - When 0 the cells’ center vertices will keep their color, when 1 the cells’ center vertices’ color will be the average of all vertices’ color in that cell, any other values will blend between the two
  • Use Averaged Material Colors - Whether materials should tint a vertex’s color based on its average color, this setting is mostly for materials that largely differ from the plastic texture such as pre-2022 granite
  • Pre 2022 Materials - Whether the algorithm should use the new materials’ averaged color or the old, pre 2022, ones’ (This should match MaterialService.Pre2022Materials)
  • Merge Vertices - Whether the algorithm should merge vertices that are really close to eachother and are similar when processing a model (I recommend leaving this off)
  • X - This is the rendering constant, I recommend keeping this between 3 and 7, the higher it is the lower the quality of the LODs
  • Unrender Cell Size - The cell size where the model should be unrendered, I recommend setting this to be the size of the model, or experimenting with the unrender distance
  • Unrender Distance - The distance at which the model would be unrender with the given unrender cell size and X
  • Model Tri Count - The tri count of the processed model (counts unprocessable parts as boxes)
  • Distance to Model - The distance to the selected model, you can use this to experiment with where LOD boundaries would be
  • Reset Settings - Resets all settings to default
  • Add Mesh Element - Adds a new mesh element to the template (mesh element meaning that it’s not a billboard element)
  • Add Billboard Element - Adds a new billboard element to the template
  • Billboard Generation State - The progress of an ongoing billboard generation
Mesh Elements
  • Cell Size - The size of each vertex clustering cell
  • Min Visible Distance - The smallest distance where the LOD level would be visible with the given cell size and X setting
  • Delete Mesh - Deletes the mesh
  • LOD Texture - The texture for the generated mesh, I only recommend using this when creating an LOD of a singular mesh with visually important textures
  • LOD SurfaceAppearance - Same as the previous but a SurfaceAppearance is used instead of a texture
  • Generate Mesh - Generates the LOD with the given cell size and other settings
  • Tri Count - The tri count of the generated LOD
Billboard Elements
  • Cell Size - Same as for the mesh elements, but has no effect on the visual outcome of the billboard
  • Min Visible Distance - Same as the mesh
  • Delete Billboard - Same as the mesh
  • Resolution - The X Resolution of each plane
  • Sides - How many vertical sides the billboard will have
  • Y Angle - The angle at which the horizontal planes will start to get blended in
  • Generate Billboard - Generates a billboard with the given settings
  • Tri Count - Same as the mesh
Finalisation
  • Start Preview - Starts a preview of the template with the given settings, with this you can test out how the template would look in game (keep in mind the previewed meshes don’t have shadows but they do in-game)
  • Stop Preview - Stops the ongoing preview
  • Template Name - The name of the generated template
  • Pixel Line Precision - How many decimals the pixel lines’ positions will be rounded to, if any of the LOD levels’ line count times the decimal precision exceeds about 1500 then it will have some of its pixel lines removed (due to memory issues)
  • Generate Template - Publishes the template, and generates it into ReplicatedStorage.LOD.Templates

MODULE USAGE
Methods:

  • LODService:SetX(X : number) - this will set X to the desired value
  • LODService:Run() - this starts LODService
  • LODService:Pause() - this pauses LODService
  • LODService:Clear() - pauses and clears the entirety of LODService, meaning all LODs are deleted
  • LODService:CreateRegion(pivot : Vector3) - creates a new ‘ModelRegion’ with the given center and returns it

ModelRegion:

  • ModelRegion:Destroy(timeout : number?) - deletes everything inside of the region with the given timeout (default value is 5)
  • ModelRegion:CreateGroup(template : Template) - creates a ‘ModelGroup’ inside of the region and returns it

ModelGroup:

  • ModelGroup:Destroy() - deletes everything inside of the group with the given timeout (default value is 5)
  • ModelGroup:RefreshScaleMultiplier() - refreshes the scale multiplier of the group, I recommend calling this if the group’s models largely differ from the template scale
  • ModelGroup:ParentTo(parent : ModelRegion)
  • ModelGroup:LODifyModel(model0 : Model, autoPivot : boolean?, loadingPenaltyMultiplier : number?) - creates an LODModel out of model0, enabling autoPivot will automatically move the lods with model0 if its pivot is moved.
loadingPenaltyMultiplier

loadingPenaltyMultiplier is the number that’s multiplied with the default loading penalty, if the loading the model is really laggy, then set this to something higher than 1, and if the opposite is true then set it to something lower than 1 (this setting can mostly be left alone)

LODModel:

  • LODModel:Destroy() - deletes the lods and removes it from its parent group, but keeps model0
  • LODModel:PivotTo(pivot : CFrame) - pivots the LODModel to the given CFrame
  • LODModel:PreloadAll() - preloads every lod level, this makes loading a lot faster but takes a lot more memory
  • LODModel.model0 - this is the original model, which gets reparented to nil when unloaded, so use this if you need to access the model during runtime

Settings:

  • MaxMemoryUsage: the number of lods needed for the script to start deleting unloaded lods to free up memory
  • PenaltyTimeout: the amount of penalties collected before halting the thread, the higher this is the faster LODs will load (it will also be laggier)
  • Timeout: how many seconds the halting lasts
  • BillboardTimeout: same as PenaltyTimeout but for billboards/pixel lines
  • BillboardUpdateDot: the cosine of the minimum delta angle - the angle between the current viewing direction of a region and the viewing direction of a region when it was last updated - needed to refresh billboards of said region

Here is an example of using the module - this groups all models that have names that match a template into regions:

local REGION_SIZE = 100

local LOD = game:GetService("ReplicatedStorage").LOD
local Templates = LOD.Templates
local LODService = require(LOD.LODService)

local regionCount = 0
local modelCount = 0
local groupCount = 0


-- you can use GetDescendants here aswell
for _, v : Instance in workspace:GetChildren() do
	if not v:IsA("Model") then
		continue
	end
	
	local templateModule = Templates:FindFirstChild(v.Name)

	if not templateModule then
		continue
	end

	modelCount += 1

	local template = require(templateModule)
	local pivot = v:GetPivot().Position

	local foundRegion = false

	for _, region in _G.regions do
		if (region.pivot - pivot).Magnitude < REGION_SIZE then
			foundRegion = true

			local foundGroup = false

			for _, group in region.groups do
				if group.template == template then
					foundGroup = true
					group:LODifyModel(v)
					break
				end
			end

			if not foundGroup then
				groupCount += 1
				region:CreateGroup(template):LODifyModel(v)
			end

			break
		end
	end

	if not foundRegion then
		regionCount += 1
		groupCount += 1
		LODService:CreateRegion(pivot):CreateGroup(template):LODifyModel(v)
	end
end

LODService:Run()
print(string.format("LODService started with %i regions, %i groups and %i models", regionCount, groupCount, modelCount))

This tutorial is pretty bad and I’m going to improve it in the future, I just wanted to make a quick guide so people don’t have to figure the module out for themselves

If you have any questions feel free to ask!

9 Likes