Efficient EditableImage Rendering for Operating System Simulation

I’m creating an operating system simulation on Roblox and am using EditableImages for graphics. I’m facing challenges with efficient rendering and updating.

When moving elements, I need to clear their previous position without causing lag. Additionally, creating individual ImageLabels for each object is inefficient.

I’ve tried to split each object into its own EditableImage, and then have a script iterating through them, and place them in an ImageLabel, but I don’t want to create EditableImages for each movable object. I’ve tried to clear the entire screen on update but that is inefficient and caused lag. The best result I got is by clearing the pixels used by the object before updating, and then display the object at its new position. The pixels that get cleared should be overwritten with the object that had a lower Z-Index.

Here is my approach for rendering a mouse on one EditableImage layer:


local uis = game:GetService("UserInputService")
local assetService = game:GetService("AssetService")
local MouseIconSource = assetService:CreateEditableImageAsync("(CURSOR ICON)")
local MouseIcon = MouseIconSource:Clone()
local FrameBuffer = Instance.new("EditableImage")
FrameBuffer.Name = "MouseBuffer"
local BlankBuffer = Instance.new("EditableImage")

BlankBuffer:WritePixels(Vector2.new(),BlankBuffer.Size,table.create(BlankBuffer.Size.X*BlankBuffer.Size.Y*4,0))

local function GetScaledVector(vec)
	local screenSize = script.Parent.VideoOutput.AbsoluteSize
	local PosRatio = vec/screenSize
	return PosRatio*FrameBuffer.Size
end
local cursorSizeOnScreen = Vector2.new(18,23) -- The image I am using is a bit asymmetric
local cursorSize = GetScaledVector(cursorSizeOnScreen)

script.Parent.VideoOutput.Changed:Connect(function()
	MouseIcon:Destroy()
	MouseIcon = MouseIconSource:Clone()
	cursorSize = GetScaledVector(cursorSizeOnScreen)
	MouseIcon:Resize(cursorSize)
	BlankBuffer:Resize(cursorSize)
end)
MouseIcon:Resize(cursorSize)
BlankBuffer:Resize(cursorSize)

FrameBuffer.Parent = script.Parent.VideoOutput
FrameBuffer.Size = Vector2.new(1024,720)


uis.MouseIconEnabled = false
local oldMousePos = Vector2.new(0,0)
uis.InputChanged:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseMovement then
		FrameBuffer:DrawImage(oldMousePos,BlankBuffer,Enum.ImageCombineType.Overwrite)
		local realMousePos = GetScaledVector(Vector2.new(input.Position.X,input.Position.Y))
		FrameBuffer:DrawImage(realMousePos,MouseIcon,Enum.ImageCombineType.BlendSourceOver)	
		oldMousePos = realMousePos	
	end	
end)
1 Like

Perhaps look into parallel processing? Like rendering different rows of pixels with different threads

Do I create an Actor for each row?

Solved the problem after finding out I was using table.create() every frame and that affected performance a lot. table.create() was used to generate an array full of zeroes, which is then written to the EditableImage to clear the screen. Did a test without it and It turns out around 10000 objects are needed to make the same laggy output.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.