/* Simplified OpenGL 4.5 demo * Seth Long, Fall 2020 * This is a *very* short demo which displays a triangle * Many of these functions can fail, and return error values * I doubt it can be done much shorter without leaving vertices in only main memory or some such */ #include #include #include #include #include #include #include #include #include #include #include "scolor.hpp" #include "util.h" char general_buffer[GBLEN]; const float height = 1080; const float width = 1920; void GLAPIENTRY MessageCallback( GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message, const void* userParam ) { fprintf( stderr, "GL CALLBACK: %s type = 0x%x, severity = 0x%x, message = %s\n", ( type == GL_DEBUG_TYPE_ERROR ? "** GL ERROR **" : "" ), type, severity, message ); } int main(int argc, char ** argv){ glfwInit(); GLFWwindow* window = glfwCreateWindow(width, height, "Simple OpenGL 4.0+ Demo", 0, 0); glfwMakeContextCurrent(window); glewInit(); // During init, enable debug output glEnable ( GL_DEBUG_OUTPUT ); glDebugMessageCallback( MessageCallback, 0 ); // Initialization part float vertices[] = { // front -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, // back -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, }; unsigned int vbuf; glGenBuffers(1, &vbuf); glBindBuffer(GL_SHADER_STORAGE_BUFFER, vbuf); glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); GLushort cube_elements[] = { // front 0, 1, 2, 3, // top 1, 5, 6, 2, // back 5, 4, 7, 6, // bottom 4, 0, 3, 7, // left 4, 5, 1, 0, // right 7, 6, 2, 3 }; unsigned int ebuf; glGenBuffers(1, &ebuf); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebuf); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW); int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); GLuint visual_program = make_program("vertex_shader.glsl", "tess_control.glsl", "tess_eval.glsl", 0, "fragment_shader.glsl"); if(!visual_program) return 1; unsigned int v_attrib = glGetAttribLocation(visual_program, "in_vertex"); unsigned int mvp_uniform = glGetUniformLocation(visual_program, "mvp"); unsigned int width_uniform = glGetUniformLocation(visual_program, "width"); unsigned int height_uniform = glGetUniformLocation(visual_program, "height"); GLuint program = glCreateProgram(); GLuint shader = make_shader("image_filter.glsl", GL_COMPUTE_SHADER); glAttachShader(program, shader); glLinkProgram(program); GLint link_ok; glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if(!link_ok){ glGetProgramInfoLog(program, GBLEN, NULL, general_buffer); puts(general_buffer); puts(RED("Link Failed").c_str()); return 1; } unsigned int compute_width_uniform = glGetUniformLocation(program, "width"); int img_width, img_height; unsigned char* image = SOIL_load_image("monster1.png", &img_width, &img_height, 0, SOIL_LOAD_RGBA); if(!image) puts(RED("No image, giving up!").c_str()); else printf(PURPLE("Image size: %d by %d\n").c_str(), img_width, img_height); unsigned int image_buffer; glGenBuffers(1, &image_buffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER, image_buffer); glBufferData(GL_SHADER_STORAGE_BUFFER, 4 * img_width * img_height, image, GL_STATIC_DRAW); int count = 0; glEnable(GL_DEPTH_TEST); while(!glfwWindowShouldClose(window)){ count++; // Run the compute shader glUseProgram(program); glUniform1ui(compute_width_uniform, img_width); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, image_buffer); glDispatchCompute(img_width*img_height, 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); // Do the visual rendering bit glfwPollEvents(); glClearColor(0, 0, 0, 1.0); glClear(GL_COLOR_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT); glm::vec3 axis_y(0, 1, 0); glm::mat4 model = glm::rotate(glm::mat4(1.0f), count/100.0f, glm::vec3(0, 1, 0)); model = glm::rotate(model, count/100.0f, glm::vec3(1, 0, 0)); glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 4.0f), glm::vec3(0, 0, 0), axis_y); glm::mat4 projection = glm::perspective(45.0f, width/height, 0.1f, 1000.0f); glm::mat4 mvp = projection * view * model; glUseProgram(visual_program); glEnableVertexAttribArray(v_attrib); glBindBuffer(GL_ARRAY_BUFFER, vbuf); glVertexAttribPointer(v_attrib, 3, GL_FLOAT, GL_FALSE, 0, 0); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, image_buffer); glUniformMatrix4fv(mvp_uniform, 1, 0, glm::value_ptr(mvp)); glUniform1ui(width_uniform, img_width); glUniform1ui(height_uniform, img_height); glPatchParameteri(GL_PATCH_VERTICES, 4); glDrawElementsInstanced(GL_PATCHES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0, 1); glfwSwapBuffers(window); } glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, img_width*img_height*sizeof(int), image); // write image SOIL_save_image("done.bmp", SOIL_SAVE_TYPE_BMP, img_width, img_height, 4, image); puts(GREEN("Saved image as done.bmp").c_str()); glDeleteProgram(program); glDeleteProgram(visual_program); glfwDestroyWindow(window); glfwTerminate(); } // g++ load_object.cpp -lGL -lglfw -lGLEW