Monday, October 8, 2007

NeHe Lesson 23: Sphere Mapping Quadrics In OpenGL

The 23rd lesson is finished. Nothing special on the D-front in this one. Go read the the text here.
Then grab the code from here.

Wednesday, October 3, 2007

NeHe Lesson 22: Bump-Mapping, Multi-Texturing & Extensions

Oh, it's been a while from my last post. Been busy with the life outside of computers.

The next lesson has been done for a quite a while now, except for a small bug. When displaying the cube with mip-mapped textures the texture is not drawn for some reason. Today I got the drawing working, but it introduced a another problem. The fix was to remove the texture flipping and rotating code from the initGL function. This has the effect of displaying the logos upside down and as mirror images, but now the mip-mapped cube is displayed correctly.

If any of you has any idea how to fix this small problem, let me know so I can fix it. Otherwise I'll move on to the next lesson.

The NeHe's lesson can be found here.

Btw, I've kept the broken mip-map version in the repository as I think it's a smaller problem than upside down logos.

Monday, August 20, 2007

NeHe tutorials ported to D news post

There is a news post of D in general and my NeHe lesson ports on http://nehe.gamedev.net. =)

Direct link: here.

Tuesday, July 24, 2007

NeHe Lesson 21: Lines, Antialiasing, Timing, Ortho View And Simple Sounds

It's time for a new lesson. This time NeHe has made a simple game for us to enjoy.

First before doing anything else make sure that you have SDL_Mixer installed on your system, as we're going to use it to play back the music and sound effects.

Next is a small improvement I made over the C version, is the use of the enemies-array. The original lesson uses it as a static array, but I made it dynamic. This way we can use the D's great foreach-loop to go over every enemy in the level.


/// Enemy Information
GameObject[] enemies;

....

/**
* Resets the player character and all the enemies.
*/
void resetObjects()
{
player.x = 0; // Reset Player X Position To Far Left Of The Screen
player.y = 0; // Reset Player Y Position To The Top Of The Screen
player.fx = 0; // Set Fine X Position To Match
player.fy = 0; // Set Fine Y Position To Match

// Create the enemies for the next level/stage
enemies = new GameObject[stage * level];
// Loop Through All The Enemies
foreach (inout enemy ; enemies)
{
// A Random X Position
enemy.x = 5 + rand.next() % 6;
// A Random Y Position
enemy.y = rand.next() % 11;
// Set Fine X To Match
enemy.fx = enemy.x * 60;
// Set Fine Y To Match
enemy.fy = enemy.y * 40;
}
}

As you can see there, we use the new operator to create just the number of enemies for the level/stage. Then we can loop over the array with foreach and be certain that we always have the correct number of enemies.

In the module constructor the parameter to SDL_Init has changed to SDL_INIT_EVERYTHING.

if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
throw new Exception("Failed to initialize SDL: " ~ getSDLError());
}

This is needed for audio. There are other options, which you can read about here.

The module destructor is responsible for freeing the textures and SDL_Mixer's buffers.

static ~this()
{
// Clean up our font list
glDeleteLists(base, 256);

// Clean up our textures
glDeleteTextures(NUM_TEXTURES, &textures[0]);

// Stop playing the music
Mix_HaltMusic();

// Free up the memory for the music
Mix_FreeMusic(music);

// Free up any memory for the sfx
Mix_FreeChunk(chunk);

// Close our audio device
Mix_CloseAudio();

SDL_Quit();
}

That's about it. Everything else is hopefully easy enough to understand, so just dig in.

Wednesday, July 4, 2007

NeHe Lesson 20: Masking

Puuh! Full 20 lessons now. =) Almost half of them. With luck I'll get them all by the end of the year. ;)

This lesson doesn't bring anything special on the D-table, but the lesson itself is interesting, so go read it.

I separated the texture loading into two functions, because there is 5 different textures which need to be loaded.

The source can be found here.

Tuesday, June 26, 2007

NeHE Lesson 19: Particle Engine Using Triangle Strips

I've been sitting on this one far too long. It's a nice tutorial on particles and NeHe has written a long explanation for it here. There shouldn't be anything new on the D front that warrants an explanation. If you disagree then leave me a note and I'll go over it.

The source can be found here.

Thursday, June 21, 2007

The OpenGL Pipeline Newsletter Volume 004

