What are good reasons to enable 2D projection with cocos2d-iphone? - cocos2d-iphone

In cocos2d-iphone the default projection type is "3D" projection. But you can also set the projection to "2D" like so:
[[CCDirector sharedDirector] setProjection:CCDirectorProjection2D];
Behind the scenes the 3D projection uses perspective projection whereas 2D projection is the OpenGL orthographic projection. The technical details about these two projection modes can be reviewed here, that's not what I'm interested in.
What are the benefits and drawbacks of 2D projection for cocos2d users? What are good reasons to switch to 2D projection?
Personally I've used 2D projection to be able to use depth buffering for isometric tilemaps. Isometric tilemaps require this for correct z ordering of tiles and objects on the tilemap.
I've also used 2D projection with depth buffering in non-tilemap projects to get complete z order control via the vertexZ property. This project used a pseudo isometric display where the vertexZ of an object is based on its Y coordinate.
That means I've been using 2D projection only to be able to use the vertexZ property, which also requires enabling depth buffering. Are there any other reasons one might want to switch to 2D projection?

Switching to 2D projection is a life saver in the following scenario:
You create a big CCRenderTexture
You draw a bunch of stuff on it, either using [... visit] or OpenGL drawing functions
You add the render texture to your layer, e.g., in order for the things you drew in point 2. to serve as the background for your game.
With 3D projection, the texture will be rendered with vertical and/or horizontal fault lines. See e.g., http://www.cocos2d-x.org/boards/6/topics/16197 which is for cocos2d-x but I have observed the same effect also for cocos2d-iphone and setting the projection to 2D got rid of the problem.

I have switched to 2D projection as the only means to resolve font rendering issues with CClabels, both font file and TTF-based labels. This is not always the cause of a font issue, but it has resolved some problems for me when all else failed.

Related

Using OpenGL for 2D

I have started with OpenGL and learned about model,view,and the projection matrix. From my understanding the projection matrix is only needed to project a 3D entity onto a 2D surface(the screen). So if I want to create a 2D game would I even need to mess around with the projection matrix?
It can still be nice to use a projection matrix for defining your coordinate system. By default a window will be defined between [-1,1] for both x and y no matter what resolution and aspect ratio. If you don't fix this using a projection matrix, you'll have to compensate in other ways. You want a square to render as a square, not a rectangle.
Depending on your GL version you can call glOrtho, construct it manually or use glm::ortho.
In my experience, working on the default [-1,1] system is extremely unpractical. For example : You don't want rotations around the z axis to deform your geometry.
No. When dealing purely with two dimensions, you can leave the projection matrix as the identity matrix.

OpenGL drawing 2D and 3D at the same time

I have a 3D scene I'm drawing and I want to draw a rectangle for a dialogue text that will be stretched for all the screen's width, what's the best way to achieve this, having performance in mind?
I found about glOrtho() that I can use for exact pixel placing, but since it's a matrix multiplication task, won't my app feel much heavier during scenes with dialogues?
If yes, should I try to find a math solution to find the X position of my left window corner according to some Z distance and draw a QUAD from there? (Is this even possible?)
glOrtho() is the way to go.
In the course of OpenGL's rendering Pipeline, during the Primitive Assembly stage, every vertex will be transformed (projected) from eye coordinates to clip coordinates. Whether your projection matrix is used for 3D perspective or 2D orthogonalization, it's still one matrix multiplication per vertex before Rasterization starts.
glOrtho() will change your projection matrix to an orthographic one but the matrix only needs to be generated once per frame and the equations required to do so are very simple:
(image credit: MSDN)
Once you have a projection matrix, don't let the thought of matrix multiplication scare you. It's exactly what video cards are designed to do and it's hardly a frightening task for any processor or GPU these days.

OpenGL 360 degree perspective

