Wednesday 20 June 2012

OpenGL ES on the raspberry pi Pt 3 Creating a window

In the previous post I discussed the EGLWindow class, this class is designed as a framework for the user of the library to create consistent windows. This post will look at how we can use the EGLWindow class and extend it.

MyEGLWindow

This class is going to inherit from the main EGLWindow class then implement the two methods initializeGL and paintGL.
#ifndef MYGLWINDOW_H__
#define MYGLWINDOW_H__

#include "EGLWindow.h"
/// @brief this class create our window by inheriting the features of the EGL Window
class MyGLWindow : public EGLWindow
{
  public :
   /// @brief ctor
   /// @param[in] _config an optional configuration for the buffers etc
   MyGLWindow(EGLconfig *_config=0);
   /// @brief dtor will close down the vc and re-set EGL
   ~MyGLWindow();
   /// @brief the is the main drawing function should only be called once initalizeGL has
   /// been called
   virtual void paintGL();
  protected :
   /// @brief one time OpenGL initialisation
   virtual void initializeGL();
};
When using the class the constructor must always call the initializeGL method, as the EGLWindow class is called first this will mean that we have a valid OpenGL context and any GL calls are going to be associated with this context. In this example we just print out that the ctor has been called and then init gl.
MyGLWindow::MyGLWindow(EGLconfig *_config) : EGLWindow(_config)
{
std::cout<<"My GL Window Ctor\n";
srand(time(NULL));
// init GL in this case we are going to create some render buffers
// for colour and depth
initializeGL();
}
The next stage is to implement the initializeGL function, this is where you should do any one off configuration for OpenGL, in this case I'm just going to set the clear colour (which will change later in the draw function)
void MyGLWindow::initializeGL()
{
 // set the clear colour
 glClearColor(1,1,1,1);
}
Next the we will create the paintGL method, this is designed to be called within our main look each time the screen needs to be updated. In this case I'm going to set the screen clear colour and clear the screen.
void MyGLWindow::paintGL()
{
 // scale the colour based on the width
 float r=(float)rand()/(float)RAND_MAX;
 float g=(float)rand()/(float)RAND_MAX;
 float b=(float)rand()/(float)RAND_MAX;
 // set the clear colour
 glClearColor(r,g,b,1);
 // clear screen
 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 // to update we need to swap the buffers
 swapBuffers();
}
Once drawing is complete the swapBuffers() method must be called to tell OpenGL to swap the back buffer with the front to show the re-drawn surface.

Using the window

The following code will create an instance of the MyGLWindow class and execute a loop calling draw.
#include <iostream>
#include "MyGLWindow.h"
#include "bcm_host.h"


int main()
{
 atexit( bcm_host_deinit); 
  
 std::cout<<"starting GL test\n";
 bcm_host_init();
 std::cout<<"done bcm init\n";
 // here I create a config with RGB bit size 5,6,5 and no alpha
 EGLconfig *config = new EGLconfig();
 config->setRGBA(5,6,5,0);
 // set the depth buffer
 config->setDepth(16);
 // now create a new window using the default config
 MyGLWindow win(config);
 // now set the size of the screen in this case I'm going to do a
 // rectangle in the middle (if you don't call this you would get a full
 // screen rect by default)
 uint32_t w=win.getMaxWidth();
 uint32_t h=win.getMaxHeight();
 // set this to true to upscale the dst rect
 win.setUpscale(false);
 win.setScreen(w/4,h/4,w/2,h/2);
 int x,y;
 while(1)
 {
  win.paintGL();
  sleep(1);
 }
}
In this example we create a custom config with R/B of bit depth 5 and green bit depth 6 and a depth buffer of 16 bits. This is then passed to the MyGLWindow ctor and used as the config when creating the EGL window. Next we re-size the screen so that is is half the screen dimensions and centred. (This will call the destroySurface method mentioned in the previous post). Finally we loop calling paintGL for each update and sleeping for 1ms (use ctrl + C to exit the program). We need a Makefile to build this program and it needs to include several libraries to get it working, for more details on this see the blog post here For the full code grab this

2 comments:

  1. Hi Jon,

    I've been following your quest for a GLUT-like API for the Raspberry Pi and I'm very glad to see someone looking to fill this void! The EGLTest framework seemed to not have complete mouse tracking and no keyboard callbacks (EGLTest2 was no longer available to download when I checked yesterday). I was wondering if you've made any progress on that? I'm very excited to see what the Pi can do!

    Ken

    ReplyDelete
  2. Hi Ken,

    I've actually decided to use SDL for mouse and keyboard control, and my framework for the GLES stuff, it seems to work ok. I've put it all on google code and you can download the framework and some demo programs here

    http://code.google.com/p/pingl/

    I will write some more stuff up soon about using SDL and my NGL library.

    Jon

    ReplyDelete