The newest edition of the Pipeline has been released. I've been reading it and there was a small paragraph which contains information about the recent debug stuff that has been going on in the D-OpenGL-land.

Here's the part:

More context creation options are available. In the previous edition of OpenGL Pipeline I described how we are planning on handling interoperability of OpenGL 2.1 and Longs Peak code. As a result, the application needs to explicitly create an OpenGL Longs Peak or OpenGL 2.x context. To aid debugging, it is also possible to request the GL to create a debug context. A debug context is only intended for use during application development. It provides additional validation, logging and error checking, but possibly at the cost of performance.

At last OpenGL itself will assist the poor programmer in debuggin.

Friday, June 15, 2007

DebugGL

After reading Daniel's excellent post here, which by the way was something I've been thinking about a little. Although not to the extend that Daniel has. But he got me working on the foundation he made in the post, and the first results can be seen here.

And thanks to h3r3tic and larsivi on #D.Tango. Without you I couldn't have done this. :)

Wednesday, May 16, 2007

New Page

I've finally made use of the OdeFu projects main page. There is now a table of the NeHe lessons that have been done, with links to their respective sources. I've also added a link to the page to my bookmarks on the right side.

NeHE Lesson 18: Quadrics

The 18th lesson gives a tour of some of the GLU functions and how to display different shapes with them. The shortish text can be read here. There shouldn't be anything special.

The D code is here.

Tuesday, May 15, 2007

NeHe Lesson 17: 2D Texture Font

This lesson should contain code for those who are interested in drawing text in an OpenGL window. After reading the tutorial text and getting the hang of it, you might want to implement support for AngelCode's Bitmap Font Generator. It's a nifty tool for making bitmap fonts for your games.

Here's the D code for the lesson.

Monday, May 14, 2007

NeHe Lesson 16: Cool Looking Fog

This lesson doesn't bring that much new to the table. The fog functions should be pretty self-explanatory, but read what Chris Aliotta has to say about it here.

The D version is here.

About Lessons 13, 14 and 15

I've decided that I'm not going to cover the next 3 lessons(13, 14 and 15). They contain platform specific code, and I'm not into that kind of stuff. The lesson 17 contains a way to show text in a platform independent way for those that want to see text in an OpenGL application.

Saturday, May 12, 2007

The New NeHe Tutorials

Some of you are probably aware that a beta version of the new NeHe tutorials have been released earlier this year. There is a window backend for all the lessons which contains window creation and a simple framework for running the lesson applications. Then they have written 5 lessons already.

I've been writing them in D for some time now. When ever I've had time. They are now done and working nicely. I'm not going to go over them yet, as the real tutorials haven't been released yet, but you can browse the sources here, or if you want to try them out just checkout them. I've written DSSS configuration files for them, so you can just do 'dsss install', for NeHeWindow, and then 'dsss build' for the lessons.

And now back to your regular old NeHe tutorial studying.

Wednesday, April 18, 2007

The New NeHe Lessons

I just noticed that a beta release is available for the new NeHe lessons. You can see the release notes here.

I took a look at the code, and apart from the horrible naming convetion and the fact that they still use C++, it looks pretty good. So I've decided to do a port of them to D, but there is a catch:

* I'll only port the SDL backend
* I'll "fix" the naming convertion to something more to my tastes
* I don't know when I have the time to do this

Probably the best place to start is from the window backend so that I can get something useful done as fast as possible.

Stay tuned.

NeHe Lesson 12: Display Lists

Ok, didn't get to test this on Windows, but it should work as the lesson doesn't contain platform specific code.

First off there's an example on how to initialize a static multi-dimensional array:
(In case you didn't know already how to do it.)
/// Array For Box Colors
GLfloat boxcol[5][3] =
[
// Bright: Red, Orange, Yellow, Green, Blue
[1.0f, 0.0f, 0.0f], [1.0f, 0.5f, 0.0f], [1.0f, 1.0f, 0.0f], [0.0f, 1.0f, 0.0f], [0.0f, 1.0f, 1.0f]
];

In the module constructor we have something new.
// Enable key repeating
if ((SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL)))
{
throw new Exception("Failed to set key repeat: " ~ getSDLError());
}
Here we enable SDL to repeat key presses if you keep a key down. I've used SDL's default values for the arguments.

There isn't really anything special about the rest of the code, so grab a cola and go read what NeHe has written on the subject, here.

Here's the link to the source.

