Planning the Spontaneous

It's more than just a blueprint.

Posts Tagged ‘Lighting’

MultiOpenGlControl Demo

Posted by Robert Chow on 16/04/2010

I’ve managed to grab some video capture software and also produce a small demo of using multiple SimpleOpenGlControls.  Each screen has it’s own camera, focusing on to the same scene.  Using lighting and picking, clicking a face of the cube will change the scene, and thus be reflected in all of the cameras.

I did have a little trouble with the picking at first – when I picked, I forgot to change the current camera, so it would register the mouse click on one screen whilst using the camera of another.  With that fixed, it was nice to be able to play around with Renderer again.

True, the videos not suppose to be a hit, but at least it’s showing what I want it to.

Posted in Computing, Placement | Tagged: , , , , , , , , , | Leave a Comment »

Renderer: Demo

Posted by Robert Chow on 16/12/2009

So now that I’ve got a lot of my functionality going for me in this component, I thought I’d try and create a snazzy demo.

My supervisor’s obsessed with it. It’s like a little game – there is a rotating cube, and the challenge is you have to click on each face before you pass on to the next level. As you progress, the cube rotates just that little bit faster, making it harder to complete the challenge. Clicking on a face will turn that face on. Clicking on a face that is already on will turn it off – you can only progress when all 6 faces are switched on.

So you can automatically see that this little demo already involves the concept of vertex buffer objects (drawing of the cube), the scene graph (rotating cube), the camera (viewing the cube, using the scene graph) and picking (turning faces on/off). But what about the others?

Well, lets place the scene into dark surroundings – we’re going to need lights to see our cube – that’s lighting handled. So where does texturing fit in?

Switching the faces on/off need an indicator to show what state they are in.  We can easily do this by simply changing the colour of a face.  But that’s kinda boring.  So instead, we’re going to take the rendering to texture example, and slap that on a face which is on.  So that’s textures included.

Here are some screenshots of this demo.

Demo Setup. From left to right: initial scene – just a white cube; let’s dim the lighting to, well, none; include some lights: green – centre, red – bottom, blue – left; create a texture.

Demo Rotate. The demo in motion – the camera is stationary, whereas the cube is rotating, and the lights are rotating independantly around it.

Demo Play.  The first and second images show what happens when a face is clicked – the texture replaces the blank face.  Once all the faces are replaced with the texture, the demo advances to the next level.

Demo Camera.  This shows added functionality of how a camera can be fixed on to a light, thus the camera is rotating around the cube too.  Here it is fixed on to the blue light.  This is done with ease by manipulating the scene graph.

I guess you can’t really get a grasp of how this demo works in its entirety – sanpshots don’t really do it much justice.  I might try and upload a video or so – how, I’m unsure of – I’m sure I can probably find screen capture software around on the net.

And unfortunately, there is no score involved. Yet. That will come when fonts come.

Posted in Computing, Placement | Tagged: , , , , , , , , | 2 Comments »

Renderer: Lighting

Posted by Robert Chow on 15/12/2009

So these are tricky too.

OpenGL only allows 8 lights at any one time, and should you need more, they suggest you ought to reconsider how you draw your model.

As it is not just one light available, we need to be able to differentiate between each light.  We do this by declaring an enum.

public enum LightNumber
{
GL_LIGHT0 = Gl.GL_LIGHT0,
GL_LIGHT1 = Gl.GL_LIGHT1,
..
..
GL_LIGHT7 = Gl.GL_LIGHT7
}

An enum, like classes, can be used as parameters, with one restriction – the value of the parameter must be equal to one of the values decalered within the enum.  In the context of lights, the LightNumber can only be either GL_LIGHT0, GL_LIGHT1, GL_LIGHT2 and so forth until GL_LIGHT7; giving us a maximum of 8 lights to choose from.  For an enum, the values on the left-hand side are names.  These names can be referred to.  However, you can then assign these names values, as I have done – in this case, it is their correspondant OpenGL value.

So now we can set our lights, and attach them to a node, similar to the camera.  Kind of.  Unlike the camera, these lights can either 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 methods.

Renderer.SwitchLightOn(LightNumber lightNumber, bool on);
Renderer.ChangeLightProperty(LightNumber lightNumber, LightProperty lightProperty, Colour colour);

We could.

But we shouldn’t.

I’ve been reading a lot lately about refactoring – cleaning up code, making it better, more extensible, and easier to read. A few months ago, I stumbled across this guide to refactoring. A lot of things were simple and made a lot of common sense. But it was intelligent. Something which, everyone becomes every now and then.  And it’s definately worth a read.  Another one I’ve ben reading of late is this book on clean code.  How good really is your code?

The Only Valid Measurement Of Code Quality.  This image has been taken from http://sayamasihbelajar.wordpress.com/2008/10/24/

Naming conventions are rather important when it comes to something like this, and using a bool as a parameter – doesn’t exactly mean much.  Once there is a bool, you will automatically know that the method does more than one thing – one thread for true, and another for false.  So split them.

Renderer.SwitchLightOn(LightNumber lightNumber);
Renderer.SwitchLightOff(LightNumber lightNumber);

There a lot of wrongs and rights, but no concrete answer – just advice that these books can give you.  So I’m not going to trip up on myself and try and give you some more advice – I’m only learning too.

Posted in Computing, Placement | Tagged: , , , , , , , | 3 Comments »

Anti-Alias = Blend * (1 – Alpha);

