Learning OpenGL ES for IOS

Erik M. Buck

Mentioned 2

Provides information on using OpenGL ES in Apple's iOS environment, covering such topics as creating textures, rendering 3D geometric objects, animating scenes, partitioning data, and implementing special effects.

More on Amazon.com

Mentioned in questions and answers.

I'm getting started with OpenGL. I need to do a project using glaux.h. My problem is that I'm running Mac OS X Lion, so I cannot use glaux.

I was searching on the web and I found some codes that try to replace glaux. Codes were fine, but they use Windows Api variables. So obviously I can't use them. Here is the code that I need to read using glaux:

#include <stdio.h>          // Header File For Standard Input/Output
#include <stdlib.h>
#include <GLUT/glut.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include "bmp.h"
#include <string.h>

const int W_WIDTH = 500;    // PreselecciÛn del ancho de la ventana
const int W_HEIGHT = 500;   // PreselecciÛn del alto de la ventana
bool    keys[256];          // Array Used For The Keyboard Routine
bool    active=1;       // Window Active Flag Set To TRUE By Default
bool    fullscreen=TRUE;    // Fullscreen Flag Set To Fullscreen Mode By Default
bool    fullscreen=0;   // Fullscreen Flag Set To Fullscreen Mode By Default
GLuint  texture[1];         // Storage For 1 Texture
GLuint  box;                // Storage For The Box Display List
GLuint  top;                // Storage For The Top Display List
GLuint  xloop;              // Loop For X Axis
GLuint  yloop;              // Loop For Y Axis

GLfloat xrot;               // Rotates Cube On The X Axis
GLfloat yrot;               // Rotates Cube On The Y Axis

static GLfloat boxcol[5][3]=
{
{1.0f,0.0f,0.0f},{1.0f,0.5f,0.0f},{1.0f,1.0f,0.0f},{0.0f,1.0f,0.0f},{0.0f,1.0f,1.0f}
};

static GLfloat topcol[5][3]=
{
{.5f,0.0f,0.0f},{0.5f,0.25f,0.0f},{0.5f,0.5f,0.0f},{0.0f,0.5f,0.0f},{0.0f,0.5f,0.5f}
};

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // Declaration For WndProc

// Build Cube Display Lists
GLvoid BuildLists()
{
box=glGenLists(2);                                                    // Generate 2 Different Lists
glNewList(box,GL_COMPILE);          // Start With The Box List
glBegin(GL_QUADS);
// Bottom Face
glNormal3f( 0.0f,-1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
// Front Face
glNormal3f( 0.0f, 0.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
// Back Face
glNormal3f( 0.0f, 0.0f,-1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
// Right face
glNormal3f( 1.0f, 0.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f, -1.0f,  1.0f);
// Left Face
glNormal3f(-1.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f, -1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
glEnd();
glEndList();
top=box+1;                                          // Storage For "Top" Is "Box" Plus One
glNewList(top,GL_COMPILE);                          // Now The "Top" Display List
glBegin(GL_QUADS);
// Top Face
glNormal3f( 0.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f,  1.0f, -1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,  1.0f,  1.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,  1.0f,  1.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f, -1.0f);
glEnd();
glEndList();
}

AUX_RGBImageRec *LoadBMP(char *Filename)    // Loads A Bitmap Image
{
FILE *File=NULL;                                            // File Handle

if (!Filename)                                      // Make Sure A Filename Was Given
{
    return NULL;                                    // If Not Return NULL
}

File=fopen(Filename,"r");                           // Check To See If The File Exists

if (File)                                           // Does The File Exist?
{
    fclose(File);                                   // Close The Handle
    return new AUX_RGBImageRec(Filename);               // Load The Bitmap And Return A Pointer
}

return NULL;                                        // If Load Failed Return NULL
}

int LoadGLTextures()        // Load Bitmaps And Convert To Textures
{
int Status=0;      // Status Indicator

char ruta[100]="Data/Cube.bmp";

AUX_RGBImageRec *TextureImage[1];   // Create Storage Space For The Texture

memset(TextureImage,0,sizeof(void *)*1);            // Set The Pointer To NULL

// Load The Bitmap, Check For Errors, If Bitmap's Not Found Quit
if (TextureImage[0]==LoadBMP(ruta))
{
    Status=1;                                   // Set The Status To TRUE

    glGenTextures(1, &texture[0]);  // Create The Texture

    // Typical Texture Generation Using Data From The Bitmap
    glBindTexture(GL_TEXTURE_2D, texture[0]);
    glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    }

if (TextureImage[0])                                    // If Texture Exists
{
    if (TextureImage[0]->data)                          // If Texture Image Exists
    {
        free(TextureImage[0]->data);                    // Free The Texture Image Memory
    }

    free(TextureImage[0]);                              // Free The Image Structure
}

return Status;                                      // Return The Status
}

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) // Resize And Initialize The GL Window
{
if (height==0)                                      // Prevent A Divide By Zero By
{
    height=1;                                       // Making Height Equal One
}

glViewport(0,0,width,height);                       // Reset The Current Viewport

glMatrixMode(GL_PROJECTION);                        // Select The Projection Matrix
glLoadIdentity();               // Reset The Projection Matrix

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f,(GLfloat)width/(GLfloat)height,0.1f,100.0f);

glMatrixMode(GL_MODELVIEW);                         // Select The Modelview Matrix
glLoadIdentity();               // Reset The Modelview Matrix
}

int InitGL()                // All Setup For OpenGL Goes Here
{
if (!LoadGLTextures())          // Jump To Texture Loading Routine
{
    return 0;           // If Texture Didn't Load Return FALSE
}
BuildLists();           // Jump To The Code That Creates Our Display Lists

glEnable(GL_TEXTURE_2D);            // Enable Texture Mapping
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);               // Black Background
glClearDepth(1.0f);                 // Depth Buffer Setup
glEnable(GL_DEPTH_TEST);            // Enables Depth Testing
glEnable(GL_COLOR_MATERIAL);            // Enable Material Coloring
return 1;                   // Initialization Went OK
}

void DrawGLScene()                  // Here's Where We Do All The Drawing
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //Clear The Screen And The DepthB 

glBindTexture(GL_TEXTURE_2D, texture[0]);
for (yloop=1;yloop<6;yloop++)
{
    for (xloop=0;xloop<yloop;xloop++)
    {
        //Poner vuestro codigo no hace falta que se ve axactamente igual
    }
}
// Vacia los buffers de dibujo
glutSwapBuffers();
glFlush();

}