Tuesday, April 17, 2007

Linux Update

I wanted to leave a quite note on the Linux support. I tested all the current lessons on a Linux box with the following setup: Tango RC1 with DMD 1.012 and Rebuild 0.18. All of the worked fine. Found only couple typos in image filenames. Wrong case.

Plus I've pretty much done lesson 12 and I'll put it up as soon as I get home.

Thursday, March 22, 2007

Small Update

I've gone through all the existing lessons and updated them to Tango beta2 and DMD 1.009. They work at least on my Windows box, but I'm having some troubles with my Linux laptop. I'll give an update when and if I get them to work on Linux too.

I also changed the links in the first five lessons to point to the source code directly and not zip files.

Wednesday, March 14, 2007

Status Update

Sorry for not posting anything for a while. I've just started this Monday in a new job at Digital Chocolate! At last got into a game company. =) My new job title is Tools Programmer, which suits me just fine. It's been great and I look forward to many interesting days ahead.

I also have other stuff going on, so it will probably be a while before I get the next lesson done.

Tuesday, March 6, 2007

NeHe Lesson 11: Flag Effect (Waving Texture)

Got the next one ready at last. This one shows you how to do a flag effect. The only hard part should be the math for calculating the wave. Go read Bosco's explanation here.

I'll add the only new D bit in the code. I've used a nice way to initialize a dynamic multi-dimensional array.

First we have at the top of the module the declaration:

GLfloat[][][] points;

Then in initGL we initialize the array, like this:

points = new GLfloat[][][](45, 45, 3);

Then we just loop through the indices and assign values to them.

Here's the whole code, and here's the flag texture.

Thursday, March 1, 2007

NeHe Lesson 10: Loading And Moving Through A 3D World

The 10th lesson is finally converted and polished. This lesson shows you how to load world data from a text file and then how to display it. And actually it's pretty simple code. The original lesson can be read here. I'll go over couple things here that are more specific to D and Tango.

First I've imported the world data at compile time into the final executable. This is a cool feature and I think very useful for static data like this. You can of course use it to import texture data or something totally different.

setupWorld(import("world.txt"));
You need at least the version 1.005 of DMD for this to work. I have no idea if GDC even supports this yet. With 1.005 you need to add the relative path to the world.txt to the string above. With 1.006 and later you don't need to change the code, but you must use the -J switch to define the search path for the compiler where it can find the file.

The setupWorld function is pretty simple. With the use of Tango's LineIterator, reading through the world data is a breeze.

Now go play with it, lesson10.d and world.txt.

Tuesday, February 27, 2007

The OpenGL SDK

The OpenGL SDK has been released recently. It's not the usual thing when you think of SDKs. This time there are tutorials, libraries and links to different tools, but the most interesting feature is the inclusion of the whole reference to OpenGL version 2.1. No need to flip through the reference manual! =)

A First Glimpse at the OpenGL SDK.

The OpenGL SDK.

Monday, February 26, 2007

NeHe Lesson 09: Moving Bitmaps In 3D Space

The 9th lesson covers more ground on moving things around and applying color to black and white textures. The lesson can be read here.

This is the first time in these tutorials where we see a nice little example on how to use the D's foreach loop. It is used to initialize all the stars in the array. It is very clean looking and easy to follow. The only thing to remember in a situation like this, is to use the 'inout' modifier on the star variable so that the changes stick.

foreach (i, inout star ; stars)
{
star.angle = 0.0f;
star.dist = cast(float)i / stars.length * 5.0f;
star.r = rand.next() % 256;
star.g = rand.next() % 256;
star.b = rand.next() % 256;
}

The foreach loop is used in the drawing function also. There too the 'inout' modifier must be used because we update the values in the star at the end.

The rest of the code can be read here.

NeHe Lesson 08: Blending

The next lesson shows us how to do blending in OpenGL. It's a very cool feature even if your just doing a glass cube. :) There isn't any differences to the original work concerning OpenGL so I'll just give you couple things you could try to change in the code. Homework so to speak.

1. Change the drawing code to only apply the blending to the front and back faces of the cube.
2. Change the texture used in the other faces.

Link to the code is here.

Friday, February 23, 2007

NeHe Lesson 07: Texture Filters, Lighting & Keyboard Control

