void AddDataToVBO(std::function<GLuint(std::vector<GLfloat>&)> function, oglplus::Buffer& buffer, const std::string& paramName)
 {
     using namespace oglplus;
     std::vector<GLfloat> data;
     GLuint n_per_vertex = function(data);
     
     buffer.Bind(BufferTarget::Array);
     Buffer::Data(BufferTarget::Array, data);
     
     VertexArrayAttrib vert_attr(program.GetProgram(), paramName.data());
     vert_attr.Setup<GLfloat>(n_per_vertex);
     vert_attr.Enable();
 }
    Application() : BaseApplication (900, 300, "Phong + Ward BRDF + Ward BRDF with map : Press space to play/stop. Press 1 or 2 to change object"), program("vertex.vert", "fragmetPhong.frag"),
        programBRDF("vertex.vert", "fragmetWardBRDF.frag"), programBRDFMap("vertex.vert", "fragmetWardBRDFMap.frag"), make_torus(0.8, 0.5, 40, 40), make_sphere(1.0, 40.0, 40.0), lightPosition(2.3, 1.3, -7.0, 1.0), rotation(true)
    {
        using namespace oglplus;
        
        program.Use();
        
        int width = 0;
        int height = 0;
        GetWidnowSize(width, height);
        
        oglplus::Mat4f projection_matrix = oglplus::CamMatrixf::PerspectiveX(
                                                     Degrees(60),
                                                     double(width / 3)/height,
                                                     1, 10.0
                                                     );
        oglplus::Mat4f camera_matrix = oglplus::CamMatrixf::LookingAt (oglplus::Vec3f(0.0, 0.0, -2.5), oglplus::Vec3f());
        
        CreateSphere();
        CreateTorus();
        
        pGLContext->ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        pGLContext->ClearDepth(1.0f);
        pGLContext->Enable(Capability::DepthTest);

        oglplus::Vec3f ambient(0.329412,	0.223529,	0.027451);
        oglplus::Vec3f diffusion(0.780392,	0.568627,	0.113725);
        oglplus::Vec3f specular(0.992157,	0.941176,	0.807843);
        
        oglplus::Mat4f cameraMatrix = camera_matrix;
        oglplus::Mat4f sphereModelMatrix;
        
        // Create shapes.
        
        // Phong shading
        {
            RenderObject sphereObject(sphere, program, shpereIndexes);
            sphereObject.Init(PrimitiveType::TriangleStrip, nShpereVertexCount);
            
            SetupCommonParams(sphereObject, ambient,diffusion,specular, cameraMatrix, sphereModelMatrix, projection_matrix, lightPosition);
            sphereObject.AddFloatParam("shininess", 25.0);
            
            spheres.push_back(sphereObject);
        }
        
        // Ward's BRDF Model: https://en.wikibooks.org/wiki/GLSL_Programming/Unity/Brushed_Metal
        {
            RenderObject sphereObject(sphere, programBRDF, shpereIndexes);
            sphereObject.Init(PrimitiveType::TriangleStrip, nShpereVertexCount);
            oglplus::Mat4f modelMatrix;
            
            SetupCommonParams(sphereObject, ambient,diffusion,specular, cameraMatrix, sphereModelMatrix, projection_matrix, lightPosition);
            
            spheres.push_back(sphereObject);
        }
        
        // Ward's SBRDF Model + map
        {
            RenderObject sphereObject(sphere, programBRDFMap, shpereIndexes);
            sphereObject.Init(PrimitiveType::TriangleStrip, nShpereVertexCount);
            oglplus::Mat4f modelMatrix;
            
            SetupCommonParams(sphereObject, ambient,diffusion,specular, cameraMatrix, sphereModelMatrix, projection_matrix, lightPosition);
            
            spheres.push_back(sphereObject);
        }
        
        // Create torus
        oglplus::Mat4f torusModelMatrix = oglplus::ModelMatrixf::RotationX(oglplus::Degrees(90));
        
        // Phong shading
        {
            RenderObject torusObject(torus, program, torusIndexes);
            torusObject.Init(PrimitiveType::TriangleStrip, nTorusVertexCount);
            
            SetupCommonParams(torusObject, ambient, diffusion, specular, cameraMatrix, torusModelMatrix, projection_matrix, lightPosition);
            torusObject.AddFloatParam("shininess", 25.0);
            
            toruses.push_back(torusObject);
        }
        
        // Ward's BRDF Model: https://en.wikibooks.org/wiki/GLSL_Programming/Unity/Brushed_Metal
        {
            RenderObject torusObject(torus, programBRDF, torusIndexes);
            torusObject.Init(PrimitiveType::TriangleStrip, nTorusVertexCount);
            
            SetupCommonParams(torusObject, ambient, diffusion, specular, cameraMatrix, torusModelMatrix, projection_matrix, lightPosition);
            
            toruses.push_back(torusObject);
        }
        
        // Ward's SBRDF Model + map
        {
            RenderObject torusObject(torus, programBRDFMap, torusIndexes);
            torusObject.Init(PrimitiveType::TriangleStrip, nTorusVertexCount);
            
            SetupCommonParams(torusObject, ambient, diffusion, specular, cameraMatrix, torusModelMatrix, projection_matrix, lightPosition);
            
            toruses.push_back(torusObject);
        }
        
        //Render spheres by default.
        activeObjects = &spheres;
        
        LoadBRDFMap(Resource::getResoucesDir() + "LoadBRDFMap.png");
        
        programBRDFMap.Use();
        UniformSampler(programBRDFMap.GetProgram(), "MapTexture").Set(0);
        
        prevTime = GetMsFromEpoch();
    }