Planning the Spontaneous

It's more than just a blueprint.

AndThenThereWas(light);

Posted by Robert Chow on 30/10/2009

Lighting and Materials. Theoretically, it’s one of the first things you should really learn when you’re getting into graphics – it’s usually within the first 10 tutorials that you’ll pick up from anywhere. In theory, no one should have much of a problem with it. In theory, theorists should have done their research before making these theories. But then again, I am no theorist.

This carries on from my last post.  So we’re going to touch up on how I made the planets glow like they do in the picture, and how lighting and materials have been an absolute pain (that is, until I finally decided to do a little reading).

Dim Lighting

The first time I touched lighting and materials was in university during an examples class – and it was easy.  All I had to do as change a couple of numbers, and voila, the lighting changed.  It’s a little bit more difficult when I was trying it out for myself.  The first thing I tried to demo was a rotating diamond, with a static light shining on it.  As the diamond rotated, the light was moving up and down.  How, and why, I have no idea, and I still don’t.  Second thing I tried was to have the light in the middle of the scene, and 2 gluSpheres either side, so each would have only the side facing the light shining, and the other dark as night.  Nope.  As I drew the second sphere, it would look exactly the same as the first – light shining on the same side.  And no idea still as to why.  Maybe I’m missing something really important, that not many people have encountered before (by the way, quite a few people have had the problem with the light moving up and down as the object rotates), or maybe I’m just unlucky.

It could be seen as a bad thing that I still don’t know why the lights weren’t working the way I wanted them to – I’ve managed to get over it.  Because now I know how lights work, and I don’t really see why I would want to replicate the problems again.

Lighting & Materials

The calls to create lighting and materials are very short and simple.  Initially, you need to enable lighting, and also, enable the lights – OpenGL allows you to use 8 lights in total, and say that you should really reconsider your model if you need any more.   So apart from the enable call, there are only 3 calls that you really need to consider. The first describes the general light model, and the other two each describe either the lighting or the materials.  These are, respectively:

Gl.glLightModelfv(pName, params);

Gl.glLightfv(light, pname, param);
where light is the light number, from Gl.GL_LIGHT0 to Gl.GL_LIGHT7.
and pName is either Gl.GL_POSITION, Gl.GL_AMBIENT, Gl.GL_DIFFUSE or Gl.GL_SPECULAR.*

Gl.glMaterialfv(face, pname, param);
where the face is either Gl.GL_FRONT, or Gl.GL_BACK.
and pName is either Gl.GL_AMBIENT, Gl.GL_DIFFUSE, Gl.GL_SPECULAR, Gl.GL_SHININESS or Gl.GL_EMISSION.*

(bearing in mind that the suffix fv applies to float arrays only – this needs to be changed if you were to use any other, say double – this would be dv).

*For now, I will only be looking at the specific parameters I have enlisted.  For further information, you can find it in the OpenGL Documentation.

Placing A Light

Where you place a light in the scene is very important – this is where the light source is, and will be used to calculate how light bounces and reflects off materials.  In order for you to be able to place your light in a desired position, you need to understand how it is set up.  To set up a light, you use the glLight() call, with parameter GL_POSITION.  Obvious right?  The params should be a vector, indicating x, y, z and w.  x, y and z are your co-ordinates of the light, and I’ve a feeling that w should always be 1.0f in order for it to work this way.  However, despite making this call, the light is not necessarily in the place you have specified in world space.  The call will always look at what is the current modelview matrix at the time of the call, and will always place the light specific to the matrix.  Therefore if the entire scene is to be translated backwards so it will fit into a frustum view volume, make a call to set the light position after the translation.

Lighting and Material Properties

The properties I have outlined, you will see everywhere in material and lighting.  The properties describe how the light reacts to surfaces.

Ambient
Describes the general lighting of an object – it has brilliantly been quoted from my 2nd year course as, “it just hangs there”.  As a result, it does not take into account how light reflects off a particular object – it is the general lighting – and as a result, it will not help to define the contours of any shape.

Diffuse
This property describes the diffuse reflection of a material.  This takes into account of how the light will reflect off a particular surface, and how some of the light will also be absorbed.  Using the ambient property will describe the general color of an object, whereas to define how the object looks in light, use the diffuse property.

Specular
Lighting will sometimes reflect entirely off an object – this depends on the angle the light is reflecting off the surface at.  Specular reflection reflects the light shining onto an object and makes it appear shiny; the scale is determined by the shininess property.

Shininess
The describes the sharpness of the light reflected due to specular lighting.  The higher the value, the more shiny it is, and therefore the sharper the image of the light reflecting off the object.

Emission
This property describes the amount of light that is emitted off an object.  In OpenGL, the property makes the object appear as if it is emitting light, however, in the model, this light does not affect any other objects – you will need to use an actual light for this.

