Beispiel #1
0
INLINE int MixREVERBLeft(int ns,int core)
{
    if(iUseReverb==1)
    {
        if(!rvb[core].StartAddr || !rvb[core].EndAddr ||
                rvb[core].StartAddr>=rvb[core].EndAddr)          // reverb is off
        {
            rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
            return 0;
        }

        rvb[core].iCnt++;

        if(rvb[core].iCnt&1)                                // we work on every second left value: downsample to 22 khz
        {
            if((spuCtrl2[core]&0x80))                         // -> reverb on? oki
            {
                int ACC0,ACC1,FB_A0,FB_A1,FB_B0,FB_B1;

                const int INPUT_SAMPLE_L=*(sRVBStart[core]+(ns<<1));
                const int INPUT_SAMPLE_R=*(sRVBStart[core]+(ns<<1)+1);

                const int IIR_INPUT_A0 = (g_buffer(rvb[core].IIR_SRC_A0,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/33768L;
                const int IIR_INPUT_A1 = (g_buffer(rvb[core].IIR_SRC_A1,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/33768L;
                const int IIR_INPUT_B0 = (g_buffer(rvb[core].IIR_SRC_B0,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_L * rvb[core].IN_COEF_L)/33768L;
                const int IIR_INPUT_B1 = (g_buffer(rvb[core].IIR_SRC_B1,core) * rvb[core].IIR_COEF)/33768L + (INPUT_SAMPLE_R * rvb[core].IN_COEF_R)/33768L;

                const int IIR_A0 = (IIR_INPUT_A0 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_A0,core) * (33768L - rvb[core].IIR_ALPHA))/33768L;
                const int IIR_A1 = (IIR_INPUT_A1 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_A1,core) * (33768L - rvb[core].IIR_ALPHA))/33768L;
                const int IIR_B0 = (IIR_INPUT_B0 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_B0,core) * (33768L - rvb[core].IIR_ALPHA))/33768L;
                const int IIR_B1 = (IIR_INPUT_B1 * rvb[core].IIR_ALPHA)/33768L + (g_buffer(rvb[core].IIR_DEST_B1,core) * (33768L - rvb[core].IIR_ALPHA))/33768L;

                s_buffer1(rvb[core].IIR_DEST_A0, IIR_A0,core);
                s_buffer1(rvb[core].IIR_DEST_A1, IIR_A1,core);
                s_buffer1(rvb[core].IIR_DEST_B0, IIR_B0,core);
                s_buffer1(rvb[core].IIR_DEST_B1, IIR_B1,core);

                ACC0 = (g_buffer(rvb[core].ACC_SRC_A0,core) * rvb[core].ACC_COEF_A)/33768L +
                       (g_buffer(rvb[core].ACC_SRC_B0,core) * rvb[core].ACC_COEF_B)/33768L +
                       (g_buffer(rvb[core].ACC_SRC_C0,core) * rvb[core].ACC_COEF_C)/33768L +
                       (g_buffer(rvb[core].ACC_SRC_D0,core) * rvb[core].ACC_COEF_D)/33768L;
                ACC1 = (g_buffer(rvb[core].ACC_SRC_A1,core) * rvb[core].ACC_COEF_A)/33768L +
                       (g_buffer(rvb[core].ACC_SRC_B1,core) * rvb[core].ACC_COEF_B)/33768L +
                       (g_buffer(rvb[core].ACC_SRC_C1,core) * rvb[core].ACC_COEF_C)/33768L +
                       (g_buffer(rvb[core].ACC_SRC_D1,core) * rvb[core].ACC_COEF_D)/33768L;

                FB_A0 = g_buffer(rvb[core].MIX_DEST_A0 - rvb[core].FB_SRC_A,core);
                FB_A1 = g_buffer(rvb[core].MIX_DEST_A1 - rvb[core].FB_SRC_A,core);
                FB_B0 = g_buffer(rvb[core].MIX_DEST_B0 - rvb[core].FB_SRC_B,core);
                FB_B1 = g_buffer(rvb[core].MIX_DEST_B1 - rvb[core].FB_SRC_B,core);

                s_buffer(rvb[core].MIX_DEST_A0, ACC0 - (FB_A0 * rvb[core].FB_ALPHA)/33768L,core);
                s_buffer(rvb[core].MIX_DEST_A1, ACC1 - (FB_A1 * rvb[core].FB_ALPHA)/33768L,core);

                s_buffer(rvb[core].MIX_DEST_B0, (rvb[core].FB_ALPHA * ACC0)/33768L - (FB_A0 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/33768L - (FB_B0 * rvb[core].FB_X)/33768L,core);
                s_buffer(rvb[core].MIX_DEST_B1, (rvb[core].FB_ALPHA * ACC1)/33768L - (FB_A1 * (int)(rvb[core].FB_ALPHA^0xFFFF8000))/33768L - (FB_B1 * rvb[core].FB_X)/33768L,core);

                rvb[core].iLastRVBLeft  = rvb[core].iRVBLeft;
                rvb[core].iLastRVBRight = rvb[core].iRVBRight;

                rvb[core].iRVBLeft  = (g_buffer(rvb[core].MIX_DEST_A0,core)+g_buffer(rvb[core].MIX_DEST_B0,core))/3;
                rvb[core].iRVBRight = (g_buffer(rvb[core].MIX_DEST_A1,core)+g_buffer(rvb[core].MIX_DEST_B1,core))/3;

                rvb[core].iRVBLeft  = (rvb[core].iRVBLeft  * rvb[core].VolLeft)  / 0x4000;
                rvb[core].iRVBRight = (rvb[core].iRVBRight * rvb[core].VolRight) / 0x4000;

                rvb[core].CurrAddr++;
                if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;

                return rvb[core].iLastRVBLeft+(rvb[core].iRVBLeft-rvb[core].iLastRVBLeft)/2;
            }
            else                                              // -> reverb off
            {
                rvb[core].iLastRVBLeft=rvb[core].iLastRVBRight=rvb[core].iRVBLeft=rvb[core].iRVBRight=0;
            }

            rvb[core].CurrAddr++;
            if(rvb[core].CurrAddr>rvb[core].EndAddr) rvb[core].CurrAddr=rvb[core].StartAddr;
        }

        return rvb[core].iLastRVBLeft;
    }
    return 0;
}
Beispiel #2
0
int main(int argc, char * argv[]) {

	char path[256];
	engine = new Engine(argc, argv);

	ShaderProgram* defergbufferShader = new ShaderProgram();
	FBO g_buffer(glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT), 1);
	FBO shadow_buffer(2000, 2000, 1);

	GET_SHADER_VISBUFFER_PATH(path, 256, "defergbuffer.vert");
	if (!defergbufferShader->AddVertexShaderPath(path)) return 0;
	GET_SHADER_VISBUFFER_PATH(path, 256, "defergbuffer.frag");
	if (!defergbufferShader->AddFragmentShaderPath(path)) return 0;
	if (!defergbufferShader->Link()) return 0;

	defergbufferShader->SetAttribVertex("vertex_coord");
	defergbufferShader->SetAttribNormal("normal_coord");

	ShaderProgram* shadowMapShader = new ShaderProgram();
	GET_SHADER_VISBUFFER_PATH(path, 256, "shadow.vert");
	if (!shadowMapShader->AddVertexShaderPath(path)) return 0;
	GET_SHADER_VISBUFFER_PATH(path, 256, "shadow.frag");
	if (!shadowMapShader->AddFragmentShaderPath(path)) return 0;
	if (!shadowMapShader->Link()) return 0;
	shadowMapShader->SetAttribVertex("vertex");

	ShaderProgram* shadowRenderShader = new ShaderProgram();
	GET_SHADER_VISBUFFER_PATH(path, 256, "shadowRender.vert");
	if (!shadowRenderShader->AddVertexShaderPath(path)) return 0;
	GET_SHADER_VISBUFFER_PATH(path, 256, "shadowRender.frag");
	if (!shadowRenderShader->AddFragmentShaderPath(path)) return 0;
	if (!shadowRenderShader->Link()) return 0;
	shadowRenderShader->SetAttribVertex("vertex");
	shadowRenderShader->SetAttribTexture("texture_coordinate");
    
	// --------------SHADER LOADING--------------------------

	GET_MODEL_PATH(path, 256, "bunny_smooth.ply");
	Mesh bunny1, bunny2, bunny3;
	Mesh shadowBunny1, shadowBunny2, shadowBunny3;
    Mesh square1, square2, square3, square4, square5, square6;
    Mesh shadowSquare1, shadowSquare2, shadowSquare3, shadowSquare4, shadowSquare5, shadowSquare6;
	bunny1.Load(path);
	bunny2.Load(path);
	bunny3.Load(path);
	shadowBunny1.Load(path);
	shadowBunny2.Load(path);
	shadowBunny3.Load(path);
    
    
    square1.LoadSquare();
    square2.LoadSquare();
    square3.LoadSquare();
    square4.LoadSquare();
    square5.LoadSquare();
    square6.LoadSquare();
    shadowSquare1.LoadSquare();
    shadowSquare2.LoadSquare();
    shadowSquare3.LoadSquare();
    shadowSquare4.LoadSquare();
    shadowSquare5.LoadSquare();
    shadowSquare6.LoadSquare();

	GET_MODEL_PATH(path, 256, "sphere.ply");
	Mesh Light1, Light2, Light3;
	Light1.Load(path);
    Light2.Load(path);
    Light3.Load(path);

	Mesh AmbientFSQ;
	AmbientFSQ.LoadSquare();
    
    Mesh ShadowRenderFSQ;
    ShadowRenderFSQ.LoadSquare();
    
    Mesh DeferredBRDFFSQ;
    DeferredBRDFFSQ.LoadSquare();

	// ---------------MODEL LOADING--------------------------

	Scene bunnyScene;
	bunnyScene.addObject(&bunny1);
	bunnyScene.addObject(&bunny2);
	bunnyScene.addObject(&bunny3);
	bunnyScene.addObject(&Light1);
    bunnyScene.addObject(&Light2);
    bunnyScene.addObject(&Light3);
    bunnyScene.addObject(&square1);
    bunnyScene.addObject(&square2);
    bunnyScene.addObject(&square3);
    bunnyScene.addObject(&square4);
    bunnyScene.addObject(&square5);
    bunnyScene.addObject(&square6);


    Scene ambientScene;
	ambientScene.addObject(&AmbientFSQ);

	Scene shadowMapScene;
	shadowMapScene.addObject(&shadowBunny1);
	shadowMapScene.addObject(&shadowBunny2);
	shadowMapScene.addObject(&shadowBunny3);
    shadowMapScene.addObject(&shadowSquare1);
    shadowMapScene.addObject(&shadowSquare2);
    shadowMapScene.addObject(&shadowSquare3);
    shadowMapScene.addObject(&shadowSquare4);
    shadowMapScene.addObject(&shadowSquare5);
    shadowMapScene.addObject(&shadowSquare6);

    Scene shadowRenderScene;
    shadowRenderScene.addObject(&ShadowRenderFSQ);
    
    Scene deferredBRDFScene;
    deferredBRDFScene.addObject(&DeferredBRDFFSQ);

	// --------------SCENE LOADING --------------------------

	Pass gbufferPass(defergbufferShader, &bunnyScene);
	Pass shadowPass(shadowMapShader, &shadowMapScene);
	Pass shadowRenderPass(shadowRenderShader, &shadowRenderScene);

	gbufferPass.BindAttribNormal();
	gbufferPass.BindAttribVertex();
	shadowPass.BindAttribVertex();
	shadowRenderPass.BindAttribVertex();
	shadowRenderPass.BindAttribTexture();

	// --------------- BIND ATTRIBUTES ---------------------

	gbufferPass.BindUniformMatrix4("ViewMatrix", &ViewMatrixPtr);
	gbufferPass.BindUniformMatrix4("ProjectionMatrix", &ProjectionMatrixPtr);
	shadowPass.BindUniformMatrix4("ViewMatrix", &Light1ViewMatrixPtr);
	shadowPass.BindUniformMatrix4("ProjectionMatrix", &ProjectionMatrixPtr);
	shadowRenderPass.BindUniformMatrix4("shadowMatrix", &Light1ShadowMatrixPtr);
	shadowRenderPass.BindUniformVec3("lightPos", &Light1PosPtr);
	shadowRenderPass.BindUniformVec3("eyePos", &EyePosPtr);
	shadowRenderPass.BindUniformVec3("lightValue", &Light1DiffusePtr);

	// ------------- BIND PASS-WISE UNIFORMS---------------

	gbufferPass.MeshBindUniformMatrix4(&bunny1, "ModelMatrix", &Bunny1ModelMatrixPtr);
	gbufferPass.MeshBindUniformMatrix4(&bunny1, "NormalMatrix", &Bunny1NormalMatrixPtr);
	shadowRenderPass.MeshBindUniformVec3(&bunny1, "diffuse", &Bunny1DiffusePtr);
	shadowRenderPass.MeshBindUniformVec3(&bunny1, "specular", &Bunny1SpecularPtr);
	gbufferPass.MeshBindUniformMatrix4(&bunny2, "ModelMatrix", &Bunny2ModelMatrixPtr);
	gbufferPass.MeshBindUniformMatrix4(&bunny2, "NormalMatrix", &Bunny2NormalMatrixPtr);
	gbufferPass.MeshBindUniformVec3(&bunny2, "diffuse", &Bunny2DiffusePtr);
	gbufferPass.MeshBindUniformVec3(&bunny2, "specular", &Bunny2SpecularPtr);
	gbufferPass.MeshBindUniformMatrix4(&bunny3, "ModelMatrix", &Bunny3ModelMatrixPtr);
	gbufferPass.MeshBindUniformMatrix4(&bunny3, "NormalMatrix", &Bunny3NormalMatrixPtr);
	gbufferPass.MeshBindUniformVec3(&bunny3, "diffuse", &Bunny3DiffusePtr);
	gbufferPass.MeshBindUniformVec3(&bunny3, "specular", &Bunny3SpecularPtr);
	gbufferPass.MeshBindUniformMatrix4(&Light1, "ModelMatrix", &Light1ModelMatrixPtr);
	gbufferPass.MeshBindUniformMatrix4(&Light1, "NormalMatrix", &Light1NormalMatrixPtr);
	gbufferPass.MeshBindUniformVec3(&Light1, "diffuse", &Light1DiffusePtr);
	gbufferPass.MeshBindUniformVec3(&Light1, "specular", &Light1SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&Light2, "ModelMatrix", &Light2ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&Light2, "NormalMatrix", &Light2NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&Light2, "diffuse", &Light2DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&Light2, "specular", &Light2SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&Light3, "ModelMatrix", &Light3ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&Light3, "NormalMatrix", &Light3NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&Light3, "diffuse", &Light3DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&Light3, "specular", &Light3SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&square1, "ModelMatrix", &Square1ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&square1, "NormalMatrix", &Square1NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&square1, "diffuse", &Square1DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&square1, "specular", &Square1SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&square2, "ModelMatrix", &Square2ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&square2, "NormalMatrix", &Square2NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&square2, "diffuse", &Square2DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&square2, "specular", &Square2SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&square3, "ModelMatrix", &Square3ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&square3, "NormalMatrix", &Square3NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&square3, "diffuse", &Square3DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&square3, "specular", &Square3SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&square4, "ModelMatrix", &Square4ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&square4, "NormalMatrix", &Square4NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&square4, "diffuse", &Square4DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&square4, "specular", &Square4SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&square5, "ModelMatrix", &Square5ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&square5, "NormalMatrix", &Square5NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&square5, "diffuse", &Square5DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&square5, "specular", &Square5SpecularPtr);
    gbufferPass.MeshBindUniformMatrix4(&square6, "ModelMatrix", &Square6ModelMatrixPtr);
    gbufferPass.MeshBindUniformMatrix4(&square6, "NormalMatrix", &Square6NormalMatrixPtr);
    gbufferPass.MeshBindUniformVec3(&square6, "diffuse", &Square6DiffusePtr);
    gbufferPass.MeshBindUniformVec3(&square6, "specular", &Square6SpecularPtr);

	shadowPass.MeshBindUniformMatrix4(&shadowBunny1, "ModelMatrix", &Bunny1ModelMatrixPtr);
	shadowPass.MeshBindUniformMatrix4(&shadowBunny2, "ModelMatrix", &Bunny2ModelMatrixPtr);
	shadowPass.MeshBindUniformMatrix4(&shadowBunny3, "ModelMatrix", &Bunny3ModelMatrixPtr);
    shadowPass.MeshBindUniformMatrix4(&shadowSquare1, "ModelMatrix", &Square1ModelMatrixPtr);
    shadowPass.MeshBindUniformMatrix4(&shadowSquare2, "ModelMatrix", &Square2ModelMatrixPtr);
    shadowPass.MeshBindUniformMatrix4(&shadowSquare3, "ModelMatrix", &Square3ModelMatrixPtr);
    shadowPass.MeshBindUniformMatrix4(&shadowSquare4, "ModelMatrix", &Square4ModelMatrixPtr);
    shadowPass.MeshBindUniformMatrix4(&shadowSquare5, "ModelMatrix", &Square5ModelMatrixPtr);
    shadowPass.MeshBindUniformMatrix4(&shadowSquare6, "ModelMatrix", &Square6ModelMatrixPtr);


	// ------------BIND MESH-WISE UNIFORMS----------------

	gbufferPass.SetTarget(&g_buffer);
	shadowPass.SetTarget(&shadow_buffer);

	Texture* visibilityTex = g_buffer.GetTexture(0);
	Texture* shadowTex = shadow_buffer.GetTexture(0);

	shadowRenderPass.BindTexture("visibilityTexture", visibilityTex);
	shadowRenderPass.BindTexture("shadowTexture", shadowTex);


	gbufferPass.SetBlend(false);
	gbufferPass.SetDepthTest(true);
    gbufferPass.SetClear(true);
	shadowPass.SetBlend(false);
	shadowPass.SetDepthTest(true);
    shadowPass.SetClear(true);
	shadowRenderPass.SetBlend(true);
	shadowRenderPass.SetDepthTest(false);
    shadowRenderPass.SetClear(false);

	// ---------------PASS CONFIG --------------------------
	engine->addPass(&gbufferPass);
	engine->addPass(&shadowPass);
	engine->addPass(&shadowRenderPass);



	// ----------------ENGINE------------------------------

#ifdef _WIN32
	glutMouseWheelFunc(mouseWheel);
#endif

	glutDisplayFunc(Draw);
	glutMouseFunc(mouseClick);
	glutMotionFunc(mouseMove);

	glutKeyboardUpFunc(keyboardPress);
	glutMainLoop();

	return 0;
}
Beispiel #3
0
/* --------------
 * Magic happens inside here
 * This is the main game loop
 * ------------- */
int Xyt::Game::run()
{

	CArcballCamera camera(glm::vec3(0.0f, 0.0f, 5.0f));

	CGBuffer g_buffer(m_main_window.screen_size_x, m_main_window.screen_size_y);
	CPickingTexture picking(m_main_window.screen_size_x, m_main_window.screen_size_y);

	CScene scene("root");

	//Sources
	CShader shader((PROJECT_PATH + "Shaders/diffuse.vs").c_str(),
		(PROJECT_PATH + "Shaders/diffuse.fs").c_str());

	CShader light_shader((PROJECT_PATH + "Shaders/light.vs").c_str(),
		(PROJECT_PATH + "Shaders/light.fs").c_str());

	CShader flat_shader((PROJECT_PATH + "Shaders/flat.vs").c_str(),
		(PROJECT_PATH + "Shaders/flat.fs").c_str());

	light_shader.use();
	glUniform1i(glGetUniformLocation(light_shader.get_program(), "gPosition"), 0);
	glUniform1i(glGetUniformLocation(light_shader.get_program(), "gNormal"), 1);
	glUniform1i(glGetUniformLocation(light_shader.get_program(), "gAlbedoSpec"), 2);
	glUniform1i(glGetUniformLocation(light_shader.get_program(), "gHighlight"), 3);

	//Scene state
	bool IsMoveMode = false;

	//Selected
	GLint selection = 0;

	std::vector<CLight> lights;
	srand(13);

	for(GLuint i = 0; i < 32; i++){
		

		GLfloat xPos = ((rand() % 100) / 100.0) * 6.0 - 3.0;
		GLfloat yPos = ((rand() % 100) / 100.0) * 6.0 - 4.0;
		GLfloat zPos = ((rand() % 100) / 100.0) * 6.0 - 3.0;

		CTransform transform;
		transform.position = glm::vec3(xPos, yPos, zPos);

		CLight light(transform);
		// Also calculate random color
		GLfloat rColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0
		GLfloat gColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0
		GLfloat bColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0
		light.color = glm::vec3(rColor, gColor, bColor);

		light.constant = 1.0f;
		light.linear = 0.7f;
		light.quadratic = 1.8;

		light.light_mesh.transform.scale = glm::vec3(0.2f, 0.2f, 0.2f);
		light.light_mesh.albedo_color = glm::vec4(light.color.x, light.color.y, light.color.z, 0.2f);

		lights.push_back(light);
	}

	/*
	//Declare Light Position
	std::vector<glm::vec3> light_positions;
	std::vector<glm::vec3> light_colors;
	srand(13);
	for (GLuint i = 0; i < 32; i++)
	{
		// Calculate slightly random offsets
		GLfloat xPos = ((rand() % 100) / 100.0) * 6.0 - 3.0;
		GLfloat yPos = ((rand() % 100) / 100.0) * 6.0 - 4.0;
		GLfloat zPos = ((rand() % 100) / 100.0) * 6.0 - 3.0;
		light_positions.push_back(glm::vec3(xPos, yPos, zPos));
		// Also calculate random color
		GLfloat rColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0
		GLfloat gColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0
		GLfloat bColor = ((rand() % 100) / 200.0f) + 0.5; // Between 0.5 and 1.0
		light_colors.push_back(glm::vec3(rColor, gColor, bColor));
	}
	*/

	float time = 0;

	auto cube = scene.add_mesh(new CMesh());
	cube->become_cube();
	cube->bind_to_gl();

	CMesh quad;
	quad.become_ndc_quad();
	quad.bind_to_gl();

	std::vector<CMesh*> objects = scene.get_all_meshes();

	//GAME LOOP START
	while (!m_main_window.is_closing()){

		time += m_delta_time;

		/* -------------------------
		* Event Handling
 		* -------------------------- */
		glfwPollEvents();

		//Render base color for texture picking
		picking.render_picking_texture(m_main_window, camera, scene);

		//Input delay
		if (time > 0.2f){

			//Picking test
			if (CInputManager::instance().mouse_button[GLFW_MOUSE_BUTTON_RIGHT] == 1){
				
				picking.pick_test(m_main_window, camera, scene, CInputManager::instance());
				time = 0;
			}

			/* 
			* Commands
			*/
			if (CInputManager::instance().keys[GLFW_KEY_G] == 1){
				if (!scene.get_selected_meshes().empty()){
					scene.command_manager.add_command(new CMoveCommand(scene.get_selected_meshes(), &camera));
				}
				time = 0;
			}


			if (CInputManager::instance().keys[GLFW_KEY_Z] == 1 && CInputManager::instance().keys[GLFW_KEY_LEFT_CONTROL]){
				scene.command_manager.undo_command();
				time = 0;
			}

			if (CInputManager::instance().keys[GLFW_KEY_Y] == 1 && CInputManager::instance().keys[GLFW_KEY_LEFT_CONTROL]){
				scene.command_manager.redo_command();
				time = 0;
			}

			scene.command_manager.input(*this, CInputManager::instance());
		
		}

		scene.command_manager.update(*this, CInputManager::instance(), m_delta_time);


		this->handle_xyt_events(camera);

		/* -------------------------
		* Rendering Pipeline
		* -------------------------- */

		std::vector<CMesh*> selected_meshes = scene.get_selected_meshes();
		//If no selection then we dont draw anything to screen
		if (selected_meshes.size() == 0){
			//Draw nothing on selection pass
			glBindFramebuffer(GL_FRAMEBUFFER, picking.m_fbo);
				m_main_window.clear_screen();
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
		} else{
			//Highlight the entire model on a texture
			glBindFramebuffer(GL_FRAMEBUFFER, picking.m_fbo);
				m_main_window.clear_screen();
				flat_shader.use();
				camera.draw(flat_shader, m_main_window.screen_size_x, m_main_window.screen_size_y);
				for (int i = 0; i < selected_meshes.size(); i++){
					selected_meshes.at(i)->draw(flat_shader);
				}
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
		}

		//1st render pass (Geometry Pass), render scene's geometry/color into gbuffer
		glBindFramebuffer(GL_FRAMEBUFFER, g_buffer.m_g_buffer);
			m_main_window.clear_screen();
			g_buffer.g_buffer_pass.use();
			camera.draw(g_buffer.g_buffer_pass, m_main_window.screen_size_x, m_main_window.screen_size_y);
			for (int i = 0; i < objects.size(); i++){
				objects.at(i)->draw(g_buffer.g_buffer_pass);			
			}
			for(int i = 0; i < lights.size(); i++){
				lights.at(i).draw_light_mesh(g_buffer.g_buffer_pass);
			}
		glBindFramebuffer(GL_FRAMEBUFFER, 0);

		//Final Deferred render pass (Lighting Pass) 
		//TOOD : Refactor to a Pipeline class
		light_shader.use();
		glActiveTexture(GL_TEXTURE0);
		glBindTexture(GL_TEXTURE_2D, g_buffer.m_g_position);
		glActiveTexture(GL_TEXTURE1);
		glBindTexture(GL_TEXTURE_2D, g_buffer.m_g_normal);
		glActiveTexture(GL_TEXTURE2);
		glBindTexture(GL_TEXTURE_2D, g_buffer.m_g_albedospec);
		glActiveTexture(GL_TEXTURE3);
		glBindTexture(GL_TEXTURE_2D, picking.m_picking_texture);

		// for (GLuint i = 0; i < light_positions.size(); i++){
		// 	glUniform3fv(glGetUniformLocation(light_shader.get_program(),
		// 		("lights[" + std::to_string(i) + "].Position").c_str()), 1, &light_positions[i][0]);

		// 	glUniform3fv(glGetUniformLocation(light_shader.get_program(),
		// 		("lights[" + std::to_string(i) + "].Color").c_str()), 1, &light_colors[i][0]);

		// 	const GLfloat constant = 1.0; // Note that we don't send this to the shader, we assume it is always 1.0 (in our case)
		// 	const GLfloat linear = 0.7;
		// 	const GLfloat quadratic = 1.8;
		// 	glUniform1f(glGetUniformLocation(light_shader.get_program(), ("lights[" + std::to_string(i) + "].Linear").c_str()), linear);
		// 	glUniform1f(glGetUniformLocation(light_shader.get_program(), ("lights[" + std::to_string(i) + "].Quadratic").c_str()), quadratic);
		// }
		// glUniform3fv(glGetUniformLocation(light_shader.get_program(), "viewPos"), 1, &camera.Position[0]);
		// quad.draw(light_shader);

		for(GLuint i = 0; i < lights.size(); i++){
			lights.at(i).light_to_shader(light_shader, i);
		}
		glUniform3fv(glGetUniformLocation(light_shader.get_program(), "viewPos"), 1, &camera.Position[0]);
		quad.draw(light_shader);

		m_main_window.draw_screen();
		m_main_window.clear_screen();

		this->calculate_delta();
	}
	//END GAME LOOP

	return 0;
}