Nice job! looks amazing! What are you planning to use for it? I’m pretty curious.
At the moment, im not planning to use it at all. I just plan to get this to look good and run at 60 FPS.
Depending on how this turns out, I might even open source this for others
Nice. thats a good item. you should sell it if you do it well.
Have you multithreaded it? If you do, and haven’t already, it will give you even more performance.
I have no idea how to multithread, or how to do it effectively
Well essentially if you have four cores, you’d 2-4x performance (not all cores are equal), roughly, depends on factors. Often times we have more.
So it would be worth it.
But essentially in roblox, we use an actor system. What you want to do is use multiple actors to raycast, so if you had 4 cores, divide the screen into 4 sections, have each actor raycast for that section only, in desynchronized mode, or, do every Nth pixel. Etc. Best to do a lot of actors tho so it works good on computers with a lot of cores.
Btw, what you’re doing is called raytracing, not pixelating, if you were not aware, some other people myself included have also messed around with this before so there should be some resources you can find on the devforum here that are either uncopylocked or explain how to do multithreaded raytracing.
Here is a staff post (warning, old, but it is open source) from when parallel luau came out in 2020.
The biggest performance improvement possible is multithreading.
There are some other techniques that can optimize it (btw i like your idea of using interlacing and pixel sleeping, that was smart!) however multithreading is the holy grail here.
I did some research, and im currently trying to implement it, and its the most painful thing i’ve ever had to do. Im having so many issues. And why do I have to do it across multiple scripts and actors?
This might take awhile…
OMG I FIGURED IT OUT!
It might have taken over a year of me actually getting any kind of multithreading working for any of my pixel-based projects, but thanks to this documentation featuring cloning one script across actors to recycle code with multi-threading, I DID IT!
We now have multi-threading on this bad boy!
Here are some tests at 200x200
BEFORE MULTI-THREADING:
Approximately 13 FPS
AFTER MULTI-THREADING (10 actors):
Approximately 31 FPS
That’s an insanely large performance boost. That’s about 2.3x faster!!
Omg this is amazing, I would LOVE to buy this! Why? Trust me, the stuff people would DO with this is amazing. I love making horror games and this would def be awesome! I am unsure how to help you, but keep at it! It looks amazing! Can’t wait to see the finish product!
I think it can be faster. How does your code look like? I am not asking for the Lua code but more of how do you actually send information between actors and things like that.
I can make lego island with this
The first video looks way better because yours has those weird visual bugs. You should probably fix that before you use it / sell it
The multithreading part was half yoinked from this on the roblox documentation.
Here’s their code:
-- Parallel execution requires the use of actors
-- This script clones itself; the original initiates the process, while the clones act as workers
local actor = script:GetActor()
if actor == nil then
local workers = {}
for i = 1, 32 do
local actor = Instance.new("Actor")
script:Clone().Parent = actor
table.insert(workers, actor)
end
-- Parent all actors under self
for _, actor in workers do
actor.Parent = script
end
-- Instruct the actors to generate terrain by sending messages
-- In this example, actors are chosen randomly
task.defer(function()
local rand = Random.new()
local seed = rand:NextNumber()
local sz = 10
for x = -sz, sz do
for y = -sz, sz do
for z = -sz, sz do
workers[rand:NextInteger(1, #workers)]:SendMessage("GenerateChunk", x, y, z, seed)
end
end
end
end)
-- Exit from the original script; the rest of the code runs in each actor
return
end
function makeNdArray(numDim, size, elemValue)
if numDim == 0 then
return elemValue
end
local result = {}
for i = 1, size do
result[i] = makeNdArray(numDim - 1, size, elemValue)
end
return result
end
function generateVoxelsWithSeed(xd, yd, zd, seed)
local matEnums = {Enum.Material.CrackedLava, Enum.Material.Basalt, Enum.Material.Asphalt}
local materials = makeNdArray(3, 4, Enum.Material.CrackedLava)
local occupancy = makeNdArray(3, 4, 1)
local rand = Random.new()
for x = 0, 3 do
for y = 0, 3 do
for z = 0, 3 do
occupancy[x + 1][y + 1][z + 1] = math.noise(xd + 0.25 * x, yd + 0.25 * y, zd + 0.25 * z)
materials[x + 1][y + 1][z + 1] = matEnums[rand:NextInteger(1, #matEnums)]
end
end
end
return {materials = materials, occupancy = occupancy}
end
-- Bind the callback to be called in parallel execution context
actor:BindToMessageParallel("GenerateChunk", function(x, y, z, seed)
local voxels = generateVoxelsWithSeed(x, y, z, seed)
local corner = Vector3.new(x * 16, y * 16, z * 16)
-- Currently, WriteVoxels() must be called in the serial phase
task.synchronize()
workspace.Terrain:WriteVoxels(
Region3.new(corner, corner + Vector3.new(16, 16, 16)),
4,
voxels.materials,
voxels.occupancy
)
end)
I basically used the exact same concept. I have 10 actors which each render a 10th of the screen (for a 100x100 resolution, that’s 100x10 each)
As for what code is contained in the parralel execution, that’s the main raytracing, pixel and colour management, and then a bindable event is fired for every pixel back to the core script to draw the pixel to the canvas
Those artefects/visuals are part of the reason why the FPS is so high. I’m only doing about 30% the calculations compared to the previous video
I think you should avoid sending many data. Can you change the pixels after the parallel phase without the need to send the data to Main script?
Could buffer serialization help at all?
Unfortunately not. I have found that this is the best method. And also, not using the bindable event at all and not even setting the pixel hardly changes FPS at all. It’s like a 1% difference, so that part cant be improved much.
Next up… Textures!
Buffer serialisation is slower than just reading/writing to an array as far as I know
It’s incredible. I wanted to try making pixel games, but after reading this, I got some hope. Are you going to sell them or are you going to distribute them for free?
I’m Korean and I used a translator, so it might be hard to understand. Sorry. If there’s anything you don’t understand, please let me know. Thank you