├── .gitmodules ├── COPYING ├── README.md ├── 00skeleton.cpp ├── CMakeLists.txt ├── 01shader_vbo1.cpp ├── 01shader_vbo2.cpp ├── 02indexed_vbo.cpp ├── 03texture.cpp ├── 04perspective.cpp ├── 07geometry_shader_blending.cpp ├── 06instancing1.cpp ├── 06instancing3_uniform_buffer.cpp ├── 06instancing2_buffer_texture.cpp ├── 08map_buffer.cpp ├── 12shader_image_load_store.cpp ├── 09transform_feedback.cpp ├── 11tesselation.cpp ├── 13compute_shader_nbody.cpp ├── 10queries_conditional_render.cpp └── 05fbo_fxaa.cpp /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "glfw"] 2 | path = glfw 3 | url = https://github.com/glfw/glfw 4 | [submodule "glxw"] 5 | path = glxw 6 | url = https://github.com/rikusalminen/glxw 7 | [submodule "glm"] 8 | path = glm 9 | url = https://github.com/Groovounet/glm 10 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Jakob Progsch 2 | 3 | This software is provided 'as-is', without any express or implied 4 | warranty. In no event will the authors be held liable for any damages 5 | arising from the use of this software. 6 | 7 | Permission is granted to anyone to use this software for any purpose, 8 | including commercial applications, and to alter it and redistribute it 9 | freely, subject to the following restrictions: 10 | 11 | 1. The origin of this software must not be misrepresented; you must not 12 | claim that you wrote the original software. If you use this software 13 | in a product, an acknowledgment in the product documentation would be 14 | appreciated but is not required. 15 | 16 | 2. Altered source versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. 18 | 19 | 3. This notice may not be removed or altered from any source 20 | distribution. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | OpenGL Example Collection 2 | ------------------------- 3 | 4 | The purpose of thise example collection is to provide short and self 5 | contained code that showcases OpenGL api functionality/features. 6 | The examples have no dependencies on any custom framework or basecode 7 | except for "canonical" libraries such as glfw, gl3w and glm. All the 8 | examples are written against core profiles of version OpenGL version 3.3 9 | or higher. 10 | 11 | Most of the examples try to show the targeted features in a relevant 12 | use case such as using Frame Buffer Objects for FXAA, Transform Feedback 13 | to update particles on the GPU or Occlusion Queries + Conditional Render 14 | to optimize rendering a Cube (Minecraftlike) Cave. At the same time 15 | the goal is to keep the examples short and simple enough to not lose 16 | the focus. 17 | 18 | The build system is cmake (only tested on my linux box...). If everything 19 | works as intended these commands should build the examples: 20 | ``` 21 | git submodule init 22 | git submodule update 23 | mkdir build 24 | cd build 25 | cmake ../ 26 | make 27 | ``` 28 | -------------------------------------------------------------------------------- /00skeleton.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Skeleton 2 | * 3 | * Skeleton code that all the other examples are based on 4 | * 5 | * Autor: Jakob Progsch 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | 13 | int main() { 14 | int width = 640; 15 | int height = 480; 16 | 17 | if(glfwInit() == GL_FALSE) { 18 | std::cerr << "failed to init GLFW" << std::endl; 19 | return 1; 20 | } 21 | 22 | // select opengl version 23 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 24 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 25 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 26 | 27 | // create a window 28 | GLFWwindow *window; 29 | if((window = glfwCreateWindow(width, height, "00skeleton", 0, 0)) == 0) { 30 | std::cerr << "failed to open window" << std::endl; 31 | glfwTerminate(); 32 | return 1; 33 | } 34 | 35 | glfwMakeContextCurrent(window); 36 | 37 | if(glxwInit()) { 38 | std::cerr << "failed to init GL3W" << std::endl; 39 | glfwDestroyWindow(window); 40 | glfwTerminate(); 41 | return 1; 42 | } 43 | 44 | // creation and initialization of stuff goes here 45 | // ... 46 | 47 | while(!glfwWindowShouldClose(window)) { 48 | glfwPollEvents(); 49 | 50 | // drawing etc goes here 51 | // ... 52 | 53 | // check for errors 54 | GLenum error = glGetError(); 55 | if(error != GL_NO_ERROR) { 56 | std::cerr << error << std::endl; 57 | break; 58 | } 59 | 60 | // finally swap buffers 61 | glfwSwapBuffers(window); 62 | } 63 | 64 | glfwDestroyWindow(window); 65 | glfwTerminate(); 66 | 67 | return 0; 68 | } 69 | 70 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.6) 2 | 3 | project(OPENGLEXAMPLES) 4 | 5 | option(BUILD_OGL43 "Bild OpenGL 4.3 examples" OFF) 6 | mark_as_advanced(BUILD_OGL43) 7 | 8 | find_package(OpenGL REQUIRED) 9 | 10 | add_subdirectory(glfw) 11 | add_subdirectory(glxw) 12 | 13 | include_directories(glfw/include) 14 | include_directories(glm) 15 | include_directories(${CMAKE_BINARY_DIR}/glxw/include) 16 | 17 | set(CMAKE_CXX_FLAGS "-O2 -Wall -Wextra") 18 | SET(LIBRARIES glfw glxw ${GLFW_LIBRARIES} ${GLXW_LIBRARY} ${OPENGL_LIBRARY} ${CMAKE_DL_LIBS}) 19 | 20 | link_directories (${OPENGLEXAMPLES_BINARY_DIR}/bin) 21 | 22 | add_executable (00skeleton 00skeleton.cpp) 23 | target_link_libraries(00skeleton ${LIBRARIES} ) 24 | 25 | add_executable (01shader_vbo1 01shader_vbo1.cpp) 26 | target_link_libraries(01shader_vbo1 ${LIBRARIES} ) 27 | 28 | add_executable (01shader_vbo2 01shader_vbo2.cpp) 29 | target_link_libraries(01shader_vbo2 ${LIBRARIES} ) 30 | 31 | add_executable (02indexed_vbo 02indexed_vbo.cpp) 32 | target_link_libraries(02indexed_vbo ${LIBRARIES} ) 33 | 34 | add_executable (03texture 03texture.cpp) 35 | target_link_libraries(03texture ${LIBRARIES} ) 36 | 37 | add_executable (04perspective 04perspective.cpp) 38 | target_link_libraries(04perspective ${LIBRARIES} ) 39 | 40 | add_executable (05fbo_fxaa 05fbo_fxaa.cpp) 41 | target_link_libraries(05fbo_fxaa ${LIBRARIES} ) 42 | 43 | add_executable (06instancing1 06instancing1.cpp) 44 | target_link_libraries(06instancing1 ${LIBRARIES} ) 45 | 46 | add_executable (06instancing2_buffer_texture 06instancing2_buffer_texture.cpp) 47 | target_link_libraries(06instancing2_buffer_texture ${LIBRARIES} ) 48 | 49 | add_executable (06instancing3_uniform_buffer 06instancing3_uniform_buffer.cpp) 50 | target_link_libraries(06instancing3_uniform_buffer ${LIBRARIES} ) 51 | 52 | add_executable (07geometry_shader_blending 07geometry_shader_blending.cpp) 53 | target_link_libraries(07geometry_shader_blending ${LIBRARIES} ) 54 | 55 | add_executable (08map_buffer 08map_buffer.cpp) 56 | target_link_libraries(08map_buffer ${LIBRARIES} ) 57 | 58 | add_executable (09transform_feedback 09transform_feedback.cpp) 59 | target_link_libraries(09transform_feedback ${LIBRARIES} ) 60 | 61 | add_executable (10queries_conditional_render 10queries_conditional_render.cpp) 62 | target_link_libraries(10queries_conditional_render ${LIBRARIES} ) 63 | 64 | add_executable (11tesselation 11tesselation.cpp) 65 | target_link_libraries(11tesselation ${LIBRARIES} ) 66 | 67 | add_executable (12shader_image_load_store 12shader_image_load_store.cpp) 68 | target_link_libraries(12shader_image_load_store ${LIBRARIES} ) 69 | 70 | add_executable (13compute_shader_nbody 13compute_shader_nbody.cpp) 71 | target_link_libraries(13compute_shader_nbody ${LIBRARIES} ) 72 | -------------------------------------------------------------------------------- /01shader_vbo1.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Shader and VBO 2 | * 3 | * This example shows the setup and usage of shaders and a vbo+vao 4 | * 5 | * Autor: Jakob Progsch 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // helper to check and display for shader compiler errors 16 | bool check_shader_compile_status(GLuint obj) { 17 | GLint status; 18 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 19 | if(status == GL_FALSE) { 20 | GLint length; 21 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 22 | std::vector log(length); 23 | glGetShaderInfoLog(obj, length, &length, &log[0]); 24 | std::cerr << &log[0]; 25 | return false; 26 | } 27 | return true; 28 | } 29 | 30 | // helper to check and display for shader linker error 31 | bool check_program_link_status(GLuint obj) { 32 | GLint status; 33 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 34 | if(status == GL_FALSE) { 35 | GLint length; 36 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 37 | std::vector log(length); 38 | glGetProgramInfoLog(obj, length, &length, &log[0]); 39 | std::cerr << &log[0]; 40 | return false; 41 | } 42 | return true; 43 | } 44 | 45 | int main() { 46 | int width = 640; 47 | int height = 480; 48 | 49 | if(glfwInit() == GL_FALSE) { 50 | std::cerr << "failed to init GLFW" << std::endl; 51 | return 1; 52 | } 53 | 54 | // select opengl version 55 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 56 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 57 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 58 | 59 | // create a window 60 | GLFWwindow *window; 61 | if((window = glfwCreateWindow(width, height, "01shader_vbo1", 0, 0)) == 0) { 62 | std::cerr << "failed to open window" << std::endl; 63 | glfwTerminate(); 64 | return 1; 65 | } 66 | 67 | glfwMakeContextCurrent(window); 68 | 69 | if(glxwInit()) { 70 | std::cerr << "failed to init GL3W" << std::endl; 71 | glfwDestroyWindow(window); 72 | glfwTerminate(); 73 | return 1; 74 | } 75 | 76 | // shader source code 77 | std::string vertex_source = 78 | "#version 330\n" 79 | "layout(location = 0) in vec4 vposition;\n" 80 | "layout(location = 1) in vec4 vcolor;\n" 81 | "out vec4 fcolor;\n" 82 | "void main() {\n" 83 | " fcolor = vcolor;\n" 84 | " gl_Position = vposition;\n" 85 | "}\n"; 86 | 87 | std::string fragment_source = 88 | "#version 330\n" 89 | "in vec4 fcolor;\n" 90 | "layout(location = 0) out vec4 FragColor;\n" 91 | "void main() {\n" 92 | " FragColor = fcolor;\n" 93 | "}\n"; 94 | 95 | // program and shader handles 96 | GLuint shader_program, vertex_shader, fragment_shader; 97 | 98 | // we need these to properly pass the strings 99 | const char *source; 100 | int length; 101 | 102 | // create and compiler vertex shader 103 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 104 | source = vertex_source.c_str(); 105 | length = vertex_source.size(); 106 | glShaderSource(vertex_shader, 1, &source, &length); 107 | glCompileShader(vertex_shader); 108 | if(!check_shader_compile_status(vertex_shader)) { 109 | glfwDestroyWindow(window); 110 | glfwTerminate(); 111 | return 1; 112 | } 113 | 114 | // create and compiler fragment shader 115 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 116 | source = fragment_source.c_str(); 117 | length = fragment_source.size(); 118 | glShaderSource(fragment_shader, 1, &source, &length); 119 | glCompileShader(fragment_shader); 120 | if(!check_shader_compile_status(fragment_shader)) { 121 | glfwDestroyWindow(window); 122 | glfwTerminate(); 123 | return 1; 124 | } 125 | 126 | // create program 127 | shader_program = glCreateProgram(); 128 | 129 | // attach shaders 130 | glAttachShader(shader_program, vertex_shader); 131 | glAttachShader(shader_program, fragment_shader); 132 | 133 | // link the program and check for errors 134 | glLinkProgram(shader_program); 135 | if(!check_program_link_status(shader_program)) { 136 | glfwDestroyWindow(window); 137 | glfwTerminate(); 138 | return 1; 139 | } 140 | 141 | // vao and vbo handle 142 | GLuint vao, vbo; 143 | 144 | // generate and bind the vao 145 | glGenVertexArrays(1, &vao); 146 | glBindVertexArray(vao); 147 | 148 | // generate and bind the buffer object 149 | glGenBuffers(1, &vbo); 150 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 151 | 152 | // data for a fullscreen quad 153 | GLfloat vertexData[] = { 154 | // X Y Z R G B 155 | 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 156 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 157 | 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 158 | 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 159 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 160 | -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 161 | }; // 6 vertices with 6 components (floats) each 162 | 163 | // fill with data 164 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); 165 | 166 | // set up generic attrib pointers 167 | glEnableVertexAttribArray(0); 168 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 169 | 170 | glEnableVertexAttribArray(1); 171 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 172 | 173 | while(!glfwWindowShouldClose(window)) { 174 | glfwPollEvents(); 175 | 176 | // clear first 177 | glClear(GL_COLOR_BUFFER_BIT); 178 | 179 | // use the shader program 180 | glUseProgram(shader_program); 181 | 182 | // bind the vao 183 | glBindVertexArray(vao); 184 | 185 | // draw 186 | glDrawArrays(GL_TRIANGLES, 0, 6); 187 | 188 | // check for errors 189 | GLenum error = glGetError(); 190 | if(error != GL_NO_ERROR) { 191 | std::cerr << error << std::endl; 192 | break; 193 | } 194 | 195 | // finally swap buffers 196 | glfwSwapBuffers(window); 197 | } 198 | 199 | // delete the created objects 200 | 201 | glDeleteVertexArrays(1, &vao); 202 | glDeleteBuffers(1, &vbo); 203 | 204 | glDetachShader(shader_program, vertex_shader); 205 | glDetachShader(shader_program, fragment_shader); 206 | glDeleteShader(vertex_shader); 207 | glDeleteShader(fragment_shader); 208 | glDeleteProgram(shader_program); 209 | 210 | glfwDestroyWindow(window); 211 | glfwTerminate(); 212 | return 0; 213 | } 214 | 215 | -------------------------------------------------------------------------------- /01shader_vbo2.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Tesselation 2 | * 3 | * This example shows the setup and usage of shaders and a vbo+vao 4 | * In this example the attrbute locations are set via BindAttribLocation 5 | * instead of layout qualifiers in the shaders 6 | * 7 | * Autor: Jakob Progsch 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | 17 | // helper to check and display for shader compiler errors 18 | bool check_shader_compile_status(GLuint obj) { 19 | GLint status; 20 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 21 | if(status == GL_FALSE) { 22 | GLint length; 23 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 24 | std::vector log(length); 25 | glGetShaderInfoLog(obj, length, &length, &log[0]); 26 | std::cerr << &log[0]; 27 | return false; 28 | } 29 | return true; 30 | } 31 | 32 | // helper to check and display for shader linker error 33 | bool check_program_link_status(GLuint obj) { 34 | GLint status; 35 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 36 | if(status == GL_FALSE) { 37 | GLint length; 38 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 39 | std::vector log(length); 40 | glGetProgramInfoLog(obj, length, &length, &log[0]); 41 | std::cerr << &log[0]; 42 | return false; 43 | } 44 | return true; 45 | } 46 | 47 | int main() { 48 | int width = 640; 49 | int height = 480; 50 | 51 | if(glfwInit() == GL_FALSE) { 52 | std::cerr << "failed to init GLFW" << std::endl; 53 | return 1; 54 | } 55 | 56 | // select opengl version 57 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 58 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 59 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 60 | 61 | // create a window 62 | GLFWwindow *window; 63 | if((window = glfwCreateWindow(width, height, "01shader_vbo2", 0, 0)) == 0) { 64 | std::cerr << "failed to open window" << std::endl; 65 | glfwTerminate(); 66 | return 1; 67 | } 68 | 69 | glfwMakeContextCurrent(window); 70 | 71 | if(glxwInit()) { 72 | std::cerr << "failed to init GL3W" << std::endl; 73 | glfwDestroyWindow(window); 74 | glfwTerminate(); 75 | return 1; 76 | } 77 | 78 | // shader source code 79 | std::string vertex_source = 80 | "#version 330\n" 81 | "in vec4 vposition;\n" 82 | "in vec4 vcolor;\n" 83 | "out vec4 fcolor;\n" 84 | "void main() {\n" 85 | " fcolor = vcolor;\n" 86 | " gl_Position = vposition;\n" 87 | "}\n"; 88 | 89 | std::string fragment_source = 90 | "#version 330\n" 91 | "in vec4 fcolor;\n" 92 | "out vec4 FragColor;\n" 93 | "void main() {\n" 94 | " FragColor = fcolor;\n" 95 | "}\n"; 96 | 97 | // program and shader handles 98 | GLuint shader_program, vertex_shader, fragment_shader; 99 | 100 | // we need these to properly pass the strings 101 | const char *source; 102 | int length; 103 | 104 | // create and compiler vertex shader 105 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 106 | source = vertex_source.c_str(); 107 | length = vertex_source.size(); 108 | glShaderSource(vertex_shader, 1, &source, &length); 109 | glCompileShader(vertex_shader); 110 | if(!check_shader_compile_status(vertex_shader)) { 111 | glfwDestroyWindow(window); 112 | glfwTerminate(); 113 | return 1; 114 | } 115 | 116 | // create and compiler fragment shader 117 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 118 | source = fragment_source.c_str(); 119 | length = fragment_source.size(); 120 | glShaderSource(fragment_shader, 1, &source, &length); 121 | glCompileShader(fragment_shader); 122 | if(!check_shader_compile_status(fragment_shader)) { 123 | glfwDestroyWindow(window); 124 | glfwTerminate(); 125 | return 1; 126 | } 127 | // create program 128 | shader_program = glCreateProgram(); 129 | 130 | // attach shaders 131 | glAttachShader(shader_program, vertex_shader); 132 | glAttachShader(shader_program, fragment_shader); 133 | 134 | // bind the attribute locations (inputs) 135 | glBindAttribLocation(shader_program, 0, "vposition"); 136 | glBindAttribLocation(shader_program, 1, "vcolor"); 137 | 138 | // bind the FragDataLocation (output) 139 | glBindFragDataLocation(shader_program, 0, "FragColor"); 140 | 141 | // link the program and check for errors 142 | glLinkProgram(shader_program); 143 | check_program_link_status(shader_program); 144 | 145 | // vao and vbo handle 146 | GLuint vao, vbo; 147 | 148 | // generate and bind the vao 149 | glGenVertexArrays(1, &vao); 150 | glBindVertexArray(vao); 151 | 152 | // generate and bind the buffer object 153 | glGenBuffers(1, &vbo); 154 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 155 | 156 | // data for a fullscreen quad 157 | GLfloat vertexData[] = { 158 | // X Y Z R G B 159 | 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 160 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 161 | 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 162 | 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 163 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 164 | -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 165 | }; // 6 vertices with 6 components (floats) each 166 | 167 | // fill with data 168 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); 169 | 170 | // set up generic attrib pointers 171 | glEnableVertexAttribArray(0); 172 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 173 | 174 | glEnableVertexAttribArray(1); 175 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 176 | 177 | while(!glfwWindowShouldClose(window)) { 178 | glfwPollEvents(); 179 | 180 | // clear first 181 | glClear(GL_COLOR_BUFFER_BIT); 182 | 183 | // use the shader program 184 | glUseProgram(shader_program); 185 | 186 | // bind the vao 187 | glBindVertexArray(vao); 188 | 189 | // draw 190 | glDrawArrays(GL_TRIANGLES, 0, 6); 191 | 192 | // check for errors 193 | GLenum error = glGetError(); 194 | if(error != GL_NO_ERROR) { 195 | std::cerr << error << std::endl; 196 | break; 197 | } 198 | 199 | // finally swap buffers 200 | glfwSwapBuffers(window); 201 | } 202 | 203 | // delete the created objects 204 | 205 | glDeleteVertexArrays(1, &vao); 206 | glDeleteBuffers(1, &vbo); 207 | 208 | glDetachShader(shader_program, vertex_shader); 209 | glDetachShader(shader_program, fragment_shader); 210 | glDeleteShader(vertex_shader); 211 | glDeleteShader(fragment_shader); 212 | glDeleteProgram(shader_program); 213 | 214 | glfwDestroyWindow(window); 215 | glfwTerminate(); 216 | return 0; 217 | } 218 | 219 | -------------------------------------------------------------------------------- /02indexed_vbo.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Indexed VBO 2 | * 3 | * same as the "Shader and VBO" example, only with an indexed vbo. 4 | * 5 | * Autor: Jakob Progsch 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // helper to check and display for shader compiler errors 16 | bool check_shader_compile_status(GLuint obj) { 17 | GLint status; 18 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 19 | if(status == GL_FALSE) { 20 | GLint length; 21 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 22 | std::vector log(length); 23 | glGetShaderInfoLog(obj, length, &length, &log[0]); 24 | std::cerr << &log[0]; 25 | return false; 26 | } 27 | return true; 28 | } 29 | 30 | // helper to check and display for shader linker error 31 | bool check_program_link_status(GLuint obj) { 32 | GLint status; 33 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 34 | if(status == GL_FALSE) { 35 | GLint length; 36 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 37 | std::vector log(length); 38 | glGetProgramInfoLog(obj, length, &length, &log[0]); 39 | std::cerr << &log[0]; 40 | return false; 41 | } 42 | return true; 43 | } 44 | 45 | int main() { 46 | int width = 640; 47 | int height = 480; 48 | 49 | if(glfwInit() == GL_FALSE) { 50 | std::cerr << "failed to init GLFW" << std::endl; 51 | return 1; 52 | } 53 | 54 | // select opengl version 55 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 56 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 57 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 58 | 59 | // create a window 60 | GLFWwindow *window; 61 | if((window = glfwCreateWindow(width, height, "02indexed_vbo", 0, 0)) == 0) { 62 | std::cerr << "failed to open window" << std::endl; 63 | glfwTerminate(); 64 | return 1; 65 | } 66 | 67 | glfwMakeContextCurrent(window); 68 | 69 | if(glxwInit()) { 70 | std::cerr << "failed to init GL3W" << std::endl; 71 | glfwDestroyWindow(window); 72 | glfwTerminate(); 73 | return 1; 74 | } 75 | 76 | // shader source code 77 | std::string vertex_source = 78 | "#version 330\n" 79 | "layout(location = 0) in vec4 vposition;\n" 80 | "layout(location = 1) in vec4 vcolor;\n" 81 | "out vec4 fcolor;\n" 82 | "void main() {\n" 83 | " fcolor = vcolor;\n" 84 | " gl_Position = vposition;\n" 85 | "}\n"; 86 | 87 | std::string fragment_source = 88 | "#version 330\n" 89 | "in vec4 fcolor;\n" 90 | "layout(location = 0) out vec4 FragColor;\n" 91 | "void main() {\n" 92 | " FragColor = fcolor;\n" 93 | "}\n"; 94 | 95 | // program and shader handles 96 | GLuint shader_program, vertex_shader, fragment_shader; 97 | 98 | // we need these to properly pass the strings 99 | const char *source; 100 | int length; 101 | 102 | // create and compiler vertex shader 103 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 104 | source = vertex_source.c_str(); 105 | length = vertex_source.size(); 106 | glShaderSource(vertex_shader, 1, &source, &length); 107 | glCompileShader(vertex_shader); 108 | if(!check_shader_compile_status(vertex_shader)) { 109 | glfwDestroyWindow(window); 110 | glfwTerminate(); 111 | return 1; 112 | } 113 | 114 | // create and compiler fragment shader 115 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 116 | source = fragment_source.c_str(); 117 | length = fragment_source.size(); 118 | glShaderSource(fragment_shader, 1, &source, &length); 119 | glCompileShader(fragment_shader); 120 | if(!check_shader_compile_status(fragment_shader)) { 121 | glfwDestroyWindow(window); 122 | glfwTerminate(); 123 | return 1; 124 | } 125 | 126 | // create program 127 | shader_program = glCreateProgram(); 128 | 129 | // attach shaders 130 | glAttachShader(shader_program, vertex_shader); 131 | glAttachShader(shader_program, fragment_shader); 132 | 133 | // link the program and check for errors 134 | glLinkProgram(shader_program); 135 | check_program_link_status(shader_program); 136 | 137 | // vao and vbo handle 138 | GLuint vao, vbo, ibo; 139 | 140 | // generate and bind the vao 141 | glGenVertexArrays(1, &vao); 142 | glBindVertexArray(vao); 143 | 144 | // generate and bind the vertex buffer object 145 | glGenBuffers(1, &vbo); 146 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 147 | 148 | // data for a fullscreen quad 149 | GLfloat vertexData[] = { 150 | // X Y Z R G B 151 | 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 152 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 153 | 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 154 | -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 3 155 | }; // 4 vertices with 6 components (floats) each 156 | 157 | // fill with data 158 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*6, vertexData, GL_STATIC_DRAW); 159 | 160 | 161 | // set up generic attrib pointers 162 | glEnableVertexAttribArray(0); 163 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 164 | 165 | glEnableVertexAttribArray(1); 166 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 167 | 168 | 169 | // generate and bind the index buffer object 170 | glGenBuffers(1, &ibo); 171 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 172 | 173 | GLuint indexData[] = { 174 | 0,1,2, // first triangle 175 | 2,1,3, // second triangle 176 | }; 177 | 178 | // fill with data 179 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); 180 | 181 | while(!glfwWindowShouldClose(window)) { 182 | glfwPollEvents(); 183 | 184 | // clear first 185 | glClear(GL_COLOR_BUFFER_BIT); 186 | 187 | // use the shader program 188 | glUseProgram(shader_program); 189 | 190 | // bind the vao 191 | glBindVertexArray(vao); 192 | 193 | // draw 194 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 195 | 196 | // check for errors 197 | GLenum error = glGetError(); 198 | if(error != GL_NO_ERROR) { 199 | std::cerr << error << std::endl; 200 | break; 201 | } 202 | 203 | // finally swap buffers 204 | glfwSwapBuffers(window); 205 | } 206 | 207 | // delete the created objects 208 | glDeleteVertexArrays(1, &vao); 209 | glDeleteBuffers(1, &vbo); 210 | glDeleteBuffers(1, &ibo); 211 | 212 | glDetachShader(shader_program, vertex_shader); 213 | glDetachShader(shader_program, fragment_shader); 214 | glDeleteShader(vertex_shader); 215 | glDeleteShader(fragment_shader); 216 | glDeleteProgram(shader_program); 217 | 218 | glfwDestroyWindow(window); 219 | glfwTerminate(); 220 | return 0; 221 | } 222 | 223 | -------------------------------------------------------------------------------- /03texture.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Texture 2 | * 3 | * apply a texture to the fullscreen quad of "Indexed VBO" 4 | * 5 | * Autor: Jakob Progsch 6 | */ 7 | 8 | #include 9 | #include 10 | 11 | #include 12 | #include 13 | #include 14 | 15 | // helper to check and display for shader compiler errors 16 | bool check_shader_compile_status(GLuint obj) { 17 | GLint status; 18 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 19 | if(status == GL_FALSE) { 20 | GLint length; 21 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 22 | std::vector log(length); 23 | glGetShaderInfoLog(obj, length, &length, &log[0]); 24 | std::cerr << &log[0]; 25 | return false; 26 | } 27 | return true; 28 | } 29 | 30 | // helper to check and display for shader linker error 31 | bool check_program_link_status(GLuint obj) { 32 | GLint status; 33 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 34 | if(status == GL_FALSE) { 35 | GLint length; 36 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 37 | std::vector log(length); 38 | glGetProgramInfoLog(obj, length, &length, &log[0]); 39 | std::cerr << &log[0]; 40 | return false; 41 | } 42 | return true; 43 | } 44 | 45 | int main() { 46 | int width = 640; 47 | int height = 480; 48 | 49 | if(glfwInit() == GL_FALSE) { 50 | std::cerr << "failed to init GLFW" << std::endl; 51 | return 1; 52 | } 53 | 54 | // select opengl version 55 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 56 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 57 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 58 | 59 | // create a window 60 | GLFWwindow *window; 61 | if((window = glfwCreateWindow(width, height, "03texture", 0, 0)) == 0) { 62 | std::cerr << "failed to open window" << std::endl; 63 | glfwTerminate(); 64 | return 1; 65 | } 66 | 67 | glfwMakeContextCurrent(window); 68 | 69 | if(glxwInit()) { 70 | std::cerr << "failed to init GL3W" << std::endl; 71 | glfwDestroyWindow(window); 72 | glfwTerminate(); 73 | return 1; 74 | } 75 | 76 | // shader source code 77 | std::string vertex_source = 78 | "#version 330\n" 79 | "layout(location = 0) in vec4 vposition;\n" 80 | "layout(location = 1) in vec2 vtexcoord;\n" 81 | "out vec2 ftexcoord;\n" 82 | "void main() {\n" 83 | " ftexcoord = vtexcoord;\n" 84 | " gl_Position = vposition;\n" 85 | "}\n"; 86 | 87 | std::string fragment_source = 88 | "#version 330\n" 89 | "uniform sampler2D tex;\n" // texture uniform 90 | "in vec2 ftexcoord;\n" 91 | "layout(location = 0) out vec4 FragColor;\n" 92 | "void main() {\n" 93 | " FragColor = texture(tex, ftexcoord);\n" 94 | "}\n"; 95 | 96 | // program and shader handles 97 | GLuint shader_program, vertex_shader, fragment_shader; 98 | 99 | // we need these to properly pass the strings 100 | const char *source; 101 | int length; 102 | 103 | // create and compiler vertex shader 104 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 105 | source = vertex_source.c_str(); 106 | length = vertex_source.size(); 107 | glShaderSource(vertex_shader, 1, &source, &length); 108 | glCompileShader(vertex_shader); 109 | if(!check_shader_compile_status(vertex_shader)) { 110 | glfwDestroyWindow(window); 111 | glfwTerminate(); 112 | return 1; 113 | } 114 | 115 | // create and compiler fragment shader 116 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 117 | source = fragment_source.c_str(); 118 | length = fragment_source.size(); 119 | glShaderSource(fragment_shader, 1, &source, &length); 120 | glCompileShader(fragment_shader); 121 | if(!check_shader_compile_status(fragment_shader)) { 122 | glfwDestroyWindow(window); 123 | glfwTerminate(); 124 | return 1; 125 | } 126 | 127 | // create program 128 | shader_program = glCreateProgram(); 129 | 130 | // attach shaders 131 | glAttachShader(shader_program, vertex_shader); 132 | glAttachShader(shader_program, fragment_shader); 133 | 134 | // link the program and check for errors 135 | glLinkProgram(shader_program); 136 | check_program_link_status(shader_program); 137 | 138 | // get texture uniform location 139 | GLint texture_location = glGetUniformLocation(shader_program, "tex"); 140 | 141 | // vao and vbo handle 142 | GLuint vao, vbo, ibo; 143 | 144 | // generate and bind the vao 145 | glGenVertexArrays(1, &vao); 146 | glBindVertexArray(vao); 147 | 148 | // generate and bind the vertex buffer object 149 | glGenBuffers(1, &vbo); 150 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 151 | 152 | // data for a fullscreen quad (this time with texture coords) 153 | GLfloat vertexData[] = { 154 | // X Y Z U V 155 | 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 156 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 157 | 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 158 | -1.0f,-1.0f, 0.0f, 0.0f, 0.0f, // vertex 3 159 | }; // 4 vertices with 5 components (floats) each 160 | 161 | // fill with data 162 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*5, vertexData, GL_STATIC_DRAW); 163 | 164 | 165 | // set up generic attrib pointers 166 | glEnableVertexAttribArray(0); 167 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 168 | 169 | glEnableVertexAttribArray(1); 170 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 171 | 172 | 173 | // generate and bind the index buffer object 174 | glGenBuffers(1, &ibo); 175 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 176 | 177 | GLuint indexData[] = { 178 | 0,1,2, // first triangle 179 | 2,1,3, // second triangle 180 | }; 181 | 182 | // fill with data 183 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); 184 | 185 | // "unbind" vao 186 | glBindVertexArray(0); 187 | 188 | // texture handle 189 | GLuint texture; 190 | 191 | // generate texture 192 | glGenTextures(1, &texture); 193 | 194 | // bind the texture 195 | glBindTexture(GL_TEXTURE_2D, texture); 196 | 197 | // create some image data 198 | std::vector image(4*width*height); 199 | for(int j = 0;j 9 | #include 10 | 11 | //glm is used to create perspective and transform matrices 12 | #include 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | // helper to check and display for shader compiler errors 22 | bool check_shader_compile_status(GLuint obj) { 23 | GLint status; 24 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 25 | if(status == GL_FALSE) { 26 | GLint length; 27 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 28 | std::vector log(length); 29 | glGetShaderInfoLog(obj, length, &length, &log[0]); 30 | std::cerr << &log[0]; 31 | return false; 32 | } 33 | return true; 34 | } 35 | 36 | // helper to check and display for shader linker error 37 | bool check_program_link_status(GLuint obj) { 38 | GLint status; 39 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 40 | if(status == GL_FALSE) { 41 | GLint length; 42 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 43 | std::vector log(length); 44 | glGetProgramInfoLog(obj, length, &length, &log[0]); 45 | std::cerr << &log[0]; 46 | return false; 47 | } 48 | return true; 49 | } 50 | 51 | int main() { 52 | int width = 640; 53 | int height = 480; 54 | 55 | if(glfwInit() == GL_FALSE) { 56 | std::cerr << "failed to init GLFW" << std::endl; 57 | return 1; 58 | } 59 | 60 | // select opengl version 61 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 62 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 63 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 64 | 65 | // create a window 66 | GLFWwindow *window; 67 | if((window = glfwCreateWindow(width, height, "04perspective", 0, 0)) == 0) { 68 | std::cerr << "failed to open window" << std::endl; 69 | glfwTerminate(); 70 | return 1; 71 | } 72 | 73 | glfwMakeContextCurrent(window); 74 | 75 | if(glxwInit()) { 76 | std::cerr << "failed to init GL3W" << std::endl; 77 | glfwDestroyWindow(window); 78 | glfwTerminate(); 79 | return 1; 80 | } 81 | 82 | // shader source code 83 | std::string vertex_source = 84 | "#version 330\n" 85 | "uniform mat4 ViewProjection;\n" // the projection matrix uniform 86 | "layout(location = 0) in vec4 vposition;\n" 87 | "layout(location = 1) in vec4 vcolor;\n" 88 | "out vec4 fcolor;\n" 89 | "void main() {\n" 90 | " fcolor = vcolor;\n" 91 | " gl_Position = ViewProjection*vposition;\n" 92 | "}\n"; 93 | 94 | std::string fragment_source = 95 | "#version 330\n" 96 | "in vec4 fcolor;\n" 97 | "layout(location = 0) out vec4 FragColor;\n" 98 | "void main() {\n" 99 | " FragColor = fcolor;\n" 100 | "}\n"; 101 | 102 | // program and shader handles 103 | GLuint shader_program, vertex_shader, fragment_shader; 104 | 105 | // we need these to properly pass the strings 106 | const char *source; 107 | int length; 108 | 109 | // create and compiler vertex shader 110 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 111 | source = vertex_source.c_str(); 112 | length = vertex_source.size(); 113 | glShaderSource(vertex_shader, 1, &source, &length); 114 | glCompileShader(vertex_shader); 115 | if(!check_shader_compile_status(vertex_shader)) { 116 | glfwDestroyWindow(window); 117 | glfwTerminate(); 118 | return 1; 119 | } 120 | 121 | // create and compiler fragment shader 122 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 123 | source = fragment_source.c_str(); 124 | length = fragment_source.size(); 125 | glShaderSource(fragment_shader, 1, &source, &length); 126 | glCompileShader(fragment_shader); 127 | if(!check_shader_compile_status(fragment_shader)) { 128 | glfwDestroyWindow(window); 129 | glfwTerminate(); 130 | return 1; 131 | } 132 | 133 | // create program 134 | shader_program = glCreateProgram(); 135 | 136 | // attach shaders 137 | glAttachShader(shader_program, vertex_shader); 138 | glAttachShader(shader_program, fragment_shader); 139 | 140 | // link the program and check for errors 141 | glLinkProgram(shader_program); 142 | check_program_link_status(shader_program); 143 | 144 | // obtain location of projection uniform 145 | GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); 146 | 147 | 148 | // vao and vbo handle 149 | GLuint vao, vbo, ibo; 150 | 151 | // generate and bind the vao 152 | glGenVertexArrays(1, &vao); 153 | glBindVertexArray(vao); 154 | 155 | // generate and bind the vertex buffer object 156 | glGenBuffers(1, &vbo); 157 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 158 | 159 | // data for a cube 160 | GLfloat vertexData[] = { 161 | // X Y Z R G B 162 | // face 0: 163 | 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 164 | -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 165 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 166 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 167 | 168 | // face 1: 169 | 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 170 | 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 171 | 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 172 | 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 173 | 174 | // face 2: 175 | 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 176 | 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 177 | -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 178 | -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 179 | 180 | // face 3: 181 | 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 182 | 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 183 | -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 184 | -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 185 | 186 | // face 4: 187 | -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 188 | -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 189 | -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 190 | -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 191 | 192 | // face 5: 193 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 194 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 195 | 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 196 | -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 197 | }; // 6 faces with 4 vertices with 6 components (floats) 198 | 199 | // fill with data 200 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); 201 | 202 | 203 | // set up generic attrib pointers 204 | glEnableVertexAttribArray(0); 205 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 206 | 207 | glEnableVertexAttribArray(1); 208 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 209 | 210 | 211 | // generate and bind the index buffer object 212 | glGenBuffers(1, &ibo); 213 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 214 | 215 | GLuint indexData[] = { 216 | // face 0: 217 | 0,1,2, // first triangle 218 | 2,1,3, // second triangle 219 | // face 1: 220 | 4,5,6, // first triangle 221 | 6,5,7, // second triangle 222 | // face 2: 223 | 8,9,10, // first triangle 224 | 10,9,11, // second triangle 225 | // face 3: 226 | 12,13,14, // first triangle 227 | 14,13,15, // second triangle 228 | // face 4: 229 | 16,17,18, // first triangle 230 | 18,17,19, // second triangle 231 | // face 5: 232 | 20,21,22, // first triangle 233 | 22,21,23, // second triangle 234 | }; 235 | 236 | // fill with data 237 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); 238 | 239 | // we are drawing 3d objects so we want depth testing 240 | glEnable(GL_DEPTH_TEST); 241 | 242 | while(!glfwWindowShouldClose(window)) { 243 | glfwPollEvents(); 244 | 245 | // get the time in seconds 246 | float t = glfwGetTime(); 247 | 248 | // clear first 249 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 250 | 251 | // use the shader program 252 | glUseProgram(shader_program); 253 | 254 | // calculate ViewProjection matrix 255 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 256 | 257 | // translate the world/view position 258 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); 259 | 260 | // make the camera rotate around the origin 261 | View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 262 | 263 | glm::mat4 ViewProjection = Projection*View; 264 | 265 | // set the uniform 266 | glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 267 | 268 | // bind the vao 269 | glBindVertexArray(vao); 270 | 271 | // draw 272 | glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0); 273 | 274 | // check for errors 275 | GLenum error = glGetError(); 276 | if(error != GL_NO_ERROR) { 277 | std::cerr << error << std::endl; 278 | break; 279 | } 280 | 281 | // finally swap buffers 282 | glfwSwapBuffers(window); 283 | } 284 | 285 | // delete the created objects 286 | 287 | glDeleteVertexArrays(1, &vao); 288 | glDeleteBuffers(1, &vbo); 289 | glDeleteBuffers(1, &ibo); 290 | 291 | glDetachShader(shader_program, vertex_shader); 292 | glDetachShader(shader_program, fragment_shader); 293 | glDeleteShader(vertex_shader); 294 | glDeleteShader(fragment_shader); 295 | glDeleteProgram(shader_program); 296 | 297 | glfwDestroyWindow(window); 298 | glfwTerminate(); 299 | return 0; 300 | } 301 | 302 | -------------------------------------------------------------------------------- /07geometry_shader_blending.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Geometry Shader and Blending 2 | * 3 | * Uses a geometry shader to expand points to billboard quads. 4 | * The billboards are then blended while drawing to create a galaxy 5 | * made of particles. 6 | * 7 | * Autor: Jakob Progsch 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | //glm is used to create perspective and transform matrices 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | // helper to check and display for shader compiler errors 25 | bool check_shader_compile_status(GLuint obj) { 26 | GLint status; 27 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 28 | if(status == GL_FALSE) { 29 | GLint length; 30 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 31 | std::vector log(length); 32 | glGetShaderInfoLog(obj, length, &length, &log[0]); 33 | std::cerr << &log[0]; 34 | return false; 35 | } 36 | return true; 37 | } 38 | 39 | // helper to check and display for shader linker error 40 | bool check_program_link_status(GLuint obj) { 41 | GLint status; 42 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 43 | if(status == GL_FALSE) { 44 | GLint length; 45 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 46 | std::vector log(length); 47 | glGetProgramInfoLog(obj, length, &length, &log[0]); 48 | std::cerr << &log[0]; 49 | return false; 50 | } 51 | return true; 52 | } 53 | 54 | int main() { 55 | int width = 640; 56 | int height = 480; 57 | 58 | if(glfwInit() == GL_FALSE) { 59 | std::cerr << "failed to init GLFW" << std::endl; 60 | return 1; 61 | } 62 | 63 | // select opengl version 64 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 65 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 66 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 67 | 68 | // create a window 69 | GLFWwindow *window; 70 | if((window = glfwCreateWindow(width, height, "07geometry_shader_blending", 0, 0)) == 0) { 71 | std::cerr << "failed to open window" << std::endl; 72 | glfwTerminate(); 73 | return 1; 74 | } 75 | 76 | glfwMakeContextCurrent(window); 77 | 78 | if(glxwInit()) { 79 | std::cerr << "failed to init GL3W" << std::endl; 80 | glfwDestroyWindow(window); 81 | glfwTerminate(); 82 | return 1; 83 | } 84 | 85 | // the vertex shader simply passes through data 86 | std::string vertex_source = 87 | "#version 330\n" 88 | "layout(location = 0) in vec4 vposition;\n" 89 | "void main() {\n" 90 | " gl_Position = vposition;\n" 91 | "}\n"; 92 | 93 | // the geometry shader creates the billboard quads 94 | std::string geometry_source = 95 | "#version 330\n" 96 | "uniform mat4 View;\n" 97 | "uniform mat4 Projection;\n" 98 | "layout (points) in;\n" 99 | "layout (triangle_strip, max_vertices = 4) out;\n" 100 | "out vec2 txcoord;\n" 101 | "void main() {\n" 102 | " vec4 pos = View*gl_in[0].gl_Position;\n" 103 | " txcoord = vec2(-1,-1);\n" 104 | " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" 105 | " EmitVertex();\n" 106 | " txcoord = vec2( 1,-1);\n" 107 | " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" 108 | " EmitVertex();\n" 109 | " txcoord = vec2(-1, 1);\n" 110 | " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" 111 | " EmitVertex();\n" 112 | " txcoord = vec2( 1, 1);\n" 113 | " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" 114 | " EmitVertex();\n" 115 | "}\n"; 116 | 117 | // the fragment shader creates a bell like radial color distribution 118 | std::string fragment_source = 119 | "#version 330\n" 120 | "in vec2 txcoord;\n" 121 | "layout(location = 0) out vec4 FragColor;\n" 122 | "void main() {\n" 123 | " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" 124 | " FragColor = s*vec4(1,0.9,0.6,1);\n" 125 | "}\n"; 126 | 127 | // program and shader handles 128 | GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; 129 | 130 | // we need these to properly pass the strings 131 | const char *source; 132 | int length; 133 | 134 | // create and compiler vertex shader 135 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 136 | source = vertex_source.c_str(); 137 | length = vertex_source.size(); 138 | glShaderSource(vertex_shader, 1, &source, &length); 139 | glCompileShader(vertex_shader); 140 | if(!check_shader_compile_status(vertex_shader)) { 141 | glfwDestroyWindow(window); 142 | glfwTerminate(); 143 | return 1; 144 | } 145 | 146 | // create and compiler geometry shader 147 | geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); 148 | source = geometry_source.c_str(); 149 | length = geometry_source.size(); 150 | glShaderSource(geometry_shader, 1, &source, &length); 151 | glCompileShader(geometry_shader); 152 | if(!check_shader_compile_status(geometry_shader)) { 153 | glfwDestroyWindow(window); 154 | glfwTerminate(); 155 | return 1; 156 | } 157 | 158 | // create and compiler fragment shader 159 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 160 | source = fragment_source.c_str(); 161 | length = fragment_source.size(); 162 | glShaderSource(fragment_shader, 1, &source, &length); 163 | glCompileShader(fragment_shader); 164 | if(!check_shader_compile_status(fragment_shader)) { 165 | glfwDestroyWindow(window); 166 | glfwTerminate(); 167 | return 1; 168 | } 169 | 170 | // create program 171 | shader_program = glCreateProgram(); 172 | 173 | // attach shaders 174 | glAttachShader(shader_program, vertex_shader); 175 | glAttachShader(shader_program, geometry_shader); 176 | glAttachShader(shader_program, fragment_shader); 177 | 178 | // link the program and check for errors 179 | glLinkProgram(shader_program); 180 | check_program_link_status(shader_program); 181 | 182 | // obtain location of projection uniform 183 | GLint View_location = glGetUniformLocation(shader_program, "View"); 184 | GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); 185 | 186 | // vao and vbo handle 187 | GLuint vao, vbo; 188 | 189 | // generate and bind the vao 190 | glGenVertexArrays(1, &vao); 191 | glBindVertexArray(vao); 192 | 193 | // generate and bind the vertex buffer object 194 | glGenBuffers(1, &vbo); 195 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 196 | 197 | const int particles = 128*1024; 198 | 199 | // create a galaxylike distribution of points 200 | std::vector vertexData(particles*3); 201 | for(int i = 0;i 10 | #include 11 | 12 | //glm is used to create perspective and transform matrices 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | // helper to check and display for shader compiler errors 22 | bool check_shader_compile_status(GLuint obj) { 23 | GLint status; 24 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 25 | if(status == GL_FALSE) { 26 | GLint length; 27 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 28 | std::vector log(length); 29 | glGetShaderInfoLog(obj, length, &length, &log[0]); 30 | std::cerr << &log[0]; 31 | return false; 32 | } 33 | return true; 34 | } 35 | 36 | // helper to check and display for shader linker error 37 | bool check_program_link_status(GLuint obj) { 38 | GLint status; 39 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 40 | if(status == GL_FALSE) { 41 | GLint length; 42 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 43 | std::vector log(length); 44 | glGetProgramInfoLog(obj, length, &length, &log[0]); 45 | std::cerr << &log[0]; 46 | return false; 47 | } 48 | return true; 49 | } 50 | 51 | int main() { 52 | int width = 640; 53 | int height = 480; 54 | 55 | if(glfwInit() == GL_FALSE) { 56 | std::cerr << "failed to init GLFW" << std::endl; 57 | return 1; 58 | } 59 | 60 | // select opengl version 61 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 62 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 63 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 64 | 65 | // create a window 66 | GLFWwindow *window; 67 | if((window = glfwCreateWindow(width, height, "06instancing1", 0, 0)) == 0) { 68 | std::cerr << "failed to open window" << std::endl; 69 | glfwTerminate(); 70 | return 1; 71 | } 72 | 73 | glfwMakeContextCurrent(window); 74 | 75 | if(glxwInit()) { 76 | std::cerr << "failed to init GL3W" << std::endl; 77 | glfwDestroyWindow(window); 78 | glfwTerminate(); 79 | return 1; 80 | } 81 | 82 | // shader source code 83 | std::string vertex_source = 84 | "#version 330\n" 85 | "uniform mat4 ViewProjection;\n" // the projection matrix uniform 86 | "layout(location = 0) in vec4 vposition;\n" 87 | "layout(location = 1) in vec4 vcolor;\n" 88 | "layout(location = 2) in vec3 voffset;\n" // the per instance offset 89 | "out vec4 fcolor;\n" 90 | "void main() {\n" 91 | " fcolor = vcolor;\n" 92 | " gl_Position = ViewProjection*(vposition + vec4(voffset, 0));\n" 93 | "}\n"; 94 | 95 | std::string fragment_source = 96 | "#version 330\n" 97 | "in vec4 fcolor;\n" 98 | "layout(location = 0) out vec4 FragColor;\n" 99 | "void main() {\n" 100 | " FragColor = fcolor;\n" 101 | "}\n"; 102 | 103 | // program and shader handles 104 | GLuint shader_program, vertex_shader, fragment_shader; 105 | 106 | // we need these to properly pass the strings 107 | const char *source; 108 | int length; 109 | 110 | // create and compiler vertex shader 111 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 112 | source = vertex_source.c_str(); 113 | length = vertex_source.size(); 114 | glShaderSource(vertex_shader, 1, &source, &length); 115 | glCompileShader(vertex_shader); 116 | if(!check_shader_compile_status(vertex_shader)) { 117 | glfwDestroyWindow(window); 118 | glfwTerminate(); 119 | return 1; 120 | } 121 | 122 | // create and compiler fragment shader 123 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 124 | source = fragment_source.c_str(); 125 | length = fragment_source.size(); 126 | glShaderSource(fragment_shader, 1, &source, &length); 127 | glCompileShader(fragment_shader); 128 | if(!check_shader_compile_status(fragment_shader)) { 129 | glfwDestroyWindow(window); 130 | glfwTerminate(); 131 | return 1; 132 | } 133 | 134 | // create program 135 | shader_program = glCreateProgram(); 136 | 137 | // attach shaders 138 | glAttachShader(shader_program, vertex_shader); 139 | glAttachShader(shader_program, fragment_shader); 140 | 141 | // link the program and check for errors 142 | glLinkProgram(shader_program); 143 | check_program_link_status(shader_program); 144 | 145 | // obtain location of projection uniform 146 | GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); 147 | 148 | 149 | // vao and vbo handles 150 | GLuint vao, vbo, tbo, ibo; 151 | 152 | // generate and bind the vao 153 | glGenVertexArrays(1, &vao); 154 | glBindVertexArray(vao); 155 | 156 | // generate and bind the vertex buffer object 157 | glGenBuffers(1, &vbo); 158 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 159 | 160 | // data for a cube 161 | GLfloat vertexData[] = { 162 | // X Y Z R G B 163 | // face 0: 164 | 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 165 | -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 166 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 167 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 168 | 169 | // face 1: 170 | 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 171 | 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 172 | 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 173 | 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 174 | 175 | // face 2: 176 | 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 177 | 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 178 | -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 179 | -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 180 | 181 | // face 3: 182 | 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 183 | 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 184 | -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 185 | -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 186 | 187 | // face 4: 188 | -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 189 | -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 190 | -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 191 | -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 192 | 193 | // face 5: 194 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 195 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 196 | 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 197 | -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 198 | }; // 6 faces with 4 vertices with 6 components (floats) 199 | 200 | // fill with data 201 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); 202 | 203 | // set up generic attrib pointers 204 | glEnableVertexAttribArray(0); 205 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 206 | 207 | glEnableVertexAttribArray(1); 208 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 209 | 210 | // generate and bind the index buffer object 211 | glGenBuffers(1, &ibo); 212 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 213 | 214 | GLuint indexData[] = { 215 | // face 0: 216 | 0,1,2, // first triangle 217 | 2,1,3, // second triangle 218 | // face 1: 219 | 4,5,6, // first triangle 220 | 6,5,7, // second triangle 221 | // face 2: 222 | 8,9,10, // first triangle 223 | 10,9,11, // second triangle 224 | // face 3: 225 | 12,13,14, // first triangle 226 | 14,13,15, // second triangle 227 | // face 4: 228 | 16,17,18, // first triangle 229 | 18,17,19, // second triangle 230 | // face 5: 231 | 20,21,22, // first triangle 232 | 22,21,23, // second triangle 233 | }; 234 | 235 | // fill with data 236 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); 237 | 238 | // generate and bind the vertex buffer object containing the 239 | // instance offsets 240 | glGenBuffers(1, &tbo); 241 | glBindBuffer(GL_ARRAY_BUFFER, tbo); 242 | 243 | // the offsets 244 | GLfloat translationData[] = { 245 | 2.0f, 2.0f, 2.0f, // cube 0 246 | 2.0f, 2.0f,-2.0f, // cube 1 247 | 2.0f,-2.0f, 2.0f, // cube 2 248 | 2.0f,-2.0f,-2.0f, // cube 3 249 | -2.0f, 2.0f, 2.0f, // cube 4 250 | -2.0f, 2.0f,-2.0f, // cube 5 251 | -2.0f,-2.0f, 2.0f, // cube 6 252 | -2.0f,-2.0f,-2.0f, // cube 7 253 | }; // 8 offsets with 3 components each 254 | 255 | // fill with data 256 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*8, translationData, GL_STATIC_DRAW); 257 | 258 | // set up generic attrib pointers 259 | glEnableVertexAttribArray(2); 260 | glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 261 | 262 | // a attrib divisor of 1 means that attribute 2 will advance once 263 | // every instance (0 would mean once per vertex) 264 | glVertexAttribDivisor(2, 1); 265 | 266 | // we are drawing 3d objects so we want depth testing 267 | glEnable(GL_DEPTH_TEST); 268 | 269 | while(!glfwWindowShouldClose(window)) { 270 | glfwPollEvents(); 271 | 272 | // get the time in seconds 273 | float t = glfwGetTime(); 274 | 275 | // clear first 276 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 277 | 278 | // use the shader program 279 | glUseProgram(shader_program); 280 | 281 | // calculate ViewProjection matrix 282 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 283 | 284 | // translate the world/view position 285 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); 286 | 287 | // make the camera rotate around the origin 288 | View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 289 | 290 | glm::mat4 ViewProjection = Projection*View; 291 | 292 | // set the uniform 293 | glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 294 | 295 | // bind the vao 296 | glBindVertexArray(vao); 297 | 298 | // draw 299 | // the additional parameter indicates how many instances to render 300 | glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8); 301 | 302 | // check for errors 303 | GLenum error = glGetError(); 304 | if(error != GL_NO_ERROR) { 305 | std::cerr << error << std::endl; 306 | break; 307 | } 308 | 309 | // finally swap buffers 310 | glfwSwapBuffers(window); 311 | } 312 | 313 | // delete the created objects 314 | 315 | glDeleteVertexArrays(1, &vao); 316 | glDeleteBuffers(1, &vbo); 317 | glDeleteBuffers(1, &ibo); 318 | glDeleteBuffers(1, &tbo); 319 | 320 | glDetachShader(shader_program, vertex_shader); 321 | glDetachShader(shader_program, fragment_shader); 322 | glDeleteShader(vertex_shader); 323 | glDeleteShader(fragment_shader); 324 | glDeleteProgram(shader_program); 325 | 326 | glfwDestroyWindow(window); 327 | glfwTerminate(); 328 | return 0; 329 | } 330 | 331 | -------------------------------------------------------------------------------- /06instancing3_uniform_buffer.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Instancing with uniform buffer object 2 | * 3 | * create 8 instances of the cube from the perspective example 4 | * the per instance data is passed with a uniform buffer object 5 | * 6 | * Autor: Jakob Progsch 7 | */ 8 | 9 | #include 10 | #include 11 | 12 | //glm is used to create perspective and transform matrices 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | // helper to check and display for shader compiler errors 23 | bool check_shader_compile_status(GLuint obj) { 24 | GLint status; 25 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 26 | if(status == GL_FALSE) { 27 | GLint length; 28 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 29 | std::vector log(length); 30 | glGetShaderInfoLog(obj, length, &length, &log[0]); 31 | std::cerr << &log[0]; 32 | return false; 33 | } 34 | return true; 35 | } 36 | 37 | // helper to check and display for shader linker error 38 | bool check_program_link_status(GLuint obj) { 39 | GLint status; 40 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 41 | if(status == GL_FALSE) { 42 | GLint length; 43 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 44 | std::vector log(length); 45 | glGetProgramInfoLog(obj, length, &length, &log[0]); 46 | std::cerr << &log[0]; 47 | return false; 48 | } 49 | return true; 50 | } 51 | 52 | int main() { 53 | int width = 640; 54 | int height = 480; 55 | 56 | if(glfwInit() == GL_FALSE) { 57 | std::cerr << "failed to init GLFW" << std::endl; 58 | return 1; 59 | } 60 | 61 | // select opengl version 62 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 63 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 64 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 65 | 66 | // create a window 67 | GLFWwindow *window; 68 | if((window = glfwCreateWindow(width, height, "06instancing3_uniform_buffer", 0, 0)) == 0) { 69 | std::cerr << "failed to open window" << std::endl; 70 | glfwTerminate(); 71 | return 1; 72 | } 73 | 74 | glfwMakeContextCurrent(window); 75 | 76 | if(glxwInit()) { 77 | std::cerr << "failed to init GL3W" << std::endl; 78 | glfwDestroyWindow(window); 79 | glfwTerminate(); 80 | return 1; 81 | } 82 | 83 | // shader source code 84 | std::string vertex_source = 85 | "#version 330\n" 86 | "layout(std140) uniform Matrices {\n" 87 | " mat4 ViewProjection;\n" 88 | " mat4 Model[8];\n" 89 | "};\n" 90 | "layout(location = 0) in vec4 vposition;\n" 91 | "layout(location = 1) in vec4 vcolor;\n" 92 | "out vec4 fcolor;\n" 93 | "void main() {\n" 94 | " fcolor = vcolor;\n" 95 | " gl_Position = ViewProjection*Model[gl_InstanceID]*vposition;\n" 96 | "}\n"; 97 | 98 | std::string fragment_source = 99 | "#version 330\n" 100 | "in vec4 fcolor;\n" 101 | "layout(location = 0) out vec4 FragColor;\n" 102 | "void main() {\n" 103 | " FragColor = fcolor;\n" 104 | "}\n"; 105 | 106 | // program and shader handles 107 | GLuint shader_program, vertex_shader, fragment_shader; 108 | 109 | // we need these to properly pass the strings 110 | const char *source; 111 | int length; 112 | 113 | // create and compiler vertex shader 114 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 115 | source = vertex_source.c_str(); 116 | length = vertex_source.size(); 117 | glShaderSource(vertex_shader, 1, &source, &length); 118 | glCompileShader(vertex_shader); 119 | if(!check_shader_compile_status(vertex_shader)) { 120 | glfwDestroyWindow(window); 121 | glfwTerminate(); 122 | return 1; 123 | } 124 | 125 | // create and compiler fragment shader 126 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 127 | source = fragment_source.c_str(); 128 | length = fragment_source.size(); 129 | glShaderSource(fragment_shader, 1, &source, &length); 130 | glCompileShader(fragment_shader); 131 | if(!check_shader_compile_status(fragment_shader)) { 132 | glfwDestroyWindow(window); 133 | glfwTerminate(); 134 | return 1; 135 | } 136 | 137 | // create program 138 | shader_program = glCreateProgram(); 139 | 140 | // attach shaders 141 | glAttachShader(shader_program, vertex_shader); 142 | glAttachShader(shader_program, fragment_shader); 143 | 144 | // link the program and check for errors 145 | glLinkProgram(shader_program); 146 | check_program_link_status(shader_program); 147 | 148 | // obtain location of the uniform block 149 | GLuint Matrices_binding = 0; 150 | GLint uniform_block_index = glGetUniformBlockIndex(shader_program, "Matrices"); 151 | // assign the block binding 152 | glUniformBlockBinding(shader_program, uniform_block_index, Matrices_binding); 153 | 154 | // create uniform buffer 155 | GLuint ubo; 156 | glGenBuffers(1, &ubo); 157 | glBindBuffer(GL_UNIFORM_BUFFER, ubo); 158 | glBufferData(GL_UNIFORM_BUFFER, 9*sizeof(float)*4*4, 0, GL_STREAM_DRAW); 159 | 160 | // fill the Model matrix array 161 | glm::mat4 ModelMatrices[8]; 162 | ModelMatrices[0] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f, 2.0f, 2.0f)); 163 | ModelMatrices[1] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f, 2.0f,-2.0f)); 164 | ModelMatrices[2] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f,-2.0f, 2.0f)); 165 | ModelMatrices[3] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f,-2.0f,-2.0f)); 166 | ModelMatrices[4] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 2.0f, 2.0f)); 167 | ModelMatrices[5] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 2.0f,-2.0f)); 168 | ModelMatrices[6] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f,-2.0f, 2.0f)); 169 | ModelMatrices[7] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f,-2.0f,-2.0f)); 170 | 171 | glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float)*4*4, 8*sizeof(float)*4*4, ModelMatrices); 172 | 173 | 174 | // vao and vbo handle 175 | GLuint vao, vbo, ibo; 176 | 177 | // generate and bind the vao 178 | glGenVertexArrays(1, &vao); 179 | glBindVertexArray(vao); 180 | 181 | // generate and bind the vertex buffer object 182 | glGenBuffers(1, &vbo); 183 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 184 | 185 | // data for a cube 186 | GLfloat vertexData[] = { 187 | // X Y Z R G B 188 | // face 0: 189 | 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 190 | -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 191 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 192 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 193 | 194 | // face 1: 195 | 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 196 | 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 197 | 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 198 | 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 199 | 200 | // face 2: 201 | 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 202 | 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 203 | -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 204 | -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 205 | 206 | // face 3: 207 | 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 208 | 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 209 | -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 210 | -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 211 | 212 | // face 4: 213 | -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 214 | -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 215 | -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 216 | -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 217 | 218 | // face 5: 219 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 220 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 221 | 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 222 | -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 223 | }; // 6 faces with 4 vertices with 6 components (floats) 224 | 225 | // fill with data 226 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); 227 | 228 | 229 | // set up generic attrib pointers 230 | glEnableVertexAttribArray(0); 231 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 232 | 233 | glEnableVertexAttribArray(1); 234 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 235 | 236 | 237 | // generate and bind the index buffer object 238 | glGenBuffers(1, &ibo); 239 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 240 | 241 | GLuint indexData[] = { 242 | // face 0: 243 | 0,1,2, // first triangle 244 | 2,1,3, // second triangle 245 | // face 1: 246 | 4,5,6, // first triangle 247 | 6,5,7, // second triangle 248 | // face 2: 249 | 8,9,10, // first triangle 250 | 10,9,11, // second triangle 251 | // face 3: 252 | 12,13,14, // first triangle 253 | 14,13,15, // second triangle 254 | // face 4: 255 | 16,17,18, // first triangle 256 | 18,17,19, // second triangle 257 | // face 5: 258 | 20,21,22, // first triangle 259 | 22,21,23, // second triangle 260 | }; 261 | 262 | // fill with data 263 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); 264 | 265 | // we are drawing 3d objects so we want depth testing 266 | glEnable(GL_DEPTH_TEST); 267 | 268 | while(!glfwWindowShouldClose(window)) { 269 | glfwPollEvents(); 270 | 271 | // get the time in seconds 272 | float t = glfwGetTime(); 273 | 274 | // clear first 275 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 276 | 277 | // use the shader program 278 | glUseProgram(shader_program); 279 | 280 | // calculate ViewProjection matrix 281 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 282 | 283 | // translate the world/view position 284 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); 285 | 286 | // make the camera rotate around the origin 287 | View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 288 | 289 | glm::mat4 ViewProjection = Projection*View; 290 | 291 | // set the ViewProjection in the uniform buffer 292 | glBindBuffer(GL_UNIFORM_BUFFER, ubo); 293 | glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float)*4*4, glm::value_ptr(ViewProjection)); 294 | glBindBufferRange(GL_UNIFORM_BUFFER, Matrices_binding, ubo, 0, sizeof(float)*4*4*9); 295 | 296 | // bind the vao 297 | glBindVertexArray(vao); 298 | 299 | // draw 300 | // the additional parameter indicates how many instances to render 301 | glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8); 302 | 303 | // check for errors 304 | GLenum error = glGetError(); 305 | if(error != GL_NO_ERROR) { 306 | std::cerr << error << std::endl; 307 | break; 308 | } 309 | 310 | // finally swap buffers 311 | glfwSwapBuffers(window); 312 | } 313 | 314 | // delete the created objects 315 | 316 | glDeleteVertexArrays(1, &vao); 317 | glDeleteBuffers(1, &vbo); 318 | glDeleteBuffers(1, &ibo); 319 | 320 | glDetachShader(shader_program, vertex_shader); 321 | glDetachShader(shader_program, fragment_shader); 322 | glDeleteShader(vertex_shader); 323 | glDeleteShader(fragment_shader); 324 | glDeleteProgram(shader_program); 325 | 326 | glfwDestroyWindow(window); 327 | glfwTerminate(); 328 | return 0; 329 | } 330 | 331 | -------------------------------------------------------------------------------- /06instancing2_buffer_texture.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Instancing with texture buffer 2 | * 3 | * create 8 instances of the cube from the perspective example 4 | * the difference to the instancing1 example is that we are 5 | * using a texture buffer for the per instance data instead of a 6 | * vertex buffer with divisor. 7 | * 8 | * Autor: Jakob Progsch 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | //glm is used to create perspective and transform matrices 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | 24 | // helper to check and display for shader compiler errors 25 | bool check_shader_compile_status(GLuint obj) { 26 | GLint status; 27 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 28 | if(status == GL_FALSE) { 29 | GLint length; 30 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 31 | std::vector log(length); 32 | glGetShaderInfoLog(obj, length, &length, &log[0]); 33 | std::cerr << &log[0]; 34 | return false; 35 | } 36 | return true; 37 | } 38 | 39 | // helper to check and display for shader linker error 40 | bool check_program_link_status(GLuint obj) { 41 | GLint status; 42 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 43 | if(status == GL_FALSE) { 44 | GLint length; 45 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 46 | std::vector log(length); 47 | glGetProgramInfoLog(obj, length, &length, &log[0]); 48 | std::cerr << &log[0]; 49 | return false; 50 | } 51 | return true; 52 | } 53 | 54 | int main() { 55 | int width = 640; 56 | int height = 480; 57 | 58 | if(glfwInit() == GL_FALSE) { 59 | std::cerr << "failed to init GLFW" << std::endl; 60 | return 1; 61 | } 62 | 63 | // select opengl version 64 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 65 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 66 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 67 | 68 | // create a window 69 | GLFWwindow *window; 70 | if((window = glfwCreateWindow(width, height, "06instancing2_buffer_texture", 0, 0)) == 0) { 71 | std::cerr << "failed to open window" << std::endl; 72 | glfwTerminate(); 73 | return 1; 74 | } 75 | 76 | glfwMakeContextCurrent(window); 77 | 78 | if(glxwInit()) { 79 | std::cerr << "failed to init GL3W" << std::endl; 80 | glfwDestroyWindow(window); 81 | glfwTerminate(); 82 | return 1; 83 | } 84 | 85 | // shader source code 86 | std::string vertex_source = 87 | "#version 330\n" 88 | "uniform mat4 ViewProjection;\n" // the projection matrix uniform 89 | "uniform samplerBuffer offset_texture;\n" // the buffer_texture sampler 90 | "layout(location = 0) in vec4 vposition;\n" 91 | "layout(location = 1) in vec4 vcolor;\n" 92 | "out vec4 fcolor;\n" 93 | "void main() {\n" 94 | // access the buffer texture with the InstanceID (tbo[InstanceID]) 95 | " vec4 offset = texelFetch(offset_texture, gl_InstanceID);\n" 96 | " fcolor = vcolor;\n" 97 | " gl_Position = ViewProjection*(vposition + offset);\n" 98 | "}\n"; 99 | 100 | std::string fragment_source = 101 | "#version 330\n" 102 | "in vec4 fcolor;\n" 103 | "layout(location = 0) out vec4 FragColor;\n" 104 | "void main() {\n" 105 | " FragColor = fcolor;\n" 106 | "}\n"; 107 | 108 | // program and shader handles 109 | GLuint shader_program, vertex_shader, fragment_shader; 110 | 111 | // we need these to properly pass the strings 112 | const char *source; 113 | int length; 114 | 115 | // create and compiler vertex shader 116 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 117 | source = vertex_source.c_str(); 118 | length = vertex_source.size(); 119 | glShaderSource(vertex_shader, 1, &source, &length); 120 | glCompileShader(vertex_shader); 121 | if(!check_shader_compile_status(vertex_shader)) { 122 | glfwDestroyWindow(window); 123 | glfwTerminate(); 124 | return 1; 125 | } 126 | 127 | // create and compiler fragment shader 128 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 129 | source = fragment_source.c_str(); 130 | length = fragment_source.size(); 131 | glShaderSource(fragment_shader, 1, &source, &length); 132 | glCompileShader(fragment_shader); 133 | if(!check_shader_compile_status(fragment_shader)) { 134 | glfwDestroyWindow(window); 135 | glfwTerminate(); 136 | return 1; 137 | } 138 | 139 | // create program 140 | shader_program = glCreateProgram(); 141 | 142 | // attach shaders 143 | glAttachShader(shader_program, vertex_shader); 144 | glAttachShader(shader_program, fragment_shader); 145 | 146 | // link the program and check for errors 147 | glLinkProgram(shader_program); 148 | check_program_link_status(shader_program); 149 | 150 | // obtain location of projection uniform 151 | GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); 152 | GLint offset_texture_location = glGetUniformLocation(shader_program, "offset_texture"); 153 | 154 | 155 | // vao and vbo handles 156 | GLuint vao, vbo, tbo, ibo; 157 | 158 | // generate and bind the vao 159 | glGenVertexArrays(1, &vao); 160 | glBindVertexArray(vao); 161 | 162 | // generate and bind the vertex buffer object 163 | glGenBuffers(1, &vbo); 164 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 165 | 166 | // data for a cube 167 | GLfloat vertexData[] = { 168 | // X Y Z R G B 169 | // face 0: 170 | 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 171 | -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 172 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 173 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 174 | 175 | // face 1: 176 | 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 177 | 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 178 | 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 179 | 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 180 | 181 | // face 2: 182 | 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 183 | 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 184 | -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 185 | -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 186 | 187 | // face 3: 188 | 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 189 | 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 190 | -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 191 | -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 192 | 193 | // face 4: 194 | -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 195 | -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 196 | -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 197 | -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 198 | 199 | // face 5: 200 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 201 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 202 | 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 203 | -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 204 | }; // 6 faces with 4 vertices with 6 components (floats) 205 | 206 | // fill with data 207 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); 208 | 209 | 210 | // set up generic attrib pointers 211 | glEnableVertexAttribArray(0); 212 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 213 | 214 | glEnableVertexAttribArray(1); 215 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 216 | 217 | 218 | // generate and bind the index buffer object 219 | glGenBuffers(1, &ibo); 220 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 221 | 222 | GLuint indexData[] = { 223 | // face 0: 224 | 0,1,2, // first triangle 225 | 2,1,3, // second triangle 226 | // face 1: 227 | 4,5,6, // first triangle 228 | 6,5,7, // second triangle 229 | // face 2: 230 | 8,9,10, // first triangle 231 | 10,9,11, // second triangle 232 | // face 3: 233 | 12,13,14, // first triangle 234 | 14,13,15, // second triangle 235 | // face 4: 236 | 16,17,18, // first triangle 237 | 18,17,19, // second triangle 238 | // face 5: 239 | 20,21,22, // first triangle 240 | 22,21,23, // second triangle 241 | }; 242 | 243 | // fill with data 244 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); 245 | 246 | // generate and bind the buffer object containing the 247 | // instance offsets 248 | glGenBuffers(1, &tbo); 249 | glBindBuffer(GL_TEXTURE_BUFFER, tbo); 250 | 251 | // the offsets 252 | GLfloat translationData[] = { 253 | 2.0f, 2.0f, 2.0f, 0.0f, // cube 0 254 | 2.0f, 2.0f,-2.0f, 0.0f, // cube 1 255 | 2.0f,-2.0f, 2.0f, 0.0f, // cube 2 256 | 2.0f,-2.0f,-2.0f, 0.0f, // cube 3 257 | -2.0f, 2.0f, 2.0f, 0.0f, // cube 4 258 | -2.0f, 2.0f,-2.0f, 0.0f, // cube 5 259 | -2.0f,-2.0f, 2.0f, 0.0f, // cube 6 260 | -2.0f,-2.0f,-2.0f, 0.0f, // cube 7 261 | }; // 8 offsets with 3 components each 262 | 263 | // fill with data 264 | glBufferData(GL_TEXTURE_BUFFER, sizeof(GLfloat)*4*8, translationData, GL_STATIC_DRAW); 265 | 266 | // texture handle 267 | GLuint buffer_texture; 268 | 269 | // generate and bind the buffer texture 270 | glGenTextures(1, &buffer_texture); 271 | glBindTexture(GL_TEXTURE_BUFFER, buffer_texture); 272 | 273 | // tell the buffer texture to use 274 | glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, tbo); 275 | 276 | 277 | // we are drawing 3d objects so we want depth testing 278 | glEnable(GL_DEPTH_TEST); 279 | 280 | 281 | while(!glfwWindowShouldClose(window)) { 282 | glfwPollEvents(); 283 | 284 | // get the time in seconds 285 | float t = glfwGetTime(); 286 | 287 | // clear first 288 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 289 | 290 | // use the shader program 291 | glUseProgram(shader_program); 292 | 293 | // calculate ViewProjection matrix 294 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 295 | 296 | // translate the world/view position 297 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); 298 | 299 | // make the camera rotate around the origin 300 | View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 301 | 302 | glm::mat4 ViewProjection = Projection*View; 303 | 304 | // bind texture to texture unit 0 305 | glActiveTexture(GL_TEXTURE0); 306 | glBindTexture(GL_TEXTURE_BUFFER, buffer_texture); 307 | 308 | 309 | // set the matrix uniform 310 | glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 311 | 312 | // set texture uniform 313 | glUniform1i(offset_texture_location, 0); 314 | 315 | 316 | // bind the vao 317 | glBindVertexArray(vao); 318 | 319 | 320 | // draw 321 | // the additional parameter indicates how many instances to render 322 | glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8); 323 | 324 | // check for errors 325 | GLenum error = glGetError(); 326 | if(error != GL_NO_ERROR) { 327 | std::cerr << error << std::endl; 328 | break; 329 | } 330 | 331 | // finally swap buffers 332 | glfwSwapBuffers(window); 333 | } 334 | 335 | // delete the created objects 336 | 337 | glDeleteVertexArrays(1, &vao); 338 | glDeleteBuffers(1, &vbo); 339 | glDeleteBuffers(1, &ibo); 340 | glDeleteBuffers(1, &tbo); 341 | 342 | glDeleteTextures(1, &buffer_texture); 343 | 344 | glDetachShader(shader_program, vertex_shader); 345 | glDetachShader(shader_program, fragment_shader); 346 | glDeleteShader(vertex_shader); 347 | glDeleteShader(fragment_shader); 348 | glDeleteProgram(shader_program); 349 | 350 | 351 | glfwDestroyWindow(window); 352 | glfwTerminate(); 353 | return 0; 354 | } 355 | 356 | -------------------------------------------------------------------------------- /08map_buffer.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - buffer mapping 2 | * 3 | * This example uses the geometry shader again for particle drawing. 4 | * The particles are animated on the cpu and uploaded every frame by 5 | * mapping vbos. Multiple vbos are used to triple buffer the particle 6 | * data. 7 | * 8 | * Autor: Jakob Progsch 9 | */ 10 | 11 | #include 12 | #include 13 | 14 | //glm is used to create perspective and transform matrices 15 | #include 16 | #include 17 | #include 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | // helper to check and display for shader compiler errors 27 | bool check_shader_compile_status(GLuint obj) { 28 | GLint status; 29 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 30 | if(status == GL_FALSE) { 31 | GLint length; 32 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 33 | std::vector log(length); 34 | glGetShaderInfoLog(obj, length, &length, &log[0]); 35 | std::cerr << &log[0]; 36 | return false; 37 | } 38 | return true; 39 | } 40 | 41 | // helper to check and display for shader linker error 42 | bool check_program_link_status(GLuint obj) { 43 | GLint status; 44 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 45 | if(status == GL_FALSE) { 46 | GLint length; 47 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 48 | std::vector log(length); 49 | glGetProgramInfoLog(obj, length, &length, &log[0]); 50 | std::cerr << &log[0]; 51 | return false; 52 | } 53 | return true; 54 | } 55 | 56 | int main() { 57 | int width = 640; 58 | int height = 480; 59 | 60 | if(glfwInit() == GL_FALSE) { 61 | std::cerr << "failed to init GLFW" << std::endl; 62 | return 1; 63 | } 64 | 65 | // select opengl version 66 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 67 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 68 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 69 | 70 | // create a window 71 | GLFWwindow *window; 72 | if((window = glfwCreateWindow(width, height, "08map_buffer", 0, 0)) == 0) { 73 | std::cerr << "failed to open window" << std::endl; 74 | glfwTerminate(); 75 | return 1; 76 | } 77 | 78 | glfwMakeContextCurrent(window); 79 | 80 | if(glxwInit()) { 81 | std::cerr << "failed to init GL3W" << std::endl; 82 | glfwDestroyWindow(window); 83 | glfwTerminate(); 84 | return 1; 85 | } 86 | 87 | // the vertex shader simply passes through data 88 | std::string vertex_source = 89 | "#version 330\n" 90 | "layout(location = 0) in vec4 vposition;\n" 91 | "void main() {\n" 92 | " gl_Position = vposition;\n" 93 | "}\n"; 94 | 95 | // the geometry shader creates the billboard quads 96 | std::string geometry_source = 97 | "#version 330\n" 98 | "uniform mat4 View;\n" 99 | "uniform mat4 Projection;\n" 100 | "layout (points) in;\n" 101 | "layout (triangle_strip, max_vertices = 4) out;\n" 102 | "out vec2 txcoord;\n" 103 | "void main() {\n" 104 | " vec4 pos = View*gl_in[0].gl_Position;\n" 105 | " txcoord = vec2(-1,-1);\n" 106 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 107 | " EmitVertex();\n" 108 | " txcoord = vec2( 1,-1);\n" 109 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 110 | " EmitVertex();\n" 111 | " txcoord = vec2(-1, 1);\n" 112 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 113 | " EmitVertex();\n" 114 | " txcoord = vec2( 1, 1);\n" 115 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 116 | " EmitVertex();\n" 117 | "}\n"; 118 | 119 | // the fragment shader creates a bell like radial color distribution 120 | std::string fragment_source = 121 | "#version 330\n" 122 | "in vec2 txcoord;\n" 123 | "layout(location = 0) out vec4 FragColor;\n" 124 | "void main() {\n" 125 | " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" 126 | " FragColor = s*vec4(0.3,0.3,1.0,1);\n" 127 | "}\n"; 128 | 129 | // program and shader handles 130 | GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; 131 | 132 | // we need these to properly pass the strings 133 | const char *source; 134 | int length; 135 | 136 | // create and compiler vertex shader 137 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 138 | source = vertex_source.c_str(); 139 | length = vertex_source.size(); 140 | glShaderSource(vertex_shader, 1, &source, &length); 141 | glCompileShader(vertex_shader); 142 | if(!check_shader_compile_status(vertex_shader)) { 143 | glfwDestroyWindow(window); 144 | glfwTerminate(); 145 | return 1; 146 | } 147 | 148 | // create and compiler geometry shader 149 | geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); 150 | source = geometry_source.c_str(); 151 | length = geometry_source.size(); 152 | glShaderSource(geometry_shader, 1, &source, &length); 153 | glCompileShader(geometry_shader); 154 | if(!check_shader_compile_status(geometry_shader)) { 155 | glfwDestroyWindow(window); 156 | glfwTerminate(); 157 | return 1; 158 | } 159 | 160 | // create and compiler fragment shader 161 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 162 | source = fragment_source.c_str(); 163 | length = fragment_source.size(); 164 | glShaderSource(fragment_shader, 1, &source, &length); 165 | glCompileShader(fragment_shader); 166 | if(!check_shader_compile_status(fragment_shader)) { 167 | glfwDestroyWindow(window); 168 | glfwTerminate(); 169 | return 1; 170 | } 171 | 172 | // create program 173 | shader_program = glCreateProgram(); 174 | 175 | // attach shaders 176 | glAttachShader(shader_program, vertex_shader); 177 | glAttachShader(shader_program, geometry_shader); 178 | glAttachShader(shader_program, fragment_shader); 179 | 180 | // link the program and check for errors 181 | glLinkProgram(shader_program); 182 | check_program_link_status(shader_program); 183 | 184 | // obtain location of projection uniform 185 | GLint View_location = glGetUniformLocation(shader_program, "View"); 186 | GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); 187 | 188 | const int particles = 128*1024; 189 | 190 | // randomly place particles in a cube 191 | std::vector vertexData(particles); 192 | std::vector velocity(particles); 193 | for(int i = 0;i( 284 | glMapBufferRange(GL_ARRAY_BUFFER, 0, 285 | sizeof(glm::vec3)*vertexData.size(), 286 | GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT 287 | ) 288 | ); 289 | 290 | // copy data into the mapped memory 291 | std::copy(vertexData.begin(), vertexData.end(), mapped); 292 | 293 | // unmap the buffer 294 | glUnmapBuffer(GL_ARRAY_BUFFER); 295 | 296 | 297 | // clear first 298 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 299 | 300 | // use the shader program 301 | glUseProgram(shader_program); 302 | 303 | // calculate ViewProjection matrix 304 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 305 | 306 | // translate the world/view position 307 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); 308 | 309 | // make the camera rotate around the origin 310 | View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); 311 | View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); 312 | 313 | // set the uniform 314 | glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); 315 | glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); 316 | 317 | // bind the current vao 318 | glBindVertexArray(vao[current_buffer]); 319 | 320 | // draw 321 | glDrawArrays(GL_POINTS, 0, particles); 322 | 323 | // check for errors 324 | GLenum error = glGetError(); 325 | if(error != GL_NO_ERROR) { 326 | std::cerr << error << std::endl; 327 | break; 328 | } 329 | 330 | // finally swap buffers 331 | glfwSwapBuffers(window); 332 | 333 | // advance buffer index 334 | current_buffer = (current_buffer + 1) % buffercount; 335 | } 336 | 337 | // delete the created objects 338 | 339 | glDeleteVertexArrays(buffercount, vao); 340 | glDeleteBuffers(buffercount, vbo); 341 | 342 | glDetachShader(shader_program, vertex_shader); 343 | glDetachShader(shader_program, geometry_shader); 344 | glDetachShader(shader_program, fragment_shader); 345 | glDeleteShader(vertex_shader); 346 | glDeleteShader(geometry_shader); 347 | glDeleteShader(fragment_shader); 348 | glDeleteProgram(shader_program); 349 | 350 | glfwDestroyWindow(window); 351 | glfwTerminate(); 352 | return 0; 353 | } 354 | 355 | -------------------------------------------------------------------------------- /12shader_image_load_store.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - shader_image_load_store 2 | * 3 | * This example solves the electromagnetic wave equation with a FDTD 4 | * scheme (finite difference time domain). Updates of the texture 5 | * representing the grid are done in place by use of image objects. 6 | * 7 | * Autor: Jakob Progsch 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | #include 19 | 20 | 21 | // helper to check and display for shader compiler errors 22 | bool check_shader_compile_status(GLuint obj) { 23 | GLint status; 24 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 25 | if(status == GL_FALSE) { 26 | GLint length; 27 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 28 | std::vector log(length); 29 | glGetShaderInfoLog(obj, length, &length, &log[0]); 30 | std::cerr << &log[0]; 31 | return false; 32 | } 33 | return true; 34 | } 35 | 36 | // helper to check and display for shader linker error 37 | bool check_program_link_status(GLuint obj) { 38 | GLint status; 39 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 40 | if(status == GL_FALSE) { 41 | GLint length; 42 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 43 | std::vector log(length); 44 | glGetProgramInfoLog(obj, length, &length, &log[0]); 45 | std::cerr << &log[0]; 46 | return false; 47 | } 48 | return true; 49 | } 50 | 51 | int main() { 52 | int width = 640; 53 | int height = 480; 54 | 55 | if(glfwInit() == GL_FALSE) { 56 | std::cerr << "failed to init GLFW" << std::endl; 57 | return 1; 58 | } 59 | 60 | // select opengl version 61 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 62 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 63 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); 64 | 65 | // create a window 66 | GLFWwindow *window; 67 | if((window = glfwCreateWindow(width, height, "12shader_image_load_store", 0, 0)) == 0) { 68 | std::cerr << "failed to open window" << std::endl; 69 | glfwTerminate(); 70 | return 1; 71 | } 72 | 73 | glfwMakeContextCurrent(window); 74 | 75 | if(glxwInit()) { 76 | std::cerr << "failed to init GL3W" << std::endl; 77 | glfwDestroyWindow(window); 78 | glfwTerminate(); 79 | return 1; 80 | } 81 | 82 | glfwSwapInterval(1); 83 | 84 | 85 | // shader source code 86 | // shared vertex shader 87 | std::string vertex_source = 88 | "#version 420\n" 89 | "layout(location = 0) in vec4 vposition;\n" 90 | "void main() {\n" 91 | " gl_Position = vposition;\n" 92 | "}\n"; 93 | 94 | // the first fragment shader doesn't output anything since it only 95 | // updates the image in place 96 | std::string fragment1_source = 97 | "#version 420\n" 98 | "uniform float dt;\n" 99 | "uniform ivec2 image_size;\n" 100 | "uniform layout(rgba32f) image2D image;\n" 101 | "layout(location = 0) out vec4 FragColor;\n" 102 | "void main() {\n" 103 | " ivec2 coords = ivec2(gl_FragCoord.xy);\n" 104 | " vec4 HE = imageLoad(image, coords);\n" 105 | " float Ezdx = HE.z-imageLoad(image, coords-ivec2(1, 0)).z;\n" 106 | " float Ezdy = HE.z-imageLoad(image, coords-ivec2(0, 1)).z;\n" 107 | " HE.xy += dt*vec2(-Ezdy, Ezdx);\n" 108 | " imageStore(image, coords, HE);\n" 109 | "}\n"; 110 | 111 | 112 | // the second fragment shader also outputs the frag color for display 113 | // purposes 114 | std::string fragment2_source = 115 | "#version 420\n" 116 | "uniform float t;\n" 117 | "uniform float dt;\n" 118 | "uniform ivec2 image_size;\n" 119 | "uniform layout(rgba32f) image2D image;\n" 120 | "layout(location = 0) out vec4 FragColor;\n" 121 | "void main() {\n" 122 | " ivec2 coords = ivec2(gl_FragCoord.xy);\n" 123 | 124 | " float e = 1;\n" 125 | " vec4 HE = imageLoad(image, coords);\n" 126 | " float r = HE.w;\n" 127 | " float Hydx = imageLoad(image, coords+ivec2(1, 0)).y\n" 128 | " -HE.y;\n" 129 | " float Hxdy = imageLoad(image, coords+ivec2(0, 1)).x\n" 130 | " -HE.x;\n" 131 | 132 | " float Eout = dt*(Hydx-Hxdy)/(e);\n" 133 | " HE.z = HE.z*(1-dt*r/e) + Eout;\n" 134 | 135 | // add source at image center 136 | " if(coords.x == image_size.x/2 && coords.y == image_size.y/2) {\n" 137 | " HE.z += 30*sin(15*t)*exp(-20*(t-2)*(t-2));\n" 138 | " }\n" 139 | 140 | " imageStore(image, coords, HE);\n" 141 | " FragColor = vec4(HE.z, HE.w, -HE.z, 1);\n" 142 | "}\n"; 143 | 144 | // program and shader handles 145 | GLuint shader1_program, shader2_program, vertex_shader, fragment1_shader, fragment2_shader; 146 | 147 | // we need these to properly pass the strings 148 | const char *source; 149 | int length; 150 | 151 | // create and compiler vertex shader 152 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 153 | source = vertex_source.c_str(); 154 | length = vertex_source.size(); 155 | glShaderSource(vertex_shader, 1, &source, &length); 156 | glCompileShader(vertex_shader); 157 | if(!check_shader_compile_status(vertex_shader)) { 158 | glfwDestroyWindow(window); 159 | glfwTerminate(); 160 | return 1; 161 | } 162 | 163 | // create and compiler fragment shader 164 | fragment1_shader = glCreateShader(GL_FRAGMENT_SHADER); 165 | source = fragment1_source.c_str(); 166 | length = fragment1_source.size(); 167 | glShaderSource(fragment1_shader, 1, &source, &length); 168 | glCompileShader(fragment1_shader); 169 | if(!check_shader_compile_status(fragment1_shader)) { 170 | glfwDestroyWindow(window); 171 | glfwTerminate(); 172 | return 1; 173 | } 174 | 175 | // create and compiler fragment shader 176 | fragment2_shader = glCreateShader(GL_FRAGMENT_SHADER); 177 | source = fragment2_source.c_str(); 178 | length = fragment2_source.size(); 179 | glShaderSource(fragment2_shader, 1, &source, &length); 180 | glCompileShader(fragment2_shader); 181 | if(!check_shader_compile_status(fragment2_shader)) { 182 | glfwDestroyWindow(window); 183 | glfwTerminate(); 184 | return 1; 185 | } 186 | 187 | // create program 188 | shader1_program = glCreateProgram(); 189 | 190 | // attach shaders 191 | glAttachShader(shader1_program, vertex_shader); 192 | glAttachShader(shader1_program, fragment1_shader); 193 | 194 | // link the program and check for errors 195 | glLinkProgram(shader1_program); 196 | check_program_link_status(shader1_program); 197 | 198 | // get texture uniform location 199 | GLint image_size_location1 = glGetUniformLocation(shader1_program, "image_size"); 200 | GLint image_location1 = glGetUniformLocation(shader1_program, "image"); 201 | GLint dt_location1 = glGetUniformLocation(shader1_program, "dt"); 202 | 203 | 204 | // create program 205 | shader2_program = glCreateProgram(); 206 | 207 | // attach shaders 208 | glAttachShader(shader2_program, vertex_shader); 209 | glAttachShader(shader2_program, fragment2_shader); 210 | 211 | // link the program and check for errors 212 | glLinkProgram(shader2_program); 213 | check_program_link_status(shader2_program); 214 | 215 | // get texture uniform location 216 | GLint image_size_location2 = glGetUniformLocation(shader2_program, "image_size"); 217 | GLint image_location2 = glGetUniformLocation(shader2_program, "image"); 218 | GLint t_location2 = glGetUniformLocation(shader2_program, "t"); 219 | GLint dt_location2 = glGetUniformLocation(shader2_program, "dt"); 220 | 221 | // vao and vbo handle 222 | GLuint vao, vbo, ibo; 223 | 224 | // generate and bind the vao 225 | glGenVertexArrays(1, &vao); 226 | glBindVertexArray(vao); 227 | 228 | // generate and bind the vertex buffer object 229 | glGenBuffers(1, &vbo); 230 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 231 | 232 | // data for a fullscreen quad 233 | GLfloat vertexData[] = { 234 | // X Y Z 235 | 1.0f, 1.0f, 0.0f, // vertex 0 236 | -1.0f, 1.0f, 0.0f, // vertex 1 237 | 1.0f,-1.0f, 0.0f, // vertex 2 238 | -1.0f,-1.0f, 0.0f, // vertex 3 239 | }; // 4 vertices with 3 components (floats) each 240 | 241 | // fill with data 242 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*3, vertexData, GL_STATIC_DRAW); 243 | 244 | 245 | // set up generic attrib pointers 246 | glEnableVertexAttribArray(0); 247 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 248 | 249 | 250 | // generate and bind the index buffer object 251 | glGenBuffers(1, &ibo); 252 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 253 | 254 | GLuint indexData[] = { 255 | 0,1,2, // first triangle 256 | 2,1,3, // second triangle 257 | }; 258 | 259 | // fill with data 260 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); 261 | 262 | // texture handle 263 | GLuint texture; 264 | 265 | // generate texture 266 | glGenTextures(1, &texture); 267 | 268 | // bind the texture 269 | glBindTexture(GL_TEXTURE_2D, texture); 270 | 271 | // create some image data 272 | std::vector image(4*width*height); 273 | for(int j = 0;j20) t = 0; 301 | 302 | // clear first 303 | glClear(GL_COLOR_BUFFER_BIT); 304 | 305 | glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); 306 | 307 | // bind the vao 308 | glBindVertexArray(vao); 309 | 310 | int substeps = 5; 311 | 312 | glUseProgram(shader1_program); 313 | 314 | glUniform2i(image_size_location1, width, height); 315 | glUniform1i(image_location1, 0); 316 | glUniform1f(dt_location1, 50*dt/substeps); 317 | 318 | glUseProgram(shader2_program); 319 | 320 | glUniform2i(image_size_location2, width, height); 321 | glUniform1i(image_location2, 0); 322 | glUniform1f(dt_location2, 50*dt/substeps); 323 | 324 | glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 325 | int i = 0; 326 | for(;i 11 | #include 12 | 13 | //glm is used to create perspective and transform matrices 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | // helper to check and display for shader compiler errors 26 | bool check_shader_compile_status(GLuint obj) { 27 | GLint status; 28 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 29 | if(status == GL_FALSE) { 30 | GLint length; 31 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 32 | std::vector log(length); 33 | glGetShaderInfoLog(obj, length, &length, &log[0]); 34 | std::cerr << &log[0]; 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | // helper to check and display for shader linker error 41 | bool check_program_link_status(GLuint obj) { 42 | GLint status; 43 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 44 | if(status == GL_FALSE) { 45 | GLint length; 46 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 47 | std::vector log(length); 48 | glGetProgramInfoLog(obj, length, &length, &log[0]); 49 | std::cerr << &log[0]; 50 | return false; 51 | } 52 | return true; 53 | } 54 | 55 | int main() { 56 | int width = 640; 57 | int height = 480; 58 | 59 | if(glfwInit() == GL_FALSE) { 60 | std::cerr << "failed to init GLFW" << std::endl; 61 | return 1; 62 | } 63 | 64 | // select opengl version 65 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 66 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 67 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 68 | 69 | // create a window 70 | GLFWwindow *window; 71 | if((window = glfwCreateWindow(width, height, "09transform_feedback", 0, 0)) == 0) { 72 | std::cerr << "failed to open window" << std::endl; 73 | glfwTerminate(); 74 | return 1; 75 | } 76 | 77 | glfwMakeContextCurrent(window); 78 | 79 | if(glxwInit()) { 80 | std::cerr << "failed to init GL3W" << std::endl; 81 | glfwDestroyWindow(window); 82 | glfwTerminate(); 83 | return 1; 84 | } 85 | 86 | // the vertex shader simply passes through data 87 | std::string vertex_source = 88 | "#version 330\n" 89 | "layout(location = 0) in vec4 vposition;\n" 90 | "void main() {\n" 91 | " gl_Position = vposition;\n" 92 | "}\n"; 93 | 94 | // the geometry shader creates the billboard quads 95 | std::string geometry_source = 96 | "#version 330\n" 97 | "uniform mat4 View;\n" 98 | "uniform mat4 Projection;\n" 99 | "layout (points) in;\n" 100 | "layout (triangle_strip, max_vertices = 4) out;\n" 101 | "out vec2 txcoord;\n" 102 | "void main() {\n" 103 | " vec4 pos = View*gl_in[0].gl_Position;\n" 104 | " txcoord = vec2(-1,-1);\n" 105 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 106 | " EmitVertex();\n" 107 | " txcoord = vec2( 1,-1);\n" 108 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 109 | " EmitVertex();\n" 110 | " txcoord = vec2(-1, 1);\n" 111 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 112 | " EmitVertex();\n" 113 | " txcoord = vec2( 1, 1);\n" 114 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 115 | " EmitVertex();\n" 116 | "}\n"; 117 | 118 | // the fragment shader creates a bell like radial color distribution 119 | std::string fragment_source = 120 | "#version 330\n" 121 | "in vec2 txcoord;\n" 122 | "layout(location = 0) out vec4 FragColor;\n" 123 | "void main() {\n" 124 | " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" 125 | " FragColor = s*vec4(0.3,0.3,1.0,1);\n" 126 | "}\n"; 127 | 128 | // program and shader handles 129 | GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; 130 | 131 | // we need these to properly pass the strings 132 | const char *source; 133 | int length; 134 | 135 | // create and compiler vertex shader 136 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 137 | source = vertex_source.c_str(); 138 | length = vertex_source.size(); 139 | glShaderSource(vertex_shader, 1, &source, &length); 140 | glCompileShader(vertex_shader); 141 | if(!check_shader_compile_status(vertex_shader)) { 142 | glfwDestroyWindow(window); 143 | glfwTerminate(); 144 | return 1; 145 | } 146 | 147 | // create and compiler geometry shader 148 | geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); 149 | source = geometry_source.c_str(); 150 | length = geometry_source.size(); 151 | glShaderSource(geometry_shader, 1, &source, &length); 152 | glCompileShader(geometry_shader); 153 | if(!check_shader_compile_status(geometry_shader)) { 154 | glfwDestroyWindow(window); 155 | glfwTerminate(); 156 | return 1; 157 | } 158 | 159 | // create and compiler fragment shader 160 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 161 | source = fragment_source.c_str(); 162 | length = fragment_source.size(); 163 | glShaderSource(fragment_shader, 1, &source, &length); 164 | glCompileShader(fragment_shader); 165 | if(!check_shader_compile_status(fragment_shader)) { 166 | glfwDestroyWindow(window); 167 | glfwTerminate(); 168 | return 1; 169 | } 170 | 171 | // create program 172 | shader_program = glCreateProgram(); 173 | 174 | // attach shaders 175 | glAttachShader(shader_program, vertex_shader); 176 | glAttachShader(shader_program, geometry_shader); 177 | glAttachShader(shader_program, fragment_shader); 178 | 179 | // link the program and check for errors 180 | glLinkProgram(shader_program); 181 | check_program_link_status(shader_program); 182 | 183 | // obtain location of projection uniform 184 | GLint View_location = glGetUniformLocation(shader_program, "View"); 185 | GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); 186 | 187 | 188 | 189 | // the transform feedback shader only has a vertex shader 190 | std::string transform_vertex_source = 191 | "#version 330\n" 192 | "uniform vec3 center[3];\n" 193 | "uniform float radius[3];\n" 194 | "uniform vec3 g;\n" 195 | "uniform float dt;\n" 196 | "uniform float bounce;\n" 197 | "uniform int seed;\n" 198 | "layout(location = 0) in vec3 inposition;\n" 199 | "layout(location = 1) in vec3 invelocity;\n" 200 | "out vec3 outposition;\n" 201 | "out vec3 outvelocity;\n" 202 | 203 | "float hash(int x) {\n" 204 | " x = x*1235167 + gl_VertexID*948737 + seed*9284365;\n" 205 | " x = (x >> 13) ^ x;\n" 206 | " return ((x * (x * x * 60493 + 19990303) + 1376312589) & 0x7fffffff)/float(0x7fffffff-1);\n" 207 | "}\n" 208 | 209 | "void main() {\n" 210 | " outvelocity = invelocity;\n" 211 | " for(int j = 0;j<3;++j) {\n" 212 | " vec3 diff = inposition-center[j];\n" 213 | " float dist = length(diff);\n" 214 | " float vdot = dot(diff, invelocity);\n" 215 | " if(dist vertexData(2*particles); 268 | for(int i = 0;i(center)); 344 | glUniform1fv(radius_location, 3, reinterpret_cast(radius)); 345 | glUniform3fv(g_location, 1, glm::value_ptr(g)); 346 | glUniform1f(dt_location, dt); 347 | glUniform1f(bounce_location, bounce); 348 | glUniform1i(seed_location, std::rand()); 349 | 350 | // bind the current vao 351 | glBindVertexArray(vao[(current_buffer+1)%buffercount]); 352 | 353 | // bind transform feedback target 354 | glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, vbo[current_buffer]); 355 | 356 | glEnable(GL_RASTERIZER_DISCARD); 357 | 358 | // perform transform feedback 359 | glBeginTransformFeedback(GL_POINTS); 360 | glDrawArrays(GL_POINTS, 0, particles); 361 | glEndTransformFeedback(); 362 | 363 | glDisable(GL_RASTERIZER_DISCARD); 364 | 365 | // clear first 366 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 367 | 368 | // use the shader program 369 | glUseProgram(shader_program); 370 | 371 | // calculate ViewProjection matrix 372 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 373 | 374 | // translate the world/view position 375 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); 376 | 377 | // make the camera rotate around the origin 378 | View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); 379 | View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); 380 | 381 | // set the uniform 382 | glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); 383 | glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); 384 | 385 | // bind the current vao 386 | glBindVertexArray(vao[current_buffer]); 387 | 388 | // draw 389 | glDrawArrays(GL_POINTS, 0, particles); 390 | 391 | // check for errors 392 | GLenum error = glGetError(); 393 | if(error != GL_NO_ERROR) { 394 | std::cerr << error << std::endl; 395 | break; 396 | } 397 | 398 | // finally swap buffers 399 | glfwSwapBuffers(window); 400 | 401 | // advance buffer index 402 | current_buffer = (current_buffer + 1) % buffercount; 403 | } 404 | 405 | // delete the created objects 406 | 407 | glDeleteVertexArrays(buffercount, vao); 408 | glDeleteBuffers(buffercount, vbo); 409 | 410 | glDetachShader(shader_program, vertex_shader); 411 | glDetachShader(shader_program, geometry_shader); 412 | glDetachShader(shader_program, fragment_shader); 413 | glDeleteShader(vertex_shader); 414 | glDeleteShader(geometry_shader); 415 | glDeleteShader(fragment_shader); 416 | glDeleteProgram(shader_program); 417 | 418 | glDetachShader(transform_shader_program, transform_vertex_shader); 419 | glDeleteShader(transform_vertex_shader); 420 | glDeleteProgram(transform_shader_program); 421 | 422 | glfwDestroyWindow(window); 423 | glfwTerminate(); 424 | return 0; 425 | } 426 | 427 | -------------------------------------------------------------------------------- /11tesselation.cpp: -------------------------------------------------------------------------------- 1 | /* OpenGL example code - Tesselation 2 | * 3 | * This example shows the usage of tesselation for terrain LOD. 4 | * The terrain is given as a texture of 3d samples (generalized 5 | * heightfield) and gets rendered without use of a vbo/vao. Instead 6 | * sample coordinates are generated from InstanceID and VertexID. 7 | * Tessellation is used to dynamically change the amount of vertices 8 | * depending on distance from the viewer. 9 | * This example requires at least OpenGL 4.0 10 | * 11 | * Autor: Jakob Progsch 12 | */ 13 | 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | // helper to check and display for shader compiler errors 28 | bool check_shader_compile_status(GLuint obj) { 29 | GLint status; 30 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 31 | if(status == GL_FALSE) 32 | { 33 | GLint length; 34 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 35 | std::vector log(length); 36 | glGetShaderInfoLog(obj, length, &length, &log[0]); 37 | std::cerr << &log[0]; 38 | return false; 39 | } 40 | return true; 41 | } 42 | 43 | // helper to check and display for shader linker error 44 | bool check_program_link_status(GLuint obj) { 45 | GLint status; 46 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 47 | if(status == GL_FALSE) 48 | { 49 | GLint length; 50 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 51 | std::vector log(length); 52 | glGetProgramInfoLog(obj, length, &length, &log[0]); 53 | std::cerr << &log[0]; 54 | return false; 55 | } 56 | return true; 57 | } 58 | 59 | int main() { 60 | int width = 640; 61 | int height = 480; 62 | 63 | if(glfwInit() == GL_FALSE) { 64 | std::cerr << "failed to init GLFW" << std::endl; 65 | return 1; 66 | } 67 | 68 | // select opengl version 69 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 70 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 71 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); 72 | 73 | // create a window 74 | GLFWwindow *window; 75 | if((window = glfwCreateWindow(width, height, "11tesselation", 0, 0)) == 0) { 76 | std::cerr << "failed to open window" << std::endl; 77 | glfwTerminate(); 78 | return 1; 79 | } 80 | 81 | glfwMakeContextCurrent(window); 82 | 83 | if(glxwInit()) { 84 | std::cerr << "failed to init GL3W" << std::endl; 85 | glfwDestroyWindow(window); 86 | glfwTerminate(); 87 | return 1; 88 | } 89 | 90 | GLuint vao; 91 | glGenVertexArrays(1, &vao); 92 | glBindVertexArray(vao); 93 | 94 | // shader source code 95 | std::string vertex_source = 96 | "#version 400\n" 97 | "uniform uint width;\n" 98 | "uniform uint height;\n" 99 | "out vec4 tposition;\n" 100 | "const vec2 quad_offsets[6] = vec2[](\n" 101 | " vec2(0,0),vec2(1,0),vec2(1,1),\n" 102 | " vec2(0,0),vec2(1,1),vec2(0,1)\n" 103 | ");\n" 104 | "void main() {\n" 105 | " vec2 base = vec2(gl_InstanceID/width, gl_InstanceID%width);\n" 106 | " vec2 offset = quad_offsets[gl_VertexID];\n" 107 | " vec2 pos = (base + offset)/vec2(width+1, height+1);\n" 108 | " tposition = vec4(pos,0,1);\n" 109 | "}\n"; 110 | 111 | std::string tess_control_source = 112 | "#version 400\n" 113 | "uniform vec3 ViewPosition;\n" 114 | "uniform float tess_scale;\n" 115 | "layout(vertices = 3) out;\n" 116 | "in vec4 tposition[];\n" 117 | "out vec4 tcposition[];\n" 118 | "void main()\n" 119 | "{\n" 120 | " tcposition[gl_InvocationID] = tposition[gl_InvocationID];\n" 121 | " if(gl_InvocationID == 0) {\n" 122 | " vec3 terrainpos = ViewPosition;\n" 123 | " terrainpos.z -= clamp(terrainpos.z,-0.1, 0.1);\n" 124 | " vec4 center = (tposition[1]+tposition[2])/2.0;\n" 125 | " gl_TessLevelOuter[0] = min(6.0, 1+tess_scale*0.5/distance(center.xyz, terrainpos));\n" 126 | " center = (tposition[2]+tposition[0])/2.0;\n" 127 | " gl_TessLevelOuter[1] = min(6.0, 1+tess_scale*0.5/distance(center.xyz, terrainpos));\n" 128 | " center = (tposition[0]+tposition[1])/2.0;\n" 129 | " gl_TessLevelOuter[2] = min(6.0, 1+tess_scale*0.5/distance(center.xyz, terrainpos));\n" 130 | " center = (tposition[0]+tposition[1]+tposition[2])/3.0;\n" 131 | " gl_TessLevelInner[0] = min(7.0, 1+tess_scale*0.7/distance(center.xyz, terrainpos));\n" 132 | " }\n" 133 | "}\n"; 134 | 135 | std::string tess_eval_source = 136 | "#version 400\n" 137 | "uniform mat4 ViewProjection;\n" 138 | "uniform sampler2D displacement;\n" 139 | "layout(triangles, equal_spacing, cw) in;\n" 140 | "in vec4 tcposition[];\n" 141 | "out vec2 tecoord;\n" 142 | "out vec4 teposition;\n" 143 | "void main()\n" 144 | "{\n" 145 | " teposition = gl_TessCoord.x * tcposition[0];\n" 146 | " teposition += gl_TessCoord.y * tcposition[1];\n" 147 | " teposition += gl_TessCoord.z * tcposition[2];\n" 148 | " tecoord = teposition.xy;\n" 149 | " vec3 offset = texture(displacement, tecoord).xyz;\n" 150 | " teposition.xyz = offset;\n" 151 | " gl_Position = ViewProjection*teposition;\n" 152 | "}\n"; 153 | 154 | std::string fragment_source = 155 | "#version 400\n" 156 | "uniform vec3 ViewPosition;\n" 157 | "uniform sampler2D displacement;\n" 158 | "in vec4 teposition;\n" 159 | "in vec2 tecoord;\n" 160 | "layout(location = 0) out vec4 FragColor;\n" 161 | "void main() {\n" 162 | " vec3 x = textureOffset(displacement, tecoord, ivec2(0,0)).xyz;\n" 163 | " vec3 t0 = x-textureOffset(displacement, tecoord, ivec2(1,0)).xyz;\n" 164 | " vec3 t1 = x-textureOffset(displacement, tecoord, ivec2(0,1)).xyz;\n" 165 | " vec3 normal = (gl_FrontFacing?1:-1)*normalize(cross(t0, t1));\n" 166 | " vec3 light = normalize(vec3(2, -1, 3));\n" 167 | " vec3 reflected = reflect(normalize(ViewPosition-teposition.xyz), normal);\n" 168 | " float ambient = 0.1;\n" 169 | " float diffuse = max(0,dot(normal, light));\n" 170 | " float specular = pow(max(0,dot(reflected, light)), 64);\n" 171 | " FragColor = vec4(vec3(ambient + 0.5*diffuse + 0.4*specular), 1);\n" 172 | "}\n"; 173 | 174 | // program and shader handles 175 | GLuint shader_program, vertex_shader, tess_control_shader, tess_eval_shader, fragment_shader; 176 | 177 | // we need these to properly pass the strings 178 | const char *source; 179 | int length; 180 | 181 | // create and compiler vertex shader 182 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 183 | source = vertex_source.c_str(); 184 | length = vertex_source.size(); 185 | glShaderSource(vertex_shader, 1, &source, &length); 186 | glCompileShader(vertex_shader); 187 | if(!check_shader_compile_status(vertex_shader)) { 188 | glfwDestroyWindow(window); 189 | glfwTerminate(); 190 | return 1; 191 | } 192 | 193 | // create and compiler tesselation control shader 194 | tess_control_shader = glCreateShader(GL_TESS_CONTROL_SHADER); 195 | source = tess_control_source.c_str(); 196 | length = tess_control_source.size(); 197 | glShaderSource(tess_control_shader, 1, &source, &length); 198 | glCompileShader(tess_control_shader); 199 | if(!check_shader_compile_status(tess_control_shader)) { 200 | glfwDestroyWindow(window); 201 | glfwTerminate(); 202 | return 1; 203 | } 204 | 205 | // create and compiler tesselation evaluation shader 206 | tess_eval_shader = glCreateShader(GL_TESS_EVALUATION_SHADER); 207 | source = tess_eval_source.c_str(); 208 | length = tess_eval_source.size(); 209 | glShaderSource(tess_eval_shader, 1, &source, &length); 210 | glCompileShader(tess_eval_shader); 211 | if(!check_shader_compile_status(tess_eval_shader)) { 212 | glfwDestroyWindow(window); 213 | glfwTerminate(); 214 | return 1; 215 | } 216 | 217 | // create and compiler fragment shader 218 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 219 | source = fragment_source.c_str(); 220 | length = fragment_source.size(); 221 | glShaderSource(fragment_shader, 1, &source, &length); 222 | glCompileShader(fragment_shader); 223 | if(!check_shader_compile_status(fragment_shader)) { 224 | glfwDestroyWindow(window); 225 | glfwTerminate(); 226 | return 1; 227 | } 228 | 229 | // create program 230 | shader_program = glCreateProgram(); 231 | 232 | // attach shaders 233 | glAttachShader(shader_program, vertex_shader); 234 | glAttachShader(shader_program, tess_control_shader); 235 | glAttachShader(shader_program, tess_eval_shader); 236 | glAttachShader(shader_program, fragment_shader); 237 | 238 | // link the program and check for errors 239 | glLinkProgram(shader_program); 240 | check_program_link_status(shader_program); 241 | 242 | GLint width_Location = glGetUniformLocation(shader_program, "width"); 243 | GLint height_Location = glGetUniformLocation(shader_program, "height"); 244 | GLint ViewProjection_Location = glGetUniformLocation(shader_program, "ViewProjection"); 245 | GLint ViewPosition_Location = glGetUniformLocation(shader_program, "ViewPosition"); 246 | GLint displacement_Location = glGetUniformLocation(shader_program, "displacement"); 247 | GLint tess_scale_Location = glGetUniformLocation(shader_program, "tess_scale"); 248 | 249 | 250 | int terrainwidth = 1024, terrainheight = 1024; 251 | std::vector displacementData(terrainwidth*terrainheight); 252 | 253 | glm::vec3 layernorm = glm::normalize(glm::vec3(0.1f,0.3f,1.0f)); 254 | glm::vec3 layerdir(0,0,1); 255 | layerdir -= layernorm*glm::dot(layernorm, layerdir); 256 | layerdir = glm::normalize(layerdir); 257 | 258 | for(int y = 0;y 9 | #include 10 | 11 | //glm is used to create perspective and transform matrices 12 | #define GLM_SWIZZLE 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | // helper to check and display for shader compiler errors 26 | bool check_shader_compile_status(GLuint obj) { 27 | GLint status; 28 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 29 | if(status == GL_FALSE) { 30 | GLint length; 31 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 32 | std::vector log(length); 33 | glGetShaderInfoLog(obj, length, &length, &log[0]); 34 | std::cerr << &log[0]; 35 | return false; 36 | } 37 | return true; 38 | } 39 | 40 | // helper to check and display for shader linker error 41 | bool check_program_link_status(GLuint obj) { 42 | GLint status; 43 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 44 | if(status == GL_FALSE) { 45 | GLint length; 46 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 47 | std::vector log(length); 48 | glGetProgramInfoLog(obj, length, &length, &log[0]); 49 | std::cerr << &log[0]; 50 | return false; 51 | } 52 | return true; 53 | } 54 | 55 | int main() { 56 | int width = 640; 57 | int height = 480; 58 | 59 | if(glfwInit() == GL_FALSE) { 60 | std::cerr << "failed to init GLFW" << std::endl; 61 | return 1; 62 | } 63 | 64 | // select opengl version 65 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 66 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); 67 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 68 | 69 | // create a window 70 | GLFWwindow *window; 71 | if((window = glfwCreateWindow(width, height, "13compute_shader_nbody", 0, 0)) == 0) { 72 | std::cerr << "failed to open window" << std::endl; 73 | glfwTerminate(); 74 | return 1; 75 | } 76 | 77 | glfwMakeContextCurrent(window); 78 | 79 | if(glxwInit()) { 80 | std::cerr << "failed to init GL3W" << std::endl; 81 | glfwDestroyWindow(window); 82 | glfwTerminate(); 83 | return 1; 84 | } 85 | 86 | // shader source code 87 | 88 | // the vertex shader simply passes through data 89 | std::string vertex_source = 90 | "#version 430\n" 91 | "layout(location = 0) in vec4 vposition;\n" 92 | "void main() {\n" 93 | " gl_Position = vposition;\n" 94 | "}\n"; 95 | 96 | // the geometry shader creates the billboard quads 97 | std::string geometry_source = 98 | "#version 430\n" 99 | "layout(location = 0) uniform mat4 View;\n" 100 | "layout(location = 1) uniform mat4 Projection;\n" 101 | "layout (points) in;\n" 102 | "layout (triangle_strip, max_vertices = 4) out;\n" 103 | "out vec2 txcoord;\n" 104 | "void main() {\n" 105 | " vec4 pos = View*gl_in[0].gl_Position;\n" 106 | " txcoord = vec2(-1,-1);\n" 107 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 108 | " EmitVertex();\n" 109 | " txcoord = vec2( 1,-1);\n" 110 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 111 | " EmitVertex();\n" 112 | " txcoord = vec2(-1, 1);\n" 113 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 114 | " EmitVertex();\n" 115 | " txcoord = vec2( 1, 1);\n" 116 | " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" 117 | " EmitVertex();\n" 118 | "}\n"; 119 | 120 | // the fragment shader creates a bell like radial color distribution 121 | std::string fragment_source = 122 | "#version 330\n" 123 | "in vec2 txcoord;\n" 124 | "layout(location = 0) out vec4 FragColor;\n" 125 | "void main() {\n" 126 | " float s = (1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" 127 | " FragColor = s*vec4(0.3,0.3,1.0,1);\n" 128 | "}\n"; 129 | 130 | // program and shader handles 131 | GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; 132 | 133 | // we need these to properly pass the strings 134 | const char *source; 135 | int length; 136 | 137 | // create and compiler vertex shader 138 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 139 | source = vertex_source.c_str(); 140 | length = vertex_source.size(); 141 | glShaderSource(vertex_shader, 1, &source, &length); 142 | glCompileShader(vertex_shader); 143 | if(!check_shader_compile_status(vertex_shader)) { 144 | glfwDestroyWindow(window); 145 | glfwTerminate(); 146 | return 1; 147 | } 148 | 149 | // create and compiler geometry shader 150 | geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); 151 | source = geometry_source.c_str(); 152 | length = geometry_source.size(); 153 | glShaderSource(geometry_shader, 1, &source, &length); 154 | glCompileShader(geometry_shader); 155 | if(!check_shader_compile_status(geometry_shader)) { 156 | glfwDestroyWindow(window); 157 | glfwTerminate(); 158 | return 1; 159 | } 160 | 161 | // create and compiler fragment shader 162 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 163 | source = fragment_source.c_str(); 164 | length = fragment_source.size(); 165 | glShaderSource(fragment_shader, 1, &source, &length); 166 | glCompileShader(fragment_shader); 167 | if(!check_shader_compile_status(fragment_shader)) { 168 | glfwDestroyWindow(window); 169 | glfwTerminate(); 170 | return 1; 171 | } 172 | 173 | // create program 174 | shader_program = glCreateProgram(); 175 | 176 | // attach shaders 177 | glAttachShader(shader_program, vertex_shader); 178 | glAttachShader(shader_program, geometry_shader); 179 | glAttachShader(shader_program, fragment_shader); 180 | 181 | // link the program and check for errors 182 | glLinkProgram(shader_program); 183 | check_program_link_status(shader_program); 184 | 185 | // straight forward implementation of the nbody kernel 186 | std::string acceleration_source = 187 | "#version 430\n" 188 | "layout(local_size_x=256) in;\n" 189 | 190 | "layout(location = 0) uniform float dt;\n" 191 | "layout(std430, binding=0) buffer pblock { vec4 positions[]; };\n" 192 | "layout(std430, binding=1) buffer vblock { vec4 velocities[]; };\n" 193 | 194 | "void main() {\n" 195 | " int N = int(gl_NumWorkGroups.x*gl_WorkGroupSize.x);\n" 196 | " int index = int(gl_GlobalInvocationID);\n" 197 | 198 | " vec3 position = positions[index].xyz;\n" 199 | " vec3 velocity = velocities[index].xyz;\n" 200 | " vec3 acceleration = vec3(0,0,0);\n" 201 | " for(int i = 0;i positionData(particles); 340 | std::vector velocityData(particles); 341 | for(int i = 0;i 15 | #include 16 | 17 | //glm is used to create perspective and transform matrices 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // chunk data structure that contains the information required to 29 | // render and cull the chunks 30 | struct Chunk { 31 | GLuint vbo, ibo, vao; 32 | GLuint bounding_vbo, bounding_ibo, bounding_vao; 33 | GLuint query; 34 | int quadcount; 35 | glm::vec3 center; 36 | }; 37 | 38 | // predicate to allow sorting chunks by distance from a point 39 | class DistancePred { 40 | public: 41 | DistancePred(glm::vec3 p) : pos(p) { } 42 | bool operator()(const Chunk &a, const Chunk &b) { 43 | return glm::distance(pos, a.center) < glm::distance(pos, b.center); 44 | } 45 | private: 46 | const glm::vec3 pos; 47 | }; 48 | 49 | // world function that defines the voxel data 50 | float world_function(glm::vec3 pos) { 51 | return glm::perlin(0.1f*(pos+glm::vec3(100,100,100))); 52 | } 53 | 54 | 55 | // helper to check and display for shader compiler errors 56 | bool check_shader_compile_status(GLuint obj) { 57 | GLint status; 58 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 59 | if(status == GL_FALSE) { 60 | GLint length; 61 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 62 | std::vector log(length); 63 | glGetShaderInfoLog(obj, length, &length, &log[0]); 64 | std::cerr << &log[0]; 65 | return false; 66 | } 67 | return true; 68 | } 69 | 70 | // helper to check and display for shader linker error 71 | bool check_program_link_status(GLuint obj) { 72 | GLint status; 73 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 74 | if(status == GL_FALSE) { 75 | GLint length; 76 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 77 | std::vector log(length); 78 | glGetProgramInfoLog(obj, length, &length, &log[0]); 79 | std::cerr << &log[0]; 80 | return false; 81 | } 82 | return true; 83 | } 84 | 85 | int main() { 86 | int width = 640; 87 | int height = 480; 88 | 89 | if(glfwInit() == GL_FALSE) { 90 | std::cerr << "failed to init GLFW" << std::endl; 91 | return 1; 92 | } 93 | 94 | // select opengl version 95 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 96 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 97 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 98 | 99 | // create a window 100 | GLFWwindow *window; 101 | if((window = glfwCreateWindow(width, height, "10queries_conditional_render", 0, 0)) == 0) { 102 | std::cerr << "failed to open window" << std::endl; 103 | glfwTerminate(); 104 | return 1; 105 | } 106 | 107 | glfwMakeContextCurrent(window); 108 | 109 | if(glxwInit()) { 110 | std::cerr << "failed to init GL3W" << std::endl; 111 | glfwDestroyWindow(window); 112 | glfwTerminate(); 113 | return 1; 114 | } 115 | 116 | // draw shader 117 | std::string vertex_source = 118 | "#version 330\n" 119 | "uniform mat4 ViewProjection;\n" 120 | "layout(location = 0) in vec4 vposition;\n" 121 | "layout(location = 1) in vec3 normal;\n" 122 | "out vec4 fcolor;\n" 123 | "void main() {\n" 124 | " float brightness = dot(normal,normalize(vec3(1,2,3)));\n" 125 | " brightness = 0.3+((brightness>0)?0.7*brightness:0.3*brightness);\n" 126 | " fcolor = vec4(brightness,brightness,brightness,1);\n" 127 | " gl_Position = ViewProjection*vposition;\n" 128 | "}\n"; 129 | 130 | std::string fragment_source = 131 | "#version 330\n" 132 | "in vec4 fcolor;\n" 133 | "layout(location = 0) out vec4 FragColor;\n" 134 | "void main() {\n" 135 | " FragColor = abs(fcolor);\n" 136 | "}\n"; 137 | 138 | // program and shader handles 139 | GLuint shader_program, vertex_shader, fragment_shader; 140 | 141 | // we need these to properly pass the strings 142 | const char *source; 143 | int length; 144 | 145 | // create and compiler vertex shader 146 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 147 | source = vertex_source.c_str(); 148 | length = vertex_source.size(); 149 | glShaderSource(vertex_shader, 1, &source, &length); 150 | glCompileShader(vertex_shader); 151 | if(!check_shader_compile_status(vertex_shader)) { 152 | glfwDestroyWindow(window); 153 | glfwTerminate(); 154 | return 1; 155 | } 156 | 157 | // create and compiler fragment shader 158 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 159 | source = fragment_source.c_str(); 160 | length = fragment_source.size(); 161 | glShaderSource(fragment_shader, 1, &source, &length); 162 | glCompileShader(fragment_shader); 163 | if(!check_shader_compile_status(fragment_shader)) { 164 | glfwDestroyWindow(window); 165 | glfwTerminate(); 166 | return 1; 167 | } 168 | 169 | // create program 170 | shader_program = glCreateProgram(); 171 | 172 | // attach shaders 173 | glAttachShader(shader_program, vertex_shader); 174 | glAttachShader(shader_program, fragment_shader); 175 | 176 | // link the program and check for errors 177 | glLinkProgram(shader_program); 178 | check_program_link_status(shader_program); 179 | 180 | // obtain location of projection uniform 181 | GLint DrawViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); 182 | 183 | 184 | // trivial shader for occlusion queries 185 | std::string query_vertex_source = 186 | "#version 330\n" 187 | "uniform mat4 ViewProjection;\n" 188 | "layout(location = 0) in vec4 vposition;\n" 189 | "void main() {\n" 190 | " gl_Position = ViewProjection*vposition;\n" 191 | "}\n"; 192 | 193 | std::string query_fragment_source = 194 | "#version 330\n" 195 | "void main() {\n" 196 | "}\n"; 197 | 198 | // program and shader handles 199 | GLuint query_shader_program, query_vertex_shader, query_fragment_shader; 200 | 201 | // create and compiler vertex shader 202 | query_vertex_shader = glCreateShader(GL_VERTEX_SHADER); 203 | source = query_vertex_source.c_str(); 204 | length = query_vertex_source.size(); 205 | glShaderSource(query_vertex_shader, 1, &source, &length); 206 | glCompileShader(query_vertex_shader); 207 | if(!check_shader_compile_status(query_vertex_shader)) { 208 | glfwDestroyWindow(window); 209 | glfwTerminate(); 210 | return 1; 211 | } 212 | 213 | // create and compiler fragment shader 214 | query_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 215 | source = query_fragment_source.c_str(); 216 | length = query_fragment_source.size(); 217 | glShaderSource(query_fragment_shader, 1, &source, &length); 218 | glCompileShader(query_fragment_shader); 219 | if(!check_shader_compile_status(query_fragment_shader)) { 220 | glfwDestroyWindow(window); 221 | glfwTerminate(); 222 | return 1; 223 | } 224 | 225 | // create program 226 | query_shader_program = glCreateProgram(); 227 | 228 | // attach shaders 229 | glAttachShader(query_shader_program, query_vertex_shader); 230 | glAttachShader(query_shader_program, query_fragment_shader); 231 | 232 | // link the program and check for errors 233 | glLinkProgram(query_shader_program); 234 | check_program_link_status(query_shader_program); 235 | 236 | // obtain location of projection uniform 237 | GLint QueryViewProjection_location = glGetUniformLocation(query_shader_program, "ViewProjection"); 238 | 239 | // chunk container and chunk parameters 240 | std::vector chunks; 241 | int chunkrange = 4; 242 | int chunksize = 32; 243 | 244 | // chunk extraction 245 | std::cout << "generating chunks, this may take a while." << std::endl; 246 | 247 | // iterate over all chunks we want to extract 248 | for(int i = -chunkrange;i vertexData; 264 | glm::vec3 offset = static_cast(chunksize) * glm::vec3(i,j,k); 265 | float threshold = 0.0f; 266 | // iterate over all blocks within the chunk 267 | for(int x = 0;x=threshold) { 274 | vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1)); 275 | vertexData.push_back(glm::vec3( 1, 0, 0)); 276 | vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1)); 277 | vertexData.push_back(glm::vec3( 1, 0, 0)); 278 | vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1)); 279 | vertexData.push_back(glm::vec3( 1, 0, 0)); 280 | vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1)); 281 | vertexData.push_back(glm::vec3( 1, 0, 0)); 282 | } 283 | if(world_function(pos+glm::vec3(0,1,0))>=threshold) { 284 | vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1)); 285 | vertexData.push_back(glm::vec3( 0, 1, 0)); 286 | vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1)); 287 | vertexData.push_back(glm::vec3( 0, 1, 0)); 288 | vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1)); 289 | vertexData.push_back(glm::vec3( 0, 1, 0)); 290 | vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1)); 291 | vertexData.push_back(glm::vec3( 0, 1, 0)); 292 | } 293 | if(world_function(pos+glm::vec3(0,0,1))>=threshold) { 294 | vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1)); 295 | vertexData.push_back(glm::vec3( 0, 0, 1)); 296 | vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1)); 297 | vertexData.push_back(glm::vec3( 0, 0, 1)); 298 | vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1)); 299 | vertexData.push_back(glm::vec3( 0, 0, 1)); 300 | vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1)); 301 | vertexData.push_back(glm::vec3( 0, 0, 1)); 302 | } 303 | if(world_function(pos-glm::vec3(1,0,0))>=threshold) { 304 | vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1)); 305 | vertexData.push_back(glm::vec3(-1, 0, 0)); 306 | vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1)); 307 | vertexData.push_back(glm::vec3(-1, 0, 0)); 308 | vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1)); 309 | vertexData.push_back(glm::vec3(-1, 0, 0)); 310 | vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1)); 311 | vertexData.push_back(glm::vec3(-1, 0, 0)); 312 | } 313 | if(world_function(pos-glm::vec3(0,1,0))>=threshold) { 314 | vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1)); 315 | vertexData.push_back(glm::vec3( 0,-1, 0)); 316 | vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1)); 317 | vertexData.push_back(glm::vec3( 0,-1, 0)); 318 | vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1)); 319 | vertexData.push_back(glm::vec3( 0,-1, 0)); 320 | vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1)); 321 | vertexData.push_back(glm::vec3( 0,-1, 0)); 322 | } 323 | if(world_function(pos-glm::vec3(0,0,1))>=threshold) { 324 | vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1)); 325 | vertexData.push_back(glm::vec3( 0, 0,-1)); 326 | vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1)); 327 | vertexData.push_back(glm::vec3( 0, 0,-1)); 328 | vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1)); 329 | vertexData.push_back(glm::vec3( 0, 0,-1)); 330 | vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1)); 331 | vertexData.push_back(glm::vec3( 0, 0,-1)); 332 | } 333 | } 334 | } 335 | } 336 | } 337 | // upload 338 | glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW); 339 | 340 | // set up generic attrib pointers 341 | glEnableVertexAttribArray(0); 342 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 343 | 344 | glEnableVertexAttribArray(1); 345 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 346 | 347 | // generate and bind the index buffer object 348 | glGenBuffers(1, &chunk.ibo); 349 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.ibo); 350 | 351 | chunk.quadcount = vertexData.size()/8; 352 | std::vector indexData(6*chunk.quadcount); 353 | for(int i = 0;i chunksize) && 562 | (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize)) 563 | continue; 564 | 565 | // begin occlusion query 566 | glBeginQuery(GL_ANY_SAMPLES_PASSED, chunks[j].query); 567 | 568 | // draw bounding box 569 | glBindVertexArray(chunks[j].bounding_vao); 570 | glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0); 571 | 572 | // end occlusion query 573 | glEndQuery(GL_ANY_SAMPLES_PASSED); 574 | } 575 | j = i; 576 | } 577 | 578 | // render the current slice 579 | glEnable(GL_CULL_FACE); 580 | 581 | // turn rendering back on 582 | glDepthMask(GL_TRUE); 583 | glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 584 | glUseProgram(shader_program); 585 | for(;j chunksize) && 589 | (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize)) 590 | continue; 591 | 592 | // begin conditional render 593 | if(occlusion_cull) 594 | glBeginConditionalRender(chunks[j].query, GL_QUERY_BY_REGION_WAIT); 595 | 596 | // draw chunk 597 | glBindVertexArray(chunks[j].vao); 598 | glDrawElements(GL_TRIANGLES, 6*chunks[j].quadcount, GL_UNSIGNED_INT, 0); 599 | 600 | // end conditional render 601 | if(occlusion_cull) 602 | glEndConditionalRender(); 603 | } 604 | i = j; 605 | maxdist += 2*chunksize; 606 | } 607 | 608 | // end timer query 609 | glEndQuery(GL_TIME_ELAPSED); 610 | 611 | // display timer query results from querycount frames before 612 | if(GL_TRUE == glIsQuery(queries[(current_query+1)%querycount])) { 613 | GLuint64 result; 614 | glGetQueryObjectui64v(queries[(current_query+1)%querycount], GL_QUERY_RESULT, &result); 615 | std::cout << result*1.e-6 << " ms/frame" << std::endl; 616 | } 617 | // advance query counter 618 | current_query = (current_query + 1)%querycount; 619 | 620 | // check for errors 621 | GLenum error = glGetError(); 622 | if(error != GL_NO_ERROR) { 623 | std::cerr << error << std::endl; 624 | break; 625 | } 626 | 627 | // finally swap buffers 628 | glfwSwapBuffers(window); 629 | } 630 | 631 | // delete the created objects 632 | 633 | for(size_t i = 0;i 10 | #include 11 | 12 | //glm is used to create perspective and transform matrices 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | 22 | // helper to check and display for shader compiler errors 23 | bool check_shader_compile_status(GLuint obj) { 24 | GLint status; 25 | glGetShaderiv(obj, GL_COMPILE_STATUS, &status); 26 | if(status == GL_FALSE) { 27 | GLint length; 28 | glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &length); 29 | std::vector log(length); 30 | glGetShaderInfoLog(obj, length, &length, &log[0]); 31 | std::cerr << &log[0]; 32 | return false; 33 | } 34 | return true; 35 | } 36 | 37 | // helper to check and display for shader linker error 38 | bool check_program_link_status(GLuint obj) { 39 | GLint status; 40 | glGetProgramiv(obj, GL_LINK_STATUS, &status); 41 | if(status == GL_FALSE) { 42 | GLint length; 43 | glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &length); 44 | std::vector log(length); 45 | glGetProgramInfoLog(obj, length, &length, &log[0]); 46 | std::cerr << &log[0]; 47 | return false; 48 | } 49 | return true; 50 | } 51 | int main() { 52 | int width = 640; 53 | int height = 480; 54 | 55 | if(glfwInit() == GL_FALSE) { 56 | std::cerr << "failed to init GLFW" << std::endl; 57 | return 1; 58 | } 59 | 60 | // select opengl version 61 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 62 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 63 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); 64 | 65 | // create a window 66 | GLFWwindow *window; 67 | if((window = glfwCreateWindow(width, height, "05fbo_fxaa", 0, 0)) == 0) { 68 | std::cerr << "failed to open window" << std::endl; 69 | glfwTerminate(); 70 | return 1; 71 | } 72 | 73 | glfwMakeContextCurrent(window); 74 | 75 | if(glxwInit()) { 76 | std::cerr << "failed to init GL3W" << std::endl; 77 | glfwDestroyWindow(window); 78 | glfwTerminate(); 79 | return 1; 80 | } 81 | 82 | // shader source code 83 | std::string vertex_source = 84 | "#version 330\n" 85 | "uniform mat4 ViewProjection;\n" // the projection matrix uniform 86 | "layout(location = 0) in vec4 vposition;\n" 87 | "layout(location = 1) in vec4 vcolor;\n" 88 | "out vec4 fcolor;\n" 89 | "void main() {\n" 90 | " fcolor = vcolor;\n" 91 | " gl_Position = ViewProjection*vposition;\n" 92 | "}\n"; 93 | 94 | std::string fragment_source = 95 | "#version 330\n" 96 | "in vec4 fcolor;\n" 97 | "layout(location = 0) out vec4 FragColor;\n" 98 | "void main() {\n" 99 | " FragColor = fcolor;\n" 100 | // the following line is required for fxaa (will not work with blending!) 101 | " FragColor.a = dot(fcolor.rgb, vec3(0.299, 0.587, 0.114));\n" 102 | "}\n"; 103 | 104 | // program and shader handles 105 | GLuint shader_program, vertex_shader, fragment_shader; 106 | 107 | 108 | // we need these to properly pass the strings 109 | const char *source; 110 | int length; 111 | 112 | // create and compiler vertex shader 113 | vertex_shader = glCreateShader(GL_VERTEX_SHADER); 114 | source = vertex_source.c_str(); 115 | length = vertex_source.size(); 116 | glShaderSource(vertex_shader, 1, &source, &length); 117 | glCompileShader(vertex_shader); 118 | if(!check_shader_compile_status(vertex_shader)) { 119 | glfwDestroyWindow(window); 120 | glfwTerminate(); 121 | return 1; 122 | } 123 | 124 | // create and compiler fragment shader 125 | fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 126 | source = fragment_source.c_str(); 127 | length = fragment_source.size(); 128 | glShaderSource(fragment_shader, 1, &source, &length); 129 | glCompileShader(fragment_shader); 130 | if(!check_shader_compile_status(fragment_shader)) { 131 | glfwDestroyWindow(window); 132 | glfwTerminate(); 133 | return 1; 134 | } 135 | 136 | // create program 137 | shader_program = glCreateProgram(); 138 | 139 | // attach shaders 140 | glAttachShader(shader_program, vertex_shader); 141 | glAttachShader(shader_program, fragment_shader); 142 | 143 | // link the program and check for errors 144 | glLinkProgram(shader_program); 145 | check_program_link_status(shader_program); 146 | 147 | // obtain location of projection uniform 148 | GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); 149 | 150 | 151 | // vao and vbo handle 152 | GLuint vao, vbo, ibo; 153 | 154 | // generate and bind the vao 155 | glGenVertexArrays(1, &vao); 156 | glBindVertexArray(vao); 157 | 158 | // generate and bind the vertex buffer object 159 | glGenBuffers(1, &vbo); 160 | glBindBuffer(GL_ARRAY_BUFFER, vbo); 161 | 162 | // data for a cube 163 | GLfloat vertexData[] = { 164 | // X Y Z R G B 165 | // face 0: 166 | 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 167 | -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 168 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 169 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 170 | 171 | // face 1: 172 | 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 173 | 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 174 | 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 175 | 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 176 | 177 | // face 2: 178 | 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 179 | 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 180 | -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 181 | -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 182 | 183 | // face 3: 184 | 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 185 | 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 186 | -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 187 | -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 188 | 189 | // face 4: 190 | -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 191 | -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 192 | -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 193 | -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 194 | 195 | // face 5: 196 | 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 197 | -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 198 | 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 199 | -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 200 | }; // 6 faces with 4 vertices with 6 components (floats) 201 | 202 | // fill with data 203 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); 204 | 205 | 206 | // set up generic attrib pointers 207 | glEnableVertexAttribArray(0); 208 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 209 | 210 | glEnableVertexAttribArray(1); 211 | glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 212 | 213 | 214 | // generate and bind the index buffer object 215 | glGenBuffers(1, &ibo); 216 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); 217 | 218 | GLuint indexData[] = { 219 | // face 0: 220 | 0,1,2, // first triangle 221 | 2,1,3, // second triangle 222 | // face 1: 223 | 4,5,6, // first triangle 224 | 6,5,7, // second triangle 225 | // face 2: 226 | 8,9,10, // first triangle 227 | 10,9,11, // second triangle 228 | // face 3: 229 | 12,13,14, // first triangle 230 | 14,13,15, // second triangle 231 | // face 4: 232 | 16,17,18, // first triangle 233 | 18,17,19, // second triangle 234 | // face 5: 235 | 20,21,22, // first triangle 236 | 22,21,23, // second triangle 237 | }; 238 | 239 | // fill with data 240 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); 241 | 242 | // "unbind" vao 243 | glBindVertexArray(0); 244 | 245 | // shader source code 246 | std::string post_effect_vertex_source = 247 | "#version 330\n" 248 | "layout(location = 0) in vec4 vposition;\n" 249 | "layout(location = 1) in vec2 vtexcoord;\n" 250 | "out vec2 ftexcoord;\n" 251 | "void main() {\n" 252 | " ftexcoord = vtexcoord;\n" 253 | " gl_Position = vposition;\n" 254 | "}\n"; 255 | 256 | // this is a Timothy Lottes FXAA 3.11 257 | // check out the following link for detailed information: 258 | // http://timothylottes.blogspot.ch/2011/07/fxaa-311-released.html 259 | // 260 | // the shader source has been stripped with a preprocessor for 261 | // brevity reasons (it's still pretty long for inlining...). 262 | // the used defines are: 263 | // #define FXAA_PC 1 264 | // #define FXAA_GLSL_130 1 265 | // #define FXAA_QUALITY__PRESET 13 266 | 267 | std::string post_effect_fragment_source = 268 | "#version 330\n" 269 | "uniform sampler2D intexture;\n" 270 | "in vec2 ftexcoord;\n" 271 | "layout(location = 0) out vec4 FragColor;\n" 272 | "\n" 273 | "float FxaaLuma(vec4 rgba) {\n" 274 | " return rgba.w;\n" 275 | "}\n" 276 | "\n" 277 | "vec4 FxaaPixelShader(\n" 278 | " vec2 pos,\n" 279 | " sampler2D tex,\n" 280 | " vec2 fxaaQualityRcpFrame,\n" 281 | " float fxaaQualitySubpix,\n" 282 | " float fxaaQualityEdgeThreshold,\n" 283 | " float fxaaQualityEdgeThresholdMin\n" 284 | ") {\n" 285 | " vec2 posM;\n" 286 | " posM.x = pos.x;\n" 287 | " posM.y = pos.y;\n" 288 | " vec4 rgbyM = textureLod(tex, posM, 0.0);\n" 289 | " float lumaS = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2( 0, 1)));\n" 290 | " float lumaE = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2( 1, 0)));\n" 291 | " float lumaN = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2( 0,-1)));\n" 292 | " float lumaW = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2(-1, 0)));\n" 293 | " float maxSM = max(lumaS, rgbyM.w);\n" 294 | " float minSM = min(lumaS, rgbyM.w);\n" 295 | " float maxESM = max(lumaE, maxSM);\n" 296 | " float minESM = min(lumaE, minSM);\n" 297 | " float maxWN = max(lumaN, lumaW);\n" 298 | " float minWN = min(lumaN, lumaW);\n" 299 | " float rangeMax = max(maxWN, maxESM);\n" 300 | " float rangeMin = min(minWN, minESM);\n" 301 | " float rangeMaxScaled = rangeMax * fxaaQualityEdgeThreshold;\n" 302 | " float range = rangeMax - rangeMin;\n" 303 | " float rangeMaxClamped = max(fxaaQualityEdgeThresholdMin, rangeMaxScaled);\n" 304 | " bool earlyExit = range < rangeMaxClamped;\n" 305 | " if(earlyExit)\n" 306 | " return rgbyM;\n" 307 | "\n" 308 | " float lumaNW = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2(-1,-1)));\n" 309 | " float lumaSE = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2( 1, 1)));\n" 310 | " float lumaNE = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2( 1,-1)));\n" 311 | " float lumaSW = FxaaLuma(textureLodOffset(tex, posM, 0.0, ivec2(-1, 1)));\n" 312 | " float lumaNS = lumaN + lumaS;\n" 313 | " float lumaWE = lumaW + lumaE;\n" 314 | " float subpixRcpRange = 1.0/range;\n" 315 | " float subpixNSWE = lumaNS + lumaWE;\n" 316 | " float edgeHorz1 = (-2.0 * rgbyM.w) + lumaNS;\n" 317 | " float edgeVert1 = (-2.0 * rgbyM.w) + lumaWE;\n" 318 | " float lumaNESE = lumaNE + lumaSE;\n" 319 | " float lumaNWNE = lumaNW + lumaNE;\n" 320 | " float edgeHorz2 = (-2.0 * lumaE) + lumaNESE;\n" 321 | " float edgeVert2 = (-2.0 * lumaN) + lumaNWNE;\n" 322 | " float lumaNWSW = lumaNW + lumaSW;\n" 323 | " float lumaSWSE = lumaSW + lumaSE;\n" 324 | " float edgeHorz4 = (abs(edgeHorz1) * 2.0) + abs(edgeHorz2);\n" 325 | " float edgeVert4 = (abs(edgeVert1) * 2.0) + abs(edgeVert2);\n" 326 | " float edgeHorz3 = (-2.0 * lumaW) + lumaNWSW;\n" 327 | " float edgeVert3 = (-2.0 * lumaS) + lumaSWSE;\n" 328 | " float edgeHorz = abs(edgeHorz3) + edgeHorz4;\n" 329 | " float edgeVert = abs(edgeVert3) + edgeVert4;\n" 330 | " float subpixNWSWNESE = lumaNWSW + lumaNESE;\n" 331 | " float lengthSign = fxaaQualityRcpFrame.x;\n" 332 | " bool horzSpan = edgeHorz >= edgeVert;\n" 333 | " float subpixA = subpixNSWE * 2.0 + subpixNWSWNESE;\n" 334 | " if(!horzSpan) lumaN = lumaW;\n" 335 | " if(!horzSpan) lumaS = lumaE;\n" 336 | " if(horzSpan) lengthSign = fxaaQualityRcpFrame.y;\n" 337 | " float subpixB = (subpixA * (1.0/12.0)) - rgbyM.w;\n" 338 | " float gradientN = lumaN - rgbyM.w;\n" 339 | " float gradientS = lumaS - rgbyM.w;\n" 340 | " float lumaNN = lumaN + rgbyM.w;\n" 341 | " float lumaSS = lumaS + rgbyM.w;\n" 342 | " bool pairN = abs(gradientN) >= abs(gradientS);\n" 343 | " float gradient = max(abs(gradientN), abs(gradientS));\n" 344 | " if(pairN) lengthSign = -lengthSign;\n" 345 | " float subpixC = clamp(abs(subpixB) * subpixRcpRange, 0.0, 1.0);\n" 346 | " vec2 posB;\n" 347 | " posB.x = posM.x;\n" 348 | " posB.y = posM.y;\n" 349 | " vec2 offNP;\n" 350 | " offNP.x = (!horzSpan) ? 0.0 : fxaaQualityRcpFrame.x;\n" 351 | " offNP.y = ( horzSpan) ? 0.0 : fxaaQualityRcpFrame.y;\n" 352 | " if(!horzSpan) posB.x += lengthSign * 0.5;\n" 353 | " if( horzSpan) posB.y += lengthSign * 0.5;\n" 354 | " vec2 posN;\n" 355 | " posN.x = posB.x - offNP.x * 1.0;\n" 356 | " posN.y = posB.y - offNP.y * 1.0;\n" 357 | " vec2 posP;\n" 358 | " posP.x = posB.x + offNP.x * 1.0;\n" 359 | " posP.y = posB.y + offNP.y * 1.0;\n" 360 | " float subpixD = ((-2.0)*subpixC) + 3.0;\n" 361 | " float lumaEndN = FxaaLuma(textureLod(tex, posN, 0.0));\n" 362 | " float subpixE = subpixC * subpixC;\n" 363 | " float lumaEndP = FxaaLuma(textureLod(tex, posP, 0.0));\n" 364 | " if(!pairN) lumaNN = lumaSS;\n" 365 | " float gradientScaled = gradient * 1.0/4.0;\n" 366 | " float lumaMM = rgbyM.w - lumaNN * 0.5;\n" 367 | " float subpixF = subpixD * subpixE;\n" 368 | " bool lumaMLTZero = lumaMM < 0.0;\n" 369 | " lumaEndN -= lumaNN * 0.5;\n" 370 | " lumaEndP -= lumaNN * 0.5;\n" 371 | " bool doneN = abs(lumaEndN) >= gradientScaled;\n" 372 | " bool doneP = abs(lumaEndP) >= gradientScaled;\n" 373 | " if(!doneN) posN.x -= offNP.x * 1.5;\n" 374 | " if(!doneN) posN.y -= offNP.y * 1.5;\n" 375 | " bool doneNP = (!doneN) || (!doneP);\n" 376 | " if(!doneP) posP.x += offNP.x * 1.5;\n" 377 | " if(!doneP) posP.y += offNP.y * 1.5;\n" 378 | " if(doneNP) {\n" 379 | " if(!doneN) lumaEndN = FxaaLuma(textureLod(tex, posN.xy, 0.0));\n" 380 | " if(!doneP) lumaEndP = FxaaLuma(textureLod(tex, posP.xy, 0.0));\n" 381 | " if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n" 382 | " if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n" 383 | " doneN = abs(lumaEndN) >= gradientScaled;\n" 384 | " doneP = abs(lumaEndP) >= gradientScaled;\n" 385 | " if(!doneN) posN.x -= offNP.x * 2.0;\n" 386 | " if(!doneN) posN.y -= offNP.y * 2.0;\n" 387 | " doneNP = (!doneN) || (!doneP);\n" 388 | " if(!doneP) posP.x += offNP.x * 2.0;\n" 389 | " if(!doneP) posP.y += offNP.y * 2.0;\n" 390 | " if(doneNP) {\n" 391 | " if(!doneN) lumaEndN = FxaaLuma(textureLod(tex, posN.xy, 0.0));\n" 392 | " if(!doneP) lumaEndP = FxaaLuma(textureLod(tex, posP.xy, 0.0));\n" 393 | " if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n" 394 | " if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n" 395 | " doneN = abs(lumaEndN) >= gradientScaled;\n" 396 | " doneP = abs(lumaEndP) >= gradientScaled;\n" 397 | " if(!doneN) posN.x -= offNP.x * 2.0;\n" 398 | " if(!doneN) posN.y -= offNP.y * 2.0;\n" 399 | " doneNP = (!doneN) || (!doneP);\n" 400 | " if(!doneP) posP.x += offNP.x * 2.0;\n" 401 | " if(!doneP) posP.y += offNP.y * 2.0;\n" 402 | " if(doneNP) {\n" 403 | " if(!doneN) lumaEndN = FxaaLuma(textureLod(tex, posN.xy, 0.0));\n" 404 | " if(!doneP) lumaEndP = FxaaLuma(textureLod(tex, posP.xy, 0.0));\n" 405 | " if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n" 406 | " if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n" 407 | " doneN = abs(lumaEndN) >= gradientScaled;\n" 408 | " doneP = abs(lumaEndP) >= gradientScaled;\n" 409 | " if(!doneN) posN.x -= offNP.x * 4.0;\n" 410 | " if(!doneN) posN.y -= offNP.y * 4.0;\n" 411 | " doneNP = (!doneN) || (!doneP);\n" 412 | " if(!doneP) posP.x += offNP.x * 4.0;\n" 413 | " if(!doneP) posP.y += offNP.y * 4.0;\n" 414 | " if(doneNP) {\n" 415 | " if(!doneN) lumaEndN = FxaaLuma(textureLod(tex, posN.xy, 0.0));\n" 416 | " if(!doneP) lumaEndP = FxaaLuma(textureLod(tex, posP.xy, 0.0));\n" 417 | " if(!doneN) lumaEndN = lumaEndN - lumaNN * 0.5;\n" 418 | " if(!doneP) lumaEndP = lumaEndP - lumaNN * 0.5;\n" 419 | " doneN = abs(lumaEndN) >= gradientScaled;\n" 420 | " doneP = abs(lumaEndP) >= gradientScaled;\n" 421 | " if(!doneN) posN.x -= offNP.x * 12.0;\n" 422 | " if(!doneN) posN.y -= offNP.y * 12.0;\n" 423 | " doneNP = (!doneN) || (!doneP);\n" 424 | " if(!doneP) posP.x += offNP.x * 12.0;\n" 425 | " if(!doneP) posP.y += offNP.y * 12.0;\n" 426 | " }\n" 427 | " }\n" 428 | " }\n" 429 | " }\n" 430 | "\n" 431 | " float dstN = posM.x - posN.x;\n" 432 | " float dstP = posP.x - posM.x;\n" 433 | " if(!horzSpan) dstN = posM.y - posN.y;\n" 434 | " if(!horzSpan) dstP = posP.y - posM.y;\n" 435 | "\n" 436 | " bool goodSpanN = (lumaEndN < 0.0) != lumaMLTZero;\n" 437 | " float spanLength = (dstP + dstN);\n" 438 | " bool goodSpanP = (lumaEndP < 0.0) != lumaMLTZero;\n" 439 | " float spanLengthRcp = 1.0/spanLength;\n" 440 | "\n" 441 | " bool directionN = dstN < dstP;\n" 442 | " float dst = min(dstN, dstP);\n" 443 | " bool goodSpan = directionN ? goodSpanN : goodSpanP;\n" 444 | " float subpixG = subpixF * subpixF;\n" 445 | " float pixelOffset = (dst * (-spanLengthRcp)) + 0.5;\n" 446 | " float subpixH = subpixG * fxaaQualitySubpix;\n" 447 | "\n" 448 | " float pixelOffsetGood = goodSpan ? pixelOffset : 0.0;\n" 449 | " float pixelOffsetSubpix = max(pixelOffsetGood, subpixH);\n" 450 | " if(!horzSpan) posM.x += pixelOffsetSubpix * lengthSign;\n" 451 | " if( horzSpan) posM.y += pixelOffsetSubpix * lengthSign;\n" 452 | " \n" 453 | " return vec4(textureLod(tex, posM, 0.0).xyz, rgbyM.w);\n" 454 | "}\n" 455 | "\n" 456 | "void main() { \n" 457 | " FragColor = FxaaPixelShader(\n" 458 | " ftexcoord,\n" 459 | " intexture,\n" 460 | " 1.0/textureSize(intexture,0),\n" 461 | " 0.75,\n" 462 | " 0.166,\n" 463 | " 0.0625\n" 464 | " );\n" 465 | "}\n"; 466 | 467 | // program and shader handles 468 | GLuint post_effect_shader_program, post_effect_vertex_shader, post_effect_fragment_shader; 469 | 470 | // create and compiler vertex shader 471 | post_effect_vertex_shader = glCreateShader(GL_VERTEX_SHADER); 472 | source = post_effect_vertex_source.c_str(); 473 | length = post_effect_vertex_source.size(); 474 | glShaderSource(post_effect_vertex_shader, 1, &source, &length); 475 | glCompileShader(post_effect_vertex_shader); 476 | if(!check_shader_compile_status(post_effect_vertex_shader)) 477 | { 478 | return 1; 479 | } 480 | 481 | // create and compiler fragment shader 482 | post_effect_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); 483 | source = post_effect_fragment_source.c_str(); 484 | length = post_effect_fragment_source.size(); 485 | glShaderSource(post_effect_fragment_shader, 1, &source, &length); 486 | glCompileShader(post_effect_fragment_shader); 487 | if(!check_shader_compile_status(post_effect_fragment_shader)) 488 | { 489 | return 1; 490 | } 491 | 492 | // create program 493 | post_effect_shader_program = glCreateProgram(); 494 | 495 | // attach shaders 496 | glAttachShader(post_effect_shader_program, post_effect_vertex_shader); 497 | glAttachShader(post_effect_shader_program, post_effect_fragment_shader); 498 | 499 | // link the program and check for errors 500 | glLinkProgram(post_effect_shader_program); 501 | check_program_link_status(post_effect_shader_program); 502 | 503 | // get texture uniform location 504 | GLint post_effect_texture_location = glGetUniformLocation(post_effect_shader_program, "intexture"); 505 | 506 | // vao and vbo handle 507 | GLuint post_effect_vao, post_effect_vbo, post_effect_ibo; 508 | 509 | // generate and bind the vao 510 | glGenVertexArrays(1, &post_effect_vao); 511 | glBindVertexArray(post_effect_vao); 512 | 513 | // generate and bind the vertex buffer object 514 | glGenBuffers(1, &post_effect_vbo); 515 | glBindBuffer(GL_ARRAY_BUFFER, post_effect_vbo); 516 | 517 | // data for a fullscreen quad (this time with texture coords) 518 | GLfloat post_effect_vertexData[] = { 519 | // X Y Z U V 520 | 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 521 | -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 522 | 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 523 | -1.0f,-1.0f, 0.0f, 0.0f, 0.0f, // vertex 3 524 | }; // 4 vertices with 5 components (floats) each 525 | 526 | // fill with data 527 | glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*5, post_effect_vertexData, GL_STATIC_DRAW); 528 | 529 | 530 | // set up generic attrib pointers 531 | glEnableVertexAttribArray(0); 532 | glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); 533 | 534 | glEnableVertexAttribArray(1); 535 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); 536 | 537 | 538 | // generate and bind the index buffer object 539 | glGenBuffers(1, &post_effect_ibo); 540 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, post_effect_ibo); 541 | 542 | GLuint post_effect_indexData[] = { 543 | 0,1,2, // first triangle 544 | 2,1,3, // second triangle 545 | }; 546 | 547 | // fill with data 548 | glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, post_effect_indexData, GL_STATIC_DRAW); 549 | 550 | // "unbind" vao 551 | glBindVertexArray(0); 552 | 553 | // texture handle 554 | GLuint texture; 555 | 556 | // generate texture 557 | glGenTextures(1, &texture); 558 | 559 | // bind the texture 560 | glBindTexture(GL_TEXTURE_2D, texture); 561 | 562 | // set texture parameters 563 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 564 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 565 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 566 | glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 567 | 568 | // set texture content 569 | glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); 570 | 571 | 572 | // renderbuffer handle 573 | GLuint rbf; 574 | 575 | // generate renderbuffers 576 | glGenRenderbuffers(1, &rbf); 577 | 578 | glBindRenderbuffer(GL_RENDERBUFFER, rbf); 579 | glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, width, height); 580 | 581 | // framebuffer handle 582 | GLuint fbo; 583 | 584 | // generate framebuffer 585 | glGenFramebuffers(1, &fbo); 586 | 587 | glBindFramebuffer(GL_FRAMEBUFFER, fbo); 588 | 589 | glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); 590 | glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbf); 591 | 592 | 593 | bool fxaa = true; 594 | bool space_down = false; 595 | while(!glfwWindowShouldClose(window)) { 596 | glfwPollEvents(); 597 | 598 | // get the time in seconds 599 | float t = glfwGetTime(); 600 | 601 | // toggle fxaa on/off with space 602 | if(glfwGetKey(window, GLFW_KEY_SPACE) && !space_down) 603 | { 604 | fxaa = !fxaa; 605 | } 606 | space_down = glfwGetKey(window, GLFW_KEY_SPACE); 607 | 608 | glEnable(GL_DEPTH_TEST); 609 | 610 | // bind target framebuffer 611 | if(fxaa) 612 | glBindFramebuffer(GL_FRAMEBUFFER, fbo); 613 | else 614 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 615 | 616 | // clear first 617 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 618 | 619 | // use the shader program 620 | glUseProgram(shader_program); 621 | 622 | // calculate ViewProjection matrix 623 | glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); 624 | 625 | // translate the world/view position 626 | glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); 627 | 628 | // make the camera rotate around the origin 629 | View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); 630 | 631 | glm::mat4 ViewProjection = Projection*View; 632 | 633 | // set the uniform 634 | glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); 635 | 636 | // bind the vao 637 | glBindVertexArray(vao); 638 | 639 | // draw 640 | glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0); 641 | 642 | // apply post processing only when fxaa is on 643 | if(fxaa) 644 | { 645 | // bind the "screen frambuffer" 646 | glBindFramebuffer(GL_FRAMEBUFFER, 0); 647 | 648 | // we are not 3d rendering so no depth test 649 | glDisable(GL_DEPTH_TEST); 650 | 651 | // use the shader program 652 | glUseProgram(post_effect_shader_program); 653 | 654 | // bind texture to texture unit 0 655 | glActiveTexture(GL_TEXTURE0); 656 | glBindTexture(GL_TEXTURE_2D, texture); 657 | 658 | // set uniforms 659 | glUniform1i(post_effect_texture_location, 0); 660 | 661 | // bind the vao 662 | glBindVertexArray(post_effect_vao); 663 | 664 | // draw 665 | glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); 666 | } 667 | 668 | // check for errors 669 | GLenum error = glGetError(); 670 | if(error != GL_NO_ERROR) { 671 | std::cerr << error << std::endl; 672 | break; 673 | } 674 | 675 | // finally swap buffers 676 | glfwSwapBuffers(window); 677 | } 678 | 679 | // delete the created objects 680 | 681 | glDeleteVertexArrays(1, &vao); 682 | glDeleteBuffers(1, &vbo); 683 | glDeleteBuffers(1, &ibo); 684 | 685 | glDetachShader(shader_program, vertex_shader); 686 | glDetachShader(shader_program, fragment_shader); 687 | glDeleteShader(vertex_shader); 688 | glDeleteShader(fragment_shader); 689 | glDeleteProgram(shader_program); 690 | 691 | glDeleteVertexArrays(1, &post_effect_vao); 692 | glDeleteBuffers(1, &post_effect_vbo); 693 | glDeleteBuffers(1, &post_effect_ibo); 694 | 695 | glDetachShader(post_effect_shader_program, post_effect_vertex_shader); 696 | glDetachShader(post_effect_shader_program, post_effect_fragment_shader); 697 | glDeleteShader(post_effect_vertex_shader); 698 | glDeleteShader(post_effect_fragment_shader); 699 | glDeleteProgram(post_effect_shader_program); 700 | 701 | glfwDestroyWindow(window); 702 | glfwTerminate(); 703 | return 0; 704 | } 705 | 706 | --------------------------------------------------------------------------------