Hi.
I am a complete beginner with both LOVE and Lua.
When I learn a new framework/engine, the first thing I always do is a raw performance test where I move and rotate around a bunch of sprites on the screen and check distance from an object that follow the mouse, once any of the moving objects get close to the mouse, I remove it from rendering and delete it.
In this test, LOVE did not performed too well compared to others. I was getting only 30FPS with 'just' 10k sprites on the screen NOT moving. Not that I need this many, but I do like to know the limits the framework has that I am using, and other frameworks do perform a lot better in similar scenario. With other frameworks, usually I get 30FPS with 20k-100k sprites MOVING on the screen on same hardware.
I am using only a for loop to iterate through each and every sprite stored in a table to draw them on the screen and compare distance and remove them from the table. It is obviously not optimal but some frameworks even this way perform 3x better than LOVE, so wondering if is there any technique I could use to get better results with LOVE in this simple test?
For one, I was thinking about batch rendering, would that be possible to draw all sprites with a single draw call for example instead of a for loop?
An other thing I was thinking about is to iterate through each instance in update asynchronously and just use a global in the draw callback function, would something like that be possible, useful?
Or any other ideas?
Here is the code to show what I'm doing:
https://gofile.io/d/Ibvlfl
I would appreciate any help.
Thanks.
Tips about optimising performance
Tips about optimising performance
Last edited by ddabrahim on Mon May 31, 2021 9:09 pm, edited 1 time in total.
Re: Tips about optimising performance
If you posted your test code, then people could tell you why you're doing it wrong.
- zorg
- Party member
- Posts: 3470
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: Tips about optimising performance
What grump said; some more info: löve already uses auto-batching (unless you do something that breaks said batching), or you can use SpriteBatch objects to do batching and draw the batch itself with one call.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: Tips about optimising performance
Re: Tips about optimising performance
Thanks, SpriteBatch sounds like what I am looking for, I'll look in to it.
Re: Tips about optimising performance
Those are not really sprites. The geometry for 20,000 circles drawn in immediate mode has to be constructed, transformed and transmitted to the GPU in every frame. At 30 fps, that's maybe 15,000,000 vertices per second streamed to the GPU, possibly more.
If you draw one pair of circles to a Canvas, which makes it an actual sprite, and use that in a SpriteBatch it should be faster. Or you can make a mesh and use drawInstanced, but that's more complicated.
If you draw one pair of circles to a Canvas, which makes it an actual sprite, and use that in a SpriteBatch it should be faster. Or you can make a mesh and use drawInstanced, but that's more complicated.
Re: Tips about optimising performance
Or use actual sprites maybe (I didn't see the code but assuming code uses love.draw.circle)
Last project:
https://togfox.itch.io/hwarang
A card game that brings sword fighting to life.
Current project:
Idle gridiron. Set team orders then idle and watch: https://togfox.itch.io/pad-and-pencil-gridiron
https://togfox.itch.io/hwarang
A card game that brings sword fighting to life.
Current project:
Idle gridiron. Set team orders then idle and watch: https://togfox.itch.io/pad-and-pencil-gridiron
Re: Tips about optimising performance
Thank you. I'm going to look in to that.
I also tried to draw images using love.graphics.draw() in case that is what you mean, but I was getting similar performance, did not make much difference.
Re: Tips about optimising performance
You could use a Canvas (aka render to Texture)
the existing code on my low end machine starts at 30 fps, the canvas code below 200 fps
edit:
and removing the coin.draw() function
to just do that render code inline gives me another 40fps
the existing code on my low end machine starts at 30 fps, the canvas code below 200 fps
Code: Select all
local player = {}
local coins = {}
function love.load(arg)
love.window.setVSync( false )
player.x = 100
player.y = 100
player.radius = 30
player.draw = function()
player.x = love.mouse.getX()
player.y = love.mouse.getY()
love.graphics.setColor(1,1,1)
love.graphics.circle('fill',player.x, player.y, player.radius)
love.graphics.setColor(1,0,0)
love.graphics.circle('line',player.x, player.y, player.radius)
end
player.distanceFrom = function(_other)
local horizontal_distance = player.x - _other.x
local vertical_distance = player.y - _other.y
local a = horizontal_distance * horizontal_distance
local b = vertical_distance ^2
local c = a + b
local distance = math.sqrt(c)
return distance
end
coinRadius = 20
canvas = love.graphics.newCanvas(coinRadius*2, coinRadius*2)
love.graphics.setCanvas(canvas)
love.graphics.clear()
love.graphics.setBlendMode("alpha")
love.graphics.setColor(0.7,0.5,0)
love.graphics.circle('fill',coinRadius, coinRadius, coinRadius)
love.graphics.setColor(1,1,1)
love.graphics.circle('line',coinRadius, coinRadius, coinRadius)
love.graphics.setCanvas()
for i =1,10000,1 do
table.insert(coins,addCoin())
end
end
function love.update(dt)
for i,coin in ipairs(coins) do
if player.distanceFrom(coin) <= player.radius + coinRadius then
table.remove(coins,i)
end
end
end
function love.draw()
player.draw()
love.graphics.setColor(1,1,1)
love.graphics.setBlendMode("alpha", "premultiplied")
for i,coin in ipairs(coins) do
coin.draw()
end
love.graphics.setBlendMode("alpha")
love.graphics.setColor(1,0,0)
love.graphics.print(love.timer.getFPS())
end
function addCoin()
local coin = {}
coin.x = math.random(0,1000)
coin.y = math.random(0,700)
coin.draw = function()
love.graphics.draw(canvas, coin.x, coin.y)
end
return coin
end
and removing the coin.draw() function
to just do that render code inline gives me another 40fps
Code: Select all
for i,coin in ipairs(coins) do
love.graphics.draw(canvas, coin.x, coin.y)
end
Re: Tips about optimising performance
Thanks a lot @Nikki, it was very useful, was not sure what is the best way to use canvas to reduce the number of draw calls.
An other thing I also did after is to draw only what is actually on the screen and even after I implement a camera and move around I get decent performance now.
An other thing I also did after is to draw only what is actually on the screen and even after I implement a camera and move around I get decent performance now.
Who is online
Users browsing this forum: Ahrefs [Bot] and 6 guests