Drawing a smaller texture on a larger OpenGL texture on iPhone - iphone

I am very new to OpenGL and this is what my goal is...
Load a texture from an image.
Load another texture which is much smaller than the first one.
Now keep drawing the smaller texture on the larger one on some chain of events, like painting on the larger texture.
Can somebody point me to some material which might help do this?
I looked into some book, but they are mostly into 3D animation kind of stuff and I do not want to go to that dept, I just need the texture manipulation stuff in 2D.
I am following the example...
http://developer.apple.com/library/ios/#samplecode/GLImageProcessing/index.html
For my experiments, I am modifying the drawGL() function in the example to do this...
First time when drawGL() is called, nothing changes, so that the full texture is drawn on the view.
In the next draw onwards, I change the flipquad array to...
V2fT2f flipquad[4] = {
{ 0, .5, 0, .5 },
{ .5, .5, .5, .5 },
{ 0, 1, 0, 0 },
{ .5, 1, .5, 0 },
};
So that only the top left quadrant is modified. This works fine on the simulator, but when I run it on device, except for the top left quadrant the rest of the view flickers, that is every alternate draw makes it black!

Others may find this sample from Apple useful:
GLPaint
Hope it helps!

Draw the large texture into the frame buffer,
Paint on it with the small texture as you wish,
Call glCopyTexImage2D or glCopyTexSubImage2D to copy the painted texture from the frame buffer back to the texture object.
The above method will work with OpenGL 1.1 or higher. However it may be not as efficient as you want. Possible optimization (depends on you OpenGL version) is to create an off-screen frame buffer bound directly to the large texture and paint there. See glGenFramebuffers.

Related

Tiling an image that is part of a texture atlas

I'm using Cocos2D. What is the most efficient way to tile an image when it's part of a texture atlas that's been generated using Texture Packer. I have an image that is 10 x 320 and I want to tile it to fill the screen.
I've used this code before for tiling images
bgHolder = [CCSprite spriteWithFile:#"bg.png" rect:CGRectMake(0, 0, 700, 300*155)];
ccTexParams params = {GL_LINEAR,GL_LINEAR,GL_REPEAT,GL_REPEAT};
[bgHolder.texture setTexParameters:&params];
[self addChild:bgHolder];
but I don't think I can use this approach when the image I want to tile isn't square and is only a small part of the over al texture.
Chaining a bunch of CCSprites seems pretty inefficient to me so I'm hoping there is a better way.
Use one sprite per tile. That's the way to do it. You should use sprite batching to keep the number of draw calls to 1. Rendering 48 sprites is not much worse than rendering one 480x320 sprite when using sprite batching.

Set UIImage as a background for 2D OpenGL ES on iPhone

once again I'm asking for help after quite a bit of research.
I need to create a view where the user can place an image to the background and draw lines/dots(touch events) on top of it and then save the "sketch" by pressing save button.
So after research I decide to pick up this code and build the thing on top of it because it already does half of what I want(it does the drawing).
The sample I have is using OpenGL for drawing and basically I don't care if it is OpenGL or CoreGraphics as soon as it does it.
The problem I have is how to put an image as a background of EAGLView I have in this sample code. My research gave me only suggestions for OpenGL experienced developers but not the working code snippet/solution.
If somebody can help me with this I would be very appreciate.
What I need is just a sample of how to put a UIImage to EAGLView background so then the user can draw(already have the code) on top of it and save the result.
One usually doesn't mix OpenGL with ordinary UI... views. Also drawing a background image using OpenGL is trivial:
First you need to load the Image into a texture. In GLPaint a image file is loaded as brush-texture
https://github.com/omeryavuz/glpaint/blob/master/Classes/PaintingView.m function initWithCoder
To draw a background, the first thing you draw after framebuffer clear is a fullscreen quad with that texture. If you build upong GLPaint, then the projection and modelview matrix and the vertex array state are set properly already. So it boils down to
GLfloat vert[] = {0,0, frame.size.width,0, frame.size.width,frame.size.height, 0,frame.size.height};
GLfloat tex[] = {0,0, 1,0, 1,1, 0,1};
GLuint indexes[] = {0, 1, 2, 2, 3, 0};
glBindTexture(GL_TEXTURE_2D, backgroundTexture);
glEnable(GL_TEXTURE_2D);
glVertexPointer(2, GL_FLOAT, 0, vert);
glTexCoordPointer(2, GL_FLOAT, 0, tex);
glDrawElements(GL_TRIANGLES, 2, GL_UNSIGNED_INT, indexes);
In PaintingView.m, on line 89, set eaglLayer.opaque = NO;.
In your viewController, put a UIImageView or whatever behind the paintingView.
Note: This will probably decrese performance.
Note: It might not initially work; the OpenGL layer may overwrite itself with some sort of default background color before rendering a frame. EDIT: Line 304 in PaintingView.m: Try setting the color to glClearColor(1.0, 1.0, 1.0, 0.0);. I am not sure this works, and don't have time to test this. If it doesn't work, wait till Brad Larson comes around, sees your question, and answers it perfectly ;)

