/* Simplified OpenGL 4.5 demo * Seth Long, Fall 2020 * Expanded demo to show an object with a vector of locations * This will demonstrate instanced rendering */ #include #include #include #include #include #include #include #include vec3 player_location; mat4 view; mat4 projection; class object { public: vector locations; // vector vertices; // maybe later // vector vertex_colors; // maybe later unsigned int vbuf, cbuf; unsigned int program; unsigned int v_attrib; unsigned int c_attrib; unsigned int mvp_uniform; void init(){ // Initialization part float vertices[] = {0, 1, 0, -0.5, 0, 0, 0.5, 0, 0}; glGenBuffers(1, &vbuf); glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); float colors[] = {1, 0, 0, 1, 0, 0, 0, 0.5, 0}; unsigned int cbuf; glGenBuffers(1, &cbuf); glBindBuffer(GL_SHADER_STORAGE_BUFFER, cbuf); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(colors), colors, GL_STATIC_DRAW); int fd = open("vertex_shader.glsl", O_RDONLY); char *source = malloc(2048); size_t readlen = read(fd, source, 2048); if(2048 == readlen) printf("Warning: vertex shader is probably too long for this read routine\n"); source[readlen] = 0; puts(source); close(fd); unsigned int vs_reference = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vs_reference, 1, (const char**)&source, 0); glCompileShader(vs_reference); fd = open("fragment_shader.glsl", O_RDONLY); readlen = read(fd, source, 2048); source[readlen] = 0; puts(source); close(fd); unsigned int fs_reference = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fs_reference, 1, (const char**)&source, 0); glCompileShader(fs_reference); free(source); program = glCreateProgram(); glAttachShader(program, vs_reference); glAttachShader(program, fs_reference); glLinkProgram(program); v_attrib = glGetAttribLocation(program, "in_vertex"); c_attrib = glGetAttribLocation(program, "in_color"); mvp_uniform = glGetUniformLocation(program, "mvp"); } void draw(){ if(locations.size() == 0) return; glUseProgram(program); glEnableVertexAttribArray(v_attrib); glBindBuffer(GL_ARRAY_BUFFER, vbuf); glVertexAttribPointer(v_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); glEnableVertexAttribArray(c_attrib); glBindBuffer(GL_ARRAY_BUFFER, cbuf); glVertexAttribPointer(c_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); mat4 model = GLM_MAT4_IDENTITY_INIT; glm_rotate(model, count / 100.0f, GLM_YUP); mat4 mvps[locations.size()]; // As long as it fits on the stack for(int i = 0; i < locations.size(); i++){ // Initialize to identity glm_mul(projection, view, mvps[i]); glm_mul(mvp, model, mvp[i]); } // All of these instead of one glUniformMatrix4fv(mvp_uniform, 1, 0, (float*)mvp); glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 10); // copy locations to the card as a uniform glDrawElementsInstanced( ... locations.size()); } }; vector game_objects; const float height = 1600; const float width = 2560/2; int main(int argc, char ** argv){ glfwInit(); GLFWwindow* window = glfwCreateWindow(width, height, "Simple OpenGL 4.0+ Demo", 0, 0); glfwMakeContextCurrent(window); glewInit(); int count = 0; glm_perspective(45.0, width/height, 0.1, 1000.0, projection); // glEnable(GL_DEPTH_TEST); while(!glfwWindowShouldClose(window)){ count++; glfwPollEvents(); glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT); for(auto o : game_objects) o.draw(); glfwSwapBuffers(window); // usleep(10000); } glDeleteProgram(program); glfwDestroyWindow(window); glfwTerminate(); }