This example can be used to play around with material settings and watch the results. Only the default non-shader materials are used in here.
You have a node with a mesh, one dynamic light and global ambient light to play around with. You can move the light with cursor-keys and +/-. You can move the camera while left-mouse button is clicked. 
#include <irrlicht.h>
#include "driverChoice.h"
#include "exampleHelper.h"
#include "main.h"
using namespace irr;
#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif
 Variables within the empty namespace are globals which are restricted to this file. 
namespace
{
    
    enum EGUI_IDS
    {
        GUI_ID_OPEN_TEXTURE = 1,
        GUI_ID_QUIT,
        GUI_ID_MAX
    };
    
    const core::stringw CLEAR_TEXTURE = L"CLEAR texture";
    
    const video::SColor SCOL_BLACK     = video::SColor(255, 0,   0,   0);
    const video::SColor SCOL_BLUE      = video::SColor(255, 0,   0,  255);
    const video::SColor SCOL_CYAN      = video::SColor(255, 0,  255, 255);
    const video::SColor SCOL_GRAY      = video::SColor(255, 128,128, 128);
    const video::SColor SCOL_GREEN     = video::SColor(255, 0,  255,  0);
    const video::SColor SCOL_MAGENTA   = video::SColor(255, 255, 0,  255);
    const video::SColor SCOL_RED       = video::SColor(255, 255, 0,   0);
    const video::SColor SCOL_YELLOW    = video::SColor(255, 255, 255, 0);
    const video::SColor SCOL_WHITE     = video::SColor(255, 255, 255, 255);
};  
 Returns a new unique number on each call. 
s32 makeUniqueId()
{
    static int unique = GUI_ID_MAX;
    ++unique;
    return unique;
}
 Find out which vertex-type is needed for the given material type. 
video::E_VERTEX_TYPE getVertexTypeForMaterialType(video::E_MATERIAL_TYPE materialType)
{
    using namespace video;
    switch ( materialType )
    {
        case EMT_SOLID:
            return EVT_STANDARD;
        case EMT_SOLID_2_LAYER:
            return EVT_STANDARD;
        case EMT_LIGHTMAP:
        case EMT_LIGHTMAP_ADD:
        case EMT_LIGHTMAP_M2:
        case EMT_LIGHTMAP_M4:
        case EMT_LIGHTMAP_LIGHTING:
        case EMT_LIGHTMAP_LIGHTING_M2:
        case EMT_LIGHTMAP_LIGHTING_M4:
            return EVT_2TCOORDS;
        case EMT_DETAIL_MAP:
            return EVT_2TCOORDS;
        case EMT_SPHERE_MAP:
            return EVT_STANDARD;
        case EMT_REFLECTION_2_LAYER:
            return EVT_2TCOORDS;
        case EMT_TRANSPARENT_ADD_COLOR:
            return EVT_STANDARD;
        case EMT_TRANSPARENT_ALPHA_CHANNEL:
            return EVT_STANDARD;
        case EMT_TRANSPARENT_ALPHA_CHANNEL_REF:
            return EVT_STANDARD;
        case EMT_TRANSPARENT_VERTEX_ALPHA:
            return EVT_STANDARD;
        case EMT_TRANSPARENT_REFLECTION_2_LAYER:
            return EVT_2TCOORDS;
        case EMT_NORMAL_MAP_SOLID:
        case EMT_NORMAL_MAP_TRANSPARENT_ADD_COLOR:
        case EMT_NORMAL_MAP_TRANSPARENT_VERTEX_ALPHA:
        case EMT_PARALLAX_MAP_SOLID:
        case EMT_PARALLAX_MAP_TRANSPARENT_ADD_COLOR:
        case EMT_PARALLAX_MAP_TRANSPARENT_VERTEX_ALPHA:
            return EVT_TANGENTS;
        case EMT_ONETEXTURE_BLEND:
            return EVT_STANDARD;
        case EMT_FORCE_32BIT:
            return EVT_STANDARD;
    }
    return EVT_STANDARD;
}
 Custom GUI-control to edit colorvalues. 
