Render nodes in single drawing pass with spritekit? - drawing

As I was looking around for information about spritekit textures, and I stumbled upon this quote:
If all of the children of a node use the same blend mode and texture atlas, then Sprite Kit can usually draw these sprites in a single drawing pass. On the other hand, if the children are organized so that the drawing mode changes for each new sprite, then Sprite Kit might perform as one drawing pass per sprite, which is quite inefficient.
But check this out:
Tiles with same texture (I assure you it's a texture, not just a color)
Tiles with their own texture
The draw count has a difference of 40, although all of the textures used came from the same atlas.
Am I interpreting the word 'atlas' wrong?
This is where I store my images:
Is my example a 'texture atlas,' or is the definition of 'atlas' here a single .png that contains all the images needed, and individual tiles are sliced from it?
Or is the problem probably in how I am loading/something else?
Thanks!

The problem here is most likely because of the node graph itself. Say you have 100 sprites as children of the scene, with not sub-children of their own, and they all use textures from the same atlas and default blend modes, then Sprite Kit will batch-draw these 100 sprites in a single draw call.
However if these tile sprites have children of their own, perhaps shape or label nodes for debugging, then this will "interrupt" the batch drawing operation.
Check your node graph. Make sure all tile sprites are children of the same parent, and have no children of their own, use the same blend modes and textures from the same atlas. Then batch drawing will definitely work.
If that doesn't work, verify that the tiles.atlas folder is correctly converted to a texture atlas in the bundle. If you open the compiled app bundle you should find a folder named 'tiles.atlasc' with a plist and one or more png files in it, containing all individual images of the folder. Furthermore none of these individual images should appear in the bundle - if they are added to the bundle as individual files using the same names as in the atlas, then Sprite Kit will default to loading the individual image files rather than obtaining them from the texture atlas.

Related

SDL: Combination of Tile sets and layered surfaces does not work

I would like to create a modularly designed game using SDL, but yet I fail to get my sprites displayed. Precisely, I am trying to implement tile sets, which are are bunch of equally sized sprites collected in one single PNG file (in my case).
My data structure should hold an array of sprites available in the tile set which can then be drawn with a method, like draw(Tile *, Position, Layer);.
As indicated, I want to feature multiple layers of surfaces to later on implement multiple independent background layers and a foreground layer. Similarly, I have an array of layers that are blitted onto my screen surface (created with SDL_SetVideoMode) in a pre-defined order.
However, I don't get what's going wrong in my code.
While a tile set is loaded, I can successfully blit the currently loaded tile onto a layer surface, like in this snippet:
this->graphic = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_SRCALPHA,
tile_widths, tile_heights, bit_depth,
rmask, gmask, bmask, amask);
SDL_BlitSurface(tileset_graphic, &tile_position, this->graphic, nullptr);
SDL_BlitSurface(tileset_graphic, &tile_position,
((VideoController::get_instance())->layers)[0], &tile_position);
In the first line, I try to blit the part of the tileset_graphic, that corresponds to a sprite, to an SDL_Surface * that is held by my Tile structure to be used later on.
However, I cannot use this surface to blit onto a layer.
The second (test) statement just copies the considered region of the tileset_graphic to the most bottom of my layers. Furthermore, I have performed several test commands in my main method.
My findings during testing:
I can blit a tileset_graphic piece to a layer and it is correctly shown (see above)
I can blit a Tile directly onto the screen:
SDL_BlitSurface(
tile->graphic,
nullptr,
(VideoController::the_instance)->screen,
&relative_position);
However, I cannot blit a Tile onto a layer:
SDL_BlitSurface(
tile->graphic,
nullptr,
(VideoController::the_instance)->layers[0],
&relative_position);
To be more precise, when I blit the whole tileset_graphic for testing and then blit a Tile onto a region that is already occupied due to this test, I can partly see my sprite. But then again, I have absolutely no clue why this is the case...
Summary:
I try to blit several SDL_Surfaces onto another, but seem to fail only by trying this (desired) chain of surfaces:
graphic --> layer --> screen
Does anyone have a clue what may go wrong, or is able to tell me which additional information is needed by you guys?
EDIT
I was able to find that blitting on the initialized (SDL_CreateRGBSurface), but still "untouched" layer surfaces seems to fail somehow. When I use SDL_FillRect on my layer surfaces before blitting a tile onto the layer, it is displayed correctly. However, I am losing transparency of layers this way...
I figured out the solution.
I had to explicitly reset the SDL_SRCALPHA flag of my graphic by doing
SDL_SetAlpha(this->graphic, 0, SDL_ALPHA_OPAQUE );

What exactly is a buffer in OpenGL, and how can I use multiple ones to my advantage?

