Skip to content
Archive of posts filed under the OpenGL ES category.

Fast Blit with OpenGL ES 2.0 and texture uploading

OpenGL ES 2.0 is fully shader based, which means you can’t draw any geometry without having the appropriate shaders loaded and bound. This means there is more setup code required to render than there was in OpenGL ES 1.1 with fixed pipeline.

Setting up the OpenGL ES 2.0 pipeline.

void glBlitter::initializeGL ()
{
    GLuint fragmentShader;
    GLuint vertexShader;
    GLint linked;

    glDepthFunc(GL_ALWAYS);
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_CULL_FACE);

    //Vertex shader
    QString srcVertShader =
        "attribute vec4 a_position; \n"
        "attribute vec2 a_texCoord; \n"
        "varying vec2 v_texCoord; \n"
        "void main() \n"
        "{ \n"
        " gl_Position = a_position; \n"
        " v_texCoord = a_texCoord; \n"
        "} \n";

    //fragment shader
    QString srcFragShader =
        "precision mediump float; \n"
        "varying vec2 v_texCoord; \n"
        "uniform sampler2D s_texture; \n"
        "void main() \n"
        "{ \n"
        " gl_FragColor = texture2D( s_texture, v_texCoord );\n"
        "} \n";

    // Create the program object
    m_program = glCreateProgram();
    if(!m_program)
      return;

    // Load the shaders
    vertexShader = loadShader(qPrintable(srcVertShader), GL_VERTEX_SHADER);
    fragmentShader = loadShader(qPrintable(srcFragShader), GL_FRAGMENT_SHADER);

    glAttachShader(m_program, vertexShader);
    glAttachShader(m_program, fragmentShader);

    // Link the program
    glLinkProgram(m_program);

    // Check the link status
    glGetProgramiv(m_program, GL_LINK_STATUS, &linked);
    if(!linked){
      GLint infoLen = 0;
      glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &infoLen);
      if(infoLen > 1){
        char* infoLog = (char*)malloc(sizeof(char) * infoLen);
        glGetProgramInfoLog(m_program, infoLen, NULL, infoLog);
        qDebug() << infoLog;
        free(infoLog);
      }
      glDeleteProgram(m_program);
      return;
    }

    m_posLoc = glGetAttribLocation ( m_program, "a_position" );
    m_texLoc = glGetAttribLocation ( m_program, "a_texCoord" );

    // Get the sampler location
    m_samplerLoc = glGetUniformLocation ( m_program, "s_texture" );

    //Init textures to plot in the paintgl function
    InitTextures();

    glClearColor(.3,.4,.6,1);

}

The actual drawing is done in the QGLWidget’s paintGL function. The OpenGL ES 2.0 guild line says that you should use upload textures with sizes of power of two. However you don’t have blit the whole texture. You can create a texCoords matrix for using only a part of the uploaded texture. There’s a really good tutorial for texturemapping in iPhone Development Blog. It’s for iPhone and it’s for OpenGL ES 1.1 or so, but the vector math in binding the textures etc. is still valid with OpenGL ES 2.0.

Continue reading ‘Fast Blit with OpenGL ES 2.0 and texture uploading’ »

Christmas present for Nokia 3rd party developers: Carbide 2.0 and Maemo 5.0

Nokia just released Carbide 2.0. And the big news is that it’s free, even the OEM edition, which was about $1200 in the past. I know that 3rd party developers don’t require the OEM edition features, but it’s still nice to receive that for free. I was able to start my own snes9x port, because I got the carbide 2.0 beta program and therefore I was able to do on device debugging and profiling (PRO edition features) for free. It seems that I will be able to continue my development for free in the future.

I have been slaking from my porting work for couple of months now. I have been busy ;-) But I still intend to continue this port. Maybe I will just make some alpha release even without sound (if I get the emulator running at decent speed).

Nokia also released Maemo 5.0 pre-aplpha SDK. The new release seems quite nice. It already contains X11-opengl support. Currently I have some experience with Snes9x, Maemo and Opengl ES, so maybe I will make a snes9x port to Maemo too.

Nokia also released Maemo 5.0 pre-aplpha SDK. The new release seems quite nice. It already contains X11-opengl support. Currently I have some experience with Snes9x, Maemo and Opengl ES, so maybe I will make a snes9x port to Maemo too.

Rendering frames with OpenGL ES

The OpenGL ES frameworks expect to have image size to be powers of two. Therefore we create 256×256 frame and then create our image into it as a sub frame.

Here is an example of opengl es init function.

#include "OpenGLES.h"
_LIT( KTESTDATASNES, "c:\\Data\\test_data\\test_565.mbm");
_LIT( KTESTDATA256x239, "c:\\Data\\test_data\\test_256x239.mbm");
static GLuint    texture;
static GLint format;
static GLint type;
static GLuint textures [2];
static EGLDisplay g_EglDisplay;
static EGLSurface g_EglSurface;

