/** * From the OpenGL Programming wikibook: http://en.wikibooks.org/wiki/OpenGL_Programming * This file is in the public domain. * Contributors: Sylvain Beucler */ #include #include #include /* Use glew.h instead of gl.h to get all the GL prototypes declared */ #include /* Using the GLUT library for the base windowing setup */ #include /* GLM */ // #define GLM_MESSAGES #define GLM_FORCE_RADIANS #include #include #include #include "../common/shader_utils.h" #include //#include "res_texture.c" int screen_width=800, screen_height=600; GLuint vbo_cube_vertices, vbo_cube_texcoords; GLuint ibo_cube_elements; GLuint program; GLuint texture_id; GLint attribute_coord3d, attribute_texcoord; GLint uniform_mvp, uniform_mytexture; GLint uniform_width, uniform_height; int width, height; GLuint input_image, output_image; int init_resources() { // Load image unsigned char* image = SOIL_load_image("brick.jpg", &width, &height, 0, SOIL_LOAD_RGBA); printf("Found Texture: (%f by %f)\n", float(width), float(height)); GLfloat cube_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, // top -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, // bottom -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, // left -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, // right 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, }; glGenBuffers(1, &vbo_cube_vertices); glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices); glBufferData(GL_ARRAY_BUFFER, sizeof(cube_vertices), cube_vertices, GL_STATIC_DRAW); float cube_texcoords[2*4*6] = { // front 0, 0, float(width), 0, float(width), float(height), 0, float(height), }; for (int i = 1; i < 6; i++) memcpy(&cube_texcoords[i*4*2], &cube_texcoords[0], 2*4*sizeof(float)); glGenBuffers(1, &vbo_cube_texcoords); glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords); glBufferData(GL_ARRAY_BUFFER, sizeof(cube_texcoords), cube_texcoords, GL_STATIC_DRAW); GLushort cube_elements[] = { // front 0, 1, 2, 2, 3, 0, // top 4, 5, 6, 6, 7, 4, // back 8, 9, 10, 10, 11, 8, // bottom 12, 13, 14, 14, 15, 12, // left 16, 17, 18, 18, 19, 16, // right 20, 21, 22, 22, 23, 20, }; glGenBuffers(1, &ibo_cube_elements); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements); glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cube_elements), cube_elements, GL_STATIC_DRAW); GLint link_ok = GL_FALSE; GLuint vs, fs; if ((vs = create_shader("cube.v.glsl", GL_VERTEX_SHADER)) == 0) return 0; if ((fs = create_shader("cube.f.glsl", GL_FRAGMENT_SHADER)) == 0) return 0; program = glCreateProgram(); glAttachShader(program, vs); glAttachShader(program, fs); glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if (!link_ok) { fprintf(stderr, "glLinkProgram:"); print_log(program); return 0; } const char* attribute_name; attribute_name = "coord3d"; attribute_coord3d = glGetAttribLocation(program, attribute_name); if (attribute_coord3d == -1) { fprintf(stderr, "Could not bind attribute %s\n", attribute_name); return 0; } attribute_name = "texcoord"; attribute_texcoord = glGetAttribLocation(program, attribute_name); if (attribute_texcoord == -1) { fprintf(stderr, "Could not bind attribute %s\n", attribute_name); return 0; } const char* uniform_name; uniform_name = "mvp"; uniform_mvp = glGetUniformLocation(program, uniform_name); if (uniform_mvp == -1) { fprintf(stderr, "Could not bind uniform %s\n", uniform_name); return 0; } uniform_name = "width"; uniform_width = glGetUniformLocation(program, uniform_name); if (uniform_width == -1) { fprintf(stderr, "Could not bind uniform %s\n", uniform_name); return 0; } uniform_name = "height"; uniform_height = glGetUniformLocation(program, uniform_name); if (uniform_height == -1) { fprintf(stderr, "Could not bind uniform %s\n", uniform_name); return 0; } // Set up compute shader GLuint image_transformer = glCreateProgram(); glAttachShader(image_transformer, create_shader("filter.c.glsl", GL_COMPUTE_SHADER)); glLinkProgram(image_transformer); glGetProgramiv(image_transformer, GL_LINK_STATUS, &link_ok); if (!link_ok) { fprintf(stderr, "glLinkProgram filter.c.glsl:"); print_log(image_transformer); return 0; } // Set up GPU buffers glGenBuffers(1, &input_image); glBindBuffer(GL_ARRAY_BUFFER, input_image); glBufferData(GL_ARRAY_BUFFER, width*height*4, image, GL_DYNAMIC_DRAW); glGenBuffers(1, &output_image); glBindBuffer(GL_ARRAY_BUFFER, output_image); glBufferData(GL_ARRAY_BUFFER, width*height*4, 0, GL_DYNAMIC_DRAW); // Bind buffers for the compute shader to use glUseProgram(image_transformer); glUniform1i(glGetUniformLocation(image_transformer, "width"), width); glUniform1i(glGetUniformLocation(image_transformer, "height"), height); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, input_image); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, output_image); // Actually run the compute shader glDispatchCompute(width * height, 1, 1); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); GLuint feedback[12]; glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, output_image); glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(feedback), feedback); for(GLuint *i = feedback; i < sizeof(feedback)/sizeof(float) + feedback; i++) printf("%x ", *i); printf("\n"); return 1; } void onIdle() { float angle = glutGet(GLUT_ELAPSED_TIME) / 1000.0 * glm::radians(15.0); // base 15° per second glm::mat4 anim = \ glm::rotate(glm::mat4(1.0f), angle*3.0f, glm::vec3(1, 0, 0)) * // X axis glm::rotate(glm::mat4(1.0f), angle*2.0f, glm::vec3(0, 1, 0)) * // Y axis glm::rotate(glm::mat4(1.0f), angle*4.0f, glm::vec3(0, 0, 1)); // Z axis glm::mat4 model = glm::translate(glm::mat4(1.0f), glm::vec3(0.0, 0.0, -4.0)); glm::mat4 view = glm::lookAt(glm::vec3(0.0, 2.0, 0.0), glm::vec3(0.0, 0.0, -4.0), glm::vec3(0.0, 1.0, 0.0)); glm::mat4 projection = glm::perspective(45.0f, 1.0f*screen_width/screen_height, 0.1f, 10.0f); glm::mat4 mvp = projection * view * model * anim; glUseProgram(program); glUniformMatrix4fv(uniform_mvp, 1, GL_FALSE, glm::value_ptr(mvp)); glutPostRedisplay(); } void onDisplay() { glClearColor(1.0, 1.0, 1.0, 1.0); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glUseProgram(program); glUniform1f(uniform_width, float(width)); glUniform1f(uniform_height, float(height)); glEnableVertexAttribArray(attribute_coord3d); // Describe our vertices array to OpenGL (it can't guess its format automatically) glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_vertices); glVertexAttribPointer( attribute_coord3d, // attribute 3, // number of elements per vertex, here (x,y,z) GL_FLOAT, // the type of each element GL_FALSE, // take our values as-is 0, // no extra data between each position 0 // offset of first element ); glEnableVertexAttribArray(attribute_texcoord); glBindBuffer(GL_ARRAY_BUFFER, vbo_cube_texcoords); glVertexAttribPointer( attribute_texcoord, // attribute 2, // number of elements per vertex, here (x,y) GL_FLOAT, // the type of each element GL_FALSE, // take our values as-is 0, // no extra data between each position 0 // offset of first element ); /* Push each element in buffer_vertices to the vertex shader */ glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, output_image); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo_cube_elements); int size; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &size); glDrawElements(GL_TRIANGLES, size/sizeof(GLushort), GL_UNSIGNED_SHORT, 0); glDisableVertexAttribArray(attribute_coord3d); glDisableVertexAttribArray(attribute_texcoord); glutSwapBuffers(); } void onReshape(int width, int height) { screen_width = width; screen_height = height; glViewport(0, 0, screen_width, screen_height); } void free_resources() { glDeleteProgram(program); glDeleteBuffers(1, &vbo_cube_vertices); glDeleteBuffers(1, &vbo_cube_texcoords); glDeleteBuffers(1, &ibo_cube_elements); glDeleteTextures(1, &texture_id); } int main(int argc, char* argv[]) { glutInit(&argc, argv); glutInitContextVersion(2,0); glutInitDisplayMode(GLUT_RGBA|GLUT_ALPHA|GLUT_DOUBLE|GLUT_DEPTH); glutInitWindowSize(screen_width, screen_height); glutCreateWindow("My Textured Cube"); GLenum glew_status = glewInit(); if (glew_status != GLEW_OK) { fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status)); return 1; } if (!GLEW_VERSION_2_0) { fprintf(stderr, "Error: your graphic card does not support OpenGL 2.0\n"); return 1; } if (init_resources()) { glutDisplayFunc(onDisplay); glutReshapeFunc(onReshape); glutIdleFunc(onIdle); glEnable(GL_BLEND); glEnable(GL_DEPTH_TEST); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glutMainLoop(); } free_resources(); return 0; }