CColorControl::CColorControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, IGUIElement* parent, s32 id)
    : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect< s32 >(pos, pos+core::dimension2d<s32>(80, 75)))
    , DirtyFlag(true)
    , Color(0)
    , ColorStatic(0)
    , EditAlpha(0)
    , EditRed(0)
    , EditGreen(0)
    , EditBlue(0)
{
    using namespace gui;
    ButtonSetId = makeUniqueId();
    const core::rect< s32 > rectControls(0,0,AbsoluteRect.getWidth(),AbsoluteRect.getHeight() );
    IGUIStaticText * groupElement = guiEnv->addStaticText (L"", rectControls, true, false, this, -1, false);
    groupElement->setNotClipped(true);
    guiEnv->addStaticText (text, core::rect<s32>(0,0,80,15), false, false, groupElement, -1, false);
    EditAlpha = addEditForNumbers(guiEnv, core::position2d<s32>(0,15), L"a", -1, groupElement );
    EditRed = addEditForNumbers(guiEnv, core::position2d<s32>(0,30), L"r", -1, groupElement );
    EditGreen = addEditForNumbers(guiEnv, core::position2d<s32>(0,45), L"g", -1, groupElement );
    EditBlue = addEditForNumbers(guiEnv, core::position2d<s32>(0,60), L"b", -1, groupElement );
    ColorStatic = guiEnv->addStaticText (L"", core::rect<s32>(60,15,80,75), true, false, groupElement, -1, true);
    guiEnv->addButton (core::rect<s32>(60,35,80,50), groupElement, ButtonSetId, L"set");
    setEditsFromColor(Color);
}
bool CColorControl::OnEvent(const SEvent &event)
{
    if ( event.EventType != EET_GUI_EVENT )
        return false;
    if ( event.GUIEvent.Caller->getID() == ButtonSetId && event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED )
    {
        Color = getColorFromEdits();
        setEditsFromColor(Color);
    }
    return false;
}
void CColorControl::setColor(const video::SColor& col)
{
    DirtyFlag = true;
    Color = col;
    setEditsFromColor(Color);
}
gui::IGUIEditBox* CColorControl::addEditForNumbers(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t *text, s32 id, gui::IGUIElement * parent)
{
    using namespace gui;
    core::rect< s32 > rect(pos, pos+core::dimension2d<s32>(10, 15));
    guiEnv->addStaticText (text, rect, false, false, parent, -1, false);
    rect += core::position2d<s32>( 20, 0 );
    rect.LowerRightCorner.X += 20;
    gui::IGUIEditBox* edit = guiEnv->addEditBox(L"0", rect, true, parent, id);
    return edit;
}
video::SColor CColorControl::getColorFromEdits() const
{
    video::SColor col;
    if (EditAlpha)
    {
        u32 alpha = core::strtoul10(core::stringc(EditAlpha->getText()).c_str());
        if (alpha > 255)
            alpha = 255;
        col.setAlpha(alpha);
    }
    if (EditRed)
    {
        u32 red = core::strtoul10(core::stringc(EditRed->getText()).c_str());
        if (red > 255)
            red = 255;
        col.setRed(red);
    }
    if (EditGreen)
    {
        u32 green = core::strtoul10(core::stringc(EditGreen->getText()).c_str());
        if (green > 255)
            green = 255;
        col.setGreen(green);
    }
    if (EditBlue)
    {
        u32 blue = core::strtoul10(core::stringc(EditBlue->getText()).c_str());
        if (blue > 255)
            blue = 255;
        col.setBlue(blue);
    }
    return col;
}
void CColorControl::setEditsFromColor(video::SColor col)
{
    DirtyFlag = true;
    if ( EditAlpha )
        EditAlpha->setText( core::stringw(col.getAlpha()).c_str() );
    if ( EditRed )
        EditRed->setText( core::stringw(col.getRed()).c_str() );
    if ( EditGreen )
        EditGreen->setText( core::stringw(col.getGreen()).c_str() );
    if ( EditBlue )
        EditBlue->setText( core::stringw(col.getBlue()).c_str() );
    if ( ColorStatic )
        ColorStatic->setBackgroundColor(col);
}
 Custom GUI-control for to edit all colors typically used in materials and lights 