The 7th lesson adds some lights and 2 more ways to make textures. Keyboard input is added to move and rotate the box. There shouldn't be anything too difficult about the lesson. Check out the new parameters to glTexParameteri and how the lights are defined. The original lesson can be read here.

The D version is here.

All the images and other data used in these lessons can be found here.

NeHe Lesson 06: Texture Mapping

So, it's been a while. I've been very busy with other stuff lately, but I haven't forgotten this blog.

The next lesson is about texture mapping. Go read it here. There's couple things I'd like to mention about SDL and OpenGL concerning this tutorial.

First of SDL has its own image loading functions, mainly SDL_LoadBMP, which loads BMP images. In a bigger project you might want to look at SDL_image for other image types.

The other thing is that you will need to flip and rotate your textures when using SDL. The following lines of code will setup OpenGL to do that for you.

glMatrixMode(GL_TEXTURE);
glRotatef(180.0f, 0.0f, 0.0f, 1.0f);
glScalef(-1.0f, 1.0f, 1.0f);
glMatrixMode(GL_MODELVIEW);

The full code listing can be found here.

Monday, February 19, 2007

Update: Lessons 1-5 use Tango now

I've updated the lessons 1-5 to use the Tango runtime. Only the to and from char* functions needed to be changed.

So from now on I'll publish code only compatible with Tango.

Friday, February 2, 2007

Let's dance to the Tango 0.95 beta 1

So Tango's first beta has been released. So the first thing I did, was to go and ask when and if Derelict will support it. "In the very near future."

I will be using Tango exclusively from now on because as far as I'm concerned it's far better than Phobos. That might be my Java background talking too.

I'll start of by converting the existing lessons to Tango. That shouldn't take too long, as they don't have many dependencies to Phobos. But first I have to wait for Mr. Parker to add the support to Derelict.

Tuesday, January 30, 2007

NeHe Lesson 05: 3D Shapes

The last lesson of the very basics is here. This lesson doesn't bring anything new to the table, but shows you how to combine triangles and quads into pyramids and cubes.
Go read the lesson here first.

I'll put the changed drawing code here for your enjoyment.

