void AssimpProgram::compile() {
    std::string vertexShaderCode("layout (location = 0) in vec3 position;\n"
                                         "layout (location = 1) in vec3 normal;\n"
                                         "layout (location = 2) in vec2 texCoords;\n"
                                         "\n"
                                         "out vec2 TexCoords;\n"
                                         "\n"
                                         "uniform mat4 uMVPMatrix;\n"
                                         "\n"
                                         "void main()\n"
                                         "{\n"
                                         "    gl_Position = uMVPMatrix * vec4(position, 1.0f);\n"
                                         "    TexCoords = texCoords;\n"
                                         "}");
    std::string fragmentShaderCode("\n"
                                           "in vec2 TexCoords;\n"
                                           "\n"
                                           "out vec4 color;\n"
                                           "\n"
                                           "uniform sampler2D textureDiffuse;\n"
                                           "\n"
                                           "void main()\n"
                                           "{\n"
                                           "    color = vec4(texture(textureDiffuse, TexCoords));\n"
                                           "}");

    programID = Shader::createShaderProgram(vertexShaderCode, fragmentShaderCode);
    uMVPMatrix = (GLuint) glGetUniformLocation(programID, "uMVPMatrix");
}
GLuint loadShaders(const std::string & vertexFilePath,
        const std::string & fragmentFilePath)
{
	// Create the shaders
	GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
	GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

	// Read the Vertex Shader code from the file
	std::ifstream vertexShaderStream(vertexFilePath);
	if(!vertexShaderStream.is_open()) {
        std::cerr << "Impossible to open " << vertexFilePath << '\n';
        return 0;
    }//if
	std::string vertexShaderCode(
            (std::istreambuf_iterator<char>(vertexShaderStream)),
            std::istreambuf_iterator<char>());

	// Read the Fragment Shader code from the file
	std::ifstream fragmentShaderStream(fragmentFilePath);
	if(!fragmentShaderStream.is_open()) {
        std::cerr << "Impossible to open " << fragmentFilePath << '\n';
        return 0;
	}//if
	std::string fragmentShaderCode(
            (std::istreambuf_iterator<char>(fragmentShaderStream)),
            std::istreambuf_iterator<char>());

	GLint status = GL_FALSE;
	int infoLogLength;

	// Compile Vertex Shader
    std::cout << "Compiling Vertex Shader: " << vertexFilePath << '\n';
	const char * vertexSourcePointer = vertexShaderCode.c_str();
	glShaderSource(vertexShaderID, 1, &vertexSourcePointer , nullptr);
	glCompileShader(vertexShaderID);

	// Check Vertex Shader
	glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &status);
	glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
	if(infoLogLength > 0){
        std::string vertexShaderErrorMessage(infoLogLength + 1, '\0');
		glGetShaderInfoLog(vertexShaderID, infoLogLength, nullptr,
                (GLchar *)(vertexShaderErrorMessage.data()));
        std::cerr << vertexShaderErrorMessage << '\n';
	}//if

	// Compile Fragment Shader
    std::cout << "Compiling Fragment Shader: " << fragmentFilePath << '\n';
	char const * fragmentSourcePointer = fragmentShaderCode.c_str();
	glShaderSource(fragmentShaderID, 1, &fragmentSourcePointer, nullptr);
	glCompileShader(fragmentShaderID);

	// Check Fragment Shader
	glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &status);
	glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength);
	if(infoLogLength > 0){
        std::string fragmentShaderErrorMessage(infoLogLength + 1, '\0');
		glGetShaderInfoLog(fragmentShaderID, infoLogLength, nullptr,
                (GLchar *)(fragmentShaderErrorMessage.data()));
        std::cerr << fragmentShaderErrorMessage << '\n';
	}//if

	// Link the program
    std::cout << "Linking program: " << vertexFilePath << " & "
        << fragmentFilePath << '\n';
	GLuint programID = glCreateProgram();
	glAttachShader(programID, vertexShaderID);
	glAttachShader(programID, fragmentShaderID);
	glLinkProgram(programID);

	// Check the program
	glGetProgramiv(programID, GL_LINK_STATUS, &status);
	glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength);
	if(infoLogLength > 0){
        std::string programErrorMessage(infoLogLength + 1, '\0');
		glGetProgramInfoLog(programID, infoLogLength, nullptr,
                (GLchar *)(programErrorMessage.data()));
        std::cerr << programErrorMessage << '\n';
	}//if

	glDeleteShader(vertexShaderID);
	glDeleteShader(fragmentShaderID);

	return programID;
}//loadShaders(vertexShaderStream, fragmentFilePath)
void Game::LoadAndCompileShaders()
{
	// In the future, this should return an GLuint ID for the shader program.
	// Also, in the future, this should be adding a shader program to a material component.
	// Essentially, the eventual purpose of this function will be to load all the shaders for all the mats.
	std::ifstream inf("vertexShader.vertex");
	std::string vertexShaderCode ( (std::istreambuf_iterator<char>(inf) ), (std::istreambuf_iterator<char>() ) );
	inf.close();
	inf.open("fragmentShader.frag");
	std::string fragmentShaderCode ( (std::istreambuf_iterator<char>(inf)), (std::istreambuf_iterator<char>() ) );
	GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
	GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);

	GLint Result = GL_FALSE;
	int InfoLogLength;

	std::ofstream log("log.txt");
	std::cout << " Compiling Vertex Shader" << std::endl;
	char const * VertexSourcePointer = vertexShaderCode.c_str();
	glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL);
	glCompileShader(VertexShaderID);

	// Check shader compilation
	glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if(InfoLogLength > 0)
	{
		std::vector<char> VertexShaderErrorMessage(InfoLogLength);
		glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
		std::cout << &VertexShaderErrorMessage[0] << std::endl;
		log << &VertexShaderErrorMessage[0] << std::endl;
	}

	std::cout << "Compiling Fragment Shader" << std::endl;
	char const * FragmentSourcePointer = fragmentShaderCode.c_str();
	glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL);
	glCompileShader(FragmentShaderID);

	glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
	if(InfoLogLength > 0)
	{
		std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
		glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
		std::cout << &FragmentShaderErrorMessage[0] << std::endl;
		log << &FragmentShaderErrorMessage[0] << std::endl;
	}

	std::cout << "Linking Program" << std::endl;

	GLuint ProgramID = glCreateProgram();
	glAttachShader(ProgramID, VertexShaderID);
	glAttachShader(ProgramID, FragmentShaderID);
	glLinkProgram(ProgramID);
	
	glGetProgramiv(ProgramID, GL_COMPILE_STATUS, &Result);
	glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
	std::vector<char> ProgramErrorMessage(std::max(InfoLogLength, int(1)));
	std::cout << &ProgramErrorMessage[0] << std::endl;

	glDeleteShader(VertexShaderID);
	glDeleteShader(FragmentShaderID);
	glValidateProgram(ProgramID);

	ShaderProgramID = ProgramID;
}