CTypicalColorsControl::CTypicalColorsControl(gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, bool hasEmissive, IGUIElement* parent, s32 id)
    : gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(60,250)))
    , ControlAmbientColor(0), ControlDiffuseColor(0), ControlSpecularColor(0), ControlEmissiveColor(0)
{
    ControlAmbientColor = new CColorControl( guiEnv, core::position2d<s32>(0, 0), L"Ambient", this);
    ControlDiffuseColor = new CColorControl( guiEnv, core::position2d<s32>(0, 75), L"Diffuse", this );
    ControlSpecularColor = new CColorControl( guiEnv, core::position2d<s32>(0, 150), L"Specular", this );
    if ( hasEmissive )
    {
        ControlEmissiveColor = new CColorControl( guiEnv, core::position2d<s32>(0, 225), L"Emissive", this );
    }
}
CTypicalColorsControl::~CTypicalColorsControl()
{
    ControlAmbientColor->drop();
    ControlDiffuseColor->drop();
    if ( ControlEmissiveColor )
        ControlEmissiveColor->drop();
    ControlSpecularColor->drop();
}
void CTypicalColorsControl::setColorsToMaterialColors(const video::SMaterial & material)
{
    ControlAmbientColor->setColor(material.AmbientColor);
    ControlDiffuseColor->setColor(material.DiffuseColor);
    ControlEmissiveColor->setColor(material.EmissiveColor);
    ControlSpecularColor->setColor(material.SpecularColor);
}
void CTypicalColorsControl::updateMaterialColors(video::SMaterial & material) const
{
    if ( ControlAmbientColor->isDirty() )
        material.AmbientColor = ControlAmbientColor->getColor();
    if ( ControlDiffuseColor->isDirty() )
        material.DiffuseColor = ControlDiffuseColor->getColor();
    if ( ControlEmissiveColor->isDirty() )
        material.EmissiveColor = ControlEmissiveColor->getColor();
    if ( ControlSpecularColor->isDirty() )
        material.SpecularColor = ControlSpecularColor->getColor();
}
void CTypicalColorsControl::setColorsToLightDataColors(const video::SLight & lightData)
{
    ControlAmbientColor->setColor(lightData.AmbientColor.toSColor());
    ControlDiffuseColor->setColor(lightData.DiffuseColor.toSColor());
    ControlSpecularColor->setColor(lightData.SpecularColor.toSColor());
}
void CTypicalColorsControl::updateLightColors(video::SLight & lightData) const
{
    if ( ControlAmbientColor->isDirty() )
        lightData.AmbientColor = video::SColorf( ControlAmbientColor->getColor() );
    if ( ControlDiffuseColor->isDirty() )
        lightData.DiffuseColor = video::SColorf( ControlDiffuseColor->getColor() );
    if ( ControlSpecularColor->isDirty() )
        lightData.SpecularColor = video::SColorf(ControlSpecularColor->getColor() );
}
void CTypicalColorsControl::resetDirty()
{
    ControlAmbientColor->resetDirty();
    ControlDiffuseColor->resetDirty();
    ControlSpecularColor->resetDirty();
    if ( ControlEmissiveColor )
        ControlEmissiveColor->resetDirty();
}
 GUI-Control to offer a selection of available textures. 
CTextureControl::CTextureControl(gui::IGUIEnvironment* guiEnv, video::IVideoDriver * driver, const core::position2d<s32> & pos, IGUIElement* parent, s32 id)
: gui::IGUIElement(gui::EGUIET_ELEMENT, guiEnv, parent,id, core::rect<s32>(pos,pos+core::dimension2d<s32>(150,15)))
, DirtyFlag(true), ComboTexture(0)
{
    core::rect<s32> rectCombo(0, 0, AbsoluteRect.getWidth(),AbsoluteRect.getHeight());
    ComboTexture = guiEnv->addComboBox (rectCombo, this);
    updateTextures(driver);
}
bool CTextureControl::OnEvent(const SEvent &event)
{
    if ( event.EventType != EET_GUI_EVENT )
        return false;
    if ( event.GUIEvent.Caller == ComboTexture && event.GUIEvent.EventType == gui::EGET_COMBO_BOX_CHANGED )
    {
        DirtyFlag = true;
    }
    return false;
}
bool CTextureControl::bringToFront(IGUIElement* element)
{
    bool result = gui::IGUIElement::bringToFront(element);
    if ( Parent && element == ComboTexture )
        result &= Parent->bringToFront(this);
    return result;
}
const wchar_t * CTextureControl::getSelectedTextureName() const
{
    s32 selected = ComboTexture->getSelected();
    if ( selected < 0 )
        return 0;
    return ComboTexture->getItem(selected);
}
void CTextureControl::selectTextureByName(const irr::core::stringw& name)
{
    for (u32 i=0; i< ComboTexture->getItemCount(); ++i)
    {
        if ( name == ComboTexture->getItem(i))
        {
            ComboTexture->setSelected(i);
            DirtyFlag = true;
            return;
        }
    }
}
void CTextureControl::updateTextures(video::IVideoDriver * driver)
{
    s32 oldSelected = ComboTexture->getSelected();
    s32 selectNew = -1;
    core::stringw oldTextureName;
    if ( oldSelected >= 0 )
    {
        oldTextureName = ComboTexture->getItem(oldSelected);
    }
    ComboTexture->clear();
    for ( u32 i=0; i < driver->getTextureCount(); ++i )
    {
        video::ITexture * texture = driver->getTextureByIndex(i);
        core::stringw name( texture->getName() );
        ComboTexture->addItem( name.c_str() );
        if ( !oldTextureName.empty() && selectNew < 0 && name == oldTextureName )
            selectNew = i;
    }
    
    ComboTexture->addItem( CLEAR_TEXTURE.c_str() );
    if ( CLEAR_TEXTURE == oldTextureName )
        selectNew = ComboTexture->getItemCount()-1;
    if ( selectNew >= 0 )
        ComboTexture->setSelected(selectNew);
    DirtyFlag = true;
}
 Control which allows setting some of the material values for a meshscenenode 
