Adding lights

In this chapter, we will learn how to illuminate a 3D scene using OpenGL lights.

Getting ready

Include the necessary files to use OpenGL lights, materials, and draw. Add the following code to the top of the source file:

#include "cinder/gl/gl.h"
#include "cinder/gl/Light.h"
#include "cinder/gl/Material.h"

Also add the following using statements:

using namespace ci;
using namespace ci::app;
using namespace std;

How to do it…

We will use the default OpenGL light rendering methods to illuminate our scene. We will use the ci::gl::Material and ci::gl::Light classes, which are wrappers around the OpenGL functionality.

  1. Declare ci::gl::Material to define the material properties of the objects being drawn and ci::Vec3f to define the lights position.
    gl::Material mMaterial;
    Vec3f mLightPos;
  2. Let's set the materials Ambient, Diffuse, Specular, Emission, and Shininess properties by adding the following code in the setup method:
    mMaterial.setAmbient( Color::black() );
    mMaterial.setDiffuse( Color( 1.0f, 0.0f, 0.0f ) );
    mMaterial.setSpecular( Color::white() );
    mMaterial.setEmission( Color::black() );
    mMaterial.setShininess( 128.0f );
  3. In the update method, we will use the mouse to define the light position. Add the following code in the update method:
    mLightPos.x = getMousePos().x;
    mLightPos.y = getMousePos().y;
    mLightPos.z = 200.0f;
  4. In the draw method, we will begin by clearing the background, setting the window's matrices, and enabling reading and writing to the depth buffer.
    gl::clear( Color::black() );
    gl::setMatricesWindowPersp( getWindowWidth(), getWindowHeight() );
    gl::enableDepthWrite();
    gl::enableDepthRead();
  5. Let's create an OpenGL light using a ci::gl::Light object. We will define it as a POINT light and set its ID to 0. We will also set its position to mLightPos and define its attenuation.
    gl::Light light( gl::Light::POINT, 0 );
    light.setPosition( mLightPos );
    light.setAttenuation( 1.0f, 0.0f, 0.0f );
  6. Let's enable OpenGL lighting, the previously created light, and apply the material.
    glEnable( GL_LIGHTING );
    light.enable();
    mMaterial.apply();
  7. Let's draw a rotating Torus at the center of the window and use the elapsed seconds to rotate it. Add the following code to the draw method:
    gl::pushMatrices();
    gl::translate( getWindowCenter() );
    float seconds = (float)getElapsedSeconds() * 100.0f;
    glRotatef( seconds, 1.0f, 0.0f, 0.0f );
    glRotatef( seconds, 0.0f, 1.0f, 0.0f );
    gl::drawTorus( 100.0f, 40.0f, 30, 30 );
    gl::popMatrices();
  8. Finally, disable the light:
    light.disable();
  9. Build and run the application; you will see a red rotating torus. Move the mouse to change the lights position.
    How to do it…

How it works…

We are using the ci::gl::Material and ci::gl::Light objects, which are helper classes to define the properties of lights and materials.

The material properties defined in the setup method, work in the following ways:

Material Property

Function

Ambient

How an object can reflect light that comes in all directions.

Diffuse

How an object reflects light that comes from a specific direction or position.

Specular

The light that an object will reflect as a result of diffuse lighting.

Emission

Light emitted by the object.

Shininess

The angle that the object will reflect specular light. Has to be a value between 1 and 128.

The material ambient, diffuse, and specular colors will multiply with the ambient, diffuse, and specular colors coming from the light source, which are all white by default.

It is possible to define three different types of lights. In the previous example, we defined our light source to be of type ci::gl::Light::POINT.

Here are the available types of light and their properties:

Light Type

Properties

ci::gl::Light::POINT

Point light is the light coming from a specific position in space and illuminating in all directions.

ci::gl::Light::DIRECTION

Directional light simulates light coming from a position so far away that all light rays are parallel and arrive in the same direction.

ci::gl::Light::SPOTLIGHT

Spotlight is the light coming from a specific position in space and a specific direction.

We also defined the attenuation values. Lights in OpenGL allow for defining the values for the constant attenuation, linear attenuation, and quadratic attenuation. These define how the light becomes dimmer as the distance from the light source increases.

To illuminate geometry, it is necessary to calculate the normal for each vertex. All shapes created using Cinder's commands have their normal calculated for us, so we don't have to worry about that.

There's more…

It is also possible to define the ambient, diffuse, and specular colors coming from the light source. The values defined in these colors will multiply with the correspondent colors of the material.

Here are the ci::gl::Light methods that allow you to define the light colors:

Method

Light

setAmbient( const Color& color )

Color of the ambient light.

setDiffuse( const Color& color )

Color of the diffuse light.

setSpecular( const Color& color )

Color of the specular light.

It is possible to create more than one light source. The amount of lights is dependent on the implementation of the graphics card, but it is always at least 8.

To create more light sources, simply create more ci::gl::Light objects and make sure each gets a unique ID.

See also

Please read the recipe Calculating vertex normals to learn how to calculate the vertex normals for user created geometry.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.188.121