Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2011-11

OpenGL ES bitmap drawing

11 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Felipe Monteiro de Carvalho

Hello,

This is a kind of "take a look at my code please" question. Normally I avoid that kind of question, but in this case my cluelessness is big enough that it would really be excellent if someone could throw some light here.

Well, basically it is simple, I have a working Android application which draws a green gradient in the screen. Of course that a green gradient is useless, I want to draw a bitmap.

There are lots of tutorials on the web, but they are mostly in Java and I am battling with the C ones to see if I can figure someone out.

So far I managed to get this:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/customdrawnobject_android.inc?view=markup&root=lazarus

The relevant code goes only up to line 300 aprox. and the real drawing is in the procedure engine_draw_frame

I draw the image at line 108, it should be a red rectangle on a black background. There do is a pixel format missmatch, but I still would expect to see something, even if a malformed image, but here I get nothing... =(

I would be immensely greatful if someone could take a look and throw some hints here at what is necessary to get this working.

Felipe Monteiro de Carvalho
Jeppe Græsdal Johansen
to Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho wrote 29 lines
Hello, This is a kind of "take a look at my code please" question. Normally I avoid that kind of question, but in this case my cluelessness is big enough that it would really be excellent if someone could throw some light here. Well, basically it is simple, I have a working Android application which draws a green gradient in the screen. Of course that a green gradient is useless, I want to draw a bitmap. There are lots of tutorials on the web, but they are mostly in Java and I am battling with the C ones to see if I can figure someone out. So far I managed to get this: http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/customdrawnobject_android.inc?view=markup&root=lazarus The relevant code goes only up to line 300 aprox. and the real drawing is in the procedure engine_draw_frame I draw the image at line 108, it should be a red rectangle on a black background. There do is a pixel format missmatch, but I still would expect to see something, even if a malformed image, but here I get nothing... =( I would be immensely greatful if someone could take a look and throw some hints here at what is necessary to get this working.

I don't quite understand what problem you are having, but I did notice that you use

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, engine^.width, engine^.height, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_6_5, Pointer(engine^.RawImage.Data));

Are you sure width and height are powers of two here?

And shouldn't you be calling glDrawArrays at line 158 instead of line 148?

Reimar Grabowski
to Felipe Monteiro de Carvalho: This is a kind of "take a look at my code please" question. Normally I avoid that kind of…

After a quick look I have some questions:

It looks like you are using lit geometry, any reason for that? Why do you enable blending after drawing and at all? Why do you set up your matrices after drawing? (See Jeppes remark about glDrawArrays) Why do you enable texturing after drawing? (You only loose the first frame as for the next it will be enabled, but it is strange nonetheless) You said there is a pixel format mismatch. AFAIR your texture should be white if something is wrong with it, but I am not 100% sure in case of a format mismatch.

To debug:

Disable blending, texturing, lighting and face culling and just draw a colored quad to check if your matrix setup in combination with placement of the quad in the world is correct. Reenable face culling and check.
Reenable texturing and check (fix your pixel format mismatch before that). Reenable lighting if needed.
Reenable blending if needed.
Be generous with glGetError calls see
http://www.khronos.org/opengles/documentation/opengles1_0/html/glGetError.html.

hope it helps
R.

Felipe Monteiro de Carvalho
to Reimar Grabowski
Jeppe Græsdal Johansen wrote
Are you sure width and height are powers of two here? And shouldn't you be calling glDrawArrays at line 158 instead of line 148?

I fixed the pixel format missmatch, made width=height=128 and changed glDrawArrays like you proposed but still no change.

Reimar Grabowski wrote
It looks like you are using lit geometry, any reason for that?

What is lit geometry? Google didn't help me here.

I just want to draw a 2D image which fills the entire screen. I don't want any 1 texture which covers the entire screen.

The worse part here is that with the power of two limitation it seams that I will have a lot of problems, because with this limitation I can't match correctly the screen format. Usually the screens are 2x3 in proporsions, but power of two allows only 1x2 from what I understand.

Why do you enable blending after drawing and at all? Why do you set up your matrices after drawing? (See Jeppes remark about glDrawArrays) Why do you enable texturing after drawing? (You only loose the first frame as for the next it will be enabled, but it is strange nonetheless)

No idea about any of this ... I copied the code from a tutorial, probably the guy wasn't vey good in OpenGL.

You said there is a pixel format mismatch. AFAIR your texture should be white if something is wrong with it, but I am not 100% sure in case of a format mismatch.

I already fixed the missmatch.

Show quoted text 7 lines
Disable blending, texturing, lighting and face culling and just draw a colored quad to check if your matrix setup in combination with placement of the quad in the world is correct. Reenable face culling and check. Reenable texturing and check (fix your pixel format mismatch before that). Reenable lighting if needed. Reenable blending if needed. Be generous with glGetError calls see http://www.khronos.org/opengles/documentation/opengles1_0/html/glGetError.html.

ok, thanks, I'll try that (as soon as figure out how to do that)

Felipe Monteiro de Carvalho
Felipe Monteiro de Carvalho
to Felipe Monteiro de Carvalho

Hello,

Ok, so now I read a couple of tutorials more and I am trying to first draw a simple rectangle, but still nothing shows. I have put glGetError calls before every single call and yet nothing is returned as wrong by OpenGL ES.

Here is my routine:

http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/lcl/interfaces/customdrawn/customdrawnobject_android.inc?revision=33807&root=lazarus

procedure engine_draw_frame(engine: Pengine);
const
  vertices: array[0..7] of GLfloat =
    (0, 300,
     300, 300,
     0, 0,
     300, 0);
var
  lError: GLenum;
begin
   if engine^.display = nil then exit;
   LOGW('[engine_draw_frame]'); // <<<--- I see this tons of times
   // Set a projection which matches the screen size
   glMatrixMode(GL_PROJECTION);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 1
Error='+IntToStr(Integer(lError))));
   glLoadIdentity();
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 2
Error='+IntToStr(Integer(lError))));
   glOrthof(0, engine^.width, engine^.height, 0, 0, 1);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 3
Error='+IntToStr(Integer(lError))));
   glMatrixMode(GL_MODELVIEW);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 4
Error='+IntToStr(Integer(lError))));
   glLoadIdentity();
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 5
Error='+IntToStr(Integer(lError))));
   // Displacement trick for exact pixelization
   glTranslatef(0.357, 0.357, 0);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 6
Error='+IntToStr(Integer(lError))));
   // Turn on 2D mode
   glDisable(GL_DEPTH_TEST);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 7
Error='+IntToStr(Integer(lError))));
   glClear(GL_COLOR_BUFFER_BIT);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 8
Error='+IntToStr(Integer(lError))));
   // Draw a square
   glVertexPointer(2, GL_FLOAT, 0, @vertices[0]);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 9
Error='+IntToStr(Integer(lError))));
   glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 10
Error='+IntToStr(Integer(lError))));
   eglSwapBuffers(engine^.display, engine^.surface);
   lError := glGetError();
   if lError  GL_NO_ERROR then LOGW(PChar('[engine_draw_frame] 11
Error='+IntToStr(Integer(lError))));
end;
Felipe Monteiro de Carvalho
Reimar Grabowski
to Felipe Monteiro de Carvalho: On Fri, Nov 25, 2011 at 7:00 PM, Jeppe Græsdal Johansen I fixed the pixel format…
What is lit geometry? Google didn't help me here.

Geometry is anything you draw in OpenGL (in CG the term mesh is preferred) and lit just means that you use lighting and must therefor provide normals, take care of setting the lights, etc.

I just want to draw a 2D image which fills the entire screen. I don't want any 1 texture which covers the entire screen.

Here is my OpenGL (note not ES) "textured fullscreen quad" code, ripped directly from my engine:

  glMatrixMode(GL_MODELVIEW);
  glPushMatrix;
  glLoadIdentity;
  glMatrixMode(GL_PROJECTION);
  glPushMatrix;
  glLoadIdentity;
  glDepthFunc(GL_LESS); <-- you don't need this if you disable the depth test before drawing
  glColor3fv(@BackgroundColor); <-- color can be set using the ordinary glColor3f/4f functions instead
  glBindTexture(GL_TEXTURE_2D, BackgroundImage.id); <-- texture is already set up, but your set up code looked ok, so I don't post mine
  glBegin(GL_QUADS); <-- this is not supported in ES as you have to use attribute arrays (like in your code)
  glTexCoord2d(0, 1); glVertex3f(-1, -1, -1); <-- these values must be stuffed in your attribute arrays only that you have to adjust the texture coordinates to your needs (see below)
  glTexCoord2d(1, 1); glVertex3f(1, -1, -1);
  glTexCoord2d(1, 0); glVertex3f(1, 1, -1);
  glTexCoord2d(0, 0); glVertex3f(-1, 1, -1);
  glEnd;
  glPopMatrix;
  glMatrixMode(GL_MODELVIEW);
  glPopMatrix;

Note: No call to glOrtho, just indentity matrices for projection and modelview. Lighting and blending is disabled when I call this function.

Show quoted text 5 lines
The worse part here is that with the power of two limitation it seams that I will have a lot of problems, because with this limitation I can't match correctly the screen format. Usually the screens are 2x3 in proporsions, but power of two allows only 1x2 from what I understand.

Nope, the only problem is that you need more texture memory for your image. Say your screen size is 640x480. Because of the pot limitation your texture must be 1024x512. Since you only want to render the 640x480 part of the texture to your quad you need to adjust your texture coordinates accordingly. Texture coordinates are in the range 0 to 1. But as you do not for example want the rightmost texel of the whole texure but the rightmost one of your smaller image you have to use 0.625 (1024/640) instead of 1. The same for the Y-coordinate.

Unfortunately we have left the realm of FPC programming and wandered of into the wonderful world of OpenGL. Perhaps a place dedicated to OpenGL development is better suited for this problem. You may take a look at the NeHe OpenGL examples. They are available in many different languages (including delphi) and cover most of the basic stuff.

R.

Sven Barth
to Felipe Monteiro de Carvalho: Ok, so now I read a couple of tutorials more and I am trying to first draw a simple…
Felipe Monteiro de Carvalho wrote
// Displacement trick for exact pixelization glTranslatef(0.357, 0.357, 0);

Untested guess: try to move your object in front of the virtual camera (which is located at (0, 0, 0) ). Thus set the Z value to something negative (e.g. -0.5 as you've set your far clipping plane to 1). [The Z axis is pointing from the infinity in front of you through the origin, thus the negative values]

Regards,
Sven

Sven Barth
to Sven Barth
Sven Barth wrote 9 lines
On 26.11.2011 21:32, Felipe Monteiro de Carvalho wrote: > // Displacement trick for exact pixelization > glTranslatef(0.357, 0.357, 0); Untested guess: try to move your object in front of the virtual camera (which is located at (0, 0, 0) ). Thus set the Z value to something negative (e.g. -0.5 as you've set your far clipping plane to 1). [The Z axis is pointing from the infinity in front of you through the origin, thus the negative values]

Ok, I have now experimented myself with glOrtho (as I had to do a homework where we need to do a simple OpenGL project (boooring) I used the time to find a solution for you ^^). The problem is not the missing translation, but your setup of the orthographic projection matrix. The coordinates you define there are NOT your viewport coordinates. Thus the origin lies not at the upper left corner, but at the center! So if you adjust your call to the following it should work:

glOrthof(-engine^.width/2, engine^.width/2, engine^.height/2,
-engine^.height/2, 0, 1);

Also it is sufficient to set the projection matrix only when a change in the size of the window happens (or when you really need to switch between rendering 3D and 2D content, e.g. when drawing a 2D GUI above a 3D scene).

Regards,
Sven

Felipe Monteiro de Carvalho
to Sven Barth
Sven Barth wrote
Ok, I have now experimented myself with glOrtho (as I had to do a homework where we need to do a simple OpenGL project (boooring) I used the time to find a solution for you ^^)

Thank you very much =)

Felipe Monteiro de Carvalho