I'm looking to capture a 360 degree - spherical panorama - photo of my scene. How can I do this best? If I have it right, I can't do this the ordinary way of setting the perspective to 360.
If I would need a vertex shader, is there one available?
This is actually a nontrivial thing to do.
In a naive approach a vertex shader that transforms the vertex positions not by matrix multiplication, but by feeding them through trigonometric functions may seem to do the trick. The problem is, that this will not make straight lines "curvy". You could use a tesselation shader to add sufficient geometry to compensate for this.
The most straightforward approach is two-fold. First you render your scene into a cubemap, i.e. render with a 90°×90° FOV into the 6 directions making up a cube. This allows you to use regular affine projections rendering the scene.
In a second step you use the generated cubemap to texture a screen filling grid, where the texture coordinates of each vertex are azimuth and elevation.
Another approach is to use tiled rendering with very small FOV and rotating the "camera", kind of like doing a panoramic picture without using a wide angle lens. As a matter of fact the cubemap based approach is tiled rendering, but its easier to get right than trying to do this directly with changed camera direction and viewport placement.

OpenGL define vertex position in pixels

I've been writing a 2D basic game engine in OpenGL/C++ and learning everything as I go along. I'm still rather confused about defining vertices and their "position". That is, I'm still trying to understand the vertex-to-pixels conversion mechanism of OpenGL. Can it be explained briefly or can someone point to an article or something that'll explain this. Thanks!
This is rather basic knowledge that your favourite OpenGL learning resource should teach you as one of the first things. But anyway the standard OpenGL pipeline is as follows:
The vertex position is transformed from object-space (local to some object) into world-space (in respect to some global coordinate system). This transformation specifies where your object (to which the vertices belong) is located in the world
Now the world-space position is transformed into camera/view-space. This transformation is determined by the position and orientation of the virtual camera by which you see the scene. In OpenGL these two transformations are actually combined into one, the modelview matrix, which directly transforms your vertices from object-space to view-space.
Next the projection transformation is applied. Whereas the modelview transformation should consist only of affine transformations (rotation, translation, scaling), the projection transformation can be a perspective one, which basically distorts the objects to realize a real perspective view (with farther away objects being smaller). But in your case of a 2D view it will probably be an orthographic projection, that does nothing more than a translation and scaling. This transformation is represented in OpenGL by the projection matrix.
After these 3 (or 2) transformations (and then following perspective division by the w component, which actually realizes the perspective distortion, if any) what you have are normalized device coordinates. This means after these transformations the coordinates of the visible objects should be in the range [-1,1]. Everything outside this range is clipped away.
In a final step the viewport transformation is applied and the coordinates are transformed from the [-1,1] range into the [0,w]x[0,h]x[0,1] cube (assuming a glViewport(0, w, 0, h) call), which are the vertex' final positions in the framebuffer and therefore its pixel coordinates.
When using a vertex shader, steps 1 to 3 are actually done in the shader and can therefore be done in any way you like, but usually one conforms to this standard modelview -> projection pipeline, too.
The main thing to keep in mind is, that after the modelview and projection transforms every vertex with coordinates outside the [-1,1] range will be clipped away. So the [-1,1]-box determines your visible scene after these two transformations.
So from your question I assume you want to use a 2D coordinate system with units of pixels for your vertex coordinates and transformations? In this case this is best done by using glOrtho(0.0, w, 0.0, h, -1.0, 1.0) with w and h being the dimensions of your viewport. This basically counters the viewport transformation and therefore transforms your vertices from the [0,w]x[0,h]x[-1,1]-box into the [-1,1]-box, which the viewport transformation then transforms back to the [0,w]x[0,h]x[0,1]-box.
These have been quite general explanations without mentioning that the actual transformations are done by matrix-vector-multiplications and without talking about homogenous coordinates, but they should have explained the essentials. This documentation of gluProject might also give you some insight, as it actually models the transformation pipeline for a single vertex. But in this documentation they actually forgot to mention the division by the w component (v" = v' / v'(3)) after the v' = P x M x v step.
EDIT: Don't forget to look at the first link in epatel's answer, which explains the transformation pipeline a bit more practical and detailed.
It is called transformation.
Vertices are set in 3D coordinates which is transformed into a viewport coordinates (into your window view). This transformation can be set in various ways. Orthogonal transformation can be easiest to understand as a starter.
http://www.songho.ca/opengl/gl_transform.html
http://www.opengl.org/wiki/Vertex_Transformation
http://www.falloutsoftware.com/tutorials/gl/gl5.htm
Firstly be aware that OpenGL not uses standard pixel coordinates. I mean by that for particular resolution, ie. 800x600 you dont have horizontal coordinates in range 0-799 or 1-800 stepped by one. You rather have coordinates ranged from -1 to 1 later send to graphic card rasterizing unit and after that matched to particular resolution.
I ommited one step here - before all that you have an ModelViewProjection matrix (or viewProjection matrix in some simple cases) which before all that will cast coordinates you use to an projection plane. Default use of that is to implement a camera which converts 3D space of world (View for placing an camera into right position and Projection for casting 3d coordinates into screen plane. In ModelViewProjection it's also step of placing a model into right place in world).
Another case (and you can use Projection matrix this way to achieve what you want) is to use these matrixes to convert one range of resolutions to another.
And there's a trick you will need. You should read about modelViewProjection matrix and camera in openGL if you want to go serious. But for now I will tell you that with proper matrix you can just cast your own coordinate system (and ie. use ranges 0-799 horizontaly and 0-599 verticaly) to standarized -1:1 range. That way you will not see that underlying openGL api uses his own -1 to 1 system.
The easiest way to achieve this is glOrtho function. Here's the link to documentation:
http://www.opengl.org/sdk/docs/man/xhtml/glOrtho.xml
This is example of proper usage:
glMatrixMode (GL_PROJECTION)
glLoadIdentity ();
glOrtho (0, 800, 600, 0, 0, 1)
glMatrixMode (GL_MODELVIEW)
Now you can use own modelView matrix ie. for translation (moving) objects but don't touch your projection example. This code should be executed before any drawing commands. (Can be after initializing opengl in fact if you wont use 3d graphics).
And here's working example: http://nehe.gamedev.net/tutorial/2d_texture_font/18002/
Just draw your figures instead of drawing text. And there is another thing - glPushMatrix and glPopMatrix for choosen matrix (in this example projection matrix) - you wont use that until you combining 3d with 2d rendering.
And you can still use model matrix (ie. for placing tiles somewhere in world) and view matrix (in example for zooming view, or scrolling through world - in this case your world can be larger than resolution and you could crop view by simple translations)
After looking at my answer I see it's a little chaotic but If you confused - just read about Model, View, and Projection matixes and try example with glOrtho. If you're still confused feel free to ask.
MSDN has a great explanation. It may be in terms of DirectX but OpenGL is more-or-less the same.
Google for "opengl rendering pipeline". The first five articles all provide good expositions.
The key transition from vertices to pixels (actually, fragments, but you won't be too far off if you think "pixels") is in the rasterization stage, which occurs after all vertices have been transformed from world-coordinates to screen coordinates and clipped.

OpenGL texture mapping to already projected shape?

Newbie to OpenGL...
I have some very simple code (non OpenGL) for rotating a rectangle around a single axis, and projecting the result down to screen coordinates. I'm now trying to map a bitmap to the resulting shape using OpenGL. When animating the rotation, the perspective of the bitmap is quite heavily distorted. Is this to be expected? Is there something I can do about it?
I know I can use OpenGL to do the whole thing instead (and that works fine), but for my current project the approach above would suit me better, if I can just get around this perspective issue... I'm thinking maybe there's not enough information after I have projected the rotated rectangle down to 2D space for OpenGL to correctly map the bitmap with the right perspective..?
Any input would be much appreciated.
Thanks,
Daniel
To clarify:
I'm using an orthographic projection, and doing the 3D calculation and projection to 2D myself. Then I just use OpenGL for rendering the resulting shape with a texture.
If you project your coordinates yourself and do the texture mapping in 2D screen coordinates you will loose all projective information and the textures will badly distort.
You can get around this by using a perspective texture mapping. A lot of different ways to do this exist. Either by writing a real perspective texture mapper or by faking and using a plain texture mapper.
Explaining how this works is somewhat beyond the scope of a single question. I assume you read the wiki-page about perspective texture mapping first and try out the subdivision method:
http://en.wikipedia.org/wiki/Texture_mapping
Then come back and ask for detail questions..
I found the following page that explains the subdivision method in detail:
http://freespace.virgin.net/hugo.elias/graphics/x_persp.htm
It worked perfectly! Thanks Nils for pointing me in the right direction.