├── .gitignore ├── .gitmodules ├── CMakeLists.txt ├── LICENSE ├── README.md └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | build 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "glfw"] 2 | path = glfw 3 | url = https://github.com/glfw/glfw 4 | [submodule "glm"] 5 | path = glm 6 | url = https://github.com/Groovounet/glm 7 | [submodule "glxw"] 8 | path = glxw 9 | url = http://glxw.dav1d.de/glxw.git 10 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | project(triangle) 3 | 4 | find_package(OpenGL REQUIRED) 5 | 6 | add_subdirectory(glfw) 7 | add_subdirectory(glxw) 8 | 9 | include_directories(glxw/include) 10 | include_directories(glfw/include) 11 | include_directories(glm) 12 | 13 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2 -Wall -Wextra -Werror -Wno-deprecated-register -Wno-shift-op-parentheses -std=c++11") 14 | SET(LIBRARIES glfw glxw ${GLFW_LIBRARIES} ${GLXW_LIBRARY} ${OPENGL_LIBRARY}) 15 | 16 | set(SOURCE_FILES main.cpp) 17 | add_executable(triangle ${SOURCE_FILES}) 18 | 19 | target_link_libraries(triangle ${LIBRARIES}) 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cpp-opengl-vbo-vao-shaders 2 | 3 | Usage: 4 | 5 | ``` 6 | git submodule init 7 | git submodule update 8 | mkdir build 9 | cd build 10 | cmake .. 11 | make 12 | ./triangle 13 | ``` 14 | 15 | Tested on Linux, MacOS and Windows. 16 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | static const GLfloat globVertexBufferData[] = { 9 | -1.0f, -1.0f, 0.0f, 10 | 1.0f, -1.0f, 0.0f, 11 | 0.0f, 1.0f, 0.0f, 12 | }; 13 | 14 | bool checkShaderCompileStatus(GLuint obj) { 15 | GLint status; 16 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 17 | if(status == GL_FALSE) { 18 | GLint length; 19 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 20 | std::vector log((unsigned long)length); 21 | glGetShaderInfoLog(obj, length, &length, &log[0]); 22 | std::cerr << &log[0]; 23 | return true; 24 | } 25 | return false; 26 | } 27 | 28 | bool checkProgramLinkStatus(GLuint obj) { 29 | GLint status; 30 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 31 | if(status == GL_FALSE) { 32 | GLint length; 33 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 34 | std::vector log((unsigned long)length); 35 | glGetProgramInfoLog(obj, length, &length, &log[0]); 36 | std::cerr << &log[0]; 37 | return true; 38 | } 39 | return false; 40 | } 41 | 42 | GLuint prepareProgram(bool *errorFlagPtr) { 43 | *errorFlagPtr = false; 44 | 45 | std::string vertexShaderSource = "" 46 | "#version 330 core\n" 47 | "layout(location = 0) in vec3 vertexPos;\n" 48 | "void main(){\n" 49 | " gl_Position.xyz = vertexPos;\n" 50 | " gl_Position.w = 1.0;\n" 51 | "}"; 52 | 53 | GLuint vertexShaderId = glCreateShader(GL_VERTEX_SHADER); 54 | const GLchar * const vertexShaderSourcePtr = vertexShaderSource.c_str(); 55 | glShaderSource(vertexShaderId, 1, &vertexShaderSourcePtr, nullptr); 56 | glCompileShader(vertexShaderId); 57 | 58 | *errorFlagPtr = checkShaderCompileStatus(vertexShaderId); 59 | if(*errorFlagPtr) return 0; 60 | 61 | std::string fragmentShaderSource = "" 62 | "#version 330 core\n" 63 | "out vec3 color;\n" 64 | "void main() { color = vec3(0,0,1); }\n"; 65 | 66 | GLuint fragmentShaderId = glCreateShader(GL_FRAGMENT_SHADER); 67 | const GLchar * const fragmentShaderSourcePtr = fragmentShaderSource.c_str(); 68 | glShaderSource(fragmentShaderId, 1, &fragmentShaderSourcePtr, nullptr); 69 | glCompileShader(fragmentShaderId); 70 | 71 | *errorFlagPtr = checkShaderCompileStatus(fragmentShaderId); 72 | if(*errorFlagPtr) return 0; 73 | 74 | GLuint programId = glCreateProgram(); 75 | glAttachShader(programId, vertexShaderId); 76 | glAttachShader(programId, fragmentShaderId); 77 | glLinkProgram(programId); 78 | 79 | *errorFlagPtr = checkProgramLinkStatus(programId); 80 | if(*errorFlagPtr) return 0; 81 | 82 | glDeleteShader(vertexShaderId); 83 | glDeleteShader(fragmentShaderId); 84 | 85 | return programId; 86 | } 87 | 88 | void windowSizeCallback(GLFWwindow *, int width, int height) { 89 | glViewport(0, 0, width, height); 90 | } 91 | 92 | int main() { 93 | if(glfwInit() == GL_FALSE) { 94 | std::cerr << "Failed to initialize GLFW" << std::endl; 95 | return -1; 96 | } 97 | 98 | glfwDefaultWindowHints(); 99 | 100 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 101 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 102 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 103 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 104 | 105 | GLFWwindow* window = glfwCreateWindow(200, 300, "Triangle", 106 | nullptr, nullptr); 107 | if(window == nullptr) { 108 | std::cerr << "Failed to open GLFW window" << std::endl; 109 | glfwTerminate(); 110 | return -1; 111 | } 112 | 113 | glfwMakeContextCurrent(window); 114 | 115 | if(glxwInit()) { 116 | std::cerr << "Failed to init GLXW" << std::endl; 117 | glfwDestroyWindow(window); 118 | glfwTerminate(); 119 | return 1; 120 | } 121 | 122 | glfwSwapInterval(1); 123 | 124 | glfwSetWindowSizeCallback(window, windowSizeCallback); 125 | 126 | glfwShowWindow(window); 127 | 128 | glEnable(GL_DOUBLEBUFFER); 129 | glEnable(GL_DEPTH_TEST); 130 | glDepthFunc(GL_LESS); 131 | 132 | glClearColor(0, 0, 0, 1); 133 | 134 | bool errorFlag; 135 | GLuint programId = prepareProgram(&errorFlag); 136 | if(errorFlag) { 137 | glfwDestroyWindow(window); 138 | glfwTerminate(); 139 | return -1; 140 | } 141 | 142 | GLuint vbo; 143 | glGenBuffers(1, &vbo); 144 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 145 | glBufferData(GL_ARRAY_BUFFER, sizeof(globVertexBufferData), globVertexBufferData, GL_STATIC_DRAW); 146 | 147 | GLuint vao; 148 | glGenVertexArrays(1, &vao); 149 | 150 | glBindVertexArray(vao); 151 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 152 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); 153 | glBindBuffer(GL_ARRAY_BUFFER, 0); // unbind VBO 154 | glBindVertexArray(0); // unbind VAO 155 | 156 | while(glfwWindowShouldClose(window) == GL_FALSE) { 157 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 158 | 159 | glUseProgram(programId); 160 | 161 | glBindVertexArray(vao); 162 | glEnableVertexAttribArray(0); 163 | glDrawArrays(GL_TRIANGLES, 0, 3); 164 | glDisableVertexAttribArray(0); 165 | 166 | glfwSwapBuffers(window); 167 | glfwPollEvents(); 168 | } 169 | 170 | glDeleteVertexArrays(1, &vao); 171 | glDeleteBuffers(1, &vbo); 172 | glDeleteProgram(programId); 173 | 174 | glfwDestroyWindow(window); 175 | glfwTerminate(); 176 | return 0; 177 | } 178 | --------------------------------------------------------------------------------