iPhone game 2d shadows

We're in the process of creating an iPhone game using cocos2d. We're trying to layer several sprites on top of each other and have them cast shadows.
Right now the shadows are rendered as sprites which works fine for the most part. But we only want the shadows to hit the closest layer.
I've made an image that hopefully explains what we're trying to accomplish:
And here's what we have at the moment:
Basically we want the sprite to only render the part of the shadow that is at the same depth as the z-buffer.
We've played around with glDepthFunc and GL_DEPTH_TEST but nothing seems to work.
Here's how we're rendering the shadow sprite (subclassed CCSprite):
- (void)draw {
glDisable( GL_BLEND );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glDepthMask( GL_FALSE );
[super draw];
glDepthMask( GL_TRUE );
glDisable( GL_DEPTH_TEST );
glEnable( GL_BLEND );
}
The GL_BLEND calls are only there so we can see the sprite at all times.
All sprites that aren't shadows use glDepthMask( GL_TRUE ) and we're clearing the depth buffer on each frame.
Any help would be much appreciated!
glDepthFunc(GL_LESS)
is actually the default value; it means "draw the pixel only if the thing currently in the depth buffer is further away". If you wanted exactly equal you'd use glDepthFunc(GL_EQUAL), but in practice you'll get all sorts of rounding oddities if you do that.
Assuming you're able to use depth values for this purpose, if you have ten objects then I'd suggest you:
set glClearDepth to 0 before you glClear; this'll fill the depth buffer with the nearest storable value so that with normal depth buffering nothing else would be drawn.
disable the depth and draw the shadows such as they're supposed to fall on the back plane; at this point your depth buffer will still be full of the nearest possible value.
enable the depth test but set glDepthFunc to GL_ALWAYS. Then draw all your solid rectangles in back to front order with their depth values set appropriately.
set glDepthFunc to GL_LESS and draw the shadows that are meant to fall on other sprites, each positioned further back than the sprite they're associated with but in front of the sprite behind.
By the time you get to step 4, you'll have correct depth information everywhere a sprite was drawn and you'll have the closest possible value set wherever the background plane was. So normal depth testing will work on the intermediate shadows — they'll draw on top of anything drawn in step 3 but not on top of anything drawn in step 2.
You're sort of using the depth buffer as a surrogate stencil, which the older iPhones don't support.
If you can't afford to use the depth buffer for this task then all I can think of is projecting the shadows as textures in the second texture unit, using the first for a mask texture (or not if you're actually drawing rectangles, but I guess you're probably not) and doing one rendering pass per sprite per shadow that falls upon it. Is that a passable solution?

Positioning elements in 2D space with OpenGL ES