/**
* The drawing function. Here we will draw the pyramid and cube.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-1.5f, 0.0f, -6.0f);

// Rotate The Triangle On The Y axis
glRotatef(rtri, 0.0f, 1.0f, 0.0f);

// Start Drawing The Pyramid
glBegin(GL_TRIANGLES);
glColor3f(1.0f,0.0f,0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Front)
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f); // Left Of Triangle (Front)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f); // Right Of Triangle (Front)

glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Right)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(1.0f, -1.0f, 1.0f); // Left Of Triangle (Right)
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f); // Right Of Triangle (Right)

glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Back)
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(1.0f, -1.0f, -1.0f); // Left Of Triangle (Back)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f); // Right Of Triangle (Back)

glColor3f(1.0f, 0.0f, 0.0f); // Red
glVertex3f(0.0f, 1.0f, 0.0f); // Top Of Triangle (Left)
glColor3f(0.0f, 0.0f, 1.0f); // Blue
glVertex3f(-1.0f, -1.0f, -1.0f); // Left Of Triangle (Left)
glColor3f(0.0f, 1.0f, 0.0f); // Green
glVertex3f(-1.0f, -1.0f, 1.0f); // Right Of Triangle (Left)
// Done Drawing The Pyramid
glEnd();

// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Right And Into The Screen
glTranslatef(1.5f, 0.0f, -7.0f);

// Rotate The Cube On X, Y & Z
glRotatef(rquad, 1.0f, 1.0f, 1.0f);

// Set The Color To Blue One Time Only
glColor3f(0.5f, 0.5f, 1.0f);

// Start Drawing The Cube
glBegin(GL_QUADS);
glColor3f(0.0f, 1.0f, 0.0f); // Set The Color To Green
glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Top)
glVertex3f(-1.0f, 1.0f, 1.0f); // Bottom Left Of The Quad (Top)
glVertex3f(1.0f, 1.0f, 1.0f); // Bottom Right Of The Quad (Top)

glColor3f(1.0f, 0.5f, 0.0f); // Set The Color To Orange
glVertex3f(1.0f, -1.0f, 1.0f); // Top Right Of The Quad (Bottom)
glVertex3f(-1.0f, -1.0f, 1.0f); // Top Left Of The Quad (Bottom)
glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Bottom)
glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Bottom)

glColor3f(1.0f, 0.0f, 0.0f); // Set The Color To Red
glVertex3f(1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Front)
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Front)
glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Front)
glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Front)

glColor3f(1.0f, 1.0f, 0.0f); // Set The Color To Yellow
glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Back)
glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Back)
glVertex3f(-1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Back)
glVertex3f(1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Back)

glColor3f(0.0f, 0.0f, 1.0f); // Set The Color To Blue
glVertex3f(-1.0f, 1.0f, 1.0f); // Top Right Of The Quad (Left)
glVertex3f(-1.0f, 1.0f, -1.0f); // Top Left Of The Quad (Left)
glVertex3f(-1.0f, -1.0f, -1.0f); // Bottom Left Of The Quad (Left)
glVertex3f(-1.0f, -1.0f, 1.0f); // Bottom Right Of The Quad (Left)

glColor3f(1.0f, 0.0f, 1.0f); // Set The Color To Violet
glVertex3f(1.0f, 1.0f, -1.0f); // Top Right Of The Quad (Right)
glVertex3f(1.0f, 1.0f, 1.0f); // Top Left Of The Quad (Right)
glVertex3f(1.0f, -1.0f, 1.0f); // Bottom Left Of The Quad (Right)
glVertex3f(1.0f, -1.0f, -1.0f); // Bottom Right Of The Quad (Right)
// Done Drawing The Cube
glEnd();

// Increase The Rotation Variable For The Triangle
rtri += 0.2f;
// Decrease The Rotation Variable For The Quad
rquad -= 0.15f;
}


You can download the code from here.

Friday, January 26, 2007

NeHe Lesson 04: Rotation

The fourth NeHe lesson is about using the glRotate*() functions. Go read what he has to say about them here. The lesson builds on the previous one. I'll show the parts the have changed here.

First of we need to declare two need variables for the rotation.

/// Angle For The Triangle
GLfloat rtri = 0.0f;
/// Angle For The Quad
GLfloat rquad = 0.0f;

Here you must be careful with how D initializes floating point variables. For example if we had declared them like this: (Like the C-version)

/// Angle For The Triangle
GLfloat rtri;
/// Angle For The Quad
GLfloat rquad;

Then the variables would have been initialized to NaN and the triangle and the quad would not have shown on the screen at all. I've fallen for this many times, especially with these tutorials.

The drawGLScene function is the same except the calls to glRotatef and the glLoadIdentity in the middle. Try to leave it out and see what happens.

Having the variables rtri and rquad initialized to 0.0f wont do us much good if we don't change them, so there is at the end we change them slightly to archive the moving rotation effect.

/**
* The drawing function. Here we will draw the triangle and the quad.
* Now with color and rotation.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-1.5f, 0.0f, -6.0f);

// Rotate The Triangle On The Y axis
glRotatef(rtri, 0.0f, 1.0f, 0.0f);

// Drawing Using Triangles
glBegin(GL_TRIANGLES);
// Set The Color To Red
glColor3f(1.0f, 0.0f, 0.0f);
// Top
glVertex3f(0.0f, 1.0f, 0.0f);

// Set The Color To Green
glColor3f(0.0f, 1.0f, 0.0f);
// Bottom Left
glVertex3f(-1.0f, -1.0f, 0.0f);

// Set The Color To Blue
glColor3f(0.0f, 0.0f, 1.0f);
// Bottom Right
glVertex3f(1.0f, -1.0f, 0.0f);
// Finished Drawing The Triangle
glEnd();

// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Right 1.5 Units And Into The Screen 6.0
glTranslatef(1.5f, 0.0f, -6.0f);

// Rotate The Quad On The X axis
glRotatef(rquad, 1.0f, 0.0f, 0.0f);

// Set The Color To Blue One Time Only
glColor3f(0.5f, 0.5f, 1.0f);

// Draw A Quad
glBegin(GL_QUADS);
// Top Left
glVertex3f(-1.0f, 1.0f, 0.0f);
// Top Right
glVertex3f(1.0f, 1.0f, 0.0f);
// Bottom Right
glVertex3f(1.0f, -1.0f, 0.0f);
// Bottom Left
glVertex3f(-1.0f, -1.0f, 0.0f);
// Done Drawing The Quad
glEnd();

// Increase The Rotation Variable For The Triangle
rtri += 0.2f;
// Decrease The Rotation Variable For The Quad
rquad -= 0.15f;
}


You can download the code from here.

NeHe Lesson 03: Adding Color

This lesson adds some color to the dark realm of OpenGL magic. Go read what the Master has to say about color incantations.

I'll show you the whole spell here for your convenience. This lesson adds directly to the previous one.


/**
* The drawing function. Here we will draw the triangle and the quad.
* Now with color.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-1.5f, 0.0f, -6.0f);

// Drawing Using Triangles
glBegin(GL_TRIANGLES);
// Set The Color To Red
glColor3f(1.0f, 0.0f, 0.0f);
// Top
glVertex3f(0.0f, 1.0f, 0.0f);

// Set The Color To Green
glColor3f(0.0f, 1.0f, 0.0f);
// Bottom Left
glVertex3f(-1.0f, -1.0f, 0.0f);

// Set The Color To Blue
glColor3f(0.0f, 0.0f, 1.0f);
// Bottom Right
glVertex3f(1.0f, -1.0f, 0.0f);
// Finished Drawing The Triangle
glEnd();

// Move Right 3 Units
glTranslatef(3.0f, 0.0f, 0.0f);

// Set The Color To Blue One Time Only
glColor3f(0.5f, 0.5f, 1.0f);

// Draw A Quad
glBegin(GL_QUADS);
// Top Left
glVertex3f(-1.0f, 1.0f, 0.0f);
// Top Right
glVertex3f(1.0f, 1.0f, 0.0f);
// Bottom Right
glVertex3f(1.0f, -1.0f, 0.0f);
// Bottom Left
glVertex3f(-1.0f, -1.0f, 0.0f);
// Done Drawing The Quad
glEnd();
}


You can download the code from here.

NeHe Lesson 02: Your First Polygon

The NeHe lesson 2 is here. There's not much new code, but the GL functions used are maybe the most important you'll ever learn when doing OpenGL coding. So I suggest if you passed the link at the beginning then don't miss is it this time. Read the tutorial. NeHe explains things so much better than I ever could. Afterwards you can marvel how similar the D version looks like. Isn't it great. :)

The only difference between the first lesson and this one is the drawing function. I'll post only it as you can go and get the first one from here and just replace the drawGLScene function.

/**
* The drawing function. Here we will draw the triangle and the quad.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Reset The Current Modelview Matrix
glLoadIdentity();

// Move Left 1.5 Units And Into The Screen 6.0
glTranslatef(-1.5f, 0.0f, -6.0f);

// Drawing Using Triangles
glBegin(GL_TRIANGLES);
glVertex3f(0.0f, 1.0f, 0.0f); // Top
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
// Finished Drawing The Triangle
glEnd();

// Move Right 3 Units
glTranslatef(3.0f, 0.0f, 0.0f);

// Draw A Quad
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f); // Top Left
glVertex3f(1.0f, 1.0f, 0.0f); // Top Right
glVertex3f(1.0f, -1.0f, 0.0f); // Bottom Right
glVertex3f(-1.0f, -1.0f, 0.0f); // Bottom Left
// Done Drawing The Quad
glEnd();
}

Don't forget to change the title of the window to "NeHe's First Polygon Tutorial (D version)". Or to something else if you feel like it.

You can download the code from here.

Thursday, January 25, 2007

A few words

I wanted to say a few words about the requirements for building the lessons from my blog. First of all I'm working on a Windows box and wont be doing very much testing on the other platforms. The code is mostly cross-platform so it should compile and run just fine on Linux or Mac OS X. I'll try to point out places where I've used platform specific code.

Next you will need the D compiler. There are two choices at the moment, the DMD from DigitalMars and GDC a GCC based compiler from here.

You also need the shared library for your platform from the SDL website.

I use Derelict for OpenGL and SDL bindings. You can grab them from there or do as I do and use DSSS, the D Shared Software System.

After that you should be ready to go.

Please note, that I'm not going to go over how you can compile a D program or the basic usage of the SDL library. For those problems there are already very good documentation on the net. Google is your friend.

NeHe Lesson 01: Setting up an OpenGL window

Hi, and welcome to the NeHe lesson 01 done in the D programming language.

This code snippet shows you how to set up SDL to display an OpenGL window, How to use Derelict to load shared libraries and a basic loop for reading input and then drawing the screen.

I'm trying to use documenting comments in the code as specified by Ddoc.


/**
* The first lesson in the NeHe tutorial series.
* Originally written by Jeff Molofee.
*
* Authors: Jeff Molofee
* Olli Aalto
*/
module lesson01;

