예제 #1
0
//! constructor
CNullDriver::CNullDriver(IFileSystem* io, const dimension2d<u32>& screenSize)
: FileSystem(io), ViewPort(0,0,0,0), ScreenSize(screenSize),
	PrimitivesDrawn(0), MinVertexCountForVBO(500), TextureCreationFlags(0),
	OverrideMaterial2DEnabled(false), AllowZWriteOnTransparent(false)
{
	DriverAttributes = new CAttributes();
	DriverAttributes->addInt("MaxTextures", _DREAM_MATERIAL_MAX_TEXTURES_);
	DriverAttributes->addInt("MaxSupportedTextures", _DREAM_MATERIAL_MAX_TEXTURES_);
	DriverAttributes->addInt("MaxLights", getMaximalDynamicLightAmount());
	DriverAttributes->addInt("MaxAnisotropy", 1);
//	DriverAttributes->addInt("MaxUserClipPlanes", 0);
//	DriverAttributes->addInt("MaxAuxBuffers", 0);
	DriverAttributes->addInt("MaxMultipleRenderTargets", 1);
	DriverAttributes->addInt("MaxIndices", -1);
	DriverAttributes->addInt("MaxTextureSize", -1);
//	DriverAttributes->addInt("MaxGeometryVerticesOut", 0);
//	DriverAttributes->addFloat("MaxTextureLODBias", 0.f);
	DriverAttributes->addInt("Version", 1);
//	DriverAttributes->addInt("ShaderLanguageVersion", 0);
//	DriverAttributes->addInt("AntiAlias", 0);

	setFog();

	setTextureCreationFlag(ETCF_ALWAYS_32_BIT, true);
	setTextureCreationFlag(ETCF_CREATE_MIP_MAPS, true);

	ViewPort = rectangle<s32>(position2d<s32>(0,0), dimension2di(screenSize));

	if (FileSystem)
		FileSystem->addRef();

	// create surface loader
#ifdef _DREAM_COMPILE_WITH_BMP_LOADER_
	SurfaceLoader.push_back(createImageLoaderBMP());
#endif
#ifdef _DREAM_COMPILE_WITH_BMP_WRITER_
	SurfaceWriter.push_back(createImageWriterBMP());
#endif


	// set ExposedData to 0
	memset(&ExposedData, 0, sizeof(ExposedData));
	for (u32 i=0; i<EVDF_COUNT; ++i)
		FeatureEnabled[i]=true;

	InitMaterial2D.AntiAliasing=EAAM_OFF;
	InitMaterial2D.Lighting=false;
	InitMaterial2D.ZWriteEnable=false;
	InitMaterial2D.ZBuffer=ECFN_NEVER;
	InitMaterial2D.UseMipMaps=false;
	for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
	{
		InitMaterial2D.TextureLayer[i].BilinearFilter=false;
		InitMaterial2D.TextureLayer[i].TextureWrapU=ETC_REPEAT;
		InitMaterial2D.TextureLayer[i].TextureWrapV=ETC_REPEAT;
	}
	OverrideMaterial2D=InitMaterial2D;
}
예제 #2
0
void GLWidget::initializeGL()
{
    if(!getExtensions())
    {
        fprintf(stderr,"Error: %s.\n","Open OpenGL Extensions Error!!!");
        exit(-1);
    }
    qglClearColor(Qt::gray);
    glClearDepth(1.0);
    glShadeModel(GL_FLAT);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LEQUAL);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
    setLight();
    setFog();



    t = startTimer(50);
}
예제 #3
0
int InitGL(GLvoid)                              // All Setup For OpenGL Goes Here
{
	if (!LoadGLTexture())                          // Jump To Texture Loading Routine ( NEW )
	{
		return FALSE;                           // If Texture Didn't Load Return FALSE ( NEW )
	}
	
	quadric = gluNewQuadric();
	glEnable(GL_TEXTURE_2D);                        // Enable Texture Mapping ( NEW )
	glShadeModel(GL_SMOOTH);                        // Enable Smooth Shading
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);                   // Black Background
	glClearDepth(1.0f);                         // Depth Buffer Setup
	glEnable(GL_DEPTH_TEST);                        // Enables Depth Testing
	glDepthFunc(GL_LEQUAL);                         // The Type Of Depth Testing To Do
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);          // Really Nice Perspective Calculations

	glEnable(GL_FOG);
	setFog();

	
	
	
	return TRUE;                                // Initialization Went OK
}
예제 #4
0
 void ScratchPad::run() {
     const string path = "/Users/saburookita/Personal Projects/Three.cpp Rev.2/examples/assets/";
     
     ForwardRenderer renderer;
     renderer.init( "Ex 001: Simple Primitives", 1600 * 2 / 4, 900 * 2 / 4 );
     renderer.setCameraControl(Arcball::create(2.0f));
     
     /* Create scene */
     auto scene = Scene::create();
     scene->setFog(Fog::create( 0x72645b / 2, 2.0, 10.0 ));
     scene->setViewport(0, 0, 1600 * 2 / 4, 900 * 2 / 4);
     
     /* Create camera */
     auto camera = PerspectiveCamera::create( 50.0, renderer.getAspectRatio(), 0.001, 100.0 );
     camera->position = glm::vec3(0.0, 0.0, 5.5);
     camera->lookAt( 0.0, 0.0, 0.0 );
     
     /* A sphere, cube, and cylinder walk into a pub */
     auto sphere = Mesh::create( SphereGeometry::create(30, 20, 0.66f ),
                                PhongMaterial::create( 0xCC00CC, 0x0, 0x0, 0x222222, 130.0, true ) );
     
     auto cube = Mesh::create( CubeGeometry::create( 1.0f ),
                              PhongMaterial::create( 0x00CCCC, 0x0, 0x0, 0x111111, 150.0, false ) );
     
     cube->translate(2.0f, 0.0f, 0.0f);
     
     auto cylinder = Mesh::create( CylinderGeometry::create(0.5, 0.3, 1.0, 30, 5, true),
                                  PhongMaterial::create( 0xCCCC00, 0x0, 0x0, 0x111111, 150.0, false ) );
     cylinder->getMaterial()->setSide( SIDE::DOUBLE_SIDE );
     cylinder->translate(-2.0f, 0.0f, 0.0f);
     
     scene->add( sphere );
     scene->add( cube );
     scene->add( cylinder );
     
     auto plane = Mesh::create( PlaneGeometry::create(20.0f, 1),
                               PhongMaterial::create(0x333333, 0x333333, 0x333333, 0x101010 ) );
     plane->rotateX(-90.0);
     plane->translate( 0.0, -1.5, 0.0 );
     scene->add( plane );
     
     /* Create directional light */
     auto dir_light = DirectionalLight::create(0x99CCFF, 1.35, glm::vec3(3.0, 1.0, 3.0) );
     scene->add( dir_light );
     
     scene->add(HemisphereLight::create(0xFFFFFF, 0x333333, 0.8));
     
     /* Create an ambient light */
     scene->add( AmbientLight::create(0x777777));
     
     /* Create a post render callback for objects rotation */
     bool rotate_objects = false;
     float light_rotation_1 = 0.0;
     renderer.setPostRenderCallbackHandler( [&](){
         dir_light->position.x = ( 2.0 * cosf( light_rotation_1 ) );
         dir_light->position.z = ( 2.0 * sinf( light_rotation_1 ) );
         
         light_rotation_1 += 0.01;
         
         if( rotate_objects ) {
             sphere->rotateY  (-1.0f);
             cube->rotateY    (-1.0f);
             cylinder->rotateX(-1.0f);
         }
     });
     
     /* Override key callback handler */
     renderer.setKeyCallbackHandler([&](GLFWwindow *window, int key, int scancode, int action, int mod) {
         if( action == GLFW_PRESS ) {
             switch ( key) {
                 case GLFW_KEY_R: /* Toggle rotation */
                     rotate_objects = !rotate_objects;
                     break;
                     
                 default:
                     break;
             }
         }
     });
     
     renderer.setGamma( true, true );
     renderer.setClearColor( scene->getFog()->getColor() );
     renderer.render(scene, camera );
 }
    void Ex_006_BoundingBoxTest::run() {
        const string path = "/Users/saburookita/Personal Projects/Three.cpp Rev.2/examples/assets/";
        
        ForwardRenderer renderer;
        renderer.init( "Ex 006: Bounding Box Tests", 1600 * 2 / 4, 900 * 2 / 4 );
        renderer.setCameraControl(Arcball::create(2.0f));
        
        /* Create scene */
        auto scene = Scene::create();
        scene->setFog(Fog::create( 0x72645b / 2, 2.0, 15.0 ));
        scene->setViewport( 0.0, 0.0, renderer.getWidth(), renderer.getHeight() );
        scene->setShadowMapType( SHADOW_MAP::PCF );
        
        /* Create camera */
        auto camera = PerspectiveCamera::create( 50.0, renderer.getAspectRatio(), 0.001, 100.0 );
        camera->translate(0.0, 1.5, 5.5);
        camera->lookAt( 0.0, 1.0, 0.0 );
        
        /* Load our ply models */
        vector<string> filenames = {
            "dragon_vrip_res3.ply",
            "happy_vrip_res3.ply",
        };
        
        vector<ptr<Mesh>> statues;
        
        float x_offset = -1.0;
        for( string filename: filenames ) {
            auto statue = Loader::loadPLY(path + "/ply models/", filename,
                                          aiProcess_Triangulate |
                                          aiProcess_OptimizeMeshes |
                                          aiProcess_JoinIdenticalVertices |
                                          aiProcess_GenSmoothNormals | aiProcess_FlipWindingOrder );
            
            statue->setMaterial(PhongMaterial::create(0xcccccc, 0x0, 0x000000, 0x999999, 10, true));
            statue->getGeometry()->setScale(10.0f);
            statue->castShadow      = true;
            statue->receiveShadow   = true;
            
            auto bbox = statue->computeBoundingBox();
            glm::vec3 center = bbox->center();
            glm::vec3 size   = bbox->size();
            statue->translate(x_offset, -(center.y - size.y * 0.5), 0.0);
            
            cout << *bbox << endl;
            
            x_offset += 2.0f;
            scene->add( statue );
            statues.push_back( statue );
        }
        
        auto box = Mesh::create( CubeGeometry::create(1.0f, 3),
                                PhongMaterial::create(0x777777, 0x777777, 0x0, 0x0, 0.0, true) );
        box->setTexture( TextureUtils::loadAsTexture( path, "crate.tga") );
        box->getGeometry()->rotateX(45.0f);
        box->getGeometry()->setScale(1.5f);
        box->translate(3.0f, 0.5, 0.0);
        box->castShadow = true;
        box->receiveShadow = true;
        scene->add( box );
        
        auto cylinder = Mesh::create( CylinderGeometry::create(0.5, 0.5, 1.0, 30, 5, false),
                                      PhongMaterial::create( 0xDDDDDD, 0x0, 0x0, 0x111111, 150.0, true )
                                     );
        cylinder->translate(-3.0f, 0.5f, 0.0f);
        cylinder->castShadow = true;
        cylinder->receiveShadow = true;
        scene->add( cylinder );
        
        
        /* And the ground plane */
        auto plane = Mesh::create( PlaneGeometry::create(50.0f), PhongMaterial::create() );
        plane->rotateX(-90.0f);
        plane->receiveShadow = true;
        scene->add( plane );

        /* Cubemap */
//        auto env = Mesh::create( CubeGeometry::create(50.0f), MeshCubeMapMaterial::create() );
//        env->setTexture( TextureUtils::loadAsEnvMap( path + "cube/pisa",
//                                                    "nx.png", "ny.png", "nz.png",
//                                                    "px.png", "py.png", "pz.png"));
//        
//        cylinder->setEnvMap( env->getTexture() );
//        scene->add( env );
        
        
        /* Create a (rotating) directional light */
        auto dir_light = DirectionalLight::create(0x99CCFF, 1.35, glm::vec3( 3.0, 1.0, 3.0 ) );
        dir_light->castShadow       = true;
        dir_light->shadowBias       = -0.0001;
        dir_light->shadowCameraNear = -10.0;
        dir_light->shadowCameraFar  =  10.0;
        dir_light->shadowMapSize    = glm::vec2(512);
        scene->add( dir_light );
        
        /* Create a spotlight, the shadow should be casted no the left hand side */
        auto spot_light = SpotLight::create(0x99CCFF, 1.0, 20.0, 50.0, 1.0 );
        spot_light->position = glm::vec3(3.0, 2.0, 3.0);
        spot_light->castShadow = true;
        scene->add( spot_light );
        
        
        /* Create an ambient light */
        scene->add( AmbientLight::create(0xCCCCCC));
        
        /* Create a post render callback for objects rotation */
        bool rotate_objects = false;
        float light_rotation_1 = 0.0;
        renderer.setPostRenderCallbackHandler( [&](){
            dir_light->position.x = ( 3.0 * cosf( light_rotation_1 ) );
            dir_light->position.z = ( 3.0 * sinf( light_rotation_1 ) );
            
            light_rotation_1 += 0.01;
            
            if( rotate_objects ) {
                box->rotateY(-1.0f);
                statues[0]->rotateY(-0.5f);
            }
        });
        
        
        renderer.setMouseButtonCallbackHandler([&] (GLFWwindow *, int button, int action, int mod){
            auto descendants = scene->getDescendants();
            /* Reset the color first */
            for( auto obj: descendants ) {
                if( instance_of(obj, Mesh)) {
                    auto mesh = downcast( obj, Mesh );
                    if( instance_of(mesh->getMaterial(), PhongMaterial)){
                        auto phong = downcast(mesh->getMaterial(), PhongMaterial);
                        phong->setDiffuseColor( 0xDDDDDD );
                    }
                }
            }
            
            if( action == GLFW_PRESS ) {
                auto raycaster = Projector::pickingRay(renderer.getCursorPosition(), camera);
                
                /* Upon selected / ray picked, change the diffuse color to red */
                for( auto obj: descendants ) {
                    if( instance_of(obj, Geometry))
                        continue;
                    
                    auto bound = obj->getBoundingBox();
                    
                    if(raycaster->ray->intersects(bound)) {
                        if( instance_of(obj, Mesh)) {
                            auto mesh = downcast( obj, Mesh );
                            
                            if( instance_of(mesh->getMaterial(), PhongMaterial)){
                                auto phong = downcast(mesh->getMaterial(), PhongMaterial);
                                phong->setDiffuseColor( 0xDD0000 );
                            }
                        }
                    }
                }
            }
        });
        
        /* Override key callback handler */
        renderer.setKeyCallbackHandler([&](GLFWwindow *, int key, int scancode, int action, int mod) {
            if( action == GLFW_PRESS ) {
                switch ( key) {
                    case GLFW_KEY_R: /* Toggle rotation */
                        rotate_objects = !rotate_objects;
                        break;
                        
                    default: break;
                }
            }
        });
        
        renderer.setGamma( true, true );
        
        renderer.setClearColor( scene->getFog()->getColor() );
        renderer.render(scene, camera );
    }