Not long ago, I tried out a program from an OpenGL guidebook that was said to be double buffered; it displayed a spinning rectangle on the screen. Unfortunately, I don't have the book anymore, and I haven't found a clear, straightforward definition of what a buffer is in general. My guess is that it is a "place" to draw things, where using a lot could be like layering?
If that is the case, I am wondering if I can use multiple buffers to my advantage for a polygon clipping program. I have a nice little window that allows the user to draw polygons on the screen, plus a utility to drag and draw a selection box over the polygons. When the user has drawn the selection rectangle and lets go of the mouse, the polygons will be clipped based on the rectangle boundaries.
That is doable enough, but I also want the user to be able to start over: when the escape key is pressed, the clip box should disappear, and the original polygons should be restored. Since I am doing things pixel-by-pixel, it seems very difficult to figure out how to change the rectangle pixel colors back to either black like the background or the color of a particular polygon, depending on where they were drawn (unless I find a way to save the colors when each polygon pixel is drawn, but that seems overboard). I was wondering if it would help to give the rectangle its own buffer, in the hopes that it would act like a sort of transparent layer that could easily be cleared off (?) Is this the way buffers can be used, or do I need to find another solution?
OpenGL does know multiple kinds of buffers:
Framebuffers: Portions of memory to which drawing operations are directed changing pixel values in the buffer. OpenGL by default has on-screen buffers, which can be split into a front and a backbuffer, where drawing operations happen invisible on the backbuffer and are swapped to the front when finishes. In addition to that OpenGL uses a depth buffer for depth testing Z sort implementation, a stencil buffer used to limit rendering to cut-out (=stencil) like selected portions of the framebuffer. There used to be auxiliary and accumulation buffers. However those have been superseeded by so called framebuffer objects, which are user created object, combining several textures or renderbuffers into new framebuffers which can be rendered to.
Renderbuffers: User created render targets, to be attached to framebuffer objects.
Buffer Objects (Vertex and Pixel): User defined data storage. Used for geometry and image data.
Textures: Textures are sort of buffers, i.e. they hold data, which can be sources in drawing operations
The usual approach with OpenGL is to rerender the whole scene whenever something changes. If you want to save those drawing operations you can copy the contents of the framebuffer to a texture and then just draw that texture to a single quad and overdraw it with your selection rubberband rectangle.

Role of CCSpriteBatchNode

The idea behind a CCSpriteBatchNode is to render a texture once for many sprites which should improve performance instead of treating each sprite as a different texture.
However, I'm confused how there is a benefit to using this as opposed to using only a single texture atlas. If you create a texture with this:
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:#"gameTexture.plist"];
and then every single image you use for sprites is pulled using frame methods, then aren't all your images using the same single rendered texture, even though a batch node was never introduced?
Of course, you can use a batchnode in combination with a texture atlas, but how is this an actual gain in performance? If you do not use a batchnode, is it rendering the texture multiple times, even though it is cached?
using the same texture you are not changing texture at each call, but you still are rendering all the sprite in different glBegin and Ends, using the CCSpriteBatchNode will make sure that every sprite in it is rendered within the same call
The performance improvement simple comes from the reduced number of OpenGL calls. If you don't use a SpriteBatchNode, your sprites will come from one texture yes but they will all make seperate OpenGL calls. The batch node object contains code to collect all of it's children and make just a single call, this is why your sprites must be a child of the same batch node to get the performance boost.
0 batch node + 100 sprites = 100 OpenGL calls.
1 batch node + 100 sprites (children of this batch node) = 1 OpenGL call.
If you're really interested have a look in CCSpriteBatchNode.m

How to use different independent overlapping layers in opengl?

I want to know if it is possible to have multiple layers which can be manipulated independently and displayed in an overlapping manner.
Here is what I want to do. I'm implemeting a Turtle Graphics API. I want to animate the turtle movement. I was wondering if i could have all the graphics in one layer and the turtle (which I'm representing using a small isosceles triangle) alone in another layer so that I can erase the turtle by clearing this layer and without affecting the graphics layer and redraw the turtle in another location/orientation on the turtle plane.
OpenGL is not a scene graph.
OpenGL is (generally) not a classic 2D framebuffer where you want to try to minimize redraws. With OpenGL you'll generally be redrawing the entire scene each frame after clearing the depth and color buffers.
You have several options:
1) Disable the depth buffer/depth check and render your layers back to front.
2) Make sure each of your layers has an appropriate Z coordinate and render them in whatever order, letting the Z buffer take care of getting the layering right. Won't work if your layers are translucent.
3) Render your turtle path to a texture via whatever method you feel like supporting (glCopyPixels(), PBOs, FBOs, cairo). Render a screen-sized textured quad and your turtle on top.
4) Redraw your turtle path in full each frame, oldest point first. Shouldn't be slow unless you have line count in the hundreds of thousands. Make sure to use vertex arrays or VBOs.

Sprite Sheet With OpenGL and SDL

I been working in a new game, and finally reached the point where I started to code the motion of my main character but I have a doubt about how do that.
Previously, I make two games in Allegro, so the spritesheets are kind of easy to implement, because I establish the frame and position on the image, and save every frame in a different bitmap, but I know that do that with OpenGL it's not neccesary and cost a little bit more.
So, I been thinking in how save my spritesheet and used in my program and I have only one idea.
I loaded the image and transformed in a texture, in my function that help me animate I simply grab a portion of the texture to draw instead of store every single texture in my program.
This is the best way to do that?
Thanks beforehand for the help.
You're on the right track.
Things to consider:
leave enough dead space around each sprite so that the video card does not blend in texels from adjacent sprites at small scales.
set texture min/mag filtering appropriately. GL_NEAREST is OK if you're going for the blocky look.
if you want to be fancy and save some texture memory, there's no reason that the sprites have to be laid out in a regular grid. Smaller sprites can be packed closer in the texture.
if your sprites are being rendered from 3D models, you could output normal & displacement maps from the model into another texture, then combine them in a fragment shader for some awesome lighting and self-shadowing.
You got the right idea, if you have a bunch of sprites it is much better to just stick them all in one big textures. Just draw your sprites as textured quads whose texture coordinates index into the frame of the sprite. You can do a few optimizations, but most of them revolve around trying to get the most out of your texture memory and packing the sprites closely together with out blending issues.
I know that do that with OpenGL it's not neccesary and cost a little bit more.
Why not? There are no real downsides to putting a lot of sprites into a single texture. All you need to do is change the texture coordinates to pick the region in question out of the texture.