8. Creating and Setting up Light Sources
<< RETURN TO THE PREVIOUS SECTION
Lighting is the basis of every scene defining colors and final look of your objects. Lights in UNIGINE are created the same way as all nodes.
#include <UnigineLights.h>
using namespace Unigine;
/* ... */
int AppWorldLogic::init()
{
// creating a world light source an setting its color to white
thesun = LightWorld::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f));
// setting light source's parameters (intensity, disable angle, scattering type, name and rotation)
thesun->setName("Sun");
thesun->setDisableAngle(90.0f);
thesun->setIntensity(1.0f);
thesun->setScattering(LightWorld::SCATTERING_SUN);
thesun->setWorldRotation(Math::quat(0.0f, 1.0f, 0.0f, 170.0f));
// passing node ownership to the editor
thesun->release();
Editor::get()->addNode(thesun->getNode());
return 1;
}
Additional information:
- For more information on light sources, see Light sources page.
- For more information on light sources API, see Lights-Related Classes page.
Project Progress
In our project we are going to use three different light sources: LightWorld, LightOmni and LightProj. To create them let us write a method called initLights.
In the AppWorldLogic.h file, we include the UnigineLights.h library, define smart pointers for the light sources and declare our initLights method.
// AppWorldLogic.h
/* ... */
#include <UnigineLights.h>
/* ... */
class AppWorldLogic : public Unigine::WorldLogic {
public:
/* .. */
private:
/* .. */
int initLights();
/* .. */
// light sources
Unigine::LightWorldPtr thesun;
Unigine::LightOmniPtr light_omni;
Unigine::LightProjPtr projector;
/* .. */
};
In the AppWorldLogic.cpp file let us implement our initLights method and insert it into the AppWorldLogic::init() method.
// AppWorldLogic.cpp
/* .. */
/// method performing initialization of lights
int AppWorldLogic::initLights()
{
// creating an omni light and setting up its parameters
light_omni = LightOmni::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f), 10.0f, "");
light_omni->setWorldPosition(Math::Vec3(0.0f, 0.0f, 5.0f));
light_omni->setIntensity(0.1f);
// passing node ownership to the editor
light_omni->release();
editor->addNode(light_omni->getNode());
// reporting progress to the console
Log::message("-> Created a %s light source.\n", light_omni->getName());
// creating a world light and setting up its parameters
thesun = LightWorld::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f));
thesun->setName("Sun");
thesun->setDisableAngle(90.0f);
thesun->setIntensity(1.0f);
thesun->setScattering(LightWorld::SCATTERING_SUN);
thesun->setWorldRotation(Math::quat(0.0f, 1.0f, 0.0f, 170.0f));
// passing node ownership to the editor
thesun->release();
editor->addNode(thesun->getNode());
// reporting progress to the console
Log::message("-> Created a %s light source.\n", thesun->getName());
// creating a proj light and setting up its parameters
projector = LightProj::create(Math::vec4(1.0f, 1.0f, 0.5f, 1.0f), 10.0f, 60.0f, "");
projector->setWorldPosition(Math::Vec3(2.5f, 2.5f, 3.0f));
projector->setName("projector");
projector->setRotation(Math::quat(-45.0f, 45.0f, 0.0f));
projector->setPenumbra(0.425f);
projector->setIntensity(1.0f);
// passing node ownership to the editor
projector->release();
editor->addNode(projector->getNode());
// reporting progress to the console
Log::message("-> Created a %s light source.\n", projector->getName());
Log::warning("Light initialization OK!\n");
return 1;
}
/* .. */
int AppWorldLogic::init()
{
/* .. */
// creating lights
initLights();
/* .. */
return 1;
}
/* .. */
Source Files
You can copy the code below and paste it to the corresponding source files of your project:
AppWorldLogic.h
#ifndef __APP_WORLD_LOGIC_H__
#define __APP_WORLD_LOGIC_H__
#include <UnigineLogic.h>
#include <UnigineStreams.h>
#include <UnigineObjects.h>
#include <UnigineEditor.h>
#include <UnigineGame.h>
#include <UnigineLights.h>
class AppWorldLogic : public Unigine::WorldLogic {
public:
AppWorldLogic();
virtual ~AppWorldLogic();
virtual int init();
virtual int update();
virtual int render();
virtual int flush();
virtual int shutdown();
virtual int destroy();
virtual int save(const Unigine::StreamPtr &stream);
virtual int restore(const Unigine::StreamPtr &stream);
private:
Unigine::Editor *editor;
Unigine::PlayerSpectatorPtr player;
// pointers to light sources
Unigine::LightWorldPtr thesun;
Unigine::LightOmniPtr light_omni;
Unigine::LightProjPtr projector;
// auxiliary functions
int addMeshToScene(const char *file_name, const char *mesh_name, const char *material_name, Unigine::Math::Vec3 position);
// initialization functions
int initObjects();
int initPlayer();
int initLights();
// scene objects vector
Unigine::Vector <Unigine::ObjectMeshDynamicPtr> Objects;
};
#endif // __APP_WORLD_LOGIC_H__
AppWorldLogic.cpp
#include "AppWorldLogic.h"
// World logic, it takes effect only when the world is loaded.
// These methods are called right after corresponding world script's (UnigineScript) methods.
using namespace Unigine;
//-----------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------- AUXILIARY FUNCTIONS AND METHODS ----------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------
/// method adding a Dynamic Mesh Object to the scene. If an empty filename is passed the method creates a default box; otherwise, loads a mesh-file with a given name.
int AppWorldLogic::addMeshToScene(const char *file_name, const char *mesh_name, const char *material_name, Math::Vec3 position)
{
MeshPtr mesh = Mesh::create();
ObjectMeshDynamicPtr omd;
if (filename){ // loading a mesh from a specified file
if (!mesh->load(filename))
{
Log::error("\nError opening .mesh file!\n");
mesh.clear();
return 0;
}
else omd = ObjectMeshDynamic::create(mesh);
}
else // creating a default box
{
mesh->addBoxSurface("box_surface", Math::vec3(0.5f));
omd = ObjectMeshDynamic::create(mesh);
}
// setting node material, name and position
omd->setMaterial(material_name, "*");
omd->setName(mesh_name);
omd->setWorldPosition(position);
// passing node ownership to the editor as a runtime node
omd->release();
editor->addNode(omd->getNode());
// updating the list of scene objects
Objects.append(omd);
// reporting progress to the console
Log::message("-> Object %s added to the scene.\n", mesh_name);
// clearing the mesh
mesh->clear();
return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------- INITIALIZATION METHODS -------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of the set of 4 boxes
int AppWorldLogic::initObjects()
{
int index = 0;
for (int x = 0; x < 2; x++)
{
for (int y = 0; y < 2; y++)
{
addMeshToScene(NULL, String::format("my_meshdynamic_%d", index).get(), "mesh_base", Math::Vec3(x, y, 1.0f));
index++;
}
}
// reporting progress to the console
Log::warning("Objects generation OK!\n\n");
return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of the player
int AppWorldLogic::initPlayer()
{
// creating a new PlayerSpectator instance
player = PlayerSpectator::create();
// setting player's FOV, ZNear, ZFar
player->setFov(90.0f);
player->setZNear(0.1f);
player->setZFar(10000.0f);
// setting player's view direction vector and position
player->setPosition(Math::Vec3(3.0f));
player->setDirection(Math::vec3(-1.0f), Math::vec3(0.0f, 0.0f, -1.0f));
// setting the player to the Game singleton instance
Game::get()->setPlayer(player->getPlayer());
player->release();
//reporting progress to the console
Log::warning("\nPlayer initialization OK!\n\n");
return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
/// method performing initialization of lights
int AppWorldLogic::initLights()
{
// creating an omni light and setting up its parameters
light_omni = LightOmni::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f), 10.0f, "");
light_omni->setWorldPosition(Math::Vec3(0.0f, 0.0f, 5.0f));
light_omni->setIntensity(0.1f);
// passing node ownership to the editor
light_omni->release();
editor->addNode(light_omni->getNode());
// reporting progress to the console
Log::message("-> Created a %s light source.\n", light_omni->getName());
// creating a world light and setting up its parameters
thesun = LightWorld::create(Math::vec4(1.0f, 1.0f, 1.0f, 1.0f));
thesun->setName("Sun");
thesun->setDisableAngle(90.0f);
thesun->setIntensity(1.0f);
thesun->setScattering(LightWorld::SCATTERING_SUN);
thesun->setWorldRotation(Math::quat(0.0f, 1.0f, 0.0f, 170.0f));
// passing node ownership to the editor
thesun->release();
editor->addNode(thesun->getNode());
// reporting progress to the console
Log::message("-> Created a %s light source.\n", thesun->getName());
// creating a proj light and setting up its parameters
projector = LightProj::create(Math::vec4(1.0f, 1.0f, 0.5f, 1.0f), 10.0f, 60.0f, "");
projector->setWorldPosition(Math::Vec3(2.5f, 2.5f, 3.0f));
projector->setName("projector");
projector->setRotation(Math::quat(-45.0f, 45.0f, 0.0f));
projector->setPenumbra(0.425f);
projector->setIntensity(1.0f);
// passing node ownership to the editor
projector->release();
editor->addNode(projector->getNode());
// reporting progress to the console
Log::message("-> Created a %s light source.\n", projector->getName());
Log::warning("Lights initialization OK!\n");
return 1;
}
//-----------------------------------------------------------------------------------------------------------------------------
AppWorldLogic::AppWorldLogic() {
}
AppWorldLogic::~AppWorldLogic() {
}
int AppWorldLogic::init() {
// Write here code to be called on world initialization: initialize resources for your world scene during the world start.
// getting a pointer to the Editor
editor = Editor::get();
// creating objects
initObjects();
// creating a player
initPlayer();
//creating lights
initLights();
return 1;
}
// start of the main loop
int AppWorldLogic::update() {
// Write here code to be called before updating each render frame: specify all graphics-related functions you want to be called every frame while your application executes.
return 1;
}
int AppWorldLogic::render() {
// The engine calls this function before rendering each render frame: correct behavior after the state of the node has been updated.
return 1;
}
int AppWorldLogic::flush() {
// Write here code to be called before updating each physics frame: control physics in your application and put non-rendering calculations.
// The engine calls flush() with the fixed rate (60 times per second by default) regardless of the FPS value.
// WARNING: do not create, delete or change transformations of nodes here, because rendering is already in progress.
return 1;
}
// end of the main loop
int AppWorldLogic::shutdown() {
// Write here code to be called on world shutdown: delete resources that were created during world script execution to avoid memory leaks.
// deleting all created nodes
for(int i = 0; i < Objects.size(); i++)
{
// removing current node from the scene
editor->removeNode(Objects[i]->get()->getNode());
}
// updating the list of scene objects
Objects.clear();
// clearing the player pointer
player.clear();
// clearing light sources
thesun.clear();
light_omni.clear();
projector.clear();
return 1;
}
int AppWorldLogic::destroy() {
// Write here code to be called when the video mode is changed or the application is restarted (i.e. video_restart is called). It is used to reinitialize the graphics context.
return 1;
}
int AppWorldLogic::save(const Unigine::StreamPtr &stream) {
// Write here code to be called when the world is saving its state (i.e. state_save is called): save custom user data to a file.
UNIGINE_UNUSED(stream);
return 1;
}
int AppWorldLogic::restore(const Unigine::StreamPtr &stream) {
// Write here code to be called when the world is restoring its state (i.e. state_restore is called): restore custom user data to a file here.
UNIGINE_UNUSED(stream);
return 1;
}