diff --git a/example/Makefile b/example/Makefile index f499f4d..9c05673 100644 --- a/example/Makefile +++ b/example/Makefile @@ -17,4 +17,4 @@ example: -L../glfw/src \ -lglew -lglfw3 \ -framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo \ - ../../main.cpp + ../../src/main.cpp diff --git a/example/main.cpp b/example/main.cpp deleted file mode 100644 index 18debc7..0000000 --- a/example/main.cpp +++ /dev/null @@ -1,53 +0,0 @@ -#include - -#include -#include - -int main() -{ - // Initialise GLFW - glewExperimental = true; // Needed for core profile - if (!glfwInit()) { - fprintf( stderr, "Failed to initialize GLFW\n" ); - return -1; - } - - glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3 - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL - - // Open a window and create its OpenGL context - GLFWwindow* window; // (In the accompanying source code, this variable is global for simplicity) - window = glfwCreateWindow( 1024, 768, "Tutorial 01", NULL, NULL); - if (window == NULL) { - fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" ); - glfwTerminate(); - return -1; - } - glfwMakeContextCurrent(window); // Initialize GLEW - glewExperimental=true; // Needed in core profile - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to initialize GLEW\n"); - return -1; - } - - // Ensure we can capture the escape key being pressed below - glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); - - do { - // Clear the screen. It's not mentioned before Tutorial 02, but it can cause flickering, so it's there nonetheless. - glClear(GL_COLOR_BUFFER_BIT); - - // Draw nothing, see you in tutorial 2 ! - - // Swap buffers - glfwSwapBuffers(window); - glfwPollEvents(); - } while ( - // Check if the ESC key was pressed or the window was closed - glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS - && glfwWindowShouldClose(window) == 0 - ); -} diff --git a/example/src/fragment.glsl b/example/src/fragment.glsl new file mode 100644 index 0000000..19c9709 --- /dev/null +++ b/example/src/fragment.glsl @@ -0,0 +1,9 @@ +#version 330 core + +in vec3 fragmentColor; + +out vec3 color; + +void main() { + color = fragmentColor; +} diff --git a/example/src/loadshaders.cpp b/example/src/loadshaders.cpp new file mode 100644 index 0000000..edc22bb --- /dev/null +++ b/example/src/loadshaders.cpp @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include + +GLuint LoadShaders(const char * vertex_file_path, const char * fragment_file_path) { + // Create the shaders + GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read the Vertex Shader code from the file + std::string VertexShaderCode; + std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); + if(VertexShaderStream.is_open()){ + std::stringstream sstr; + sstr << VertexShaderStream.rdbuf(); + VertexShaderCode = sstr.str(); + VertexShaderStream.close(); + }else{ + printf("Impossible to open %s. Are you in the right directory ? Don't forget to read the FAQ !\n", vertex_file_path); + return 0; + } + + // Read the Fragment Shader code from the file + std::string FragmentShaderCode; + std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); + if(FragmentShaderStream.is_open()){ + std::stringstream sstr; + sstr << FragmentShaderStream.rdbuf(); + FragmentShaderCode = sstr.str(); + FragmentShaderStream.close(); + } + + GLint Result = GL_FALSE; + int InfoLogLength; + + // Compile Vertex Shader + printf("Compiling shader : %s\n", vertex_file_path); + char const * VertexSourcePointer = VertexShaderCode.c_str(); + glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL); + glCompileShader(VertexShaderID); + + // Check Vertex Shader + glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if ( InfoLogLength > 0 ){ + std::vector VertexShaderErrorMessage(InfoLogLength+1); + glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); + printf("%s\n", &VertexShaderErrorMessage[0]); + } + + // Compile Fragment Shader + printf("Compiling shader : %s\n", fragment_file_path); + char const * FragmentSourcePointer = FragmentShaderCode.c_str(); + glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL); + glCompileShader(FragmentShaderID); + + // Check Fragment Shader + glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if ( InfoLogLength > 0 ){ + std::vector FragmentShaderErrorMessage(InfoLogLength+1); + glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); + printf("%s\n", &FragmentShaderErrorMessage[0]); + } + + // Link the program + printf("Linking program\n"); + GLuint ProgramID = glCreateProgram(); + glAttachShader(ProgramID, VertexShaderID); + glAttachShader(ProgramID, FragmentShaderID); + glLinkProgram(ProgramID); + + // Check the program + glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); + glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if ( InfoLogLength > 0 ){ + std::vector ProgramErrorMessage(InfoLogLength+1); + glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); + printf("%s\n", &ProgramErrorMessage[0]); + } + + glDetachShader(ProgramID, VertexShaderID); + glDetachShader(ProgramID, FragmentShaderID); + + glDeleteShader(VertexShaderID); + glDeleteShader(FragmentShaderID); + + return ProgramID; +} diff --git a/example/src/main.cpp b/example/src/main.cpp new file mode 100644 index 0000000..93e885d --- /dev/null +++ b/example/src/main.cpp @@ -0,0 +1,211 @@ +#include + +#include +#include + +#include "loadshaders.cpp" + +#define HANDMADE_MATH_IMPLEMENTATION +#include "../../HandmadeMath.h" + +int main() +{ + // Initialise GLFW + glewExperimental = true; // Needed for core profile + if (!glfwInit()) { + fprintf( stderr, "Failed to initialize GLFW\n" ); + return -1; + } + + glfwWindowHint(GLFW_SAMPLES, 4); // 4x antialiasing + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3 + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // To make MacOS happy; should not be needed + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL + + // Open a window and create its OpenGL context + GLFWwindow* window; // (In the accompanying source code, this variable is global for simplicity) + window = glfwCreateWindow( 1024, 768, "Tutorial 01", NULL, NULL); + if (window == NULL) { + fprintf( stderr, "Failed to open GLFW window. If you have an Intel GPU, they are not 3.3 compatible. Try the 2.1 version of the tutorials.\n" ); + glfwTerminate(); + return -1; + } + glfwMakeContextCurrent(window); // Initialize GLEW + glewExperimental=true; // Needed in core profile + if (glewInit() != GLEW_OK) { + fprintf(stderr, "Failed to initialize GLEW\n"); + return -1; + } + + // Ensure we can capture the escape key being pressed below + glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); + + GLuint VertexArrayID; + glGenVertexArrays(1, &VertexArrayID); + glBindVertexArray(VertexArrayID); + + // Our vertices. Three consecutive floats give a 3D vertex; Three consecutive vertices give a triangle. + // A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices + static const GLfloat g_vertex_buffer_data[] = { + -1.0f,-1.0f,-1.0f, // triangle 1 : begin + -1.0f,-1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, // triangle 1 : end + 1.0f, 1.0f,-1.0f, // triangle 2 : begin + -1.0f,-1.0f,-1.0f, + -1.0f, 1.0f,-1.0f, // triangle 2 : end + 1.0f,-1.0f, 1.0f, + -1.0f,-1.0f,-1.0f, + 1.0f,-1.0f,-1.0f, + 1.0f, 1.0f,-1.0f, + 1.0f,-1.0f,-1.0f, + -1.0f,-1.0f,-1.0f, + -1.0f,-1.0f,-1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f, 1.0f,-1.0f, + 1.0f,-1.0f, 1.0f, + -1.0f,-1.0f, 1.0f, + -1.0f,-1.0f,-1.0f, + -1.0f, 1.0f, 1.0f, + -1.0f,-1.0f, 1.0f, + 1.0f,-1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f,-1.0f,-1.0f, + 1.0f, 1.0f,-1.0f, + 1.0f,-1.0f,-1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f,-1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + 1.0f, 1.0f,-1.0f, + -1.0f, 1.0f,-1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f,-1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f, 1.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 1.0f,-1.0f, 1.0f + }; + + // This will identify our vertex buffer + GLuint vertexbuffer; + // Generate 1 buffer, put the resulting identifier in vertexbuffer + glGenBuffers(1, &vertexbuffer); + // The following commands will talk about our 'vertexbuffer' buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + // Give our vertices to OpenGL. + glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), g_vertex_buffer_data, GL_STATIC_DRAW); + + // One color for each vertex. They were generated randomly. + static const GLfloat g_color_buffer_data[] = { + 0.583f, 0.771f, 0.014f, + 0.609f, 0.115f, 0.436f, + 0.327f, 0.483f, 0.844f, + 0.822f, 0.569f, 0.201f, + 0.435f, 0.602f, 0.223f, + 0.310f, 0.747f, 0.185f, + 0.597f, 0.770f, 0.761f, + 0.559f, 0.436f, 0.730f, + 0.359f, 0.583f, 0.152f, + 0.483f, 0.596f, 0.789f, + 0.559f, 0.861f, 0.639f, + 0.195f, 0.548f, 0.859f, + 0.014f, 0.184f, 0.576f, + 0.771f, 0.328f, 0.970f, + 0.406f, 0.615f, 0.116f, + 0.676f, 0.977f, 0.133f, + 0.971f, 0.572f, 0.833f, + 0.140f, 0.616f, 0.489f, + 0.997f, 0.513f, 0.064f, + 0.945f, 0.719f, 0.592f, + 0.543f, 0.021f, 0.978f, + 0.279f, 0.317f, 0.505f, + 0.167f, 0.620f, 0.077f, + 0.347f, 0.857f, 0.137f, + 0.055f, 0.953f, 0.042f, + 0.714f, 0.505f, 0.345f, + 0.783f, 0.290f, 0.734f, + 0.722f, 0.645f, 0.174f, + 0.302f, 0.455f, 0.848f, + 0.225f, 0.587f, 0.040f, + 0.517f, 0.713f, 0.338f, + 0.053f, 0.959f, 0.120f, + 0.393f, 0.621f, 0.362f, + 0.673f, 0.211f, 0.457f, + 0.820f, 0.883f, 0.371f, + 0.982f, 0.099f, 0.879f + }; + + GLuint colorbuffer; + glGenBuffers(1, &colorbuffer); + glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW); + + // Create and compile our GLSL program from the shaders + GLuint programID = LoadShaders("src/vertex.glsl", "src/fragment.glsl"); + if (!programID) { + return 1; + } + + // Get a handle for our "MVP" uniform + // Only during the initialisation + GLuint MatrixID = glGetUniformLocation(programID, "MVP"); + + // Enable depth test + glEnable(GL_DEPTH_TEST); + // Accept fragment if it closer to the camera than the former one + glDepthFunc(GL_LESS); + + do { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(0); + glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); + glVertexAttribPointer( + 0, // attribute 0. No particular reason for 0, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // 2nd attribute buffer : colors + glEnableVertexAttribArray(1); + glBindBuffer(GL_ARRAY_BUFFER, colorbuffer); + glVertexAttribPointer( + 1, // attribute. No particular reason for 1, but must match the layout in the shader. + 3, // size + GL_FLOAT, // type + GL_FALSE, // normalized? + 0, // stride + (void*)0 // array buffer offset + ); + + // Use our shader + glUseProgram(programID); + + hmm_mat4 projection = HMM_Perspective(90.0f, 1024.0f / 768.0f, 0.1f, 100.0f); + // hmm_mat4 projection = HMM_Orthographic(-2.0f, 2.0f, -2.0f, 2.0f, 0.1f, 100.0f); + hmm_mat4 view = HMM_LookAt(HMM_Vec3(4.0f, 3.0f, 3.0f), HMM_Vec3(0.0f, 0.0f, 0.0f), HMM_Vec3(0.0f, 1.0f, 0.0f)); + hmm_mat4 model = HMM_Mat4d(1.0f); + + hmm_mat4 mvp = projection * view * model; + + // Send our transformation to the currently bound shader, in the "MVP" uniform + // This is done in the main loop since each model will have a different MVP matrix (At least for the M part) + glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp.Elements[0][0]); + + // Draw the triangle ! + glDrawArrays(GL_TRIANGLES, 0, 36); // Starting from vertex 0; 3 vertices total -> 1 triangle + glDisableVertexAttribArray(0); + + // Swap buffers + glfwSwapBuffers(window); + glfwPollEvents(); + } while ( + // Check if the ESC key was pressed or the window was closed + glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS + && glfwWindowShouldClose(window) == 0 + ); +} diff --git a/example/src/vertex.glsl b/example/src/vertex.glsl new file mode 100644 index 0000000..1924553 --- /dev/null +++ b/example/src/vertex.glsl @@ -0,0 +1,15 @@ +#version 330 core + +layout(location = 0) in vec3 vertexPosition_modelspace; +// Notice that the "1" here equals the "1" in glVertexAttribPointer +layout(location = 1) in vec3 vertexColor; + +uniform mat4 MVP; + +out vec3 fragmentColor; + +void main(){ + // Output position of the vertex, in clip space : MVP * position + gl_Position = MVP * vec4(vertexPosition_modelspace, 1); + fragmentColor = vertexColor; +}