Can I create a HUGE bitmap and then display it?

BlitzMax Forums/BlitzMax Programming/Can I create a HUGE bitmap and then display it?

SofaKng(Posted 2007) [#1]
Can I create a huge bitmap/texture (5000x3000 pixels @ ARGB), draw on it and then display it? (eg. TPixMap?)

I know that video card textures are usually limited to 2096x2096 but I'm hoping to store my huge texture/bitmap in system memory and then upload only parts of it to the video card.

The keys parts of what I'm trying to do are:

1) Storing a huge bitmap (ARGB format)
2) Drawing on it (changing alpha values mostly)
3) Display part of the bitmap to the screen

Every so-often I will need to change the huge bitmap (alpha values).

Thanks for any help!


Dreamora(Posted 2007) [#2]
With pixmaps you can, images will not work with that size.
You don't need to upload it, you can draw pixmaps or paste parts of the pixmap to a different pixmap and only draw that pixmap.

Problem is the massive size of it 58 MB RAM usage.

BUT: you can not draw on anything. BM has no buffer support.
What you would have to do is to manually modify pixel after pixel or paste a different pixmap into this pixmap. Alternative you access the byte ptr of the pixmap and modify it "in data" directly without all "looking nice but beeing slower" wrapping functions.

Main problem is that Alpha does not work when drawing pixmaps. Only Images have Alpha as only Images are 3D objects, pixmaps are copied directly into the backbuffer, not rendered. No alpha support therefor.


Sounds like you want to use it for a worms like terrain and use the alpha to destroy pixels?
If you plan to use it for something like this, you might consider using a more tilemap like approach to restrict the "modification access size" drastically to 1-X tiles instead of 58MB of data. That would drastically reduce the upload time as well as you only upload modified tiles, not a whole screen full of data, which will not work in realtime. and upload sadly is needed if you plan to use image alpha.


ImaginaryHuman(Posted 2007) [#3]
There's no problem with you creating a large pixmap, it can be pretty much as large as you like. The fastest way to modify pixels in it, even if it's just the alpha values, is to read the whole pixel using an Int Pointer, based on the PixmapPtr(), changing the component that you want to modify, then writing it back to the same pointer. Alternatively you can use ReadPixmap and WritePixmap (or is it ReadPixel and WritePixel).

Like Dreamora says, it is going to consume quite a few megs of ram to keep a pixmap that large - but hey, that's your decision, and on today's machines people tend to have a lot more ram than they used to.

What you then want to do is treat your pixmap like a pool of image data (for example, similar to the megatexture system which is becoming popular right now) - where you spool small sections of image from your pixmap into images in video ram on an as-needed basis, for display purposes only. The fastest way to do that is create empty textures and then upload the texture data, using the appropriate values to read a window in your pixmap. You should not need to be grabbing whole sections of pixmap and pasting it back into a pixmap just to get the window functionality.

Then when you render your display you are pulling from the images that you've uploaded previously, reusing those that were on-screen in the last frame, and those which you just pre-uploaded for the areas of screen that are just off the display. Then you only need a little more than 1 screen's worth of images consuming video ram. It's much faster to draw an image, and to re-use an image that you uploaded some time previously, rather than to upload whole pixmaps of data every frame for the whole display. You will still take a performance hit for transferring pixmap data to the texture(s) but nowhere near as much as drawing entire pixmaps. And then you can render with alpha blending.


SofaKng(Posted 2007) [#4]
Thanks for the replies!!

@Dreamora: Can you explain the tiling idea a little more? I'd like to create my terrain dynamically in a process like this:

1) Create outline of terrain
2) Fill terrain with mountain image
3) Draw tunnels (eg. another image) inside of terrain
4) Place grass (another image) on top of terrain

The end result would be my terrain (and would be very huge, perhaps 5000x3000 to fill a few screens of 1920x1200, but would scale down for lower resolutions)

I don't think tiling would really work because no two sections of my terrain would be the same...

@ImaginaryHuman: That is the exact idea I had for streaming textures. (eg. the video card would only contain one screen worth of data [plus a little more] and as the user scrolled the map new texture data would be uploaded, thus drastically reducing the amount of video ram required).

How can I create textures on the video card? (do I need D3D/OGL specific calls?)

How do I upload data from my pixmap to the textures?

Also, can I use the built-in per-pixel collision with a pixmap?

