Simple shaders such as Visualizers, can hit 200 fps at the same resolution. If your shader is horizontal only, you can hit 500 fps with heavy interlacing.
Should I use CanvasDraw or write a Shader?
Shaders are extremely fast, but without math skills, you’re limited to what’s on Shadertoy.
CanvasDraw is more of a “2D Game Engine”, but is quite a bit laggier.
If you want to make Games Inside A GUI, CanvasDraw is better, although you’re stuck to low resolution.
For Backgrounds, VFX, Audio Visualizers, Ray-Tracing, etc at higher resolutions, this Shader System is better.
If you are clever, you could even use this Shader System to add expensive VFX to CanvasDraw projects.
It is a shader engine that writes to a canvas efficiently, using optimizations such as interlacing, pre-calculation, and low-precision math.
Using shader algorithms, you can create pretty much anything at high fps.
3D Models, Backdrops, Visualizers, etc…
You can actually use CanvasDraw with this shader system instead of EditableImage.
All you have to do is replace the line that says EditableImage:WritePixels()
Although using CanvasDraw just for mass-drawing pixel data might be silly.
Well aside from using !native, the first thing I have done is ensured the :WritePixels() method was only being used once per frame, which is easy enough, but then you have to figure out how to change each individual pixel, and to do that I used a 1D table of pure RGBA values in order.
I then made a :SetRGBA() method to set the individual pixels in the 1D array.
--!native (Gotta have this man)
local Grid = table.create(ResX * ResY * 4, 1) -- A blank grid of white pixels
-- Converts the X and Y into a 1D index for the grid
function GetGridIndex(X, Y)
return (X + (Y - 1) * ResX) * 4 - 3 -- Not sure if this is the fastest formula
end
-- Sets the specified RGBA value in the 1D array
function SetRGBA(X, Y, R, G, B, A)
local Index = GetGridIndex(X, Y)
Grid[Index] = R
Grid[Index + 1] = G
Grid[Index + 2] = B
Grid[Index + 2] = A
end
-- Draws the final image
function Render()
EditableImage:WritePixels(Grid)
end
This is pretty well the barebone methods that the new canvas uses.
i haven’t really anything else for the rendering aside from having a manual :Render() method available to avoid doing it every frame.
The majority of my other optimisations have been for image processing, getting RGBA values, and texturing of polygons and other textured mapped things.
I actually have hardly ever heard the phrase in programming before, what does this method do? it’s not just a glorified v-sync thing? or is this something else I haven’t heard of before?
I use :SetPixel/:SetRGB for every pixel on a popular roblox game of mine with the module and they work great. Super fast and simple code. Even for the UI gradient version the game uses.
Buuuut, i gotta admit, if your doing just per-pixel shader like stuff, then your better off using just the raw editable image lol
Interlacing is where you render odd rows pixels on one frame, and even on the next.
This obviously speeds things up 2X.
On slow-moving scenes, it does not look worse.
In fact it made my hat shader look better by shuffing the gaps between the lines for a fabric effect.
In extreme cases, you can render even less rows of pixels per frame and still look good.
Modded Playstation 2’s achieved 1080p by using this technique.
I just checked your powder game.
You can probably get away with rendering 1/4th of the vertical rows per frame lol.
It wouldn’t look weird because the powder rarely moves horizontally.
I’m gonna split up my pixel choosing algorithm into it’s own module today.
Probably something like this:
local pixelChooser = PixelChooser.new()
pixelChooser.InterlaceFactor = 4 --1/4th of rows will be rendered each frame
pixelChooser.EdgeFPSFactor = 2 --half fps at corners (added it for shader purposes)
pixelChooser.EdgePercent = 0.1 --farthest 10% of pixels will only be iterated half as much
--more optional optimizations will be added too
--render loop or whatever
while true do
for x,row in pixelChooser:Next() do --returns pixels to render on each frame
for y,_ in row do
--shader code or whatever
end
end
end
Game dev ain’t a competition, so feel free to implement it if you give credit. : )
Added you on Discord so I’ll let you know when it’s cooked.
And yeah it’s worth working on for my portfolio.
There’s something oddly appealing about making a fake RTX hat spin around like a hamster.
Update: I sped up the system by another 2x using some “techniques”
Now ray-marching and craftmine are possible!
I’ll remake this post with a link to proper documentation github page soon.
In all honesty though, this is actually extremely cool. I’ve been dying to make an outline shader for a long time, hopefully this will make it far faster!