#ifdef OPENGL_ES_BENCHMARK
static CFbsBitmap* iBitmap;
#endif

void InitializeOpenGLES(EGLDisplay aDisplay, EGLSurface aSurface)
{    {
#ifdef OPENGL_ES_BENCHMARK
iBitmap = new (ELeave) CFbsBitmap();
TInt error = iBitmap->Load( KTESTDATA256x239, 0 );
TDisplayMode mode = iBitmap->DisplayMode();
if( mode == EColor64K )
{
// 64k maps to RGB565, which we will use as opengl es texture,
RDebug::Print(_L("Colour mode is correct"));
}

RDebug::Print(_L("ConstructL complete"));
#endif
g_EglDisplay = aDisplay;
g_EglSurface = aSurface;
glClear(GL_COLOR_BUFFER_BIT);
glClearColor(0.0, 0.0, 0.0, 0.0); // set background to black
// Textures are initialized in OpenGL ES API by this function.
glGenTextures( 1, textures[0] );
//Bind the background texture to iTexturesID[0], set the texture environment.
glBindTexture( GL_TEXTURE_2D, textures[0] );

glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB,
256, 256, 0,
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, NULL);

glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glMatrixMode(GL_PROJECTION);
// Push on a new matrix so that we can just pop it off to go back to perspective mode
glDisable( GL_DEPTH_TEST );
glDisable( GL_CULL_FACE  );
// Reset the current matrix to our identify matrix
glLoadIdentity();
// Pass in our 2D ortho screen coordinates (left, right, bottom, top, near, far).
glOrthof( 0, 1, 0, 1, -1, 1 );
// Switch to model view so that we can render the texture
glMatrixMode(GL_MODELVIEW);
// Initialize the current model view matrix with the identity matrix
glLoadIdentity();
glMatrixMode( GL_PROJECTION );
//glEnable( GL_DEPTH_TEST );
//glEnable( GL_CULL_FACE  );
}
}

And then the DeInit function. Only texture is deleted in here. The Screen surface is handled elsewhere.

void DeInitOpenGLES()
{
glDeleteTextures(1, textures[0]);
}

And here is the putframe function. Currently there are


static const GLbyte bgverts[8] =
{
0, 0,
1, 0,
0, 1,
1, 1
};

static const GLubyte bgtex[8] =
{
0, 1,
1, 1,
0, 0,
1, 0
};
//Use rotated matrix for N95, since the phone should be turned upside down.
static const GLubyte rot180_bgtex[8] =
{
1, 0,
0, 0,
1, 1,
0, 1
};
static const GLbyte vertices[3 * 3] =
{
-1,    1,    0,
1,   -1,    0,
1,    1,    0
};

static const GLubyte colors[3 * 4] =
{
255,      0,    0,    255,
0,    255,    0,    255,
0,      0,  255,    255
};

void PutS9xFrame( int aWith, int aHeight )
{
#ifdef OPENGL_ES_BENCHMARK
iBitmap->LockHeap();
TUint8 *data = (TUint8 *) iBitmap->DataAddress();
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 8, 256, 239,
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, data);

iBitmap->UnlockHeap();
#else
//y-offset8, TODO: calculate this for each resolution
glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 8, 256, 239,
GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GFX.Screen);
#endif

// Enable vertex arrays.
glEnableClientState( GL_VERTEX_ARRAY );
// Set array pointers.
glVertexPointer( 2, GL_BYTE, 0, bgverts );
// Enable texture arrays
glEnableClientState( GL_TEXTURE_COORD_ARRAY );
// Set texture coords
glTexCoordPointer( 2, GL_BYTE, 0, rot180_bgtex );
glEnable(GL_TEXTURE_2D);
glBindTexture( GL_TEXTURE_2D, textures[0] );
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glDisable(GL_TEXTURE_2D);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);

// Go back to model view matrix
glMatrixMode( GL_MODELVIEW );
eglSwapBuffers( g_EglDisplay, g_EglSurface);

}

Continue reading ‘Rendering frames with OpenGL ES’ »

Studying Opengl ES

I have purchased two books about OpenGL ES. The one on the right “OpenGL ES game development” I bought several years ago. Its primary focused for an average developer, who wants to learn OpenGL ES and has OpenGL background. The book has chapter about fixed point math and other limitations to deal with mobile devices. So it’s really not ideal for a mobile developer, who want’s to learn OpenGL ES. It’s a good book about limitations of mobile platform, but not really good book for learning to develop for OpenGL ES.

The book on the left”Mobile 3D Graphics with OpenGL ES and M3G” I got recently. It is primary targeting mobile developers, who want to create 3d-grapcics. So this was the right book for me. The first chapters handle 3d graphics and math in general levels and the later chapters tell you about OpenGL ES and M3G. The book also had chapter about EGL, which is used to create OpenGL surfaces in Symbian OS, so it really has everything that I need for developing OpenGL ES for Symbian/S60.

Continue reading ‘Studying Opengl ES’ »