int main(int argc, char **argv) {

glutInit(&argc, argv);
glutInitWindowPosition(100,100);
glutInitWindowSize (W_WIDTH, W_HEIGHT);
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Ventana con el Visual C++ y glut");

glutDisplayFunc(DrawGLScene);
glutReshapeFunc(ReSizeGLScene);

// Funciones de inicializacion
InitGL();

glutMainLoop();
return 0;
}

Now that GLKit is available on OS X, I suggest you give that a look. Erik Buck's book Learning OpenGL ES for iOS is written around that framework, with an iOS focus, but he has a blog post and sample project showing a port to OS X 10.8.

Another idea, if you're allowed to step back from OpenGL, is to use SceneKit. It's a 10.8 only framework, not available on any platform other than Mac. It exposes most of the same controls that you have in OpenGL, but it is fundamentally an Objective-C, object-based design, and integrates well with Core Animation. Documentation is sparse but it's pretty easy to get things running. I found it much easier to wrap my brain around SceneKit than around OpenGL. Best intro is the WWDC 2012 video.

DESIRED EFFECT:

Imagine a UIScrollView such that as you scroll in any direction, you feel like you're looking around inside a dome. As in, the screen is stretched/warped/distorted at the edges by a filter/mesh of some sort. Think of a 3D game where you're looking up at the sky.

WHAT IT'S FOR:

I plan on plastering menu items on a sky of sorts. Imagine looking at the sky where clouds are tappable menu items and there are enough clouds such that you have to scroll around to find them all. This is just a menu to the actual content; it isn't a full 3D game where you can move around and such. I am therefore hoping that I can fake the 3D effect by stretching/warping/distorting the edges of the screen.

WHAT I NEED:

I need to at least know the direction to look in so that I can see how feasible and how much work it will take. If it's too much, I'll unfortunately have to do something else.

From what I've looked at so far, it appears that QuartzCore isn't enough and I suspect that OpenGL is the only way to do it. Before I throw myself into OpenGL though (I'm a complete noob at it), I'd like to know if that's even the correct technology that I should be looking at. And if it is, what area of it I should be looking at (initial searches indicated stuff like texture warping might be what I'm looking for?).

Thanks!

You’re on the right track. You’ll want to use OpenGL ES for this. The basic idea behind this that I’ve seen used to great effect is to project the scene on the inside of a cube, rotating the cube when the user moves their finger. This book really helped me when I got started with OpenGL.

Realated tags

iosopenglosxuiscrollview