예제 #6
0
void Camera::prepareRender()
{
	//Profile pr( "camera.prepareRender" );

	// - update transform hierarchy
	// - find out front and back plane distances
	// - collect visible objects and lights
	// - update node visibility
	// - sort visible objects by ascending distance
	// - set viewport, view- and projection transformation
	// - add affecting lights to rendering device
	// - set fog and ambient if any

	// - update transform hierarchy
	Node* root = this->root();
	Scene* scene = dynamic_cast<Scene*>( root );
	root->validateHierarchy();
	updateCachedTransforms();
	Vector3 camWorldPos = cachedWorldTransform().translation();
	Vector3 camWorldDir = cachedWorldTransform().rotation().getColumn(2);
	
	// - collect visible objects and lights
	s_objs.clear();
	s_lights.clear();

	for ( Node* obj = root ; obj ; )
	{
		//assert( obj->name().length() > 0 );
		obj->m_flags &= ~NODE_RENDEREDINLASTFRAME;

		if ( obj->enabled() )
		{
			if ( obj->renderable() )
			{
				Light* light = dynamic_cast<Light*>( obj );

				if ( light )
				{
					s_lights.add( light );
					++m_renderedLights;
				}
				else
				{
					obj->m_distanceToCamera = obj->boundSphere() + 
						(obj->m_worldTransform.translation() 
						- camWorldPos).dot( camWorldDir );

					if ( obj->updateVisibility(this) )
					{
						obj->m_flags |= NODE_RENDEREDINLASTFRAME;
						s_objs.add( obj );
						++m_renderedObjects;
					}
				}
			}
		}

		++m_processedObjects;
		obj = obj->nextInHierarchy( Node::NODE_ENABLED );
	}

	// - sort visible objects by ascending distance
	std::sort( s_objs.begin(), s_objs.end(), NodeDistanceToCameraLess() );

	// - set viewport, view- and projection transformation
	gd::GraphicsDevice* dev = Context::device();
	dev->setViewport( m_x, m_y, viewportWidth(), viewportHeight() );
	dev->setViewTransform( m_worldToCamera );
	dev->setProjectionTransform( projectionTransform() );

	// - add affecting lights to rendering device
	dev->removeLights();
	for ( int i = 0 ; i < (int)s_lights.size() ; ++i )
		s_lights[i]->apply();

	// - set fog and ambient if any
	if ( scene )
	{
		setFog( dev, scene );

		Colorf amb = Colorf( scene->ambientColor() );
		dev->setAmbient( Color(amb) );
	}
}
예제 #7
0
파일: skydome.cpp 프로젝트: LanJian/Surreal
void SkyDome::loadGradient(char* filename){
  m_gradient = loadTextureBMP(filename);
  setFog(filename);
}
 void Ex_004_ShadowMapping::run() {
     const string path = "/Users/saburookita/Personal Projects/Three.cpp Rev.2/examples/assets/";
     
     ForwardRenderer renderer;
     renderer.init( "Ex 004: Shadow Mapping", 1600 * 2 / 4, 900 * 2 / 4 );
     renderer.setCameraControl(Arcball::create(2.0f));
     
     
     /* Create scene */
     auto scene = Scene::create();
     scene->setFog(Fog::create( 0x72645b / 2, 2.0, 15.0 ));
     scene->setViewport( 0.0, 0.0, renderer.getWidth(), renderer.getHeight() );
     scene->setShadowMapType( SHADOW_MAP::PCF_SOFT );
     
     /* Create camera */
     auto camera = PerspectiveCamera::create( 50.0, renderer.getAspectRatio(), 0.001, 100.0 );
     camera->translate(0.0, 1.5, 5.5);
     camera->lookAt( 0.0, 0.0, 0.0 );
     
     /* Create our objects */
     auto sphere = Mesh::create( SphereGeometry::create(30, 20, 0.66f ),
                                PhongMaterial::create(0x777777, 0x0, 0x0, 0x999999, 30, true) );
     
     sphere->setNormalMap( TextureUtils::loadAsNormalMap  ( path, "tutorial_normals07.gif" ) );
     sphere->translate(-2.0, 0.66f, 0.0);
     sphere->castShadow = true;
     sphere->receiveShadow = true;
     
     auto cube = Mesh::create( CubeGeometry::create(1.0, 10),
                              PhongMaterial::create(0x777777, 0x0, 0x0, 0x0, 30, false) );
     cube->setTexture( TextureUtils::loadAsTexture( path, "four_shapes_color.tga" ) );
     cube->translate(0.0, 0.5, 0.0);
     cube->castShadow = true;
     cube->receiveShadow = true;
     
     auto cylinder = Mesh::create( CylinderGeometry::create(0.5, 0.5, 1.0, 30, 5, true),
                                  PhongMaterial::create( 0xCCCCCC, 0x0, 0x0, 0x111111, 150.0, false ) );
     cylinder->getMaterial()->setSide( SIDE::DOUBLE_SIDE );
     cylinder->castShadow = true;
     cylinder->receiveShadow = true;
     cylinder->setTexture  ( TextureUtils::loadAsTexture   ( path, "rock_color.tga" ) );
     cylinder->setNormalMap( TextureUtils::loadAsNormalMap ( path, "rock_normal.tga" ) );
     cylinder->translate(+2.0f, 0.5f, -2.0f);
     
     scene->add( cylinder );
     scene->add( cube );
     scene->add( sphere );
     
     /* And the ground plane */
     auto plane = Mesh::create( PlaneGeometry::create(20.0f),
                               PhongMaterial::create(0x777777, 0x777777, 0x0, 0x999999, 30) );
     plane->name = "plane";
     plane->rotateX(-90.0f);
     plane->translate(0.0, 0.0, 0.0);
     plane->receiveShadow = true;
     scene->add( plane );
     
     /* Cubemap */
     auto env = Mesh::create( CubeGeometry::create(20.0f), MeshCubeMapMaterial::create() );
     env->setTexture( TextureUtils::loadAsEnvMap( path + "cube/pisa",
                                               "nx.png", "ny.png", "nz.png",
                                               "px.png", "py.png", "pz.png"));
     
     sphere->setEnvMap( downcast(env->getTexture(), EnvMap) );
     scene->add( env );
     
     
     /* Create a (rotating) directional light */
     auto dir_light = DirectionalLight::create(0x99CCFF, 1.35, glm::vec3( 3.0, 1.0, 3.0 ) );
     dir_light->castShadow       = true;
     dir_light->shadowBias       = -0.0005;
     dir_light->shadowMapSize    = glm::vec2(512);
     scene->add( dir_light );
     
     /* Create a spotlight, the shadow should be casted no the left hand side */
     auto spot_light = SpotLight::create(0x99CCFF, 1.0, 20.0, 50.0, 1.0 );
     spot_light->position = glm::vec3(3.0, 2.0, 3.0);
     spot_light->castShadow = true;
     scene->add( spot_light );
     
     /* Create an ambient light */
     scene->add( AmbientLight::create(0x777777));
     
     /* Create a post render callback for objects rotation */
     bool rotate_objects = false;
     float light_rotation_1 = 0.0;
     renderer.setPostRenderCallbackHandler( [&](){
         dir_light->position.x = ( 3.0 * cosf( light_rotation_1 ) );
         dir_light->position.z = ( 3.0 * sinf( light_rotation_1 ) );
         
         light_rotation_1 += 0.01;
         
         if( rotate_objects ) {
             cube->rotateX(-1.0f);
             cylinder->rotateX(1.0f);
         }
     });
     
     /* Override key callback handler */
     renderer.setKeyCallbackHandler([&](GLFWwindow *window, int key, int scancode, int action, int mod) {
         if( action == GLFW_PRESS ) {
             switch ( key) {
                 case GLFW_KEY_R: /* Toggle rotation */
                     rotate_objects = !rotate_objects;
                     break;
                     
                 default:
                     break;
             }
         }
     });
     
     renderer.setGamma( true, true );
     
     renderer.setClearColor( scene->getFog()->getColor() );
     renderer.render(scene, camera );
 }
    void Ex_008_FontStashIntegration::run() {
//        const string path = "/Users/saburookita/Personal Projects/Three.cpp Rev.2/examples/assets/";
        const string path = "../examples/assets/";
        
        ForwardRenderer renderer;
        renderer.init( "Ex 008: FontStash integration test", 1600 * 2 / 4, 900 * 2 / 4 );
        renderer.setCameraControl(Arcball::create(2.0f));
        
        
        /* First load the fonts */
        renderer.addFont("droid-regular",   path + "fonts/DroidSerif-Regular.ttf");
        renderer.addFont("droid-italic",    path + "fonts/DroidSerif-Italic.ttf");
        renderer.addFont("droid-bold",      path + "fonts/DroidSerif-Bold.ttf");
        renderer.addFont("droid-japanese",  path + "fonts/DroidSansJapanese.ttf");
        
        /*Then write on screen*/
        renderer.addText( "Test FontStash",     100, 100, "droid-regular", 0x0, 32.0f );
        renderer.addText( "writing in italic",  100, 130, "droid-italic", 0x00FF00, 24.0f );
        renderer.addText( "... or bold",        250, 130, "droid-bold", 0xFF0000, 24.0f );
        
        renderer.addText( "éßüä",               400, 90, "droid-regular", 0x0000FF, 24.0f );
        renderer.addText( "日本語もできます。",    400, 120, "droid-japanese", 0xFFFFFF, 24.0f );
        
        renderer.addText( "spacing = 1.0",   100, 200, "droid-italic", 0x00FF00, 20.0f, 1.0f );
        renderer.addText( "spacing = 5.0",   100, 225, "droid-italic", 0xFFFF00, 20.0f, 5.0f );
        renderer.addText( "spacing = 10.0",  100, 250, "droid-italic", 0x00FFFF, 20.0f, 10.0f );
        
        renderer.addText( "blur = 1.0",   400, 200, "droid-bold", 0x99CCFF, 30.0f, 0.0f, 1.0f );
        renderer.addText( "blur = 5.0",   400, 240, "droid-bold", 0xFFCC99, 30.0f, 0.0f, 5.0f );
        renderer.addText( "blur = 10.0",  400, 280, "droid-bold", 0xCCFF99, 30.0f, 0.0f, 10.0f );
        
        int cursor_pos_text = renderer.addText( "Cursor Position: ", 80, 400, "droid-regular", 0xFFFFFF, 20.0f );
        
        /* Create scene */
        auto scene = Scene::create();
        scene->setFog(Fog::create( 0x72645b, 2.0, 15.0 ));
        scene->setViewport( 0.0, 0.0, renderer.getWidth(), renderer.getHeight() );
        scene->setShadowMapType( SHADOW_MAP::PCF );
        
        /* Create camera */
        auto camera = PerspectiveCamera::create( 50.0, renderer.getAspectRatio(), 0.001, 100.0 );
        camera->translate(0.0, 1.5, 5.5);
        camera->lookAt( 0.0, 1.0, 0.0 );
        
        /* Load our ply models */
        float x_offset = -1.0;
        auto statue = Loader::loadPLY(path + "/ply models/", "happy_vrip_res3.ply",
                                      aiProcess_JoinIdenticalVertices |
                                      aiProcess_GenSmoothNormals | aiProcess_FlipWindingOrder );
        
        statue->setMaterial(PhongMaterial::create(0x777777, 0x0, 0x777777, 0x0, 0, true));
        statue->getGeometry()->setScale(10.f);
        statue->castShadow      = true;
        statue->receiveShadow   = true;
        
        auto bounding_box = statue->computeBoundingBox();
        glm::vec3 size    = bounding_box->size();
        glm::vec3 center  = bounding_box->center();
        statue->translate(x_offset, -(center.y - size.y * 0.5), 0.0);
        
        x_offset += 2.0f;
        scene->add( statue );
     
        
        /* A sphere, cube, and cylinder walk into a pub */
        auto sphere = Mesh::create( SphereGeometry::create(30, 20, 0.66f ),
                                   PhongMaterial::create( 0xCCCCCC, 0x0, 0x0, 0x222222, 130.0, true ) );
        
        sphere->setTexture      ( TextureUtils::loadAsTexture    ( path + "planets", "earth_atmos_2048.jpg") );
        sphere->setNormalMap    ( TextureUtils::loadAsNormalMap  ( path + "planets", "earth_normal_2048.jpg" ) );
        sphere->setSpecularMap  ( TextureUtils::loadAsSpecularMap( path + "planets", "earth_specular_2048.jpg" ) );
        sphere->receiveShadow = true;
        sphere->castShadow    = true;
        sphere->translate( x_offset, 0.66f, 0.0f );
        scene->add( sphere );
        
        
        auto plane = Mesh::create( PlaneGeometry::create(20.0f),
                                   PhongMaterial::create(0x777777, 0x777777, 0x0, 0x999999, 30) );
        plane->name = "plane";
        plane->rotateX(-90.0f);
        plane->receiveShadow = true;
        scene->add( plane );
        
        /* Cubemap */
        auto env = Mesh::create( CubeGeometry::create(50.0f), MeshCubeMapMaterial::create() );
        env->setTexture( TextureUtils::loadAsEnvMap( path + "cube/pisa",
                                                    "nx.png", "ny.png", "nz.png",
                                                    "px.png", "py.png", "pz.png"));
        statue->setEnvMap( env->getTexture() );
        scene->add( env );
        
        
        /* Create a (rotating) directional light */
        auto dir_light = DirectionalLight::create(0x99CCFF, 1.35, glm::vec3( 3.0, 1.0, 3.0 ) );
        dir_light->castShadow       = true;
        dir_light->shadowBias       = -0.001;
        dir_light->shadowCameraNear = -10.0;
        dir_light->shadowCameraFar  =  10.0;
        scene->add( dir_light );
        
        /* Create a spotlight, the shadow should be casted no the left hand side */
        auto spot_light = SpotLight::create(0x99CCFF, 1.0, 20.0, 50.0, 1.0 );
        spot_light->position = glm::vec3(3.0, 2.0, 3.0);
        spot_light->castShadow = true;
        scene->add( spot_light );
        
        /* Create an ambient light */
        scene->add( AmbientLight::create(0x777777));
        
        /* Create a post render callback for objects rotation */
        bool rotate_objects = false;
        float light_rotation_1 = 0.0;
        renderer.setPostRenderCallbackHandler( [&](){
            dir_light->position.x = ( 3.0 * cosf( light_rotation_1 ) );
            dir_light->position.z = ( 3.0 * sinf( light_rotation_1 ) );
            
            light_rotation_1 += 0.01;
            
            if( rotate_objects ) {
                statue->rotateY(1.0f);
                sphere->rotateY(-1.0f);
            }
        });
        
        renderer.setCursorCallbackHandler([&](GLFWwindow *, double x, double y){
            stringstream ss;
            ss.precision(4);
            ss << "Cursor Position: (" << x << ", " << y << ")";
            renderer.setText(cursor_pos_text, ss.str() );
        });
        
        /* Override key callback handler */
        renderer.setKeyCallbackHandler([&](GLFWwindow *window, int key, int scancode, int action, int mod) {
            if( action == GLFW_PRESS ) {
                switch ( key) {
                    case GLFW_KEY_R: /* Toggle rotation */
                        rotate_objects = !rotate_objects;
                        break;
                        
                    default:
                        break;
                }
            }
        });
        
        
        renderer.setGamma( true, true );
        
        renderer.setClearColor( scene->getFog()->getColor() );
        renderer.render(scene, camera );
    }