![]() |
|
Bitmap region vs Transforms for a camera |
Rodolfo Lam
Member #16,045
August 2015
|
So I was looking at the wiki for examples of a camera implementation for Allegro 5.0.10 (yes, I know 5.1 has now a camera somewhere around) and found two different options, drawing a bitmap region to the screen and calculate myself the camera position, or using an ALLEGRO_TRANSFORM to move the display to the position where the camera must be. But would like to have advice on which method could be better in the long term
|
Thomas Fjellstrom
Member #476
June 2000
![]() |
Well, I think for a camera, you'd keep track of the camera position and only draw the bits of your level/game that fit in the current screen area. You can use transforms to store your camera position, but its probably easier to just use some regular old variables[1] to track the position. I'm imagining you have a 2d map, maybe a side scroller or a tile map. In these cases you don't really want to do any bitmap region magic or transforms to move the drawing around because you can just take the camera position and figure out the current bits of the map to draw from that (from the camera origin minus half the screen, to camera origin plus half the screen, or something similar). References
-- |
Rodolfo Lam
Member #16,045
August 2015
|
Seems pretty reasonable... The solution I right now have for the tilemap is drawing everything (all the layers, the entire map) to the screen directly, so the amount of offscreen objects is huge and will definitely not scale with even bigger maps. Wanted to get away with not translating the world coords to screen coords with the transform
|
Mark Oates
Member #1,146
March 2001
![]() |
Rodolfo Lam said: tilemap is drawing everything (all the layers, the entire map) to the screen directly Yikes. Yea, that'll cost ya. I much prefer to use the transforms. It can be kinda tricky, but once your camera is setup it's not difficult to translate both to and from world and camera coordinates. You get the advantage of having zoom and rotation which is nice to have in your pocket, and you won't have pos-camera_x, pos-camer_y cluttering all your drawing code. Overall, you get more control, simplicity, and power if you choose to use transforms, but there is a learning curve. -- |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Mark Oates said: Yikes. Yea, that'll cost ya. Depends. It should be fine if you use tile sheets and bitmap holding. I don't really see how a transform is any better than just clipping like I suggested. Using transforms for translation implies you're drawing everything unless you also handle not drawing around where the transform is (which needs you to keep track of the translation separately...) But yeah, if you want things like simple zoom and rotation, a transform is the way to go, but i think you still want to store the camera coordinates separately and then just "translate" to that in the transform. -- |
Mark Oates
Member #1,146
March 2001
![]() |
Thomas Fjellstrom said: Depends. It should be fine if you use tile sheets and bitmap holding. Which I didn't But even with bitmap holding and sprite sheets, I've run into (extremer) cases where performance took a hit, (probably because you're still sending a lot of drawing calls, and allegro is building transforms for each al_draw_bitmap call on the backend). I think the ultimate optimization is making the tilemap one large ALLEGRO_VERTEX tile_map_prim[], every tile being 2 triangles, and the texture is the tile atlas. That's my next pet project, really looking forward to trying that out. Quote: I don't really see how a transform is any better than just clipping like I suggested. Using transforms for translation implies you're drawing everything unless you also handle not drawing around where the transform is (which needs you to keep track of the translation separately...) Not separately, you can extract them from the transform. If your camera has a camera_width and camera_height, you can al_transform_coordinates() on camera_x, camera_y, camera_x+camera_width, and camera_y+camera_hight. That'll give you your clipping rectangle in world coordinates. If you then divide each coordinate by 16 (or whatever your tile size is), then you get the row/column of the tilemap. -- |
Chris Katko
Member #1,881
January 2002
![]() |
I'm reading this tutorial as we speak. -----sig: |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Mark Oates said: But even with bitmap holding and sprite sheets, I've run into (extremer) cases where performance took a hit, (probably because you're still sending a lot of drawing calls, and allegro is building transforms for each al_draw_bitmap call on the backend). I think the ultimate optimization is making the tilemap one large ALLEGRO_VERTEX tile_map_prim[], every tile being 2 triangles, and the texture is the tile atlas. That's my next pet project, really looking forward to trying that out. Yeah, your best bet is to draw the geometry in one go. Bitmap holding is supposed to do that, as long as you only use the same actual texture for ALL calls. Of course using a single batch for all of the map is going to need to use the same texture regardless. Though I've been experimenting with setting up multiple texture atlases, and having the geometry data send in the texture id to pick the correct one. If more things supported Texture Arrays, this would be so much simpler, but its not a 100% supported thing yet. Quote: Not separately, you can extract them from the transform. If your camera has a camera_width and camera_height, you can al_transform_coordinates() on camera_x, camera_y, camera_x+camera_width, and camera_y+camera_hight. That'll give you your clipping rectangle in world coordinates. If you then divide each coordinate by 16 (or whatever your tile size is), then you get the row/column of the tilemap. You could but I'm not sure how that's simpler or better -- |
Mark Oates
Member #1,146
March 2001
![]() |
Thomas Fjellstrom said: Though I've been experimenting with setting up multiple texture atlases, and having the geometry data send in the texture id to pick the correct one. If more things supported Texture Arrays, this would be so much simpler, but its not a 100% supported thing yet. That's cool. I've ended up just using a custom ALLEGRO_VERTEX that includes the 3D normal for, well, everything 3D. It's just use it by default now. -- |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Mark Oates said: I've ended up just using a custom ALLEGRO_VERTEX that includes the 3D normal for, well, everything 3D. It's just use it by default now. What are you using it for? Isn't it normally for doing lighting and stuff like that? -- |
Mark Oates
Member #1,146
March 2001
![]() |
Yea, lighting. And anything for shader materials like reflectance, skybox, specular shading, normal maps, etc. use a normal. typedef struct { float x, y, z; float u, v; ALLEGRO_COLOR color; float nx, ny, nz; } ALLEGRO_VERTEX_WITH_NORMAL; I also meant to say I'm using ALLEGRO_PRIM_TEX_COORD instead of allegro's default ALLEGRO_PRIM_TEX_COORD_PIXEL. So UV coordinates are in 0.0 to 1.0 rather than texture_width or texture_height. Here's what my vertex declaration looks like. ALLEGRO_VERTEX_ELEMENT elems[] = { {ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_3, offsetof(ALLEGRO_VERTEX_WITH_NORMAL, x)}, {ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(ALLEGRO_VERTEX_WITH_NORMAL, u)}, {ALLEGRO_PRIM_COLOR_ATTR, 0, offsetof(ALLEGRO_VERTEX_WITH_NORMAL, color)}, {ALLEGRO_PRIM_USER_ATTR, ALLEGRO_PRIM_FLOAT_3, offsetof(ALLEGRO_VERTEX_WITH_NORMAL, nx)}, {0, 0, 0} }; vertex_declaration = al_create_vertex_decl(elems, sizeof(ALLEGRO_VERTEX_WITH_NORMAL));
-- |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Yeah, thats more or less what I have. ALLEGRO_VERTEX_ELEMENT elements[] = { { ALLEGRO_PRIM_POSITION, ALLEGRO_PRIM_FLOAT_3, offsetof(CustomVertex, pos) }, { ALLEGRO_PRIM_TEX_COORD, ALLEGRO_PRIM_FLOAT_2, offsetof(CustomVertex, txcoord) }, { ALLEGRO_PRIM_USER_ATTR, ALLEGRO_PRIM_FLOAT_1, offsetof(CustomVertex, tx_page) }, { ALLEGRO_PRIM_COLOR_ATTR, ALLEGRO_PRIM_FLOAT_4, offsetof(CustomVertex, color) }, { 0, 0, 0 } };
-- |
|