void CMaterialControl::init(scene::IMeshSceneNode* node, IrrlichtDevice * device, const core::position2d<s32> & pos, const wchar_t * description)
{
    if ( Initialized || !node || !device) 
        return;
    Driver = device->getVideoDriver ();
    gui::IGUIEnvironment* guiEnv = device->getGUIEnvironment();
    
    const video::SMaterial & material = node->getMaterial(0);
    s32 top = pos.Y;
    
    guiEnv->addStaticText(description, core::rect<s32>(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false);
    top += 15;
    
    core::rect<s32> rectCombo(pos.X, top, 150, top+15);
    top += 15;
    ComboMaterial = guiEnv->addComboBox (rectCombo);
    for ( int i=0; i <= (int)video::EMT_ONETEXTURE_BLEND; ++i )
    {
        ComboMaterial->addItem( core::stringw(video::sBuiltInMaterialTypeNames[i]).c_str() );
    }
    ComboMaterial->setSelected( (s32)material.MaterialType );
    
    core::rect<s32> rectBtn(core::position2d<s32>(pos.X, top), core::dimension2d<s32>(100, 15));
    top += 15;
    ButtonLighting = guiEnv->addButton (rectBtn, 0, -1, L"Lighting");
    ButtonLighting->setIsPushButton(true);
    ButtonLighting->setPressed(material.Lighting);
    core::rect<s32> rectInfo( rectBtn.LowerRightCorner.X, rectBtn.UpperLeftCorner.Y, rectBtn.LowerRightCorner.X+40, rectBtn.UpperLeftCorner.Y+15 );
    InfoLighting = guiEnv->addStaticText(L"", rectInfo, true, false );
    InfoLighting->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER );
    
    TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, top), true, guiEnv->getRootGUIElement());
    top += 300;
    TypicalColorsControl->setColorsToMaterialColors(material);
    
    guiEnv->addStaticText(L"Textures", core::rect<s32>(pos.X, top, pos.X+60, top+15), false, false, 0, -1, false);
    top += 15;
    for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
    {
        TextureControls[i] = new CTextureControl(guiEnv, Driver, core::position2di(pos.X, top), guiEnv->getRootGUIElement());
        top += 15;
    }
    Initialized = true;
}
void CMaterialControl::update(scene::IMeshSceneNode* sceneNode, scene::IMeshSceneNode* sceneNode2T, scene::IMeshSceneNode* sceneNodeTangents)
{
    if ( !Initialized )
        return;
    video::SMaterial & material = sceneNode->getMaterial(0);
    video::SMaterial & material2T = sceneNode2T->getMaterial(0);
    video::SMaterial & materialTangents = sceneNodeTangents->getMaterial(0);
    s32 selectedMaterial = ComboMaterial->getSelected();
    if ( selectedMaterial >= (s32)video::EMT_SOLID && selectedMaterial <= (s32)video::EMT_ONETEXTURE_BLEND)
    {
        
        video::E_VERTEX_TYPE vertexType = getVertexTypeForMaterialType((video::E_MATERIAL_TYPE)selectedMaterial);
        switch ( vertexType )
        {
            case video::EVT_STANDARD:
                material.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
                sceneNode->setVisible(true);
                sceneNode2T->setVisible(false);
                sceneNodeTangents->setVisible(false);
                break;
            case video::EVT_2TCOORDS:
                material2T.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
                sceneNode->setVisible(false);
                sceneNode2T->setVisible(true);
                sceneNodeTangents->setVisible(false);
                break;
            case video::EVT_TANGENTS:
                materialTangents.MaterialType = (video::E_MATERIAL_TYPE)selectedMaterial;
                sceneNode->setVisible(false);
                sceneNode2T->setVisible(false);
                sceneNodeTangents->setVisible(true);
                break;
        }
    }
    
    updateMaterial(material);
    updateMaterial(material2T);
    updateMaterial(materialTangents);
    if ( ButtonLighting->isPressed() )
        InfoLighting->setText(L"is on");
    else
        InfoLighting->setText(L"is off");
    TypicalColorsControl->resetDirty();
    for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
        TextureControls[i]->resetDirty();
}
void CMaterialControl::updateTextures()
{
    for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
        TextureControls[i]->updateTextures(Driver);
}
void CMaterialControl::selectTextures(const irr::core::stringw& name)
{
    for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
        TextureControls[i]->selectTextureByName(name);
}
bool CMaterialControl::isLightingEnabled() const
{
    return ButtonLighting && ButtonLighting->isPressed();
}
void CMaterialControl::updateMaterial(video::SMaterial & material)
{
    TypicalColorsControl->updateMaterialColors(material);
    material.Lighting = ButtonLighting->isPressed();
    for (irr::u32 i=0; i<irr::video::MATERIAL_MAX_TEXTURES; ++i)
    {
        if ( TextureControls[i]->isDirty() )
        {
            material.TextureLayer[i].Texture = Driver->getTexture( io::path(TextureControls[i]->getSelectedTextureName()) );
        }
    }
}
 Control to allow setting the color values of a lightscenenode. 
