text: #include "Globals.h"
  #include "Application.h"
  #include "ModuleRenderer3D.h"
  #include "ModuleWindow.h"
  #include "ModuleCamera3D.h"
  
  #include "Primitive.h"
  
  #include "OpenGL.h"
  
  #include "Imgui/imgui.h"
  #include "Imgui/imgui_impl_sdl_gl3.h"
  
  #pragma comment (lib, "opengl32.lib") /* link Microsoft OpenGL lib   */
  #pragma comment (lib, "glu32.lib")    /* link OpenGL Utility lib     */
  #pragma comment (lib, "Glew/libx86/glew32.lib") /* link Microsoft OpenGL lib   */
  
  
  
  
  ModuleRenderer3D::ModuleRenderer3D(Application* app, bool start_enabled) : Module(app, start_enabled)
  {
  }
  
  // Destructor
  ModuleRenderer3D::~ModuleRenderer3D()
  {}
  
  // Called before render is available
  bool ModuleRenderer3D::Init()
  {
  	SDL_Log("Creating 3D Renderer context");
  	bool ret = true;
  
  	//Create context
  	context = SDL_GL_CreateContext(App->window->GetWindow());
  	if (context == nullptr)
  	{
  		SDL_Log("OpenGL context could not be created! SDL_Error: %s\n", SDL_GetError());
  		ret = false;
  	}
  
  	GLenum err = glewInit();
  
  	if (err != GLEW_OK)
  	{
  		SDL_Log("Glew library could not init %s\n", glewGetErrorString(err));
  		ret = false;
  	}
  	else
  		SDL_Log("Using Glew %s", glewGetString(GLEW_VERSION));
  
  	if (ret == true)
  	{
  		// get version info
  		SDL_Log("Vendor: %s", glGetString(GL_VENDOR));
  		SDL_Log("Renderer: %s", glGetString(GL_RENDERER));
  		SDL_Log("OpenGL version supported %s", glGetString(GL_VERSION));
  		SDL_Log("GLSL: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
  
  		//Use Vsync
  		//bool set_vsync = config->GetBool("Vertical Sync", false);
  		//vsync = !set_vsync; // force change
  		//SetVSync(set_vsync);
  
  		//Initialize Projection Matrix
  		glMatrixMode(GL_PROJECTION);
  		glLoadIdentity();
  
  		//Check for error
  		GLenum error = glGetError();
  		if (error != GL_NO_ERROR)
  		{
  			SDL_Log("Error initializing OpenGL! %s\n", gluErrorString(error));
  			ret = false;
  		}
  
  		//Initialize Modelview Matrix
  		glMatrixMode(GL_MODELVIEW);
  		glLoadIdentity();
  
  		//Check for error
  		error = glGetError();
  		if (error != GL_NO_ERROR)
  		{
  			SDL_Log("Error initializing OpenGL! %s\n", gluErrorString(error));
  			ret = false;
  		}
  
  		glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  		glClearDepth(1.0f);
  
  		//Initialize clear color
  		glClearColor(0.f, 0.f, 0.f, 1.f);
  
  		//Check for error
  		error = glGetError();
  		if (error != GL_NO_ERROR)
  		{
  			SDL_Log("Error initializing OpenGL! %s\n", gluErrorString(error));
  			ret = false;
  		}
  
  		// Blend for transparency
  		//glBlendEquation(GL_FUNC_ADD);
  		//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  
  
  		GLfloat LightModelAmbient[] = { 0.0f, 0.0f, 0.0f, 1.0f };
  		glLightModelfv(GL_LIGHT_MODEL_AMBIENT, LightModelAmbient);
  
  		lights[0].ref = GL_LIGHT0;
  		lights[0].ambient.Set(0.25f, 0.25f, 0.25f, 1.0f);
  		lights[0].diffuse.Set(0.75f, 0.75f, 0.75f, 1.0f);
  		//lights[0].position = float3::zero;
  		lights[0].Init();
  
  		GLfloat MaterialAmbient[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  		glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, MaterialAmbient);
  
  		GLfloat MaterialDiffuse[] = { 1.0f, 1.0f, 1.0f, 1.0f };
  		glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialDiffuse);
  
  		glEnable(GL_DEPTH_TEST);
  		glEnable(GL_CULL_FACE);
  		lights[0].Active(true);
  		glEnable(GL_LIGHTING);
  		glEnable(GL_COLOR_MATERIAL);
  		//glEnable(GL_TEXTURE_2D);
  
  		glShadeModel(GL_SMOOTH);		 // Enables Smooth Shading
  		
  	}
  
  	OnResize(SCREEN_WIDTH, SCREEN_HEIGHT);
  	return ret;
  }
  
  // PreUpdate: clear buffer
  update_status ModuleRenderer3D::PreUpdate(float dt)
  {
  	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  	glLoadIdentity();
  
  	glMatrixMode(GL_MODELVIEW);
  	glLoadMatrixf(App->camera->GetViewMatrix());
  
  	// light 0 on cam pos
  	lights[0].SetPos(App->camera->Position.x, App->camera->Position.y, App->camera->Position.z);
  
  	for(uint i = 0; i < MAX_LIGHTS; ++i)
  		lights[i].Render();
  
  	return UPDATE_CONTINUE;
  }
  
  // PostUpdate present buffer to screen
  update_status ModuleRenderer3D::PostUpdate(float dt)
  {
  	
  
  
  
  	SDL_GL_SwapWindow(App->window->window);
  	return UPDATE_CONTINUE;
  }
  
  // Called before quitting
  bool ModuleRenderer3D::CleanUp()
  {
  	SDL_Log("Destroying 3D Renderer");
  
  	SDL_GL_DeleteContext(context);
  
  	return true;
  }
  
  
  void ModuleRenderer3D::OnResize(int width, int height)
  {
  	glViewport(0, 0, width, height);
  
  	glMatrixMode(GL_PROJECTION);
  	glLoadIdentity();
  	ProjectionMatrix = perspective(60.0f, (float)width / (float)height, 0.125f, 512.0f);
  	glLoadMatrixf(&ProjectionMatrix);
  
  	glMatrixMode(GL_MODELVIEW);
  	glLoadIdentity();
  }
  