import derelict.opengl.gl;
import derelict.opengl.glu;
import derelict.sdl.sdl;

import tango.stdc.stringz;

/// The window title
const char[] WINDOW_TITLE = "NeHe's OpenGL Lesson 01 (D version)";

/// The main loop flag
bool running;

/**
* Module constructor. Here we load the GL, GLU and SDL shared libraries,
* and the initialize SDL.
*/
static this()
{
DerelictGL.load();
DerelictGLU.load();
DerelictSDL.load();

if (SDL_Init(SDL_INIT_VIDEO) < args =" the" fullscreen =" false;"> 1)
{
fullScreen = args[1] == "-fullscreen";
}

createGLWindow(WINDOW_TITLE, 640, 480, 16, fullScreen);
initGL();

running = true;
while (running)
{
processEvents();

drawGLScene();

SDL_GL_SwapBuffers();
SDL_Delay(10);
}
}

/**
* Process all the pending events.
*/
void processEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYUP:
keyReleased(event.key.keysym.sym);
break;
case SDL_QUIT:
running = false;
break;
default:
break;
}
}
}

/**
* Process a key released event.
*/
void keyReleased(int key)
{
switch (key)
{
case SDLK_ESCAPE:
running = false;
break;
default:
break;
}
}

/**
* Resize and initialize the OpenGL window.
*/
void resizeGLScene(GLsizei width, GLsizei height)
{
if (height == 0)
{
height = 1;
}

// Reset The Current Viewport
glViewport(0, 0, width, height);

// Select The Projection Matrix
glMatrixMode(GL_PROJECTION);

// Reset The Projection Matrix
glLoadIdentity();

// Calculate The Aspect Ratio Of The Window
gluPerspective(45.0f, cast(GLfloat)width / cast(GLfloat)height,
0.1f, 100.0f);

// Select The Modelview Matrix
glMatrixMode(GL_MODELVIEW);

// Reset The Modelview Matrix
glLoadIdentity();
}