void CLightNodeControl::init(scene::ILightSceneNode* node, gui::IGUIEnvironment* guiEnv, const core::position2d<s32> & pos, const wchar_t * description)
{
    if ( Initialized || !node || !guiEnv) 
        return;
    guiEnv->addStaticText(description, core::rect<s32>(pos.X, pos.Y, pos.X+70, pos.Y+15), false, false, 0, -1, false);
    TypicalColorsControl = new CTypicalColorsControl(guiEnv, core::position2d<s32>(pos.X, pos.Y+15), false, guiEnv->getRootGUIElement());
    const video::SLight & lightData = node->getLightData();
    TypicalColorsControl->setColorsToLightDataColors(lightData);
    Initialized = true;
}
void CLightNodeControl::update(scene::ILightSceneNode* node)
{
    if ( !Initialized )
        return;
    video::SLight & lightData = node->getLightData();
    TypicalColorsControl->updateLightColors(lightData);
}
 Main application class 
 Event handler 
bool CApp::OnEvent(const SEvent &event)
{
    if (event.EventType == EET_GUI_EVENT)
    {
        gui::IGUIEnvironment* env = Device->getGUIEnvironment();
        switch(event.GUIEvent.EventType)
        {
            case gui::EGET_MENU_ITEM_SELECTED:
            {
                gui::IGUIContextMenu* menu = (gui::IGUIContextMenu*)event.GUIEvent.Caller;
                s32 id = menu->getItemCommandId(menu->getSelectedItem());
                switch(id)
                {
                    case GUI_ID_OPEN_TEXTURE: 
                        env->addFileOpenDialog(L"Please select a texture file to open");
                    break;
                    case GUI_ID_QUIT: 
                        setRunning(false);
                    break;
                }
            }
            break;
            case gui::EGET_FILE_SELECTED:
            {
                
                gui::IGUIFileOpenDialog* dialog =
                    (gui::IGUIFileOpenDialog*)event.GUIEvent.Caller;
                loadTexture(io::path(dialog->getFileName()).c_str());
            }
            break;
            default:
            break;
        }
    }
    else if (event.EventType == EET_KEY_INPUT_EVENT)
    {
        KeysPressed[event.KeyInput.Key] = event.KeyInput.PressedDown;
    }
    else if (event.EventType == EET_MOUSE_INPUT_EVENT)
    {
        if (!MousePressed && event.MouseInput.isLeftPressed())
        {
            gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
            if ( guiEnv->getHovered() == guiEnv->getRootGUIElement() )  
            {
                MousePressed  = true;
                MouseStart.X = event.MouseInput.X;
                MouseStart.Y = event.MouseInput.Y;
            }
        }
        else if (MousePressed && !event.MouseInput.isLeftPressed())
        {
            MousePressed = false;
        }
    }
    return false;
}
bool CApp::init(int argc, char *argv[])
{
    
    Config.DriverType=driverChoiceConsole();
    if (Config.DriverType==video::EDT_COUNT)
        return false;
    
    Device = createDevice(Config.DriverType, Config.ScreenSize);
    if (!Device)
        return false;
    Device->setWindowCaption( core::stringw(video::DRIVER_TYPE_NAMES[Config.DriverType]).c_str() );
    Device->setEventReceiver(this);
    scene::ISceneManager* smgr = Device->getSceneManager();
    video::IVideoDriver * driver = Device->getVideoDriver ();
    gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
    MeshManipulator = smgr->getMeshManipulator();
    
    gui::IGUISkin* skin = guiEnv->getSkin();
    gui::IGUIFont* font = guiEnv->getFont(getExampleMediaPath() + "fonthaettenschweiler.bmp");
    if (font)
        skin->setFont(font);
    
    video::SColor col3dHighLight( skin->getColor(gui::EGDC_APP_WORKSPACE) );
    col3dHighLight.setAlpha(255);
    video::SColor colHighLight( col3dHighLight );
    skin->setColor(gui::EGDC_HIGH_LIGHT, colHighLight );
    skin->setColor(gui::EGDC_3D_HIGH_LIGHT, col3dHighLight );
    
    createDefaultTextures(driver);
    
    gui::IGUIContextMenu * menuBar = guiEnv->addMenu();
    menuBar->addItem(L"File", -1, true, true);
    gui::IGUIContextMenu* subMenuFile = menuBar->getSubMenu(0);
    subMenuFile->addItem(L"Open texture ...", GUI_ID_OPEN_TEXTURE);
    subMenuFile->addSeparator();
    subMenuFile->addItem(L"Quit", GUI_ID_QUIT);
    
    Camera = smgr->addCameraSceneNode (0, core::vector3df(0, 40, -40),
                                        core::vector3df(0, 10, 0),
                                        -1);
    
    video::SMaterial defaultMaterial;
    defaultMaterial.Shininess = 20.f;
    
    SceneNode = smgr->addCubeSceneNode (30.0f, 0, -1,
                                       core::vector3df(0, 0, 0),
                                       core::vector3df(0.f, 45.f, 0.f),
                                       core::vector3df(1.0f, 1.0f, 1.0f));
    SceneNode->getMaterial(0) = defaultMaterial;
    const s32 controlsTop = 20;
    MeshMaterialControl = new CMaterialControl();
    MeshMaterialControl->init( SceneNode, Device, core::position2d<s32>(10,controlsTop), L"Material" );
    MeshMaterialControl->selectTextures(core::stringw("CARO_A8R8G8B8"));    
    
    scene::IMesh * mesh2T = MeshManipulator->createMeshWith2TCoords(SceneNode->getMesh());
    SceneNode2T = smgr->addMeshSceneNode(mesh2T, 0, -1, SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
    mesh2T->drop();
    scene::IMesh * meshTangents = MeshManipulator->createMeshWithTangents(SceneNode->getMesh(), false, false, false);
    SceneNodeTangents = smgr->addMeshSceneNode(meshTangents, 0, -1
                                        , SceneNode->getPosition(), SceneNode->getRotation(), SceneNode->getScale() );
    meshTangents->drop();
    
    NodeLight = smgr->addLightSceneNode(0, core::vector3df(0, 0, -40),
                                            video::SColorf(1.0f, 1.0f, 1.0f),
                                            35.0f);
    LightControl = new CLightNodeControl();
    LightControl->init(NodeLight, guiEnv, core::position2d<s32>(550,controlsTop), L"Dynamic light" );
    
    scene::IMeshSceneNode* backgroundCube = smgr->addCubeSceneNode (200.0f, 0, -1, core::vector3df(0, 0, 0),
                                       core::vector3df(45, 0, 0),
                                       core::vector3df(1.0f, 1.0f, 1.0f));
    backgroundCube->getMaterial(0).BackfaceCulling = false;         
    backgroundCube->getMaterial(0).EmissiveColor.set(255,50,50,50); 
    
    guiEnv->addStaticText(L"Mesh", core::rect<s32>(200, controlsTop, 270, controlsTop+15), false, false, 0, -1, false);
    ControlVertexColors = new CColorControl( guiEnv, core::position2d<s32>(200, controlsTop+15), L"Vertex colors", guiEnv->getRootGUIElement());
    video::S3DVertex * vertices =  (video::S3DVertex *)SceneNode->getMesh()->getMeshBuffer(0)->getVertices();
    if ( vertices )
    {
        ControlVertexColors->setColor(vertices[0].Color);
    }
    
    GlobalAmbient = new CColorControl( guiEnv, core::position2d<s32>(550, 300), L"Global ambient", guiEnv->getRootGUIElement());
    GlobalAmbient->setColor( smgr->getAmbientLight().toSColor() );
    return true;
}
 Update one frame 
bool CApp::update()
{
    using namespace irr;
    video::IVideoDriver* videoDriver =  Device->getVideoDriver();
    if ( !Device->run() )
        return false;
    
    ITimer * timer = Device->getTimer();
    u32 newTick = timer->getRealTime();
    f32 deltaTime = RealTimeTick > 0 ? f32(newTick-RealTimeTick)/1000.f : 0.f;  
    RealTimeTick = newTick;
    if ( Device->isWindowActive() || Config.RenderInBackground )
    {
        gui::IGUIEnvironment* guiEnv = Device->getGUIEnvironment();
        scene::ISceneManager* smgr = Device->getSceneManager();
        gui::IGUISkin * skin = guiEnv->getSkin();
        
        MeshMaterialControl->update(SceneNode, SceneNode2T, SceneNodeTangents);
        LightControl->update(NodeLight);
        
        if ( ControlVertexColors->isDirty() )
        {
            MeshManipulator->setVertexColors (SceneNode->getMesh(), ControlVertexColors->getColor());
            MeshManipulator->setVertexColors (SceneNode2T->getMesh(), ControlVertexColors->getColor());
            MeshManipulator->setVertexColors (SceneNodeTangents->getMesh(), ControlVertexColors->getColor());
            ControlVertexColors->resetDirty();
        }
        
        if ( GlobalAmbient->isDirty() )
        {
            smgr->setAmbientLight( GlobalAmbient->getColor() );
            GlobalAmbient->resetDirty();
        }
        
        const float zoomSpeed = 10.f * deltaTime;
        const float rotationSpeed = 100.f * deltaTime;
        if ( KeysPressed[KEY_PLUS] || KeysPressed[KEY_ADD])
            ZoomOut(NodeLight, zoomSpeed);
        if ( KeysPressed[KEY_MINUS] || KeysPressed[KEY_SUBTRACT])
            ZoomOut(NodeLight, -zoomSpeed);
        if ( KeysPressed[KEY_RIGHT])
            RotateHorizontal(NodeLight, rotationSpeed);
        if ( KeysPressed[KEY_LEFT])
            RotateHorizontal(NodeLight, -rotationSpeed);
        UpdateRotationAxis(NodeLight, LightRotationAxis);
        if ( KeysPressed[KEY_UP])
            RotateAroundAxis(NodeLight, rotationSpeed, LightRotationAxis);
        if ( KeysPressed[KEY_DOWN])
            RotateAroundAxis(NodeLight, -rotationSpeed, LightRotationAxis);
        
        if (MousePressed)
        {
            gui::ICursorControl* cursorControl = Device->getCursorControl();
            const core::position2d<s32>& mousePos = cursorControl->getPosition ();
            RotateHorizontal(Camera, rotationSpeed * (MouseStart.X - mousePos.X));
            RotateAroundAxis(Camera, rotationSpeed * (mousePos.Y - MouseStart.Y), CameraRotationAxis);
            MouseStart = mousePos;
        }
        
        video::SColor bkColor( skin->getColor(gui::EGDC_APP_WORKSPACE) );
        videoDriver->beginScene(video::ECBF_COLOR | video::ECBF_DEPTH, bkColor);
        smgr->drawAll();
        guiEnv->drawAll();
        if ( MeshMaterialControl->isLightingEnabled() )
        {
            
            video::SMaterial lineMaterial;
            lineMaterial.Lighting = false;
            videoDriver->setMaterial(lineMaterial);
            videoDriver->setTransform(video::ETS_WORLD, core::IdentityMatrix);
            videoDriver->draw3DLine(NodeLight->getAbsolutePosition(), SceneNode->getAbsolutePosition());
        }
        videoDriver->endScene();
    }
    
    Device->sleep( 5 );
    return true;
}
void CApp::quit()
{
    IsRunning = false;
    delete LightControl;
    LightControl = NULL;
    delete MeshMaterialControl;
    MeshMaterialControl = NULL;
    if ( ControlVertexColors )
    {
        ControlVertexColors->drop();
        ControlVertexColors = NULL;
    }
    if ( GlobalAmbient )
    {
        GlobalAmbient->drop();
        GlobalAmbient = NULL;
    }
    if ( Device )
    {
        Device->closeDevice();
        Device->drop();
        Device = NULL;
    }
}
void CApp::createDefaultTextures(video::IVideoDriver * driver)
{
    const u32 width = 256;
    const u32 height = 256;
    video::IImage * imageA8R8G8B8 = driver->createImage (video::ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
    if ( !imageA8R8G8B8 )
        return;
    const u32 pitch = imageA8R8G8B8->getPitch();
    
    
    for ( u32 y = 0; y < height; ++ y )
    {
        for ( u32 x = 0; x < pitch; ++x )
        {
            if ( y < height/3 )
            {
                if ( x < width/3 )
                    imageA8R8G8B8->setPixel (x, y, SCOL_BLACK);
                else if ( x < 2*width/3 )
                    imageA8R8G8B8->setPixel (x, y, SCOL_BLUE);
                else
                    imageA8R8G8B8->setPixel (x, y, SCOL_CYAN);
            }
            else if ( y < 2*height/3 )
            {
                if ( x < width/3 )
                    imageA8R8G8B8->setPixel (x, y, SCOL_GRAY);
                else if ( x < 2*width/3 )
                    imageA8R8G8B8->setPixel (x, y, SCOL_GREEN);
                else
                    imageA8R8G8B8->setPixel (x, y, SCOL_MAGENTA);
            }
            else
            {
                if ( x < width/3 )
                    imageA8R8G8B8->setPixel (x, y, SCOL_RED);
                else if ( x < 2*width/3 )
                    imageA8R8G8B8->setPixel (x, y, SCOL_YELLOW);
                else
                    imageA8R8G8B8->setPixel (x, y, SCOL_WHITE);
            }
        }
    }
    driver->addTexture (io::path("CARO_A8R8G8B8"), imageA8R8G8B8);
    
    imageA8R8G8B8->fill(SCOL_WHITE);
    driver->addTexture (io::path("WHITE_A8R8G8B8"), imageA8R8G8B8);
    
    imageA8R8G8B8->fill(SCOL_BLACK);
    driver->addTexture (io::path("BLACK_A8R8G8B8"), imageA8R8G8B8);
    
    for ( u32 y = 0; y < height; ++ y )
    {
        for ( u32 x = 0; x < pitch; ++x )
        {
            imageA8R8G8B8->setPixel (x, y, video::SColor(y, x,x,x) );
        }
    }
    driver->addTexture (io::path("GRAYSCALE_A8R8G8B8"), imageA8R8G8B8);
    imageA8R8G8B8->drop();
}
void CApp::loadTexture(const io::path &name)
{
    Device->getVideoDriver()->getTexture(name);
    MeshMaterialControl->updateTextures();
}
void CApp::RotateHorizontal(irr::scene::ISceneNode* node, irr::f32 angle)
{
    if ( node )
    {
        core::vector3df pos(node->getPosition());
        core::vector2df dir(pos.X, pos.Z);
        dir.rotateBy(angle);
        pos.X = dir.X;
        pos.Z = dir.Y;
        node->setPosition(pos);
    }
}
void CApp::RotateAroundAxis(irr::scene::ISceneNode* node, irr::f32 angle, const irr::core::vector3df& axis)
{
    if ( node )
    {
        
        core::vector3df pos(node->getPosition());
        core::matrix4 mat;
        mat.setRotationAxisRadians (core::degToRad(angle), axis);
        mat.rotateVect(pos);
        node->setPosition(pos);
    }
}
void CApp::ZoomOut(irr::scene::ISceneNode* node, irr::f32 units)
{
    if ( node )
    {
        core::vector3df pos(node->getPosition());
        irr::f32 len = pos.getLength() + units;
        pos.setLength(len);
        node->setPosition(pos);
    }
}
void CApp::UpdateRotationAxis(irr::scene::ISceneNode* node, irr::core::vector3df& axis)
{
    
    core::vector3df pos(node->getPosition());
    if ( !core::equals(pos.X, 0.f) || !core::equals(pos.Z, 0.f) )
    {
        axis.X = -pos.Z;
        axis.Z = pos.X;
        axis.normalize();
    }
}
 Short main as most is done in classes. 
int main(int argc, char *argv[])
{
    CApp APP;
    if ( !APP.init(argc, argv) )
    {
        printf("init failed\n");
        APP.quit();
        return 1;
    }
    APP.setRunning(true);
 main application loop 
    while(APP.isRunning())
    {
        if ( !APP.update() )
            break;
    }
    APP.quit();
    return 0;
}