In my spare time I like to play around with game development on the iPhone with OpenGL ES. I'm throwing together a small 2D side-scroller demo for fun, and I'm relatively new to OpenGL, and I wanted to get some more experienced developers' input on this.
So here is my question: does it make sense to specify the vertices of each 2D element in model space, then translate each element to it's final view space each time a frame is drawn?
For example, say I have a set of blocks (squares) that make up the ground in my side-scroller. Each square is defined as:
const GLfloat squareVertices[] = {
-1.0, 1.0, -6.0, // Top left
-1.0, -1.0, -6.0, // Bottom left
1.0, -1.0, -6.0, // Bottom right
1.0, 1.0, -6.0 // Top right
}
Say I have 10 of these squares that I need to draw together as the ground for the next frame. Should I do something like this, for each square visible in the current scene?
glPushMatrix();
{
glTranslatef(currentSquareX, currentSquareY, 0.0);
glVertexPointer(3, GL_FLOAT, 0, squareVertices);
glEnableClientState(GL_VERTEX_ARRAY);
// Do the drawing
}
glPopMatrix();
It seems to me that doing this for every 2D element in the scene, for every frame, gets a bit intense and I would imagine the smarter people who use OpenGL much more than I do may have a better way of doing this.
That all being said, I'm expecting to hear that I should profile the code and see where any bottlenecks may be: to those people, I say: I haven't written any of this code yet, I'm simply in the process of wrapping my mind around it so that when I do go to write it it goes smoother.
On the subject of profiling and optimization, I'm really not trying to prematurely optimize here, I'm just trying to wrap my mind around how one would set up a 2D scene and render it. Like I said, I'm relatively new to OpenGL and I'm just trying to get a feel for how things are done. If anyone has any suggestions on a better way to do this, I'd love to hear your thoughts.
Please keep in mind that I'm not interested in 3D, just 2D for now. Thanks!
You are concerned with the overhead it takes to transform a model (in this case a square) from model coordinates to world coordinates when you have a lot of models. This seems like an obvious optimization for static models.
If you build your square's vertices in world coordinates, then of course it is going to be faster as each square will avoid the extra cost of these three functions (glPushMatrix, glPopMatrix, and glTranslatef) since there is no need to translate from model to world coordinates at render time. I have no idea how much faster this will be, I suspect that it won't be a humongous optimization, and you lose the modularity of keeping the squares in model coordinates: What if in the future you decide you want these squares to be moveable? That will be a lot harder if you're keeping their vertices in world coordinates.
In short, it's a tradeoff:
World Coordinates
More Memory - each square needs its
own set of vertices.
Less computation - no need to perform
glPushMatrix, glPopMatrix, or
glTranslatef for each square at render time.
Less flexible - lacks support (or
complicates) for dynamically moving these squares
Model Coordinates
Less memory - the squares can share the same vertex data
More Computation - each square must
perform three extra functions at
render time.
More Flexible - squares can easily be
moved by manipulating the
glTranslatef call.
I guess the only way to know what is the right decision is by doing and profiling. I know you said you haven't written this yet, but I suspect that whether your squares are in model or world coordinates it won't make much of a difference - and if it does, I can't imagine an architecture that you could create where it would be hard to switch your squares from model to world coordinates or vice-versa.
Good luck to you and your adventures in iPhone game development!
If you are only using screen aligned quads it might be easier to use the OES Draw Texture extension. Then you can use a single texture to hold all your game "sprites". First specify the crop rectangle by setting the GL_TEXTURE_CROP_RECT_OES TexParameter. This is the boundry of the sprite within the larger texture. To render, call glDrawTexiOES passing in the desired position & size in viewport coordinates.
int rect[4] = {0, 0, 16, 16};
glBindTexture(GL_TEXTURE_2D, sprites);
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
glDrawTexiOES(x, y, z, width, height);
This extension isn't available on all devices, but it works great on the iPhone.
You might also consider using a static image and just scrolling that instead of drawing each individual block of the floor, and translating its position, etc.

OpenGL ES - how to keep some object at a fixed size?

I'm working on a little game in OpenGL ES.
In the background, there is a world/map. The map is just a large texture.
Zoom/pinch/pan is used to move around. And I'm using glOrthof (left, right, bottom, top, zNear, zFar) to implement the zoom/pinch.
When I zoom in, the sprites on top of the map is also zoomed in. But I would like to have some sprites stay at a fixed size.
I could probably calculate a scale factor, depending on the parameters to glOrthof, but there must be a more natural and straightforward way of doing that, instead of scaling the sprites down when I zoom in.
If I add some text or some GUI elements on top of the map, they should definately have a fixed size.
Is there a solution to do this, or do I have to leave fixed values in glOrthof and implement zoom/pinch in another way?
EDIT: To be more clear: I want sprites that zoom in/out along with the map, but stay at the same size.
I have some elements that are like the pins on the iPhone's map application. When you zoom, the pins stay the same size, but move around on the screen to stay on the same spot on the map. That is mainly what I want a solution for.
Solutions for this already came below, thanks!
First call glOrthof with the settings you have, then draw the things that scale. Then make another call to glOrthof with different settings (after glLoadIdentity probably), and then draw the things that should not be scaled.
you can use something like this to draw fixed size elements at a given 3D position, keeping the current projection settings :
// go to correct coordinates
double v[3] = { x , y , z };
glRasterPos3dv( v );
glBitmap( 0 , 0 , 0 , 0 , -center_pix_x , -center_pix_y , NULL );
// and draw pixels
glPixelStorei( GL_PACK_LSB_FIRST , true );
glPixelStorei( GL_PACK_ALIGNMENT , 1 );
glDrawPixels( img_width , img_height , GL_RGBA , GL_UNSIGNED_BYTE , img_data_ptr );
center_pix are the coordinates of the reference point in the sprite that will match the 3D point.
Found one solution in this thread:
Drawing "point-like" shapes in OpenGL, indifferent to zoom
Point sprites... Apple's GLPaint example also uses this.
Quite simple to use. Uses the current texture.
glEnable(GL_POINT_SPRITE_OES);
glTexEnvf(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
glPointSize(40.0f);
glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);
glDrawArrays(GL_POINTS, 0, 4);
These will move when the map moves, but does not change the size.
Edit: A small tip: Remember that the point coordinate is the middle of the texture, not a corner or anything. I struggled a bit with my sprites apparently "moving", because I used only the 35x35 upper left pixels in a 64x64 texture. Move your graphics to the middle of the texture and you'll be fine.