Thanks again for your help!


ImaginaryHuman(Posted 2007) [#5]
You could use the helper functions that Blitz provides to convert a pixmap to a texture, returning a texture handle, or do your own direct GL calls. No idea about DX.

Look at the sourcecode for those helper functions for an idea how to do it.

You cannot use collision detection with pixmaps, I'm fairly sure it's image based. Nevertheless I would code your own collision detection which uses the pixmap, so you can read from it very quickly (compared to transferring data from the backbuffer).

Also for your update sequence, where you're uploading newly required images, considering spreading out/staggering the number of image pieces that need to be uploaded per frame, based on how many pixels the world has scrolled, so that you aren't uploading lots at a time - ie just one or two uploads per frame.


Dreamora(Posted 2007) [#6]
Tiling this massive sizes is what is done in other hardware accelerated 2D games as well.

The best known example most likely is Clonks in its newer incarnations.
The tiling there is done for the simple reason to reduce the amount of image data needed to modify the terrain dynamically.

If you do not need it for dynamic alteration at runtime, you could easily create a massive pixmap for your terrain and paste in object after object.

When you are done, create textures out of subsections (256x256 or 512x512 I would suggest for performance reasons on slower / capped cards with only 64bit bus ie 70% of all users) and use those textures to draw, as textures are 10 times faster and more, depending on the hardware.


if you need dynamic modification, then you do the same steps as so far but you would use subsections far smaller. 64x64 or 128x128, to make the amount of data you need to reupload smaller which makes the whole dynamic update and modification of the images seriously faster. (the smaller the section you download and upload, the less time the card will be locked and the less rendertime lost as a general rule)


ImaginaryHuman(Posted 2007) [#7]
I agree. Also as you scroll the view of the game world you should be progressively uploading the `tile` sections which are about to come into view - rather than upload a whole horizontal and/or vertical strip of tiles all in one frame you should spread the upload out over the number of frames it takes before they become visible, so that with slower scrolling you upload less frequently and faster scrolling it adapts to the scroll speed. Then you are only uploading a few tiles per frame, and by the time you've scrolled say 64 pixels and are ready to see the newly uploaded tiles coming into view, you might've taken 16 frames to upload them, which is better than creating a sudden jerk due to a mass upload.

I also recommend keeping a fairly decent sized `extra` number of tiles in video ram that have been `used recently`, which are further away from the current camera view but which were perhaps uploaded not long ago. While you're still within a given megabyte limit, you can just let the uploaded tiles accumulate into new image sections so that when you change scroll direction and go back where you just came from you don't have to start uploading new stuff. OR, you could start uploading new stuff but at the far outer edges of the parts which are cached, meaning you have much more time to upload them before you need to start worrying about not having time to get them all updated.

Also you have to ask yourself how much of your landscape will likely get modified and how much of it will likely stay unchanged. If there are only going to be a few modifications then the unmodified areas could use repeating textures versus per-pixel state.


MGE(Posted 2007) [#8]
As far as rendering goes, wouldn't the 3D card only keep in Vram what it needs, in basically a FIFO style? Bmax uses managed resources so in theory you should be able to load everything in system memory using normal image load functions and the gpu will cache as needed. ? ? ?


Dreamora(Posted 2007) [#9]
No it wouldn't
A card does not keep anything, it is like RAM.

On DX Side, DX itself manages the needed stuff in VRAM according its rendering.
In OpenGL you must do it or BM does it by reuploading images from pixmaps as needed.

But in both cases, we are not talking about keeping stuff in VRAM.

We are talking about what you need to render!

If you use larger images, you potentially risk to keep a large image in VRAM and render it even if you only need a small part on a corner of that image. That effect is reduced with smaller images where only a subsection of the image is used.

As well as mentioned above: most users don't have XX GB bandwidth on their video cards, so its a wise decision not to block it with 90% of image data you do not need (-> large images).
Especially as we are talking of 2D here. If you do 2D, follow common 2D principles. Might be that current cards are very capable in 3D, but believe me, thanks to their total incapability on the over draw end, you will bring them down extremely fast with 2D if you don't use all the tricks known from pure 2D!


ImaginaryHuman(Posted 2007) [#10]
I agree. You can define priorities in GL so that when it runs out of video ram it starts spooling textures off to main memory, but you do NOT want that to happen, it is extraordinarily slow and will totally cripple your game.