Texture2D iPhone SDK openGL - iphone

I'm using the Texture2D class in an iPhone game using OpenGL ES.
Are their any good tutorials for understanding the Texture2D class?
Specifically I'm looking at the initWithString method for printing text. As the way it is implemented, you get white text when you use it. I would like to modify the method so I could specify the RGB color of the text. Any help / pointers?

Because the class uses an alpha-only texture (read the code!), it will display in whatever color glColor has set. See this line in initWithData (which gets called by initWithString):
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA,
width, height, 0, GL_ALPHA,
GL_UNSIGNED_BYTE, data);
For red text, just call glColor4ub(255, 0, 0, 255) prior to drawing the texture.
Make sure you enable GL_BLEND and GL_COLOR_MATERIAL prior to drawing.
The class is small. I recommend you just read it.

Related

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 ;)

Why is the framerate of my tweaked OpenGL ES 2.0 template so slow on the iPad?

I've modified the OpenGL es 2.0 template in Xcode to render that little box to an offscreen texture (50*50), then reset the view port and render the texture to the screen using a fullscreen quad. But the FPS dropped down so much that obvious lags were seen (about 10).
I know iPad has problems concerning fillrate, but this just doesn't seem right. I used only one FBO and changed its color attachment between texture and renderBuffer in the loop. Does this have any influence?
Besides, I was writing an audio visualizer (like the one in Windows Media Player) editing pixel values in OpenGL. Any suggestions?
here goes the code:
//implement the texture in -(id)init
glGenTextures(1, &ScreenTex);
glBindTexture(GL_TEXTURE_2D, ScreenTex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texSize, texSize, 0, GL_RGB, GL_UNSIGNED_BYTE, nil);
//And in the render loop
//draw to the texture
glViewport(0, 0, texSize, texSize);
glBindTexture(GL_TEXTURE_2D, ScreenTex);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ScreenTex, 0);
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
glUniform1i(Htunnel, 0);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//switch to render to render buffer here
glViewport(0, 0, backingWidth, backingHeight);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,colorRenderbuffer);
glClear(GL_COLOR_BUFFER_BIT);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, texVertices);
glUniform1i(Htunnel, 1);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
//vertex shader
void main()
{
if (tunnel==0) {
gl_Position = position;
gl_Position.y += sin(translate) / 2.0;
colorVarying = color;
}else {
f_texCoord = v_texCoord;
gl_Position = position;
}
}
//frag shader
void main()
{
if (tunnel==0) {
gl_FragColor = colorVarying;
} else {
gl_FragColor = texture2D(s_texture, f_texCoord);
}
}
Without actual code, it will be difficult to pick out where the bottleneck is. However, you can get an idea of where the problem is by using Instruments to localize the causes.
Create a new Instruments document using both the OpenGL ES instrument and the new Time Profiler one. In the OpenGL ES instrument, hit the little inspector button on its right side, then click on the Configure button. Make sure pretty much every logging option is checked on the resulting page, particularly the Tiler Utilization % and Renderer Utilization %. Click Done and make sure that both of those statistics are checked in the Select statistics to list page.
Run this set of instruments against your application on the iPad for a little while during rendering. Stop it and look at the numbers. As explained in Pivot's answer to my question, if you are seeing the Tiler Utilization % in the OpenGL ES instrument hitting 100%, you are being limited by your geometry (unlikely here). Likewise, if the Renderer Utilization % is near 100%, you are fill-rate limited. You can also look to the other statistics you've logged to pull out what might be happening.
You can then turn to the Time Profiler results to see if you can narrow down the hotspots in your code where things might be getting slowed down. Find the items near the top of the list there. If they are in your code, double-click on them to see what's going on. If they are in system libraries, filter the results until you see something more relevant by right-clicking on the symbol name and choosing either Charge Library to Callers or Charge Symbol to Caller.
At some point, you'll start seeing OpenGL-related symbols up there, which should clue you in to what the GPU is doing. Also, you may be surprised to find some of your own code slowing things down.
There's another OpenGL ES instrument that you might try, but it's part of the Xcode 4 beta and is currently under NDA. Check out the WWDC 2010 session videos for more about that one.

glReadPixels and GL_ALPHA

I'm trying to read the alpha pixel values using glReadPixels. The first thing I did was read the pixels individually. To try to speed things up, I tried reading all the pixels at once :
GLubyte *pixels = new GLubyte[w*h*4];
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
and it worked, but really slow. Now I'm trying to just retrieve the alpha value, without wasting space to the RGB components :
GLubyte *pixels = new GLubyte[w*h];
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glReadPixels(0, 0, w, h, GL_ALPHA, GL_UNSIGNED_BYTE, pixels);
But I get : OpenGL error 0x0500 in -[EAGLView swapBuffers].
Any idea as to why a INVALID_ENUM (0x0500) is thrown?
According to the documentation on glReadPixels() for OpenGL ES, the only valid enum values for the format parameter are GL_RGBA and GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES. You'd need to check and see what GL_IMPLEMENTATION_COLOR_READ_FORMAT_OES means as a format for the iPhone, but it may not provide support for GL_ALPHA.
In any case, I doubt that going that route will dramatically speed up your reads, because all that will do is discard the RGB components. Your performance issues with glReadPixels() probably lie elsewhere. A good discussion of the reasons for this can be found in the discussion thread here.
Would it be possible for you to render into an offscreen framebuffer that was backed by a texture, then do further processing on the GPU using that texture? This sounds like it would yield better performance than using glReadPixels().

