#include <iostream>
// GLEW
#define GLEW_STATIC
#include <GL/glew.h>
// GLFW
#include <GLFW/glfw3.h>
// Other includes
#include "shader.h"

// Function prototypes
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode);

// Window dimensions
const GLuint WIDTH = 800, HEIGHT = 600;

// The MAIN function, from here we start the application and run the game loop
int main()
{
    // Init GLFW
    glfwInit();
    // Set all the required options for GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    // Create a GLFWwindow object that we can use for GLFW's functions
    GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "LearnOpenGL", nullptr, nullptr);
    glfwMakeContextCurrent(window);

    // Set the required callback functions
    glfwSetKeyCallback(window, key_callback);

    // Set this to true so GLEW knows to use a modern approach to retrieving function pointers and extensions
    glewExperimental = GL_TRUE;
    // Initialize GLEW to setup the OpenGL Function pointers
    glewInit();

    // Define the viewport dimensions
    glViewport(0, 0, WIDTH, HEIGHT);


    //��ȡshader�ļ��������룬��shader.h����
    Shader ourShader("shader.vs", "shader.frag");


    // һά���飬ÿ��������һ���������ԣ�ǰ��������λ�����ԣ�������������ɫ����
    GLfloat vertices[] = {
        // Positions         // Colors
        0.5f, -0.5f, 0.0f,   1.0f, 0.0f, 0.0f,  // Bottom Right
        -0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,  // Bottom Left
        0.0f,  0.5f, 0.0f,   0.0f, 0.0f, 1.0f   // Top 
    };
    GLuint VBO, VAO;//�������㻺�壬���������������ڹ�����������
    glGenVertexArrays(1, &VAO);//�����������飬����һ����һ�޶�����������ʶ����
    glGenBuffers(1, &VBO);//�������㻺�壬����һ����һ�޶�����������ʶ������
    
    glBindVertexArray(VAO);//�󶨶�������
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//�󶨶��㻺��
	//ָ���������������ԴΪvertices�����ĸ����������Կ���ι������������ݣ�GL_STATIC_DRWA������������ı�
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    // ָ���������ԵĽ�����ʽ��������δӶ��㻺���ȡ��Ӧ�Ķ������Ժ���Ӧ����ɫ���ԡ�����˵��������ɫ�������֪��ȥ�ĸ��������Է�������ɫ��
	//��ÿһ��������ԣ�������2�֣�һ��λ�����ԣ�������ɫ���ԣ����ÿ����������������һ�������λ�ú���ɫ

	//������ɫ����ʹ��layout(location = 0)������position�������Ե�λ��ֵ(Location)����˵�һ���������������Է���������
	//������������λ�����Ե�ά�ȣ��������������������������ͣ�������:�Ƿ��׼���������壬����λ�����Ե����ֽڳ��ȣ����������ڻ��������е�ƫ����������ʼλ��
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);//��������0����ΪĬ���ǽ��õ�

    // ����һ����Ӧ������ɫ���е�layout (location = 1) in vec3 color;��������˵����ɫ���Ե�ƫ������������������������verticesһ��
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);//��������1.

	//�����������(Vertex Array Object, VAO)�ĺô����ǣ������ö�������ָ��ʱ����ֻ��Ҫ������Ĵ������ִ��һ�Σ�֮���ٻ��������ʱ��ֻ��Ҫ����Ӧ��VAO�����ˡ�������ѭ���еİ��ٽ��
    glBindVertexArray(0); // ��� VAO
    // Game loop
    while (!glfwWindowShouldClose(window))
    {
        // ����¼���������Ӧ�Ļص������������ĵ�key_callback����
        glfwPollEvents();

        // Render
        // Clear the colorbuffer
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);//��Ⱦ��ɫ����̨����
        glClear(GL_COLOR_BUFFER_BIT);//���ǰ̨����

        // Draw the triangle
        ourShader.Use();//������ɫ������
        glBindVertexArray(VAO);//ÿ��ѭ�������ã��󶨺�����VAO
        glDrawArrays(GL_TRIANGLES, 0, 3);
        glBindVertexArray(0);//���

        // Swap the screen buffers
        glfwSwapBuffers(window);
    }
    // Properly de-allocate all resources once they've outlived their purpose
    glDeleteVertexArrays(1, &VAO);
    glDeleteBuffers(1, &VBO);
    // Terminate GLFW, clearing any resources allocated by GLFW.
    glfwTerminate();
    return 0;
}


// Is called whenever a key is pressed/released via GLFW
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
    if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
        glfwSetWindowShouldClose(window, GL_TRUE);
}