Setting the material properties will affect how light reacts to an object – the light properties also need to be set for this to happen.  All of the above properties take a float array, representing red, green, blue and alpha, with the exception of shininess, which takes a number between 0 and 128.

Light PropertiesLight Properties.  This depicts how, from left to right, ambient, diffuse and specular lighting can be used together to represent a 3-D sphere, far right.

Solar System

So now you know how it is done, it’s time to put it all together.  In my solar system model, I used two lights: one to represent the sun; and the other, to add a little extra.

To set up, we describe the light model, and then the lights we’re going to use – do this at the start so it doesn’t get called millions of times in the render loop. As we are simulating outer space, the light model is set at very low, near black.  The ambient and diffuse settings for the lights are also set up.

Gl.glLightModelfv(Gl.GL_LIGHT_MODEL_AMBIENT, new float[] { 0.05f, 0.05f, 0.05f, 1.0f });

Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_AMBIENT, new float[] { 0.0f, 0.0f, 0.0f, 1.0f });
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_DIFFUSE, new float[] { 1.0f, 1.0f, 1.0f, 1.0f });
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_AMBIENT, new float[] { 0.0f, 0.0f, 0.0f, 1.0f });
Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_DIFFUSE, new float[] { 1.0f, 1.0f, 1.0f, 1.0f });

Gl.glEnable(Gl.GL_LIGHTING);
Gl.glEnable(Gl.GL_LIGHT0);

You will have noticed that I have also enabled lighting, and Light0, but not Light1.  Using light0 as my main light to represent the sun, this will be constantly on, and therefore we do not need to call this in the render loop, as it only needs to be called once.  I am using Light1 as an effect on the sun, to make it appear 3-D, and therefore should only be turned on when I render the sun, but turned off when I render everything else.  The reason behind using the light as an effect on the sun is because I am setting the sun to have an emission property.  The makes the sun appear as if it is giving out light.  Not only this, but the light source representing the sun is inside the sun sphere, and will not affect the outside, making the sphere look flat.  Turning a light onto the sun, and using a diffuse property, will make the sun appear 3-D.  Now to render the scene.

First we translate the scene into view, it is here, where we place the light representing the sun.  Note that I am placing the light position after the translation so the light is also in view.  The light is not, however, affected by the rotation after the position call, nor any other call after regarding the matrix stacks.

Gl.glMatrixMode(Gl.GL_MODELVIEW);
Gl.glLoadIdentity();

Gl.glTranslatef(-2000.0f, 0.0f, -4000.0f);
Gl.glLightfv(Gl.GL_LIGHT0, Gl.GL_POSITION, new float[] { 0f, 0f, 0f, 1.0f });
Gl.glRotatef(30, 1, 0, 0);

We want to draw the sun, with a radius of about 140.0f, and to have a light shining onto it so it appears 3-D.  This is where Light1 comes in.  It is placed just outside of the sun so it is able to hint the sphere with a bit of light.

Gl.glLightfv(Gl.GL_LIGHT1, Gl.GL_POSITION, new float[] { 150.0f, 150.0f, 150.0f, 1.0f });
Gl.glEnable(Gl.GL_LIGHT1);
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_AMBIENT_AND_DIFFUSE, new float[] {1.0f, 1.0f, 0.5f, 1.0f });
Gl.glMaterialfv(Gl.GL_FRONT, Gl.GL_EMISSION, new float[] { 1.0f, 1.0f, 0.5f, 1.0f });
// Draw GluSphere here
Gl.glDisable(Gl.GL_LIGHT1);

I have used a little shortcut here, declaring the ambient and diffuse property at the same time.  This is very useful, as the cahnces are, these will be the same values for the majority of basic objects anyway.  Enabling the light before and after drawing the sun makes sure that the light only affects the sun and no other object that is being rendered.  Now we are free to draw the other planets.  Using a similar approach, we set the position, and material, and draw.  We only need to set the material once if the following objects use the same material.  Similar to glColor() – you only set the color if the next vertex to be drawn is a different color to that of the current one being drawn.  Therefore when we draw the other planets, we have to make sure we set the emission to black, otherwise it will appear all the planets are giving off light!

Do bear in mind that in order for your lighting and materials to work properly, enable lighting.  The material settings will automatically override the color settings you have, so if you want to draw an object without the material lighting, just remember to disable it first!

I know this post has been very long, slightly overdue, and may seem like it’s been cut short, and to be fair, it could be a lot longer and more well covered.  I’ll try to keep the next one shorter, I promise!

 

Advertisements

One Response to “AndThenThereWas(light);”

  1. […] be switched on or off, and have different properties to one another – going back to the lighting post, the ambient, diffuse and specular properties of a light can be defined. We could do this using two […]

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: