Faster pixel by pixel render?

General discussion about LÖVE, Lua, game development, puns, and unicorns.
User avatar
mapimopi
Prole
Posts: 3
Joined: Wed Jun 10, 2015 11:17 am

Faster pixel by pixel render?

Post by mapimopi »

Hello lovers!

I'm trying to improve my rendering method. It's really simple, 320x200 canvas with 16 colors, but I need to draw it pixel by pixel, taking a value from a 2d array.

What I do now is have a spritebatch and 16 1x1 quads (for each color), and when I need to render the canvas, I clean the batch, go through the array and add each pixel to the batch, and then draw. It works fine for now (without much logic) if I skip 2 or 3 frames.

Is there a better way? Shaders maybe?

Thanks!
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Faster pixel by pixel render?

Post by T-Bone »

From what you write, I don't think it's clear how you can solve this problem. Here are however some things to think about:

1. Have you considered not storing it as a 2D array in the first place? A 2D array is sort of an image already, why not use an image-like format directly? It could be ImageData (if you want to use threads) or a Canvas or SpriteBatch. That way, you skip the conversion step.

2. Shaders could be used, but I don't think you can send a large-ish 2D array to the GPU, to be accesed from the shader, without converting it to some kind of image first. The largest supported matrix size is 4x4. I guess you could divide your 2D array into a whole bunch of 4x4-matrices and send all of those... Not sure if that's going to be slow or not.
User avatar
mapimopi
Prole
Posts: 3
Joined: Wed Jun 10, 2015 11:17 am

Re: Faster pixel by pixel render?

Post by mapimopi »

The thing is I want to update it often, once per two frames preferably.

What I'm trying to do is something like http://en.wikipedia.org/wiki/Memory-mapped_I/O. Basically, there is a programmable computer inside a love game, and to draw to the screen you'd need to set a value to some address in memory (which, in the end, is a lua array). The main bottleneck I see with lua is drawing to the screen.

Please, don't crash my hopes by telling me that the only solution to this is to redo everything in C...
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Faster pixel by pixel render?

Post by Positive07 »

T-Bone wrote: 1. Have you considered not storing it as a 2D array in the first place? A 2D array is sort of an image already, why not use an image-like format directly? It could be ImageData (if you want to use threads) or a Canvas or SpriteBatch. That way, you skip the conversion step.
ImageData:
  1. Can be passed to other threads as T-Bone said, this means you could render it in other thread then pass it to the main thread
  2. You can set and get data from each pixel with [wiki]ImageData:setPixel[/wiki] and [wiki]ImageData:getPixel[/wiki]
  3. You can render it really fast with the map function [wiki]ImageData:mapPixel[/wiki]
I'm not sure about what T-Bone said about directly storing your data inside of an ImageData, althought its possible you may need to update a pixel many times in a single update, which is not nice. What I consider to be the best alternative is doing something like this:

Code: Select all

ImageData:mapPixel(function (x,y, oldr, oldg, oldb, olda)
    return unpack(Your2DArray[x][y])
end)
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
User avatar
mapimopi
Prole
Posts: 3
Joined: Wed Jun 10, 2015 11:17 am

Re: Faster pixel by pixel render?

Post by mapimopi »

Just tried both mapPixel and setPixel. Using setPixel was twice faster than mapPixel for some reason, but still twice slower than useing spriteBatch with 64000 sprites...

I guess optimizing spriteBatch method is the only optimal way. So far I found these ways for optimization: use set instead of clearing and adding sprites each time, use bind and unbind, use 256 2x1 quads instead of 16 1x1 (and cutting sprite number in half). Is there something else you can think of?
User avatar
T-Bone
Inner party member
Posts: 1492
Joined: Thu Jun 09, 2011 9:03 am

Re: Faster pixel by pixel render?

Post by T-Bone »

When you tried working with ImageData, did you use another thread? I don't think there's much point to it unless you use more than one thread. Optimally you should use as many threads as there are CPU cores.
Daniel_Cortez
Prole
Posts: 11
Joined: Sun Apr 06, 2014 4:43 pm
Location: Novokuznetsk, Russia

Re: Faster pixel by pixel render?

Post by Daniel_Cortez »

mapimopi wrote:Is there something else you can think of?
Maybe you could use the FFI replacements for ImageData functions: https://github.com/slime73/love-snippet ... ta-ffi.lua
Probably not a best solution though since these functions are not thread-safe (you'll have to only use them in the main thread).
Also there won't be any performance increase on iOS because LuaJIT can't compile bytecode to a native code on that platform thanks to Apple.
↑↑↓↓↑↑↑↑
User avatar
Positive07
Party member
Posts: 1014
Joined: Sun Aug 12, 2012 4:34 pm
Location: Argentina

Re: Faster pixel by pixel render?

Post by Positive07 »

Daniel_Cortez wrote: Probably not a best solution though since these functions are not thread-safe (you'll have to only use them in the main thread).
Or in another thread, since they exist in the thread /threads that require the functions
T-Bone wrote:When you tried working with ImageData, did you use another thread? I don't think there's much point to it unless you use more than one thread. Optimally you should use as many threads as there are CPU cores.
THIS! ENTIRELY!
for i, person in ipairs(everybody) do
[tab]if not person.obey then person:setObey(true) end
end
love.system.openURL(github.com/pablomayobre)
Daniel_Cortez
Prole
Posts: 11
Joined: Sun Apr 06, 2014 4:43 pm
Location: Novokuznetsk, Russia

Re: Faster pixel by pixel render?

Post by Daniel_Cortez »

T-Bone wrote:When you tried working with ImageData, did you use another thread? I don't think there's much point to it unless you use more than one thread. Optimally you should use as many threads as there are CPU cores.
Do you mean manipulating an image data in multiple threads or just moving all the manipulation code to another thread?
Because using multiple threads will only make sense if you're going to manipulate 2 or more images in separate threads since setPixel and mapPixel methods are using mutexes.
↑↑↓↓↑↑↑↑
User avatar
Inny
Party member
Posts: 652
Joined: Fri Jan 30, 2009 3:41 am
Location: New York

Re: Faster pixel by pixel render?

Post by Inny »

One idea I've mulled over is that if you have a lot of calls to love.graphics.setColor, maybe you can figure a way to batch process the pixels. If you figure that each pixel can be described by a number between 0 and 64000 (320*200), then you could have preallocated arrays set up, one for each color, each table using a key like N to mark the end of the array, and then when time comes to paint, iterate over your pixel grid, and for each color you find, add that location at color[id][color[id].N+1] = location. Then, you render by setting the color once, and then drawing your single pixel rectangle to the locations indicated in each list.

I'm... not certain this would get too much faster. It may be a better idea for simulating ASCII text rendering and not the actual pixels, but I could see it being worth a shot, just for laughs.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 11 guests