/**
* Initialize OpenGL.
*/
void initGL()
{
// Enables Smooth Shading
glShadeModel(GL_SMOOTH);

// Black Background
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

// Depth Buffer Setup
glClearDepth(1.0f);

// Enables Depth Testing
glEnable(GL_DEPTH_TEST);

// The Type Of Depth Test To Do
glDepthFunc(GL_LEQUAL);

// Really Nice Perspective Calculations
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

/**
* The drawing function. Now we only clear the color and depht buffers, so that
* the window stays black.
*/
void drawGLScene()
{
// Clear The Screen And The Depth Buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

// Reset The Current Modelview Matrix
glLoadIdentity();
}

/**
* Initializes and opens the SDL window.
*/
void createGLWindow(char[] title, int width, int height, int bits,
bool fullScreen)
{
// Set the OpenGL attributes
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 6);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);

// Set the window title
SDL_WM_SetCaption(toUtf8z(title), null);

// Note the SDL_DOUBLEBUF flag is not required to enable double
// buffering when setting an OpenGL video mode.
// Double buffering is enabled or disabled using the
// SDL_GL_DOUBLEBUFFER attribute. (See above.)
int mode = SDL_OPENGL;
if (fullScreen)
{
mode |= SDL_FULLSCREEN;
}

// Now open a SDL OpenGL window with the given parameters
if (SDL_SetVideoMode(width, height, bits, mode) is null)
{
throw new Exception("Failed to open OpenGL window: " ~ getSDLError());
}

resizeGLScene(width, height);
}

/**
* Get the SDL error as a D string.
*
* Returns: A D string containing the current SDL error.
*/
char[] getSDLError()
{
return fromUtf8z(SDL_GetError());
}

You can download the code from here.

Introduction

So here it is. My very first blog post. Been thinking about this for a while now. Finally figured out what I could write about. I'm going to put my versions of the NeHe OpenGL tutorials, written in the D programming language, here. I will be using the SDL library for window handling and input.

I have also some other stuff which relates to D, OpenGL and games. I'll be posting about them too when I feel that I have a single module which is "good enough" to post about. Right now I have almost finished vector and matrix templates.

But now I will welcome you to my blog. Let the writing commence.