Posted by Robert Chow on 05/11/2009

So the term alpha, in computing, has many meanings. There is alpha testing, where a piece of software is tested by giving it out to the internal users of an organisation to tear to pieces – the stage before the public get their betas (I think this is the appropriate time to say that I just got VS2010 beta 2 the other day, and it’s as sexy as hell, but more on that another time). It can also be used to describe the weighting of data in machine learning. But I’m not doing machine learning. Or testing (yet). I’m doing graphics.

The alpha I am referring to is the alpha channel used to represent a colour, and it’s very handy. Although it can be a little misunderstood, as I learnt during my experiments.

The Alpha Channel

To represent a color, you usually have the option of choosing the red, green and blue components of a color, but what if you want it to be slightly translucent?  There is an alpha component – this determines how “full” the color is.  On a scale of 0 to 1, 0 is transparent, and 1 is opaque; anywhere in between is translucent.  So this is fairly easy to declare in OpenGL.  Where red, green, blue and alpha are float values between 0 and 1:

Gl.glColor4f(red, green, blue, alpha);

Of course, OpenGL doesn’t like to make life easy for us, no.  We have to also enable blending.  This allows for the alpha channel to do its magic, and the blend function also determines on how the alpha channel is used.

Gl.glEnable(Gl.GL_BLEND);
Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA);

The 2 parameters of the blend function determine how the alpha channel is used – the parameters I have used in the example are the ones best used for transparency.  These parameters allow you to do lots of different blending techniques, such as blend towards no transparency or full transparency, or reverse blend – I’m not really the one to ask on how these work, because I’m not entirely sure – you’re best looking it up.  Of course, the complexity doesn’t stop there either.

A Trick of Light

When working with transparency, the order of the objects when being drawn is important.  Especially if you are using lighting.

As a general rule, for opaque objects, draw them in the order of front to back (taking the front as the nearest to you), and for transparent or translucent objects, back to front.

For opaque objects, this is because (I believe, but not entirely sure)  OpenGL is clever enough to deduce on if an object at the back needs to drawn or not – it will not be drawn if there is an object in front of it, obscuring the camera view from the object.  Of course, the only way to deduce if there is an object in front of it, is if there is an object already there.

For transparent and translucent objects, drawing them back to front ensures that the lighting algorithm in OpenGL works properly.  As the object is drawn, it OpenGL will always look at what is behind the object, and try to blend the current object being drawn with what is behind it accordingly.  An object at the front with transparency property will not take into account what is behind it, if the object behind it is being drawn after it.  I found this out when I was trying to draw partially transparent boxes.

Transparency DrawingTransparency Drawing.  This shows how drawing partially transparent objects has to be done in a particular way for OpenGL to display the scen properly.  The top two pictures show the component this cube is made out of: an blue opaque base, and a clear, green front.  The picture in the bottom-left shows what happens when the translucent part, at the front, is drawn before the opaque part, behind it.  It looks exactly the same as the picture in the top-right – this is because it both pictures, the front is blending what was initially behind the it – the black background.  The bottom-right picture shows the drawing when drawn in the correct order, base first, then the translucent front.

Anti-Aliasing

Anti-aliasing is an effect used to make lines and shapes appear smoother, and less discrete, or pixelated.  This effect does this by a slight blurring, and in effect, is using blending.  As a result, the same rule of drawing transparent objects from back to front should be applied to when trying to use an anti-alias effect.

There are 3 types of anti-aliasing that OpenGL offers with easy access.  Any other types of anti-aliasing, you will have to look elsewhere – I am no expert of OpenGL.  Essentially, if you refer back to when I was creating fonts, it uses mip-mapping as a way of keeping detail and quality as images are getting smaller and smaller – you could argue that this is a form of anti-aliasing too.

The 3 OpenGL offers are line, point and polygon anti-aliasing, and unsurprisingly, they refer to lines, points and polygons.

These are easy to switch on with an enable call.  You can then provide OpenGL with a parameter on how you want the anti-aliasing effect to behave.

Gl.glEnable(Gl.GL_LINE_SMOOTH);
Gl.glHint(Gl.GL_LINE_SMOOTH_HINT, Gl.GL_FASTEST);

Gl.glEnable(Gl.GL_POINT_SMOOTH);
Gl.glHint(Gl.GL_POINT_SMOOTH_HINT, Gl.GL_NICEST);

Gl.glEnable(Gl.GL_POLYGON_SMOOTH);
Gl.glHint(Gl.GL_POLYGON_SMOOTH_HINT, Gl.GL_DONT_CARE);

The hints describe how you want OpenGL to do the anti-aliasing – you can either have it as the nicest OpenGL will allow, the fastest to calculate to save on speed, or nor preference.

Anti-Alias TrianglesAnti-Alias Triangles.  The picture on the left is similar to the picture on the right, with the exception that anti-aliasing is on.  You can notice a subtle difference in the smoothness of the edges on the triangles.  OpenGL achieves this effect using blurring and blending techniques.

As a side note, I’ve now finally started the Renderer component!  So the majority, if not all, of what I have covered so far regarding OpenGL will go into this component.  This will mean that I won’t be updating big tutorial-esque posts on OpenGL anymore – there might be something every now and then.  I will however, be posting any revelations I come across!

 

Posted in Computing, Placement | Tagged: , , , , , , , | Leave a Comment »

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!

 

Posted in Computing, Placement | Tagged: , , , , , , , | 1 Comment »