I'm creating a game that uses WebGL. Most of the time, everything is fine. However, for one particular call to gl.texImage2D with a 640x360 image, it takes 800ms rather than the usual 0.8ms.
What affects the performance of texImage2D?
All other gl.texImage2D with the same image size takes less than 1ms. The problematic gl.texImage2D is called after calling gl.texImage2D on a 100x100 texture.
Related
I have a 2D game in 4 directions, and I'm having problems with FPS (or GPU) because I have to draw a lot of textures.
I've read a lot about techniques to optimize performance, but I don't know what I can do anymore.
The main problem is that in some occasions I have about 200 creatures, where I have to draw his body (it is a single sprite) but also draw spells and other animations on his body. So, I think that is when it starts to give conflicts because the loop where I draw each creature, must change the textures for each creature, that is body>animation1>animation2>animation3 and this about 200 (creatures) times at 60 fps. Which lowers the fps to about 40-50.
Any suggestions?
This is how it looks:
The issue is probably - as you have already suggested - the constant switching between different textures. This is much slower than drawing the same number of sprites with the same texture.
To change this, consider putting all your textures into a single big texture. You then always draw that texture. This obviously would look quite wrong, so you also have to tell XNA which part of the texture you want to draw. For that, you can use the SourceRectangle parameter that can be passed to SpriteBatch.Draw(...). That way, you can always render the same texture but can still have different images on screen.
See also this answer about texture atlasses for more details.
I've written an app with an object detection model and process images when an object is detected. The problem I'm running into is when an object is detected with 99% confidence but the frame I'm processing is very blurry.
I've considered analyzing the frame and attempting to detect blurriness or detecting device movement and not analyzing frames when the device is moving a lot.
Do you have any other suggestions to only process un-blurry photos or solutions other than the ones I've proposed? Thanks
You might have issues detecting "movement" when for instance driving in car. In that case looking at something inside your car is not considered as movement while looking at something outside is (if it's not far away anyway). There can be many other cases for this.
I would start by checking if camera is in focus. It is not the same as checking if frame is blurry but it might be very close.
The other option I can think of is simply checking 2 or more sequential frames and see if they are relatively the same. To do something like that it is bast to define a grid for instance 16x16 on which you evaluate similar values. You would need to mipmap your photos which manually means resizing it by half till you get to 16x16 image (2000x1500 would become 1024x1024 -> 512x512 -> 256x256 ...). Then grab those 16x16 pixels and store them. Once you have enough frames (at least 2) you can start comparing these values. GPU is perfect for resizing but those 16x16 values are probably best evaluated on the CPU. What you need to do is basically find an average pixel difference in 2 sequential 16x16 buffers. Then use that to evaluate if detection should be enabled.
This procedure may still not be perfect but it should be relatively feasible from performance perspective. There may be some shortcuts as some tools maybe already do resizing so that you don't need to "halve" them manually. From theoretical perspective you are creating sectors and compute their average color. If all the sectors have almost same color between 2 or more frames there is a high chance the camera did not move in that time much and the image should not be blurry from movement. Still if camera is not in focus you can have multiple sequential frames that are exactly the same but in fact they are all blurry. Same happens if you detect phone movement.
I'm currently trying to reduce the memory size of my textures. I use texture packer already, as well as .pvr.cczs with either RGB565 or RGB5551. This, however, often leads to a huge, unacceptable reduction in texture quality.
Specifically, I got a spritesheet for the main character. In size it's roughly 4k*2.5k pixels. This is not really negotiable as we have lots of different animations and we need the character in a size acceptable for retina displays of ipads. So reducing the size of the character sprite would again result in huge reductions of quality when we use him in the scene.
So of course I'm trying to use 16 bit textures as often as possible. Using the above mentioned spritesheet as a 16 bit texture takes about 17 mb of memory. This is already a lot. As it's a spritesheet for a character, the texture needs transparency and therefor I need to use rgb5551 as colour depth. With only 1 bit for the alpha channel, the character just looks plain ugly. In fact, everything that needs alpha looks rather ugly with only 1 bit for the alpha channel.
However, if I'd use RGB8888 instead the spritesheet uses double the memory, around 34mb. Now imagine several characters in a scene and you'll end up with 100mb memory for characters alone. Add general overhead, sound, background, foreground, objects and UI to it and you'll end up with far too much memory. In fact, 100mb is "far too much memory" as far as I'm concerned.
I feel like I'm overlooking something in the whole process. Like something obvious I didn't do or something. RGB4444 is no solution either, it really looks unacceptably bad.
In short: How do I get acceptable texture quality including alpha channel for less than 100mb of memory? "Not at all"? Because that's kinda where it leads as far as I can see.
Split your main texture in 'per character/peranimation/per resolution' files. Use .pvr.ccz because they load faster (much faster, i've measured 8x faster on some devices'). If you are using TexturePacker, you should be able to eliminate most if not all artefacts from the 'pvr' conversion.
When running your scenes, preload only the 'next' posture/stance/combat that you know will need. Experiment with asynchronous loading, with completion block, to signal when the texture is available for use. Dump your unused texture as fast as you can. This will tend to keep the memory requirement flatish at a much lower clip than if you load all animations at once.
Finally, do you really need 15 frames for all these animations ? I get away with as few as 5 frames for some of the animations (idle, asleep, others too). TexturePacker takes of symetrical animations around a certain frame, just points frames midPoint +1 ... midPoint + N to MidPoint -N ... MidPoint -1.
Imagine, I have a picture (Texture2D in XNA) scalled 256x256, but sometimes I want to use it with a size of 64x64 in the application.
I learned on regular Windows Forms or WPF applications, when I have to resize an image, I should store it in a field so that I have to do the resizing only once. It would massively slow down the performance when resizing in the game loop over and over again.
Do I have to that in XNA too? I didn't find anything about it. I can resize the texture when drawing with the spritebatch but that would be the same as just explained. I would resize the texture every frame and not only once in the field. I don't even know how to resize a texture2d without spritebatch in XNA.
There is no reason to create a resized copy of the original texture. Just draw it at whatever size you want. Drawing a texture at a different size than the original image is essentially free on modern graphics hardware.
With modern hardware, you rarely need to manually resize textures, the hardware does all that automatically. However, you must make sure you are using mipmapping, else the result will be very aliased.
If mipmapping is enabled on your current texture, it will be resized when it is loaded. Just make sure trilinear filtering render state is enabled and draw whatever size you need and it will automatically use a mix of the best resized textures.
When we draw 300 sprites on the iPad using opengl 2.0 with glEnable(GL_BLEND) (which we need because the sprites need tranparency and alpha blending) we get an framerate of around 40. But when we disable the blending we get an framerate of 60.
Now is (alpha) blending really that costly or are we doing something wrong?
Thanks for your time,
Richard.
Alpha blending really IS that costly. The problem is that you can solve a lot of overdraw issues (something the PowerVR is very good at) by using Z-Buffering. It can save a tonne of memory bandwidth by not writing to the Z-buffer and draw buffer.
The moment you start alpha blending then you instantly need to read from the frame buffer blend and then write back (Read-Modify-Write or RMW). Effectively if you have 10 overlapping sprites then they need to be drawn 10 times where as with a Z-Buffered (again ish .. the PowerVR is odd on that front) un-blended system you only actually need to draw ONE pixel. So in that edge case you have saved a tenth of the WRITE bandwidth by simply not alpha blending. And don't forget there is also the read from the frame buffer that needs to take place for alpha blending on top of that.
As I alluded to it does get more complicated when Z-buffering is involved. Mainly because a Z-buffer requires a read, a compare and potentially a write but using Z-buffering you can discard pixels much earlier in the pipeline meaning you can save even more processing time. Couple that with the tiling system the PowerVR still, I believe, uses and your main concern is that RMW bandwidth loss to alpha blending.
It is really that costly. It requires a read-modify-write for each pixel. the modify operation is of the form
fragment * alpha + previous * (1 - alpha)
Count the number of pixels you do that on, and you'll soon realize you do a lot of math (and require more memory bandwidth). It all depends on how big your sprites are, but it is not surprising to slow down heavily when you have a lot of overdraw.