Hello,
I'm trying to draw 2D primitives on a 3D plane using OpenGL ES 1.1. Basically, I want rectangular planes that can move in a 3D space acting like regular 3D objects. On these surfaces i want to use the 3D hardware to draw 2D rectangular primitivies such as text, images, and solid colored rectangles.
The major issue here is z-fighting due to the coplanar surfaces of drawing 2D primitives on top of one another. To resolve this issue I've come up with the strategy to initially draw the 3D surface as rectangle only on the z-buffer, offset slightly using glPolygonOffset. Then all the 2D primitives are drawn with a back to front ordering with the glDepthMask disabled but with depth testing on.
This strategy works fine with the Imagination's PC implementation of 1.1 on Windows XP, however it fails to work our TI OMAP 2530 hardware running Windows CE 5.0. I'm using a 24-bit depth buffer and rgb565 for color. My drawing code can be found below. The code draws a blue rectangle inside a larger red one and rotates it slowly. On the 2530 there is flickering between the red and blue rectangles whenever the rectangle is not facing the screen directly. On the PC there is no flickering. I hope someone can point out to me if I'm doing something wrong or if there is is some fundamental difference between the PC and the MBX.
void SetPerspective(void)
{
const float PI = 3.141592f;
float fovy = 70.0f;
float aspect = (float)800/480;
float fW,fH;
float znear = 2.0f;
float zfar = 10.0f;
{
const float PI = 3.141592f;
float fovy = 70.0f;
float aspect = (float)800/480;
float fW,fH;
float znear = 2.0f;
float zfar = 10.0f;
fH = (float)tan((double)fovy * PI / 360.0f)*znear;
fW = fH * aspect;
fW = fH * aspect;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glLoadIdentity();
glFrustumf(-fW, fW, -fH, fH, znear, zfar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
}
}
void DrawRectangle(int x, int y, int width, int height)
{
GLshort vertices[8];
vertices[0] = x;
vertices[1] = y;
vertices[2] = x + width;
vertices[3] = y;
vertices[4] = x;
vertices[5] = y + height;
vertices[6] = x + width;
vertices[7] = y + height;
{
GLshort vertices[8];
vertices[0] = x;
vertices[1] = y;
vertices[2] = x + width;
vertices[3] = y;
vertices[4] = x;
vertices[5] = y + height;
vertices[6] = x + width;
vertices[7] = y + height;
static const GLushort indices[4] = { 0, 2 , 3, 1 };
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_SHORT, 0, vertices );
glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices );
glDisableClientState( GL_VERTEX_ARRAY );
}
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_SHORT, 0, vertices );
glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices );
glDisableClientState( GL_VERTEX_ARRAY );
}
void Draw()
{
float factor = 1.1f;
float unit = 4.0f;
{
float factor = 1.1f;
float unit = 4.0f;
int x = -2;
int y = -2;
int width = 4;
int height = 4;
int y = -2;
int width = 4;
int height = 4;
glPushMatrix();
angle += 1.0f;
if( angle >= 360.0f ) {
angle = 0.0f;
}
glRotatef( angle, 0.0f, 1.0f, 0.0f );
if( angle >= 360.0f ) {
angle = 0.0f;
}
glRotatef( angle, 0.0f, 1.0f, 0.0f );
// Draw depth buffer face
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_TRUE );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_TRUE );
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset (factor, unit );
glPolygonOffset (factor, unit );
DrawRectangle( x, y, width, height );
glPolygonOffset( 0.0f, 0.0f );
glDisable( GL_POLYGON_OFFSET_FILL );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glDepthMask( GL_FALSE );
glPolygonOffset( 0.0f, 0.0f );
glDisable( GL_POLYGON_OFFSET_FILL );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glDepthMask( GL_FALSE );
// Draw red rectangle
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f );
DrawRectangle( x, y, width, height );
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f );
DrawRectangle( x, y, width, height );
// Draw blue rectangle
glColor4f( 0.0f, 0.0f, 1.0f, 0.0f );
DrawRectangle( x+1, y+1, width-2, height-2 );
glColor4f( 0.0f, 0.0f, 1.0f, 0.0f );
DrawRectangle( x+1, y+1, width-2, height-2 );
glDepthMask( GL_TRUE );
glPopMatrix();
}
glPopMatrix();
}
...
SetPerspective();
glEnable( GL_DEPTH_TEST) ;
glDisable( GL_LIGHTING );
glDisable( GL_CULL_FACE );
glDisable( GL_TEXTURE_2D );
glDisable( GL_LIGHTING );
glDisable( GL_CULL_FACE );
glDisable( GL_TEXTURE_2D );
bool quit = false;
while( !quit ) {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
while( !quit ) {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Draw();
eglSwapBuffers( g_EglDisplay, g_EglSurface );
eglSwapBuffers( g_EglDisplay, g_EglSurface );
...
[/CODE]
void SetPerspective(void)
{
const float PI = 3.141592f;
float fovy = 70.0f;
float aspect = (float)800/480;
float fW,fH;
float znear = 2.0f;
float zfar = 10.0f;
{
const float PI = 3.141592f;
float fovy = 70.0f;
float aspect = (float)800/480;
float fW,fH;
float znear = 2.0f;
float zfar = 10.0f;
fH = (float)tan((double)fovy * PI / 360.0f)*znear;
fW = fH * aspect;
fW = fH * aspect;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glLoadIdentity();
glFrustumf(-fW, fW, -fH, fH, znear, zfar);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
}
}
void DrawRectangle(int x, int y, int width, int height)
{
GLshort vertices[8];
vertices[0] = x;
vertices[1] = y;
vertices[2] = x + width;
vertices[3] = y;
vertices[4] = x;
vertices[5] = y + height;
vertices[6] = x + width;
vertices[7] = y + height;
{
GLshort vertices[8];
vertices[0] = x;
vertices[1] = y;
vertices[2] = x + width;
vertices[3] = y;
vertices[4] = x;
vertices[5] = y + height;
vertices[6] = x + width;
vertices[7] = y + height;
static const GLushort indices[4] = { 0, 2 , 3, 1 };
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_SHORT, 0, vertices );
glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices );
glDisableClientState( GL_VERTEX_ARRAY );
}
glEnableClientState( GL_VERTEX_ARRAY );
glVertexPointer( 2, GL_SHORT, 0, vertices );
glDrawElements( GL_TRIANGLE_FAN, 4, GL_UNSIGNED_SHORT, indices );
glDisableClientState( GL_VERTEX_ARRAY );
}
void Draw()
{
float factor = 1.1f;
float unit = 4.0f;
{
float factor = 1.1f;
float unit = 4.0f;
int x = -2;
int y = -2;
int width = 4;
int height = 4;
int y = -2;
int width = 4;
int height = 4;
glPushMatrix();
angle += 1.0f;
if( angle >= 360.0f ) {
angle = 0.0f;
}
glRotatef( angle, 0.0f, 1.0f, 0.0f );
if( angle >= 360.0f ) {
angle = 0.0f;
}
glRotatef( angle, 0.0f, 1.0f, 0.0f );
// Draw depth buffer face
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_TRUE );
glEnable( GL_DEPTH_TEST );
glDepthFunc( GL_LESS );
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
glDepthMask( GL_TRUE );
glEnable( GL_POLYGON_OFFSET_FILL );
glPolygonOffset (factor, unit );
glPolygonOffset (factor, unit );
DrawRectangle( x, y, width, height );
glPolygonOffset( 0.0f, 0.0f );
glDisable( GL_POLYGON_OFFSET_FILL );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glDepthMask( GL_FALSE );
glPolygonOffset( 0.0f, 0.0f );
glDisable( GL_POLYGON_OFFSET_FILL );
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
glDepthMask( GL_FALSE );
// Draw red rectangle
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f );
DrawRectangle( x, y, width, height );
glColor4f( 1.0f, 0.0f, 0.0f, 0.0f );
DrawRectangle( x, y, width, height );
// Draw blue rectangle
glColor4f( 0.0f, 0.0f, 1.0f, 0.0f );
DrawRectangle( x+1, y+1, width-2, height-2 );
glColor4f( 0.0f, 0.0f, 1.0f, 0.0f );
DrawRectangle( x+1, y+1, width-2, height-2 );
glDepthMask( GL_TRUE );
glPopMatrix();
}
glPopMatrix();
}
...
SetPerspective();
glEnable( GL_DEPTH_TEST) ;
glDisable( GL_LIGHTING );
glDisable( GL_CULL_FACE );
glDisable( GL_TEXTURE_2D );
glDisable( GL_LIGHTING );
glDisable( GL_CULL_FACE );
glDisable( GL_TEXTURE_2D );
bool quit = false;
while( !quit ) {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
while( !quit ) {
glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
Draw();
eglSwapBuffers( g_EglDisplay, g_EglSurface );
eglSwapBuffers( g_EglDisplay, g_EglSurface );
...
[/CODE]