int main() { // init the library piguInit(); int width, height; piguGetScreenSize(&width, &height); float aspect = static_cast<float>(width)/height; // create the window if(piguCreateWindow(width, height, 8, 8, 8, 8, 24, 8, 0)<0) { std::cerr << "failed to create window" << std::endl; return 1; } // vsync piguSwapInterval(1); // shader source code std::string vertex_source = "uniform mat4 ViewProjection;\n" // the projection matrix uniform "attribute vec4 vposition;\n" "attribute vec4 vcolor;\n" "varying vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = ViewProjection*vposition;\n" "}\n"; std::string fragment_source = "varying vec4 fcolor;\n" "void main() {\n" " gl_FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { std::cerr << "failed to compile vertex shader" << std::endl; return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { std::cerr << "failed to compile fragment shader" << std::endl; return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); glBindAttribLocation(shader_program, 0, "vposition"); glBindAttribLocation(shader_program, 1, "vcolor"); // link the program and check for errors glLinkProgram(shader_program); if(!check_program_link_status(shader_program)) { std::cerr << "failed to link shaders" << std::endl; return 1; } // obtain location of projection uniform GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); // vao and vbo handle GLuint vbo, ibo; // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a cube GLfloat vertexData[] = { // X Y Z R G B // face 0: 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 // face 1: 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 // face 2: 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 // face 3: 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 // face 4: -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 // face 5: 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 }; // 6 faces with 4 vertices with 6 components (floats) // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLushort indexData[] = { // face 0: 0,1,2, // first triangle 2,1,3, // second triangle // face 1: 4,5,6, // first triangle 6,5,7, // second triangle // face 2: 8,9,10, // first triangle 10,9,11, // second triangle // face 3: 12,13,14, // first triangle 14,13,15, // second triangle // face 4: 16,17,18, // first triangle 18,17,19, // second triangle // face 5: 20,21,22, // first triangle 22,21,23, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort)*6*2*3, indexData, GL_STATIC_DRAW); // we are drawing 3d objects so we want depth testing glEnable(GL_DEPTH_TEST); glDisable(GL_BLEND); glClearColor(0, 0, 0, 1); running = true; while(running) { // get the time in seconds float t = piguGetTime(); // poll events so key state is updated piguPollEvents(); // terminate on escape if(piguIsKeyDown(KEY_ESC)) { running = false; } // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, aspect, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); // make the camera rotate around the origin View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); glm::mat4 ViewProjection = Projection*View; // set the uniform glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); // draw glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_SHORT, 0); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << "error: " << error << std::endl; running = false; } // finally swap buffers piguSwapBuffers(); } // delete the created objects glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); piguTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // sadly glew doesn't play nice with core profiles... glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code std::string vertex_source = "#version 330\n" "uniform mat4 ViewProjection;\n" // the projection matrix uniform "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "layout(location = 2) in vec3 voffset;\n" // the per instance offset "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = ViewProjection*(vposition + vec4(voffset, 0));\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); // vao and vbo handles GLuint vao, vbo, tbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a cube GLfloat vertexData[] = { // X Y Z R G B // face 0: 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 // face 1: 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 // face 2: 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 // face 3: 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 // face 4: -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 // face 5: 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 }; // 6 faces with 4 vertices with 6 components (floats) // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { // face 0: 0,1,2, // first triangle 2,1,3, // second triangle // face 1: 4,5,6, // first triangle 6,5,7, // second triangle // face 2: 8,9,10, // first triangle 10,9,11, // second triangle // face 3: 12,13,14, // first triangle 14,13,15, // second triangle // face 4: 16,17,18, // first triangle 18,17,19, // second triangle // face 5: 20,21,22, // first triangle 22,21,23, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); // generate and bind the vertex buffer object containing the // instance offsets glGenBuffers(1, &tbo); glBindBuffer(GL_ARRAY_BUFFER, tbo); // the offsets GLfloat translationData[] = { 2.0f, 2.0f, 2.0f, // cube 0 2.0f, 2.0f,-2.0f, // cube 1 2.0f,-2.0f, 2.0f, // cube 2 2.0f,-2.0f,-2.0f, // cube 3 -2.0f, 2.0f, 2.0f, // cube 4 -2.0f, 2.0f,-2.0f, // cube 5 -2.0f,-2.0f, 2.0f, // cube 6 -2.0f,-2.0f,-2.0f, // cube 7 }; // 8 offsets with 3 components each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*8, translationData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // a attrib divisor of 1 means that attribute 2 will advance once // every instance (0 would mean once per vertex) glVertexAttribDivisor(2, 1); // "unbind" vao glBindVertexArray(0); // we are drawing 3d objects so we want depth testing glEnable(GL_DEPTH_TEST); running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on excape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); // make the camera rotate around the origin View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); glm::mat4 ViewProjection = Projection*View; // set the uniform glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); // bind the vao glBindVertexArray(vao); // draw // the additional parameter indicates how many instances to render glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDeleteBuffers(1, &tbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); // create a window GLFWwindow *window; if((window = glfwCreateWindow(width, height, "02indexed_vbo", 0, 0)) == 0) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } glfwMakeContextCurrent(window); if(glxwInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwDestroyWindow(window); glfwTerminate(); return 1; } // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { glfwDestroyWindow(window); glfwTerminate(); return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { glfwDestroyWindow(window); glfwTerminate(); return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // vao and vbo handle GLuint vao, vbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z R G B 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 3 }; // 4 vertices with 6 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { 0,1,2, // first triangle 2,1,3, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); while(!glfwWindowShouldClose(window)) { glfwPollEvents(); // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind the vao glBindVertexArray(vao); // draw glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << error << std::endl; break; } // finally swap buffers glfwSwapBuffers(window); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwDestroyWindow(window); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; UserData userdata; userdata.running = true; GLWTConfig glwt_config; glwt_config.red_bits = 8; glwt_config.green_bits = 8; glwt_config.blue_bits = 8; glwt_config.alpha_bits = 8; glwt_config.depth_bits = 24; glwt_config.stencil_bits = 8; glwt_config.samples = 0; glwt_config.sample_buffers = 0; glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE; glwt_config.api_version_major = 3; glwt_config.api_version_minor = 3; GLWTAppCallbacks app_callbacks; app_callbacks.error_callback = error_callback; app_callbacks.userdata = &userdata; if(glwtInit(&glwt_config, &app_callbacks) != 0) { std::cerr << "failed to init GLWT" << std::endl; return 1; } GLWTWindowCallbacks win_callbacks; win_callbacks.close_callback = close_callback; win_callbacks.expose_callback = 0; win_callbacks.resize_callback = 0; win_callbacks.show_callback = 0; win_callbacks.focus_callback = 0; win_callbacks.key_callback = key_callback, win_callbacks.motion_callback = 0; win_callbacks.button_callback = 0; win_callbacks.mouseover_callback = 0; win_callbacks.userdata = &userdata; // create a window GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0); if(window == 0) { std::cerr << "failed to open window" << std::endl; glwtQuit(); return 1; } if (glxwInit()) { std::cerr << "failed to init GLXW" << std::endl; glwtWindowDestroy(window); glwtQuit(); return 1; } glwtWindowShow(window, 1); glwtMakeCurrent(window); glwtSwapInterval(window, 1); // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 330\n" "uniform mat4 View;\n" "uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(1,0.9,0.6,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint View_location = glGetUniformLocation(shader_program, "View"); GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); const int particles = 128*1024; // create a galaxylike distribution of points std::vector<GLfloat> vertexData(particles*3); for(int i = 0;i<particles;++i) { int arm = 3*(std::rand()/float(RAND_MAX)); float alpha = 1/(0.1f+std::pow(std::rand()/float(RAND_MAX),0.7f))-1/1.1f; float r = 4.0f*alpha; alpha += arm*2.0f*3.1416f/3.0f; vertexData[3*i+0] = r*std::sin(alpha); vertexData[3*i+1] = 0; vertexData[3*i+2] = r*std::cos(alpha); vertexData[3*i+0] += (4.0f-0.2*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+ std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX))); vertexData[3*i+1] += (2.0f-0.1*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+ std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX))); vertexData[3*i+2] += (4.0f-0.2*alpha)*(2-(std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX)+ std::rand()/float(RAND_MAX)+std::rand()/float(RAND_MAX))); } // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); while(userdata.running) { // get the time in seconds float t = glwtGetNanoTime()*1.e-9f; // update events glwtEventHandle(0); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -50.0f)); // make the camera rotate around the origin View = glm::rotate(View, 30.0f*std::sin(0.1f*t), glm::vec3(1.0f, 0.0f, 0.0f)); View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); // set the uniform glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { userdata.running = false; } // finally swap buffers glwtSwapBuffers(window); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glwtWindowDestroy(window); glwtQuit(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); glfwSwapInterval(0); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 430\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 430\n" "layout(location = 0) uniform mat4 View;\n" "layout(location = 1) uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = (1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(0.3,0.3,1.0,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); std::string acceleration_source = "#version 430\n" "layout(local_size_x=256) in;\n" "layout(location = 0) uniform float dt;\n" "layout(rgba32f, location = 1) uniform imageBuffer positions;\n" "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n" "void main() {\n" " int N = int(gl_NumWorkGroups.x*gl_WorkGroupSize.x);\n" " int index = int(gl_GlobalInvocationID);\n" " vec3 position = imageLoad(positions, index).xyz;\n" " vec3 velocity = imageLoad(velocities, index).xyz;\n" " vec3 acceleration = vec3(0,0,0);\n" " for(int i = 0;i<N;++i) {\n" " vec3 other = imageLoad(positions, i).xyz;\n" " vec3 diff = position - other;\n" " float dist = length(diff)+0.001;\n" " acceleration -= 0.1*diff/(dist*dist*dist);\n" " }\n" " imageStore(velocities, index, vec4(velocity+dt*acceleration,0));\n" "}\n"; // program and shader handles GLuint acceleration_program, acceleration_shader; // create and compiler vertex shader acceleration_shader = glCreateShader(GL_COMPUTE_SHADER); source = acceleration_source.c_str(); length = acceleration_source.size(); glShaderSource(acceleration_shader, 1, &source, &length); glCompileShader(acceleration_shader); if(!check_shader_compile_status(acceleration_shader)) { return 1; } // create program acceleration_program = glCreateProgram(); // attach shaders glAttachShader(acceleration_program, acceleration_shader); // link the program and check for errors glLinkProgram(acceleration_program); check_program_link_status(acceleration_program); std::string tiled_acceleration_source = "#version 430\n" "layout(local_size_x=256) in;\n" "layout(location = 0) uniform float dt;\n" "layout(rgba32f, location = 1) uniform imageBuffer positions;\n" "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n" "layout(location = 3) uniform int tile;\n" "shared vec4 tmp[256];\n" "void main() {\n" " int index = int(gl_GlobalInvocationID);\n" " vec3 position = imageLoad(positions, index).xyz;\n" " vec3 velocity = imageLoad(velocities, index).xyz;\n" " vec3 acceleration = vec3(0,0,0);\n" " tmp[gl_LocalInvocationIndex] = imageLoad(positions, 256*tile + int(gl_LocalInvocationIndex));\n" " groupMemoryBarrier();\n" " barrier();\n" " for(int i = 0;i<gl_WorkGroupSize.x;++i) {\n" " vec3 other = tmp[i].xyz;\n" " vec3 diff = position - other;\n" " float invdist = 1/sqrt(dot(diff,diff)+0.00001);\n" " acceleration -= diff*0.1*invdist*invdist*invdist;\n" " }\n" " imageStore(velocities, index, vec4(velocity+dt*acceleration,0));\n" "}\n"; // program and shader handles GLuint tiled_acceleration_program, tiled_acceleration_shader; // create and compiler vertex shader tiled_acceleration_shader = glCreateShader(GL_COMPUTE_SHADER); source = tiled_acceleration_source.c_str(); length = tiled_acceleration_source.size(); glShaderSource(tiled_acceleration_shader, 1, &source, &length); glCompileShader(tiled_acceleration_shader); if(!check_shader_compile_status(tiled_acceleration_shader)) { return 1; } // create program tiled_acceleration_program = glCreateProgram(); // attach shaders glAttachShader(tiled_acceleration_program, tiled_acceleration_shader); // link the program and check for errors glLinkProgram(tiled_acceleration_program); check_program_link_status(tiled_acceleration_program); std::string integrate_source = "#version 430\n" "layout(local_size_x=256) in;\n" "layout(location = 0) uniform float dt;\n" "layout(rgba32f, location = 1) uniform imageBuffer positions;\n" "layout(rgba32f, location = 2) uniform imageBuffer velocities;\n" "void main() {\n" " int index = int(gl_GlobalInvocationID);\n" " vec4 position = imageLoad(positions, index);\n" " vec4 velocity = imageLoad(velocities, index);\n" " position.xyz += dt*velocity.xyz;\n" " imageStore(positions, index, position);\n" "}\n"; // program and shader handles GLuint integrate_program, integrate_shader; // create and compiler vertex shader integrate_shader = glCreateShader(GL_COMPUTE_SHADER); source = integrate_source.c_str(); length = integrate_source.size(); glShaderSource(integrate_shader, 1, &source, &length); glCompileShader(integrate_shader); if(!check_shader_compile_status(integrate_shader)) { return 1; } // create program integrate_program = glCreateProgram(); // attach shaders glAttachShader(integrate_program, integrate_shader); // link the program and check for errors glLinkProgram(integrate_program); check_program_link_status(integrate_program); const int particles = 32*1024; // randomly place particles in a cube std::vector<glm::vec4> positionData(particles); std::vector<glm::vec4> velocityData(particles); for(int i = 0;i<particles;++i) { // initial position positionData[i] = glm::vec4( 1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX), 1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX), 1.5f-(float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX+float(std::rand())/RAND_MAX), 0 ); positionData[i] = glm::vec4(0.0f,0.0f,0.0f,1) + glm::vec4(4.0f,1.0f,4.0f,1)*positionData[i]; velocityData[i] = 40.0f*glm::vec4(glm::cross(glm::vec3(positionData[i].xyz()), glm::vec3(0,1,0)), 0)/glm::dot(glm::vec3(positionData[i].xyz()),glm::vec3(positionData[i].xyz())); } // generate positions_vbos and vaos GLuint vao, positions_vbo, velocities_vbo; glGenVertexArrays(1, &vao); glGenBuffers(1, &positions_vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, positions_vbo); // fill with initial data glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*particles, &positionData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); glm::vec4 zero(0,0,0,0); glGenBuffers(1, &velocities_vbo); glBindBuffer(GL_TEXTURE_BUFFER, velocities_vbo); glBufferData(GL_TEXTURE_BUFFER, sizeof(glm::vec4)*particles, &velocityData[0], GL_STATIC_DRAW); // texture handle GLuint positions_texture, velocities_texture; glGenTextures(1, &positions_texture); glBindTexture(GL_TEXTURE_BUFFER, positions_texture); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, positions_vbo); glGenTextures(1, &velocities_texture); glBindTexture(GL_TEXTURE_BUFFER, velocities_texture); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, velocities_vbo); // bind images glBindImageTexture(0, positions_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); glBindImageTexture(1, velocities_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); // physical parameters float dt = 1.0f/60.0f; // setup uniforms glUseProgram(tiled_acceleration_program); glUniform1f(0, dt); glUniform1i(1, 0); glUniform1i(2, 1); glUseProgram(acceleration_program); glUniform1f(0, dt); glUniform1i(1, 0); glUniform1i(2, 1); glUseProgram(integrate_program); glUniform1f(0, dt); glUniform1i(1, 0); glUniform1i(2, 1); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); GLuint query; glGenQueries(1, &query); bool tiled = false; bool space_down = false; running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on excape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // toggle occlusion culling if(glfwGetKey(GLFW_KEY_SPACE) && !space_down) { tiled = !tiled; } space_down = glfwGetKey(GLFW_KEY_SPACE); glBeginQuery(GL_TIME_ELAPSED, query); if(tiled) { glUseProgram(tiled_acceleration_program); int tiles = particles/256; for(int tile = 0;tile<tiles;++tile) { glUniform1i(3, tile); glDispatchCompute(particles/256, 1, 1); } } else { glUseProgram(acceleration_program); glDispatchCompute(particles/256, 1, 1); } glEndQuery(GL_TIME_ELAPSED); glUseProgram(integrate_program); glDispatchCompute(particles/256, 1, 1); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); // tilt the camera View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); // set the uniforms glUniformMatrix4fv(0, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(1, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the current vao glBindVertexArray(vao); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); { GLuint64 result; glGetQueryObjectui64v(query, GL_QUERY_RESULT, &result); std::cout << result*1.e-6 << " ms/frame" << std::endl; } } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &positions_vbo); glDeleteBuffers(1, &velocities_vbo); glDeleteTextures(1, &positions_texture); glDeleteTextures(1, &velocities_texture); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glDetachShader(acceleration_program, acceleration_shader); glDeleteShader(acceleration_shader); glDeleteProgram(acceleration_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code std::string vertex_source = "#version 330\n" "in vec4 vposition;\n" "in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // bind the attribute locations (inputs) glBindAttribLocation(shader_program, 0, "vposition"); glBindAttribLocation(shader_program, 1, "vcolor"); // bind the FragDataLocation (output) glBindFragDataLocation(shader_program, 0, "FragColor"); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z R G B 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 }; // 6 vertices with 6 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); running = true; while(running) { // terminate on escape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_TRIANGLES, 0, 6); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 512; int height = 512; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } glfwSwapInterval(1); // shader source code // shared vertex shader std::string vertex_source = "#version 420\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the first fragment shader doesn't output anything since it only // updates the image in place std::string fragment1_source = "#version 420\n" "uniform float dt;\n" "uniform ivec2 image_size;\n" "uniform layout(rgba32f) image2D image;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " ivec2 coords = ivec2(gl_FragCoord.xy);\n" " vec4 HE = imageLoad(image, coords);\n" " float Ezdx = HE.z-imageLoad(image, coords-ivec2(1, 0)).z;\n" " float Ezdy = HE.z-imageLoad(image, coords-ivec2(0, 1)).z;\n" " HE.xy += dt*vec2(-Ezdy, Ezdx);\n" " imageStore(image, coords, HE);\n" "}\n"; // the second fragment shader also outputs the frag color for display // purposes std::string fragment2_source = "#version 420\n" "uniform float t;\n" "uniform float dt;\n" "uniform ivec2 image_size;\n" "uniform layout(rgba32f) image2D image;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " ivec2 coords = ivec2(gl_FragCoord.xy);\n" " float e = 1;\n" " vec4 HE = imageLoad(image, coords);\n" " float r = HE.w;\n" " float Hydx = imageLoad(image, coords+ivec2(1, 0)).y\n" " -HE.y;\n" " float Hxdy = imageLoad(image, coords+ivec2(0, 1)).x\n" " -HE.x;\n" " float Eout = dt*(Hydx-Hxdy)/(e);\n" " HE.z = HE.z*(1-dt*r/e) + Eout;\n" // add source at image center " if(coords.x == image_size.x/2 && coords.y == image_size.y/2) {\n" " HE.z += 30*sin(15*t)*exp(-10*(t-2)*(t-2));\n" " }\n" " imageStore(image, coords, HE);\n" " FragColor = vec4(HE.z, HE.w, -HE.z, 1);\n" "}\n"; // program and shader handles GLuint shader1_program, shader2_program, vertex_shader, fragment1_shader, fragment2_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment1_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment1_source.c_str(); length = fragment1_source.size(); glShaderSource(fragment1_shader, 1, &source, &length); glCompileShader(fragment1_shader); if(!check_shader_compile_status(fragment1_shader)) { return 1; } // create and compiler fragment shader fragment2_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment2_source.c_str(); length = fragment2_source.size(); glShaderSource(fragment2_shader, 1, &source, &length); glCompileShader(fragment2_shader); if(!check_shader_compile_status(fragment2_shader)) { return 1; } // create program shader1_program = glCreateProgram(); // attach shaders glAttachShader(shader1_program, vertex_shader); glAttachShader(shader1_program, fragment1_shader); // link the program and check for errors glLinkProgram(shader1_program); check_program_link_status(shader1_program); // get texture uniform location GLint image_size_location1 = glGetUniformLocation(shader1_program, "image_size"); GLint image_location1 = glGetUniformLocation(shader1_program, "image"); GLint dt_location1 = glGetUniformLocation(shader1_program, "dt"); // create program shader2_program = glCreateProgram(); // attach shaders glAttachShader(shader2_program, vertex_shader); glAttachShader(shader2_program, fragment2_shader); // link the program and check for errors glLinkProgram(shader2_program); check_program_link_status(shader2_program); // get texture uniform location GLint image_size_location2 = glGetUniformLocation(shader2_program, "image_size"); GLint image_location2 = glGetUniformLocation(shader2_program, "image"); GLint t_location2 = glGetUniformLocation(shader2_program, "t"); GLint dt_location2 = glGetUniformLocation(shader2_program, "dt"); // vao and vbo handle GLuint vao, vbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z 1.0f, 1.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 0.0f, // vertex 3 }; // 4 vertices with 3 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*3, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { 0,1,2, // first triangle 2,1,3, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); // "unbind" vao glBindVertexArray(0); // texture handle GLuint texture; // generate texture glGenTextures(1, &texture); // bind the texture glBindTexture(GL_TEXTURE_2D, texture); // create some image data std::vector<GLfloat> image(4*width*height); for(int j = 0;j<height;++j) for(int i = 0;i<width;++i) { size_t index = j*width + i; image[4*index + 0] = 0.0f; image[4*index + 1] = 0.0f; image[4*index + 2] = 0.0f; image[4*index + 3] = 20.0f*glm::clamp(glm::perlin(0.008f*glm::vec2(i,j+70)),0.0f,0.1f); } // set texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); // set texture content glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, width, height, 0, GL_RGBA, GL_FLOAT, &image[0]); float t = 0; float dt = 1.0f/60.0f; running = true; while(running) { t += dt; // reset time every 10 seconds to repeat the sequence if(t>10) t -= 10; // terminate on escape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // clear first glClear(GL_COLOR_BUFFER_BIT); glBindImageTexture(0, texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); // bind the vao glBindVertexArray(vao); int substeps = 5; glUseProgram(shader1_program); glUniform2i(image_size_location1, width, height); glUniform1i(image_location1, 0); glUniform1f(dt_location1, 50*dt/substeps); glUseProgram(shader2_program); glUniform2i(image_size_location2, width, height); glUniform1i(image_location2, 0); glUniform1f(dt_location2, 50*dt/substeps); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); int i = 0; for(;i<substeps-1;++i) { glUseProgram(shader1_program); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glUseProgram(shader2_program); glUniform1f(t_location2, t+i*dt/substeps); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } glUseProgram(shader1_program); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glUseProgram(shader2_program); glUniform1f(t_location2, t+i*dt/substeps); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteTextures(1, &texture); glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDetachShader(shader1_program, vertex_shader); glDetachShader(shader1_program, fragment1_shader); glDetachShader(shader2_program, vertex_shader); glDetachShader(shader2_program, fragment2_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment1_shader); glDeleteProgram(shader1_program); glDeleteShader(fragment2_shader); glDeleteProgram(shader2_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; UserData userdata; userdata.running = true; GLWTConfig glwt_config; glwt_config.red_bits = 8; glwt_config.green_bits = 8; glwt_config.blue_bits = 8; glwt_config.alpha_bits = 8; glwt_config.depth_bits = 24; glwt_config.stencil_bits = 8; glwt_config.samples = 0; glwt_config.sample_buffers = 0; glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE; glwt_config.api_version_major = 3; glwt_config.api_version_minor = 3; GLWTAppCallbacks app_callbacks; app_callbacks.error_callback = error_callback; app_callbacks.userdata = &userdata; if(glwtInit(&glwt_config, &app_callbacks) != 0) { std::cerr << "failed to init GLWT" << std::endl; return 1; } GLWTWindowCallbacks win_callbacks; win_callbacks.close_callback = close_callback; win_callbacks.expose_callback = 0; win_callbacks.resize_callback = 0; win_callbacks.show_callback = 0; win_callbacks.focus_callback = 0; win_callbacks.key_callback = key_callback, win_callbacks.motion_callback = 0; win_callbacks.button_callback = 0; win_callbacks.mouseover_callback = 0; win_callbacks.userdata = &userdata; // create a window GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0); if(window == 0) { std::cerr << "failed to open window" << std::endl; glwtQuit(); return 1; } if (glxwInit()) { std::cerr << "failed to init GLXW" << std::endl; glwtWindowDestroy(window); glwtQuit(); return 1; } glwtWindowShow(window, 1); glwtMakeCurrent(window); glwtSwapInterval(window, 1); // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z R G B 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 }; // 6 vertices with 6 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); while(userdata.running) { // update events glwtEventHandle(0); // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_TRIANGLES, 0, 6); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { userdata.running = false; } // finally swap buffers glwtSwapBuffers(window); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glwtWindowDestroy(window); glwtQuit(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); // this time we disable the mouse cursor since we want differential // mouse input glfwDisable(GLFW_MOUSE_CURSOR); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // draw shader std::string vertex_source = "#version 330\n" "uniform mat4 ViewProjection;\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec3 normal;\n" "out vec4 fcolor;\n" "void main() {\n" " float brightness = dot(normal,normalize(vec3(1,2,3)));\n" " brightness = 0.3+((brightness>0)?0.7*brightness:0.3*brightness);\n" " fcolor = vec4(brightness,brightness,brightness,1);\n" " gl_Position = ViewProjection*vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = abs(fcolor);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint DrawViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); // trivial shader for occlusion queries std::string query_vertex_source = "#version 330\n" "uniform mat4 ViewProjection;\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = ViewProjection*vposition;\n" "}\n"; std::string query_fragment_source = "#version 330\n" "void main() {\n" "}\n"; // program and shader handles GLuint query_shader_program, query_vertex_shader, query_fragment_shader; // create and compiler vertex shader query_vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = query_vertex_source.c_str(); length = query_vertex_source.size(); glShaderSource(query_vertex_shader, 1, &source, &length); glCompileShader(query_vertex_shader); if(!check_shader_compile_status(query_vertex_shader)) { return 1; } // create and compiler fragment shader query_fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = query_fragment_source.c_str(); length = query_fragment_source.size(); glShaderSource(query_fragment_shader, 1, &source, &length); glCompileShader(query_fragment_shader); if(!check_shader_compile_status(query_fragment_shader)) { return 1; } // create program query_shader_program = glCreateProgram(); // attach shaders glAttachShader(query_shader_program, query_vertex_shader); glAttachShader(query_shader_program, query_fragment_shader); // link the program and check for errors glLinkProgram(query_shader_program); check_program_link_status(query_shader_program); // obtain location of projection uniform GLint QueryViewProjection_location = glGetUniformLocation(query_shader_program, "ViewProjection"); // chunk container and chunk parameters std::vector<Chunk> chunks; int chunkrange = 4; int chunksize = 32; // chunk extraction std::cout << "generating chunks, this may take a while." << std::endl; // iterate over all chunks we want to extract for(int i = -chunkrange;i<chunkrange;++i) for(int j = -chunkrange;j<chunkrange;++j) for(int k = -chunkrange;k<chunkrange;++k) { Chunk chunk; // chunk data // generate and bind the vao glGenVertexArrays(1, &chunk.vao); glBindVertexArray(chunk.vao); // generate and bind the vertex buffer object glGenBuffers(1, &chunk.vbo); glBindBuffer(GL_ARRAY_BUFFER, chunk.vbo); std::vector<glm::vec3> vertexData; glm::vec3 offset = static_cast<float>(chunksize) * glm::vec3(i,j,k); float threshold = 0.0f; // iterate over all blocks within the chunk for(int x = 0;x<chunksize;++x) for(int y = 0;y<chunksize;++y) for(int z = 0;z<chunksize;++z) { glm::vec3 pos = glm::vec3(x,y,z) + offset; // insert quads if current block is solid and neighbors are not if(world_function(pos)<threshold) { if(world_function(pos+glm::vec3(1,0,0))>=threshold) { vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1)); vertexData.push_back(glm::vec3( 1, 0, 0)); vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1)); vertexData.push_back(glm::vec3( 1, 0, 0)); vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1)); vertexData.push_back(glm::vec3( 1, 0, 0)); vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1)); vertexData.push_back(glm::vec3( 1, 0, 0)); } if(world_function(pos+glm::vec3(0,1,0))>=threshold) { vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1)); vertexData.push_back(glm::vec3( 0, 1, 0)); vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1)); vertexData.push_back(glm::vec3( 0, 1, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1)); vertexData.push_back(glm::vec3( 0, 1, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1)); vertexData.push_back(glm::vec3( 0, 1, 0)); } if(world_function(pos+glm::vec3(0,0,1))>=threshold) { vertexData.push_back(pos+0.5f*glm::vec3( 1, 1, 1)); vertexData.push_back(glm::vec3( 0, 0, 1)); vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1)); vertexData.push_back(glm::vec3( 0, 0, 1)); vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1)); vertexData.push_back(glm::vec3( 0, 0, 1)); vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1)); vertexData.push_back(glm::vec3( 0, 0, 1)); } if(world_function(pos-glm::vec3(1,0,0))>=threshold) { vertexData.push_back(pos+0.5f*glm::vec3(-1, 1, 1)); vertexData.push_back(glm::vec3(-1, 0, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1)); vertexData.push_back(glm::vec3(-1, 0, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1)); vertexData.push_back(glm::vec3(-1, 0, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1)); vertexData.push_back(glm::vec3(-1, 0, 0)); } if(world_function(pos-glm::vec3(0,1,0))>=threshold) { vertexData.push_back(pos+0.5f*glm::vec3( 1,-1, 1)); vertexData.push_back(glm::vec3( 0,-1, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1,-1, 1)); vertexData.push_back(glm::vec3( 0,-1, 0)); vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1)); vertexData.push_back(glm::vec3( 0,-1, 0)); vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1)); vertexData.push_back(glm::vec3( 0,-1, 0)); } if(world_function(pos-glm::vec3(0,0,1))>=threshold) { vertexData.push_back(pos+0.5f*glm::vec3( 1, 1,-1)); vertexData.push_back(glm::vec3( 0, 0,-1)); vertexData.push_back(pos+0.5f*glm::vec3( 1,-1,-1)); vertexData.push_back(glm::vec3( 0, 0,-1)); vertexData.push_back(pos+0.5f*glm::vec3(-1, 1,-1)); vertexData.push_back(glm::vec3( 0, 0,-1)); vertexData.push_back(pos+0.5f*glm::vec3(-1,-1,-1)); vertexData.push_back(glm::vec3( 0, 0,-1)); } } } // upload glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &chunk.ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.ibo); chunk.quadcount = vertexData.size()/8; std::vector<GLuint> indexData(6*chunk.quadcount); for(int i = 0;i<chunk.quadcount;++i) { indexData[6*i + 0] = 4*i + 0; indexData[6*i + 1] = 4*i + 1; indexData[6*i + 2] = 4*i + 2; indexData[6*i + 3] = 4*i + 2; indexData[6*i + 4] = 4*i + 1; indexData[6*i + 5] = 4*i + 3; } // upload glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*indexData.size(), &indexData[0], GL_STATIC_DRAW); // chunk bounding box // generate and bind the vao glGenVertexArrays(1, &chunk.bounding_vao); glBindVertexArray(chunk.bounding_vao); // generate and bind the vertex buffer object glGenBuffers(1, &chunk.bounding_vbo); glBindBuffer(GL_ARRAY_BUFFER, chunk.bounding_vbo); // data for the bounding cube GLfloat boundingVertexData[] = { // X Y Z // face 0: offset.x+chunksize-0.5f, offset.y+chunksize-0.5f, offset.z+chunksize-0.5f, offset.x-0.5f, offset.y+chunksize-0.5f, offset.z+chunksize-0.5f, offset.x+chunksize-0.5f, offset.y-0.5f, offset.z+chunksize-0.5f, offset.x-0.5f, offset.y-0.5f, offset.z+chunksize-0.5f, // face 1: offset.x+chunksize-0.5f, offset.y+chunksize-0.5f, offset.z+chunksize-0.5f, offset.x+chunksize-0.5f, offset.y-0.5f, offset.z+chunksize-0.5f, offset.x+chunksize-0.5f, offset.y+chunksize-0.5f, offset.z-0.5f, offset.x+chunksize-0.5f, offset.y-0.5f, offset.z-0.5f, // face 2: offset.x+chunksize-0.5f, offset.y+chunksize-0.5f, offset.z+chunksize-0.5f, offset.x+chunksize-0.5f, offset.y+chunksize-0.5f, offset.z-0.5f, offset.x-0.5f, offset.y+chunksize-0.5f, offset.z+chunksize-0.5f, offset.x-0.5f, offset.y+chunksize-0.5f, offset.z-0.5f, // face 3: offset.x+chunksize-0.5f, offset.y+chunksize-0.5f, offset.z-0.5f, offset.x+chunksize-0.5f, offset.y-0.5f, offset.z-0.5f, offset.x-0.5f, offset.y+chunksize-0.5f, offset.z-0.5f, offset.x-0.5f, offset.y-0.5f, offset.z-0.5f, // face 4: offset.x-0.5f, offset.y+chunksize-0.5f, offset.z+chunksize-0.5f, offset.x-0.5f, offset.y+chunksize-0.5f, offset.z-0.5f, offset.x-0.5f, offset.y-0.5f, offset.z+chunksize-0.5f, offset.x-0.5f, offset.y-0.5f, offset.z-0.5f, // face 5: offset.x+chunksize-0.5f, offset.y-0.5f, offset.z+chunksize-0.5f, offset.x-0.5f, offset.y-0.5f, offset.z+chunksize-0.5f, offset.x+chunksize-0.5f, offset.y-0.5f, offset.z-0.5f, offset.x-0.5f, offset.y-0.5f, offset.z-0.5f, }; // 6 faces with 4 vertices with 6 components (floats) // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*3, boundingVertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &chunk.bounding_ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, chunk.bounding_ibo); GLuint boundingIndexData[] = { 0, 1, 2, 2, 1, 3, 4, 5, 6, 6, 5, 7, 8, 9,10,10, 9,11, 12,13,14,14,13,15,16,17,18,18,17,19,20,21,22,22,21,23, }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, boundingIndexData, GL_STATIC_DRAW); // generate the query object for the occlusion query glGenQueries(1, &chunk.query); // set the center location of the chunk chunk.center = offset + 0.5f*chunksize; // add to container chunks.push_back(chunk); } // "unbind" vao glBindVertexArray(0); // timer query setup // use multiple queries to avoid stalling on getting the results const int querycount = 5; GLuint queries[querycount]; int current_query = 0; glGenQueries(querycount, queries); // we are drawing 3d objects so we want depth testing glEnable(GL_DEPTH_TEST); // camera position and orientation glm::vec3 position; glm::mat4 rotation = glm::mat4(1.0f); running = true; float t = glfwGetTime(); bool occlusion_cull = true; bool space_down = false; // mouse position int mousex, mousey; glfwGetMousePos(&mousex, &mousey); while(running) { // calculate timestep float new_t = glfwGetTime(); float dt = new_t - t; t = new_t; // update mouse differential int tmpx, tmpy; glfwGetMousePos(&tmpx, &tmpy); glm::vec2 mousediff(tmpx-mousex, tmpy-mousey); mousex = tmpx; mousey = tmpy; // find up, forward and right vector glm::mat3 rotation3(rotation); glm::vec3 up = glm::transpose(rotation3)*glm::vec3(0.0f, 1.0f, 0.0f); glm::vec3 right = glm::transpose(rotation3)*glm::vec3(1.0f, 0.0f, 0.0f); glm::vec3 forward = glm::transpose(rotation3)*glm::vec3(0.0f, 0.0f,-1.0f); // apply mouse rotation rotation = glm::rotate(rotation, 0.2f*mousediff.x, up); rotation = glm::rotate(rotation, 0.2f*mousediff.y, right); // roll if(glfwGetKey('Q')) { rotation = glm::rotate(rotation, 180.0f*dt, forward); } if(glfwGetKey('E')) { rotation = glm::rotate(rotation,-180.0f*dt, forward); } // movement if(glfwGetKey('W')) { position += 10.0f*dt*forward; } if(glfwGetKey('S')) { position -= 10.0f*dt*forward; } if(glfwGetKey('D')) { position += 10.0f*dt*right; } if(glfwGetKey('A')) { position -= 10.0f*dt*right; } // toggle occlusion culling if(glfwGetKey(GLFW_KEY_SPACE) && !space_down) { occlusion_cull = !occlusion_cull; } space_down = glfwGetKey(GLFW_KEY_SPACE); // terminate on escape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 200.f); glm::mat4 View = rotation*glm::translate(glm::mat4(1.0f), -position); glm::mat4 ViewProjection = Projection*View; // set matrices for both shaders glUseProgram(query_shader_program); glUniformMatrix4fv(QueryViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); glUseProgram(shader_program); glUniformMatrix4fv(DrawViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); // set clear color to sky blue glClearColor(0.5f,0.8f,1.0f,1.0f); // clear glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // sort chunks by distance std::sort(chunks.begin(), chunks.end(), DistancePred(position)); size_t i = 0; float maxdist = chunksize; // start timer query glBeginQuery(GL_TIME_ELAPSED, queries[current_query]); // peel chunks while(i!=chunks.size()) { size_t j = i; if(occlusion_cull) { // start occlusion queries and render for the current slice glDisable(GL_CULL_FACE); // we don't want the queries to actually render something glDepthMask(GL_FALSE); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glUseProgram(query_shader_program); for(;j<chunks.size() && glm::distance(chunks[j].center, position)<maxdist;++j) { // frustum culling glm::vec4 projected = ViewProjection*glm::vec4(chunks[j].center,1); if( (glm::distance(chunks[j].center,position) > chunksize) && (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize)) continue; // begin occlusion query glBeginQuery(GL_ANY_SAMPLES_PASSED, chunks[j].query); // draw bounding box glBindVertexArray(chunks[j].bounding_vao); glDrawElements(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0); // end occlusion query glEndQuery(GL_ANY_SAMPLES_PASSED); } j = i; } // render the current slice glEnable(GL_CULL_FACE); // turn rendering back on glDepthMask(GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glUseProgram(shader_program); for(;j<chunks.size() && glm::distance(chunks[j].center, position)<maxdist;++j) { // frustum culling glm::vec4 projected = ViewProjection*glm::vec4(chunks[j].center,1); if( (glm::distance(chunks[j].center,position) > chunksize) && (std::max(std::abs(projected.x), std::abs(projected.y)) > projected.w+chunksize)) continue; // begin conditional render if(occlusion_cull) glBeginConditionalRender(chunks[j].query, GL_QUERY_BY_REGION_WAIT); // draw chunk glBindVertexArray(chunks[j].vao); glDrawElements(GL_TRIANGLES, 6*chunks[j].quadcount, GL_UNSIGNED_INT, 0); // end conditional render if(occlusion_cull) glEndConditionalRender(); } i = j; maxdist += 2*chunksize; } // end timer query glEndQuery(GL_TIME_ELAPSED); // display timer query results from querycount frames before if(GL_TRUE == glIsQuery(queries[(current_query+1)%querycount])) { GLuint64 result; glGetQueryObjectui64v(queries[(current_query+1)%querycount], GL_QUERY_RESULT, &result); std::cout << result*1.e-6 << " ms/frame" << std::endl; } // advance query counter current_query = (current_query + 1)%querycount; // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects for(size_t i = 0;i<chunks.size();++i) { glDeleteVertexArrays(1, &chunks[i].vao); glDeleteBuffers(1, &chunks[i].vbo); glDeleteBuffers(1, &chunks[i].ibo); glDeleteVertexArrays(1, &chunks[i].bounding_vao); glDeleteBuffers(1, &chunks[i].bounding_vbo); glDeleteBuffers(1, &chunks[i].bounding_ibo); glDeleteQueries(1, &chunks[i].query); } glDeleteQueries(querycount, queries); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glDetachShader(query_shader_program, query_vertex_shader); glDetachShader(query_shader_program, query_fragment_shader); glDeleteShader(query_vertex_shader); glDeleteShader(query_fragment_shader); glDeleteProgram(query_shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 330\n" "uniform mat4 View;\n" "uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(0.3,0.3,1.0,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint View_location = glGetUniformLocation(shader_program, "View"); GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); const int particles = 128*1024; // randomly place particles in a cube std::vector<glm::vec3> vertexData(particles); std::vector<glm::vec3> velocity(particles); for(int i = 0; i<particles; ++i) { vertexData[i] = glm::vec3(0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX); vertexData[i] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[i]; } int buffercount = 3; // generate vbos and vaos GLuint vao[buffercount], vbo[buffercount]; glGenVertexArrays(buffercount, vao); glGenBuffers(buffercount, vbo); for(int i = 0; i<buffercount; ++i) { glBindVertexArray(vao[i]); glBindBuffer(GL_ARRAY_BUFFER, vbo[i]); // fill with initial data glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), &vertexData[0], GL_DYNAMIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); } // "unbind" vao glBindVertexArray(0); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); // define spheres for the particles to bounce off const int spheres = 3; glm::vec3 center[spheres]; float radius[spheres]; center[0] = glm::vec3(0,12,1); radius[0] = 3; center[1] = glm::vec3(-3,0,0); radius[1] = 7; center[2] = glm::vec3(5,-10,0); radius[2] = 12; // physical parameters float dt = 1.0f/60.0f; glm::vec3 g(0.0f, -9.81f, 0.0f); float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f int current_buffer=0; running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on escape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // update physics for(int i = 0; i<particles; ++i) { // resolve sphere collisions for(int j = 0; j<spheres; ++j) { glm::vec3 diff = vertexData[i]-center[j]; float dist = glm::length(diff); if(dist<radius[j] && glm::dot(diff, velocity[i])<0.0f) velocity[i] -= bounce*diff/(dist*dist)*glm::dot(diff, velocity[i]); } // euler iteration velocity[i] += dt*g; vertexData[i] += dt*velocity[i]; // reset particles that fall out to a starting position if(vertexData[i].y<-30.0) { vertexData[i] = glm::vec3( 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX ); vertexData[i] = glm::vec3(0.0f,20.0f,0.0f) + 5.0f*vertexData[i]; velocity[i] = glm::vec3(0,0,0); } } // bind a buffer to upload to glBindBuffer(GL_ARRAY_BUFFER, vbo[(current_buffer+buffercount-1)%buffercount]); // explicitly invalidate the buffer glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec3)*vertexData.size(), 0, GL_DYNAMIC_DRAW); // map the buffer glm::vec3 *mapped = reinterpret_cast<glm::vec3*>( glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(glm::vec3)*vertexData.size(), GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT ) ); // copy data into the mapped memory std::copy(vertexData.begin(), vertexData.end(), mapped); // unmap the buffer glUnmapBuffer(GL_ARRAY_BUFFER); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); // make the camera rotate around the origin View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); // set the uniform glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the current vao glBindVertexArray(vao[current_buffer]); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); // advance buffer index current_buffer = (current_buffer + 1) % buffercount; } // delete the created objects glDeleteVertexArrays(buffercount, vao); glDeleteBuffers(buffercount, vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 4); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code // the vertex shader simply passes through data std::string vertex_source = "#version 430\n" "layout(location = 0) in vec4 vposition;\n" "void main() {\n" " gl_Position = vposition;\n" "}\n"; // the geometry shader creates the billboard quads std::string geometry_source = "#version 430\n" "uniform mat4 View;\n" "uniform mat4 Projection;\n" "layout (points) in;\n" "layout (triangle_strip, max_vertices = 4) out;\n" "out vec2 txcoord;\n" "void main() {\n" " vec4 pos = View*gl_in[0].gl_Position;\n" " txcoord = vec2(-1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1,-1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2(-1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" " txcoord = vec2( 1, 1);\n" " gl_Position = Projection*(pos+0.2*vec4(txcoord,0,0));\n" " EmitVertex();\n" "}\n"; // the fragment shader creates a bell like radial color distribution std::string fragment_source = "#version 330\n" "in vec2 txcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " float s = 0.2*(1/(1+15.*dot(txcoord, txcoord))-1/16.);\n" " FragColor = s*vec4(0.3,0.3,1.0,1);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, geometry_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler geometry shader geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); source = geometry_source.c_str(); length = geometry_source.size(); glShaderSource(geometry_shader, 1, &source, &length); glCompileShader(geometry_shader); if(!check_shader_compile_status(geometry_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, geometry_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint View_location = glGetUniformLocation(shader_program, "View"); GLint Projection_location = glGetUniformLocation(shader_program, "Projection"); std::string compute_source = "#version 430\n" "layout(local_size_x=256) in;\n" "uniform vec3 center[3];\n" "uniform float radius[3];\n" "uniform vec3 g;\n" "uniform float dt;\n" "uniform float bounce;\n" "uniform int seed;\n" "uniform layout(rgba32f) imageBuffer particles;\n" "float hash(int x) {\n" " x = x*1235167 + int(gl_GlobalInvocationID)*948737 + seed*9284365;\n" " x = (x >> 13) ^ x;\n" " return ((x * (x * x * 60493 + 19990303) + 1376312589) & 0x7fffffff)/float(0x7fffffff-1);\n" "}\n" "void main() {\n" " int index = int(gl_GlobalInvocationID);\n" " vec3 inposition = imageLoad(particles, 2*index).xyz;\n" " vec3 invelocity = imageLoad(particles, 2*index+1).xyz;\n" " vec3 outvelocity = invelocity;\n" " for(int j = 0;j<3;++j) {\n" " vec3 diff = inposition-center[j];\n" " float dist = length(diff);\n" " float vdot = dot(diff, invelocity);\n" " if(dist<radius[j] && vdot<0.0)\n" " outvelocity -= bounce*diff*vdot/(dist*dist);\n" " }\n" " outvelocity += dt*g;\n" " vec3 outposition = inposition + dt*outvelocity;\n" " if(outposition.y < -30.0)\n" " {\n" " outvelocity = vec3(0,0,0);\n" " outposition = 0.5-vec3(hash(3*index+0),hash(3*index+1),hash(3*index+2));\n" " outposition = vec3(0,20,0) + 5.0*outposition;\n" " }\n" " imageStore(particles, 2*index, vec4(outposition,1));\n" " imageStore(particles, 2*index+1, vec4(outvelocity,1));\n" "}\n"; // program and shader handles GLuint compute_program, compute_shader; // create and compiler vertex shader compute_shader = glCreateShader(GL_COMPUTE_SHADER); source = compute_source.c_str(); length = compute_source.size(); glShaderSource(compute_shader, 1, &source, &length); glCompileShader(compute_shader); if(!check_shader_compile_status(compute_shader)) { return 1; } // create program compute_program = glCreateProgram(); // attach shaders glAttachShader(compute_program, compute_shader); // link the program and check for errors glLinkProgram(compute_program); check_program_link_status(compute_program); GLint center_location = glGetUniformLocation(compute_program, "center"); GLint radius_location = glGetUniformLocation(compute_program, "radius"); GLint g_location = glGetUniformLocation(compute_program, "g"); GLint dt_location = glGetUniformLocation(compute_program, "dt"); GLint bounce_location = glGetUniformLocation(compute_program, "bounce"); GLint seed_location = glGetUniformLocation(compute_program, "seed"); GLint particles_location = glGetUniformLocation(compute_program, "particles"); const int particles = 128*1024; // randomly place particles in a cube std::vector<glm::vec4> vertexData(2*particles); for(int i = 0;i<particles;++i) { // initial position vertexData[2*i+0] = glm::vec4( 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0.5f-float(std::rand())/RAND_MAX, 0 ); vertexData[2*i+0] = glm::vec4(0.0f,20.0f,0.0f,1) + 5.0f*vertexData[2*i+0]; // initial velocity vertexData[2*i+1] = glm::vec4(0,0,0,0); } // generate vbos and vaos GLuint vao, vbo; glGenVertexArrays(1, &vao); glGenBuffers(1, &vbo); glBindVertexArray(vao); glBindBuffer(GL_ARRAY_BUFFER, vbo); // fill with initial data glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec4)*vertexData.size(), &vertexData[0], GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // set up generic attrib pointers glEnableVertexAttribArray(1); glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (char*)0 + 4*sizeof(GLfloat)); // "unbind" vao glBindVertexArray(0); // texture handle GLuint buffer_texture; // generate and bind the buffer texture glGenTextures(1, &buffer_texture); glBindTexture(GL_TEXTURE_BUFFER, buffer_texture); // tell the buffer texture to use glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32F, vbo); // we are blending so no depth testing glDisable(GL_DEPTH_TEST); // enable blending glEnable(GL_BLEND); // and set the blend function to result = 1*source + 1*destination glBlendFunc(GL_ONE, GL_ONE); // define spheres for the particles to bounce off const int spheres = 3; glm::vec3 center[spheres]; float radius[spheres]; center[0] = glm::vec3(0,12,1); radius[0] = 3; center[1] = glm::vec3(-3,0,0); radius[1] = 7; center[2] = glm::vec3(5,-10,0); radius[2] = 12; // physical parameters float dt = 1.0f/60.0f; glm::vec3 g(0.0f, -9.81f, 0.0f); float bounce = 1.2f; // inelastic: 1.0f, elastic: 2.0f int current_buffer=0; running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on excape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // use the transform shader program glUseProgram(compute_program); // set the uniforms glUniform3fv(center_location, 3, reinterpret_cast<GLfloat*>(center)); glUniform1fv(radius_location, 3, reinterpret_cast<GLfloat*>(radius)); glUniform3fv(g_location, 1, glm::value_ptr(g)); glUniform1f(dt_location, dt); glUniform1f(bounce_location, bounce); glUniform1i(seed_location, std::rand()); glBindImageTexture(0, buffer_texture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32F); glUniform1i(particles_location, 0); glDispatchCompute(particles/256, 1, 1); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -30.0f)); // make the camera rotate around the origin View = glm::rotate(View, 30.0f, glm::vec3(1.0f, 0.0f, 0.0f)); View = glm::rotate(View, -22.5f*t, glm::vec3(0.0f, 1.0f, 0.0f)); // set the uniform glUniformMatrix4fv(View_location, 1, GL_FALSE, glm::value_ptr(View)); glUniformMatrix4fv(Projection_location, 1, GL_FALSE, glm::value_ptr(Projection)); // bind the current vao glBindVertexArray(vao); // draw glDrawArrays(GL_POINTS, 0, particles); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteTextures(1, &buffer_texture); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, geometry_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(geometry_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glDetachShader(compute_program, compute_shader); glDeleteShader(compute_shader); glDeleteProgram(compute_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; UserData userdata; userdata.running = true; GLWTConfig glwt_config; glwt_config.red_bits = 8; glwt_config.green_bits = 8; glwt_config.blue_bits = 8; glwt_config.alpha_bits = 8; glwt_config.depth_bits = 24; glwt_config.stencil_bits = 8; glwt_config.samples = 0; glwt_config.sample_buffers = 0; glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE; glwt_config.api_version_major = 3; glwt_config.api_version_minor = 3; GLWTAppCallbacks app_callbacks; app_callbacks.error_callback = error_callback; app_callbacks.userdata = &userdata; if(glwtInit(&glwt_config, &app_callbacks) != 0) { std::cerr << "failed to init GLWT" << std::endl; return 1; } GLWTWindowCallbacks win_callbacks; win_callbacks.close_callback = close_callback; win_callbacks.expose_callback = 0; win_callbacks.resize_callback = 0; win_callbacks.show_callback = 0; win_callbacks.focus_callback = 0; win_callbacks.key_callback = key_callback, win_callbacks.motion_callback = 0; win_callbacks.button_callback = 0; win_callbacks.mouseover_callback = 0; win_callbacks.userdata = &userdata; // create a window GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0); if(window == 0) { std::cerr << "failed to open window" << std::endl; glwtQuit(); return 1; } if (glxwInit()) { std::cerr << "failed to init GLXW" << std::endl; glwtWindowDestroy(window); glwtQuit(); return 1; } glwtWindowShow(window, 1); glwtMakeCurrent(window); glwtSwapInterval(window, 1); // shader source code std::string vertex_source = "#version 330\n" "uniform mat4 ViewProjection;\n" // the projection matrix uniform "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "layout(location = 2) in vec3 voffset;\n" // the per instance offset "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = ViewProjection*(vposition + vec4(voffset, 0));\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of projection uniform GLint ViewProjection_location = glGetUniformLocation(shader_program, "ViewProjection"); // vao and vbo handles GLuint vao, vbo, tbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a cube GLfloat vertexData[] = { // X Y Z R G B // face 0: 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 // face 1: 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 // face 2: 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 // face 3: 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 // face 4: -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 // face 5: 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 }; // 6 faces with 4 vertices with 6 components (floats) // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { // face 0: 0,1,2, // first triangle 2,1,3, // second triangle // face 1: 4,5,6, // first triangle 6,5,7, // second triangle // face 2: 8,9,10, // first triangle 10,9,11, // second triangle // face 3: 12,13,14, // first triangle 14,13,15, // second triangle // face 4: 16,17,18, // first triangle 18,17,19, // second triangle // face 5: 20,21,22, // first triangle 22,21,23, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); // generate and bind the vertex buffer object containing the // instance offsets glGenBuffers(1, &tbo); glBindBuffer(GL_ARRAY_BUFFER, tbo); // the offsets GLfloat translationData[] = { 2.0f, 2.0f, 2.0f, // cube 0 2.0f, 2.0f,-2.0f, // cube 1 2.0f,-2.0f, 2.0f, // cube 2 2.0f,-2.0f,-2.0f, // cube 3 -2.0f, 2.0f, 2.0f, // cube 4 -2.0f, 2.0f,-2.0f, // cube 5 -2.0f,-2.0f, 2.0f, // cube 6 -2.0f,-2.0f,-2.0f, // cube 7 }; // 8 offsets with 3 components each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*3*8, translationData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(2); glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 3*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); // a attrib divisor of 1 means that attribute 2 will advance once // every instance (0 would mean once per vertex) glVertexAttribDivisor(2, 1); // "unbind" vao glBindVertexArray(0); // we are drawing 3d objects so we want depth testing glEnable(GL_DEPTH_TEST); while(userdata.running) { // get the time in seconds float t = glwtGetNanoTime()*1.e-9f; // update events glwtEventHandle(0); // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); // make the camera rotate around the origin View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); glm::mat4 ViewProjection = Projection*View; // set the uniform glUniformMatrix4fv(ViewProjection_location, 1, GL_FALSE, glm::value_ptr(ViewProjection)); // bind the vao glBindVertexArray(vao); // draw // the additional parameter indicates how many instances to render glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { userdata.running = false; } // finally swap buffers glwtSwapBuffers(window); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDeleteBuffers(1, &tbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glwtWindowDestroy(window); glwtQuit(); return 0; }
int main() { int width = 640; int height = 480; UserData userdata; userdata.running = true; GLWTConfig glwt_config; glwt_config.red_bits = 8; glwt_config.green_bits = 8; glwt_config.blue_bits = 8; glwt_config.alpha_bits = 8; glwt_config.depth_bits = 24; glwt_config.stencil_bits = 8; glwt_config.samples = 0; glwt_config.sample_buffers = 0; glwt_config.api = GLWT_API_OPENGL | GLWT_PROFILE_CORE; glwt_config.api_version_major = 3; glwt_config.api_version_minor = 3; GLWTAppCallbacks app_callbacks; app_callbacks.error_callback = error_callback; app_callbacks.userdata = &userdata; if(glwtInit(&glwt_config, &app_callbacks) != 0) { std::cerr << "failed to init GLWT" << std::endl; return 1; } GLWTWindowCallbacks win_callbacks; win_callbacks.close_callback = close_callback; win_callbacks.expose_callback = 0; win_callbacks.resize_callback = 0; win_callbacks.show_callback = 0; win_callbacks.focus_callback = 0; win_callbacks.key_callback = key_callback, win_callbacks.motion_callback = 0; win_callbacks.button_callback = 0; win_callbacks.mouseover_callback = 0; win_callbacks.userdata = &userdata; // create a window GLWTWindow *window = glwtWindowCreate("", width, height, &win_callbacks, 0); if(window == 0) { std::cerr << "failed to open window" << std::endl; glwtQuit(); return 1; } if (glxwInit()) { std::cerr << "failed to init GLXW" << std::endl; glwtWindowDestroy(window); glwtQuit(); return 1; } glwtWindowShow(window, 1); glwtMakeCurrent(window); glwtSwapInterval(window, 1); // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec2 vtexcoord;\n" "out vec2 ftexcoord;\n" "void main() {\n" " ftexcoord = vtexcoord;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "uniform sampler2D tex;\n" // texture uniform "in vec2 ftexcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = texture(tex, ftexcoord);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // get texture uniform location GLint texture_location = glGetUniformLocation(shader_program, "tex"); // vao and vbo handle GLuint vao, vbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad (this time with texture coords) GLfloat vertexData[] = { // X Y Z U V 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 0.0f, 0.0f, 0.0f, // vertex 3 }; // 4 vertices with 5 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*5, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { 0,1,2, // first triangle 2,1,3, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); // "unbind" vao glBindVertexArray(0); // texture handle GLuint texture; // generate texture glGenTextures(1, &texture); // bind the texture glBindTexture(GL_TEXTURE_2D, texture); // create some image data std::vector<GLubyte> image(4*width*height); for(int j = 0;j<height;++j) for(int i = 0;i<width;++i) { size_t index = j*width + i; image[4*index + 0] = 0xFF*(j/10%2)*(i/10%2); // R image[4*index + 1] = 0xFF*(j/13%2)*(i/13%2); // G image[4*index + 2] = 0xFF*(j/17%2)*(i/17%2); // B image[4*index + 3] = 0xFF; // A } // set texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // set texture content glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]); while(userdata.running) { // update events glwtEventHandle(0); // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind texture to texture unit 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); // set texture uniform glUniform1i(texture_location, 0); // bind the vao glBindVertexArray(vao); // draw glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { userdata.running = false; } // finally swap buffers glwtSwapBuffers(window); } // delete the created objects glDeleteTextures(1, &texture); glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glwtWindowDestroy(window); glwtQuit(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // select opengl version glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code std::string vertex_source = "#version 330\n" "layout(std140) uniform Matrices {\n" " mat4 ViewProjection;\n" " mat4 Model[8];\n" "};\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = ViewProjection*Model[gl_InstanceID]*vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // obtain location of the uniform block GLuint Matrices_binding = 0; GLint uniform_block_index = glGetUniformBlockIndex(shader_program, "Matrices"); // assign the block binding glUniformBlockBinding(shader_program, uniform_block_index, Matrices_binding); // create uniform buffer GLuint ubo; glGenBuffers(1, &ubo); glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferData(GL_UNIFORM_BUFFER, 9*sizeof(float)*4*4, 0, GL_STREAM_DRAW); // fill the Model matrix array glm::mat4 ModelMatrices[8]; ModelMatrices[0] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f, 2.0f, 2.0f)); ModelMatrices[1] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f, 2.0f,-2.0f)); ModelMatrices[2] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f,-2.0f, 2.0f)); ModelMatrices[3] = glm::translate(glm::mat4(1.0f), glm::vec3( 2.0f,-2.0f,-2.0f)); ModelMatrices[4] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 2.0f, 2.0f)); ModelMatrices[5] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f, 2.0f,-2.0f)); ModelMatrices[6] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f,-2.0f, 2.0f)); ModelMatrices[7] = glm::translate(glm::mat4(1.0f), glm::vec3(-2.0f,-2.0f,-2.0f)); glBufferSubData(GL_UNIFORM_BUFFER, sizeof(float)*4*4, 8*sizeof(float)*4*4, ModelMatrices); // vao and vbo handle GLuint vao, vbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a cube GLfloat vertexData[] = { // X Y Z R G B // face 0: 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 1 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 0.0f, // vertex 3 // face 1: 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 3 // face 2: 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 0 1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 -1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 2 -1.0f, 1.0f,-1.0f, 0.0f, 0.0f, 1.0f, // vertex 3 // face 3: 1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 0 1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 1 -1.0f, 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 1.0f, 0.0f, // vertex 3 // face 4: -1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 -1.0f, 1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 1 -1.0f,-1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 0.0f, 1.0f, 1.0f, // vertex 3 // face 5: 1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 0 -1.0f,-1.0f, 1.0f, 1.0f, 0.0f, 1.0f, // vertex 1 1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 2 -1.0f,-1.0f,-1.0f, 1.0f, 0.0f, 1.0f, // vertex 3 }; // 6 faces with 4 vertices with 6 components (floats) // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*4*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { // face 0: 0,1,2, // first triangle 2,1,3, // second triangle // face 1: 4,5,6, // first triangle 6,5,7, // second triangle // face 2: 8,9,10, // first triangle 10,9,11, // second triangle // face 3: 12,13,14, // first triangle 14,13,15, // second triangle // face 4: 16,17,18, // first triangle 18,17,19, // second triangle // face 5: 20,21,22, // first triangle 22,21,23, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*6*2*3, indexData, GL_STATIC_DRAW); // "unbind" vao glBindVertexArray(0); // we are drawing 3d objects so we want depth testing glEnable(GL_DEPTH_TEST); running = true; while(running) { // get the time in seconds float t = glfwGetTime(); // terminate on escape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // clear first glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // calculate ViewProjection matrix glm::mat4 Projection = glm::perspective(90.0f, 4.0f / 3.0f, 0.1f, 100.f); // translate the world/view position glm::mat4 View = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f)); // make the camera rotate around the origin View = glm::rotate(View, 90.0f*t, glm::vec3(1.0f, 1.0f, 1.0f)); glm::mat4 ViewProjection = Projection*View; // set the ViewProjection in the uniform buffer glBindBuffer(GL_UNIFORM_BUFFER, ubo); glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(float)*4*4, glm::value_ptr(ViewProjection)); glBindBufferRange(GL_UNIFORM_BUFFER, Matrices_binding, ubo, 0, sizeof(float)*4*4*9); // bind the vao glBindVertexArray(vao); // draw // the additional parameter indicates how many instances to render glDrawElementsInstanced(GL_TRIANGLES, 6*6, GL_UNSIGNED_INT, 0, 8); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) < 0) { std::cerr << "failed to init SDL" << std::endl; return 1; } // select opengl version SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); // create a window SDL_Window *window; if((window = SDL_CreateWindow("SDL2", 0, 0, width, height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN)) == 0) { std::cerr << "failed to open window" << std::endl; SDL_Quit(); return 1; } SDL_GLContext context = SDL_GL_CreateContext(window); if(gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 1; } // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); if(!check_program_link_status(shader_program)) { SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 1; } // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z R G B 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 }; // 6 vertices with 6 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); bool closed = false; while(!closed) { SDL_Event event; while(SDL_PollEvent(&event)) { if(event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_CLOSE) { closed = true; } } // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_TRIANGLES, 0, 6); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << error << std::endl; break; } // finally swap buffers SDL_GL_SwapWindow(window); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 0; }
int main() { int width = 640; int height = 480; if(glfwInit() == GL_FALSE) { std::cerr << "failed to init GLFW" << std::endl; return 1; } // sadly glew doesn't play nice with core profiles... glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 3); // create a window if(glfwOpenWindow(width, height, 0, 0, 0, 8, 24, 8, GLFW_WINDOW) == GL_FALSE) { std::cerr << "failed to open window" << std::endl; glfwTerminate(); return 1; } // setup windows close callback glfwSetWindowCloseCallback(closedWindow); if (gl3wInit()) { std::cerr << "failed to init GL3W" << std::endl; glfwCloseWindow(); glfwTerminate(); return 1; } // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec2 vtexcoord;\n" "out vec2 ftexcoord;\n" "void main() {\n" " ftexcoord = vtexcoord;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "uniform sampler2D tex;\n" // texture uniform "in vec2 ftexcoord;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = texture(tex, ftexcoord);\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); check_program_link_status(shader_program); // get texture uniform location GLint texture_location = glGetUniformLocation(shader_program, "tex"); // vao and vbo handle GLuint vao, vbo, ibo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the vertex buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad (this time with texture coords) GLfloat vertexData[] = { // X Y Z U V 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, // vertex 1 1.0f,-1.0f, 0.0f, 1.0f, 0.0f, // vertex 2 -1.0f,-1.0f, 0.0f, 0.0f, 0.0f, // vertex 3 }; // 4 vertices with 5 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*5, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); // generate and bind the index buffer object glGenBuffers(1, &ibo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo); GLuint indexData[] = { 0,1,2, // first triangle 2,1,3, // second triangle }; // fill with data glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint)*2*3, indexData, GL_STATIC_DRAW); // "unbind" vao glBindVertexArray(0); // texture handle GLuint texture; // generate texture glGenTextures(1, &texture); // bind the texture glBindTexture(GL_TEXTURE_2D, texture); // create some image data std::vector<GLubyte> image(4*width*height); for(int j = 0;j<height;++j) for(int i = 0;i<width;++i) { size_t index = j*width + i; image[4*index + 0] = 0xFF*(j/10%2)*(i/10%2); // R image[4*index + 1] = 0xFF*(j/13%2)*(i/13%2); // G image[4*index + 2] = 0xFF*(j/17%2)*(i/17%2); // B image[4*index + 3] = 0xFF; // A } // set texture parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // set texture content glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]); running = true; while(running) { // terminate on excape if(glfwGetKey(GLFW_KEY_ESC)) { running = false; } // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind texture to texture unit 0 glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, texture); // set texture uniform glUniform1i(texture_location, 0); // bind the vao glBindVertexArray(vao); // draw glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << gluErrorString(error); running = false; } // finally swap buffers glfwSwapBuffers(); } // delete the created objects glDeleteTextures(1, &texture); glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDeleteBuffers(1, &ibo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); glfwCloseWindow(); glfwTerminate(); return 0; }
int main() { int width = 640; int height = 480; sf::Window window(sf::VideoMode(width, height), "sfml", sf::Style::Default, sf::ContextSettings(0,0,0,3,3)); // using glew since sfml doesn create a core context if(glewInit()) { std::cerr << "failed to init GLEW" << std::endl; return 1; } // shader source code std::string vertex_source = "#version 330\n" "layout(location = 0) in vec4 vposition;\n" "layout(location = 1) in vec4 vcolor;\n" "out vec4 fcolor;\n" "void main() {\n" " fcolor = vcolor;\n" " gl_Position = vposition;\n" "}\n"; std::string fragment_source = "#version 330\n" "in vec4 fcolor;\n" "layout(location = 0) out vec4 FragColor;\n" "void main() {\n" " FragColor = fcolor;\n" "}\n"; // program and shader handles GLuint shader_program, vertex_shader, fragment_shader; // we need these to properly pass the strings const char *source; int length; // create and compiler vertex shader vertex_shader = glCreateShader(GL_VERTEX_SHADER); source = vertex_source.c_str(); length = vertex_source.size(); glShaderSource(vertex_shader, 1, &source, &length); glCompileShader(vertex_shader); if(!check_shader_compile_status(vertex_shader)) { return 1; } // create and compiler fragment shader fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); source = fragment_source.c_str(); length = fragment_source.size(); glShaderSource(fragment_shader, 1, &source, &length); glCompileShader(fragment_shader); if(!check_shader_compile_status(fragment_shader)) { return 1; } // create program shader_program = glCreateProgram(); // attach shaders glAttachShader(shader_program, vertex_shader); glAttachShader(shader_program, fragment_shader); // link the program and check for errors glLinkProgram(shader_program); if(!check_program_link_status(shader_program)) { return 1; } // vao and vbo handle GLuint vao, vbo; // generate and bind the vao glGenVertexArrays(1, &vao); glBindVertexArray(vao); // generate and bind the buffer object glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); // data for a fullscreen quad GLfloat vertexData[] = { // X Y Z R G B 1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 0 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 1 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 2 1.0f,-1.0f, 0.0f, 0.0f, 0.0f, 1.0f, // vertex 3 -1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, // vertex 4 -1.0f,-1.0f, 0.0f, 1.0f, 0.0f, 0.0f, // vertex 5 }; // 6 vertices with 6 components (floats) each // fill with data glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*6*6, vertexData, GL_STATIC_DRAW); // set up generic attrib pointers glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 0*sizeof(GLfloat)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6*sizeof(GLfloat), (char*)0 + 3*sizeof(GLfloat)); bool closed = false; while(!closed) { sf::Event event; while(window.pollEvent(event)) { if(event.type == sf::Event::Closed) { closed = true; } } // clear first glClear(GL_COLOR_BUFFER_BIT); // use the shader program glUseProgram(shader_program); // bind the vao glBindVertexArray(vao); // draw glDrawArrays(GL_TRIANGLES, 0, 6); // check for errors GLenum error = glGetError(); if(error != GL_NO_ERROR) { std::cerr << error << std::endl; break; } // finally swap buffers window.display(); } // delete the created objects glDeleteVertexArrays(1, &vao); glDeleteBuffers(1, &vbo); glDetachShader(shader_program, vertex_shader); glDetachShader(shader_program, fragment_shader); glDeleteShader(vertex_shader); glDeleteShader(fragment_shader); glDeleteProgram(shader_program); return 0; }