I need to refresh a bitmap every frame, so the Texture2D.SetPixel / Apply doesn’t work for me 'cause it’s REALLY slow. So I need a faster alternative. In my case, I need to send less than a byte for pixel (just the indexes of a 16 color palette), is there a faster way to send this information to the video card? I don’t know much about shaders, so any code or pseudocode will be appreciated!
Sure its slow, you have to reupload the texture every frame.
There is no way to accelerate it, as the upload must happen or there is nothing to render.
Optimally you just don’t come up with rather unsmart ideas like having larger textures you want to update or doing so every frame but instead 30 times per second for example.
Also there is no such thing as 16color palette. Its 16bit at least and 128bit at max
I’ve tried updating 30 times per second and I know that there’s no 16 color palette, but I want to know if there is a way to send an array of bytes to a shader so I can generate the texture with that information or some workaround to achieve that.
I believe (!!!) I’ve done some succesfull Apply()'s on every single frame. Just be sure to call Apply once all your SetPixel changes have been made on the Texture2D. For example:
don’t use setpixel, always use SetPixels if you want to apply whole lines / rects etc
the single pixel operations (read as write) is fine if you want to update a handful of pixels at max.
as for sending it to a shader: Sure, you can feed registers on a custom shader you write, thats no problem. if its 16, you can technically even feed a 4x4 matrix if you want for example or 4 vector4
Hmmm that’s still odd, I do it too and I’ve got perfectly good framerates. You should run through your code, see if anything else is causing the framelag, because I believe (!!! BIG EFFING EXCLAMATION MARKS !!!) it should be possible.
I need to update a 400x300 texture per frame. I do use SetPixels and I apply once all the texture has been updated. But it doesn’t work very well. That’s why I want an faster alternative like sending one byte per pixel to a shader instead of 32bits (or 24) per pixel.
My application uses a 1024x1024 texture, plots a bunch of pixels every frame and after that Apply’s, every single frame. No problems in framerates, even on slower computers. I don’t want to sound like a stubborn asshole, I really want to help you (either that or I’m terribly wrong )
If you don’t mind forcing OpenGL you can use native OpenGL calls to update the texture and it will be much faster. Or you can just update the portion of the texture that changes rather than updating the whole thing. If only a small portion changes then it will update quicker.
I’ve changed the texture from 400x300 to 512x512 (power of 2) and now it works MUCH faster. It’s seems to be a problem that it tries to convert the texture to a power of two every time one call the Apply.
Apply() causes a big performance hit; a Mac Pro with a 5870 is reduced to 55fps or so when doing nothing but setting one pixel and calling Apply() on a 1024x1024 texture every frame, and a Mac mini with a GMA 950 can only manage 26-27fps when doing the same thing. It uses hardly any CPU though, so it must be limited by bandwidth. Depending on what you’re doing, that speed may be acceptable, but it’s still a big hit. Going down to 256x256 for the texture makes the fps go up to 500 (Mac Pro) and 90 (Mac mini) though.
Apply() = “Call Apply to actually upload the changed pixels to the graphics card.” as the manual says.
So this copies the system memory copy of the texture (which you modify) to the graphics card - so is not a CPU hit so much as bandwidth indeed.
SetPixel must modify the system copy of the texture - it will not be fast if you want to modify say every pixel because just the fact that you are calling a function width*height times is a big CPU cost - thus to modify loads of pixels you could grab a copy of all pixels at program start - then each frame modify that array of Colors and call SetPixels.
However - Unity must convert every Color value into the correct format for the texture which must be not cheap in itself.