Hello dear reader,

Today I present to you how to make D program using 2D and 3D with SDL and OpenGL.

Prerequisites

Add the D repository as explained here: Repo for D-programming
Then install the packages Derelict-SDL and Derelict-GL, static libraries and development :

# yum install  derelict-SDL* derelict-GL*

Example

Create a file that contains main.d

private import Display;
private import derelict.sdl.sdl:    SDL_Event, SDL_PollEvent, SDL_QUIT;
 
void main(){
    bool    isRunning   = true;
    Display display     = new Display();
    scope(exit) display.cleanup();
    while(isRunning){
        isRunning = display.event();
        // clear the screen. by default it clears to black
        display.clear();
        //display graphic
        display.drawGLFrame();
    }
}
  1. We set a boolean to the main program loop
  2. We creates an instance of display class that we will its contents later
  3. When program will exit , it will execute mandatory display.cleanup ()
  4. So an event not give the order to leave (close button for example) a boolean will be true
    • It is refreshed image

Now create our file Display.d

private import derelict.sdl.sdl;
private import derelict.opengl.gl;
private import derelict.opengl.glu;
private import tango.stdc.stringz;
//private import tango.io.Stdout;
 
class Display{
    // horizontal and vertical screen resolution
    private uint height;
    private uint width;
    // number of bits per pixel used for display. 24 => true color
    private uint bitsPerPixel;
    // field of view => the angle our camera will see vertically
    private float fov;
    // distance of the near clipping plane
    private float nearPlane;
    // distance of the far clipping plane
    private float farPlane;
    /**
     * Setup some basic OpenGL parameters
     */
    private void setupGL(){
        // switch to the projection mode matrix
        glMatrixMode(GL_PROJECTION);
        // load the identity matrix for projection
        glLoadIdentity();
        // setup a perspective projection matrix
        gluPerspective(fov, cast(float)height / width, nearPlane, farPlane);
        // switch back to the modelview transformation matrix
        glMatrixMode(GL_MODELVIEW);
        // load the identity matrix for modelview
        glLoadIdentity();
    }
    /**
     * Library initializer
     */
    private void init(){
        // initialize SDL, GL and GLU Derelict modules
        DerelictSDL.load();
        DerelictGL.load();
        DerelictGLU.load();
        // initialize SDL's VIDEO module
        SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
        // enable double-buffering
        SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
        // create our OpenGL window
        SDL_SetVideoMode(height, width, bitsPerPixel, SDL_OPENGL);
        SDL_WM_SetCaption(toStringz("D is the best"), null);
        setupGL();
    }
    /**
     * Constructor
     */
    public this(){
        height      = 800;
        width       = 600;
        bitsPerPixel= 24;
        fov         = 90;
        nearPlane   = 0.1f;
        farPlane    = 100.f;
        init();
    }
    public ~this(){
        //cleanup();
    }
    /**
     * be nice and release all resources
     */
    public static void cleanup(){
        // tell SDL to quit
        if(SDL_Quit !is null)
            SDL_Quit();
        // release GL, GLU and SDL's shared libs
        DerelictGLU.unload();
        DerelictGL.unload();
        DerelictSDL.unload();
    }
    public void clear(){
        glClear(GL_COLOR_BUFFER_BIT);
    }
    public void drawGLFrame(){
        glBegin(GL_TRIANGLES);
            glColor3f (1,  0,  0);
            glVertex3f(-1, -1, -2);
            glColor3f (0,  1,  0);
            glVertex3f(1, -1, -2);
            glColor3f (0,  0,  1);
            glVertex3f(0,  1, -2);
        glEnd();
        // swap the buffers, making our backbuffer the visible one
        SDL_GL_SwapBuffers();
    }
 
    public bool event(){
        bool isRunning = true;
        SDL_Event event;
        // handle all SDL events that we might've received in this loop iteration
        while(SDL_PollEvent(&event)){
            switch(event.type){
                // user has clicked on the window's close button
                case SDL_QUIT:
                    isRunning = false;
                    break;
                // by default, we do nothing => break from the switch
                default:
                    break;
            }
            //Stdout.formatln("event.type: {}",event.type);
        }
        return isRunning;
    }
}

Here we create a class to manage the display quel'on called Display.

It contains attributes for:

  • The resolution of a window (height, width)
  • The quality of the image (BitsPerPixel)
  • Camera angle (fov)
  • Specifies the minimum distance between the viewer from the plane (nearPlane)
  • Specifies the maximum distance between the viewer from the plan (farPlane)

The default constructor initializes the attributes and the OpenGL library / SDL by calling the init() function
The event function returns a boolean, false if it wishes to leave if true
The function drawGLFrame draw triangle
The static function cleanup is optional it ensures proper to leave

I will let you work on the code :)

Compilation

To compile the application you must specify the libraries with which it is bound to be here:

$ ldc -g -w -L -ldl -L -lDerelictGL -L -lDerelictGLU  -L -lDerelictSDL -L -lDerelictUtil *.d -of example

Produce an executable named example

Execution

Just after compiling

$ ./example

Result

Capture-D_is_the_best.png

It's beautiful

Link

Cheers

Signed: bioinfornatics, Jonathan MERCIER