iPhone : Texture bigger than 64x64?

I took the example of GLPaint... I'm trying to put a background into the "PaintingView", so you could draw over the background and finally save the image as a file..... I'm lost.
I'm loading the PNG (512x512) and try to "paint with it" at the very beginning of the program, but it's painted as 64x64 instead of 512x512...
I tried before to load is as a subview of the painting view... but then, glReadPixels doesn't work as expected (it only take in consideration the PaintingView, not the subview). Also the PaintingView doesn't have a method as initWithImage... I NEED glReadPixels work on the image (and in the modification) but i really don't know why when i load it, the texture has a 64x64 size..
The GLPaint example project uses GL_POINT_SPRITE to draw copies of the brush texture as you move the brush. On the iPhone, the glPointSize is limited to 64x64 pixels. This is a hardware limitation, and in the simulator I think you can make it larger.
It sounds like you're trying to use a GL_POINT_SPRITE method to draw your background image, and that's really not what you want. Instead, try drawing a flat, textured box that fills the screen.
Here's a bit of OpenGL code that sets up vertices and texcoords for a 2D box and then draws it:
const GLfloat verticies[] = {
0.0f, 0.0f,
1.0f, 0.0f,
0.0f, 1.0f,
1.0f, 1.0f,
};
const GLfloat texcoords[] = {
0, 0,
1, 0,
0, 1,
1, 1,
};
glVertexPointer(2, GL_FLOAT, 0, verticies);
glEnableClientState(GL_VERTEX_ARRAY);
glTexCoordPointer(2, GL_FLOAT, 0, texcoords);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
Hope that helps! Note that you need to specify the vertices differently depending on how your camera projection is set up. In my case, I set up my GL_MODELVIEW using the code below - I'm not sure how the GLPaint example does it.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glOrtho(0, 1.0, 0, 1.0, -1, 1);
First, glReadPixels() is only going to see whatever framebuffer is associated with your current OpenGL context. That might explain why you're not getting the pixels you expect.
Second, what do you mean by the texture being rendered at a specific pixel size? I assume the texture is rendered as a quad, and then the size of that quad ought to be under your control, code-wise.
Also, check that the loading of the texture doesn't generate an OpenGL error, I'm not sure what the iPhone's limitations on texture sizes are. It's quite conceivable that 512x512 is out of range. You could of course investigate this yourself, by calling glGetIntegerv() and using the GL_MAX_TEXTURE_SIZE constant.

OpenGL ES iPhone - drawing anti aliased lines

Normally, you'd use something like:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
glLineWidth(2.0f);
glVertexPointer(2, GL_FLOAT, 0, points);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_LINE_STRIP, 0, num_points);
glDisableClientState(GL_VERTEX_ARRAY);
It looks good in the iPhone simulator, but on the iPhone the lines get extremely thin and w/o any anti aliasing.
How do you get AA on iPhone?
One can achieve the effect of anti aliasing very cheaply using vertices with opacity 0.
Here's an image example to explain:
Comparison with AA:
You can read a paper about this here:
http://research.microsoft.com/en-us/um/people/hoppe/overdraw.pdf
You could do something along this way:
// Colors is a pointer to unsigned bytes (4 per color).
// Should alternate in opacity.
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors);
glEnableClientState(GL_COLOR_ARRAY);
// points is a pointer to floats (2 per vertex)
glVertexPointer(2, GL_FLOAT, 0, points);
glEnableClientState(GL_VERTEX_ARRAY);
glDrawArrays(GL_TRIANGLE_STRIP, 0, points_count);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
Starting in iOS Version 4.0 you have an easy solution, it's now possible to use Antialiasing for the whole OpenGL ES scene with just a few lines of added code. (And nearly no performance loss, at least on the SGX GPU).
For the code please read the following Apple Dev-Forum Thread.
There are also some sample pictures how it looks for me on my blog.
Using http://answers.oreilly.com/topic/1669-how-to-render-anti-aliased-lines-with-textures-in-ios-4/ as a starting point, I was able to get anti-aliased lines like these:
They aren't perfect nor are they as nice as the ones that I had been drawing with Core Graphics, but they are pretty good. I am actually drawing same lines (vertices) twice - once with bigger texture and color, then with smaller texture and translucent white.
There are artifacts when lines overlap too tightly and alphas start to accumulate.
One approach around this limitation is tessellating your lines into textured triangle strips (as seen here).
The problem is that on the iPhone OpenGl renders to a frame buffer object rather than the main frame buffer and as I understand it FBO's don't support multisampling.
There are various tricks that can be done, such as rendering to another FBO at twice the display size and then relying on texture filtering to smooth things out, not something that I've tried though so can't comment on how well this works.
I remember very specifically that I tried this and there is no simple way to do this using OpenGL on the iPhone. You can draw using CGPaths and a CGContextRef, but that will be significantly slower.
Put this in your render method and setUpFrame buffer...
You will get anti-aliased appearance.
/*added*/
//[_context presentRenderbuffer:GL_RENDERBUFFER];
//Bind both MSAA and View FrameBuffers.
glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, msaaFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, framebuffer );
// Call a resolve to combine both buffers
glResolveMultisampleFramebufferAPPLE();
// Present final image to screen
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
[_context presentRenderbuffer:GL_RENDERBUFFER];
/*added*/