rendered paste body#include <GL/glew.h>#include <GL/glut.h>#include <stdio.h>#include <stdarg.h>#include <stdlib.h>#include <math.h>#include <time.h>#define CHECK_ERROR \ do { \ GLenum error; \ error = glGetError(); \ if (error != 0) \ printf("*LINE: %d %s\n", __LINE__, gluErrorString(error)); \ } while(0)GLuint fb;GLuint tex[64];GLuint output_tex[64];GLuint n = 4, real_n;GLuint num_tex;GLuint num_levels;GLuint startsize_w = 4, startsize_h = 4;GLint *level_n;GLuint uniformTex, uniformTex2;GLuint DoDot, DoAdd;GLfloat *vectors[2];// GLSL Shader Code!GLuint progid;#define GL_STRINGIFY(x) _GL_STRINGIFY(x)#define _GL_STRINGIFY(x) #x#define VERTEX_SHADER \ varying vec3 normal; \ \ void main() \ { \ normal = normalize(gl_NormalMatrix * gl_Normal); \ gl_TexCoord[0] = gl_MultiTexCoord0; \ gl_TexCoord[1] = gl_MultiTexCoord1; \ gl_FrontColor = gl_Color; \ gl_Position = ftransform(); \ }#define FRAGMENT_SHADER \ varying vec3 normal; \ varying vec3 halfvector; \ uniform sampler2D tex; \ uniform sampler2D tex2; \ uniform bool enabledot; \ uniform bool enableadd; \ uniform bool texON; \ \ void main() \ { \ if (enabledot) { \ gl_FragColor = vec4( texture2D(tex, gl_TexCoord[0].st).r * \ texture2D(tex2, gl_TexCoord[0].st).r, \ 0.25, \ 0.25, \ 1); \ } else if (enableadd) { \ gl_FragColor = vec4( texture2D(tex, gl_TexCoord[0].st).r + \ texture2D(tex2, gl_TexCoord[0].st).r, \ 0.0, \ 0.0, \ 1); \ } else { \ gl_FragColor = texture2D(tex, gl_TexCoord[0].st); \ } \ }const char *vertex = GL_STRINGIFY(VERTEX_SHADER);const char *fragment = GL_STRINGIFY(FRAGMENT_SHADER);int window_width, window_height;voidusage ( void ){ printf("********************\n"); printf("Usage:\n" "Invoke with -f flag for FULLSCREEN\n" "\n\n" ); printf("********************\n"); return;}voidkb_cb ( unsigned char key, int x, int y ){ switch(key) { case 27: exit(0); break; default: break; } return;}voidspecial_cb ( int key, int x, int y ){ switch(key) { case GLUT_KEY_LEFT: break; case GLUT_KEY_RIGHT: break; case GLUT_KEY_DOWN: break; case GLUT_KEY_UP: break; default: break; } return;}void draw_quad ( const float size ){ glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.0f, 0.0f, 0.0f ); glTexCoord2f(1.0f, 0.0f); glVertex3f(size, 0.0f, 0.0f); glTexCoord2f(1.0f, 1.0f); glVertex3f(size, size, 0.0f); glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f, size, 0.0f); glEnd(); }voidprint_texture_vector ( GLuint texid, char *prefix, ...){ GLfloat readbackBuffer[123456]; GLint texwidth; int i; va_list args; va_start(args, prefix); vprintf(prefix, args); va_end(args); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, texid); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texwidth); glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, readbackBuffer); CHECK_ERROR; for (i = 0; i < 4*texwidth; i+=4) { printf("%f ", readbackBuffer[i]); } printf("\n"); glBindTexture(GL_TEXTURE_2D, 0);}voiddo_dot ( void ){ static GLuint loop = 0; int j; glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); // attach texture glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, output_tex[0], 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE) printf("FRAMEBUFFER NOT READY!\n"); glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glClearColor(0.0, 0.0, 0.0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); // First level: // 2 inputs of size = level_n[0] // 1 output of size = level_n[0] // Render to output by setting Viewport to 0->level_n[0] in X dir printf("Changing view port for level %d to %d\n", 0, level_n[0]); glViewport(0, 0, level_n[0], 1); // Dot Multiple the first two 'vectors' glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex[0]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, tex[1]); glUseProgram(progid); glUniform1i(DoDot, 1); glUniform1i(DoAdd, 0); glUniform1i(uniformTex, 0); glUniform1i(uniformTex2, 1); draw_quad(1.0); glUseProgram(0); print_texture_vector(output_tex[0], "OutputTex 0: "); //glBindTexture(GL_TEXTURE_2D, 0); // For all remaining levels, we need to sum recursively until we have // only 1 value remaining for (j = 1; j <= num_levels; j++) { // input texs @ 2*j and 2*j + 1 for level j // copy output of previous stage printf("*** Level %d: Copying %d into two %d textures\n", j, level_n[j-1], level_n[j]); //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); printf("indices: 0->%d , %d->%d\n", level_n[j]-1, level_n[j], level_n[j]+level_n[j]-1); // Copy first half of the results from FBO into next input texture glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, tex[2*j]); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, level_n[j], 1); CHECK_ERROR; // Copy last half of the results from FBO into next input texture + 1 glBindTexture(GL_TEXTURE_2D, tex[2*j + 1]); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, level_n[j], 0, level_n[j], 1); CHECK_ERROR; print_texture_vector(tex[2*j], "Tex%d: ", 2*j); print_texture_vector(tex[2*j + 1], "Tex%d: ", 2*j+1); // Rebind the framebuffer to the next level output texture glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, output_tex[j], 0); if (glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE) printf("FRAMEBUFFER NOT READY!\n"); // Clear and Resize the framebuffer again to next level size glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); glReadBuffer(GL_COLOR_ATTACHMENT0_EXT); glClearColor(0.0, 0.0, 0.0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); // The next output level should have half the previous level's size // Change the viewport to draw to 0->new_size printf("Changing view port for level %d to %d\n", j, level_n[j]); glViewport(0, 0, level_n[j], 1); // Rebind the input textures for next round glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex[2*j]); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, tex[2*j + 1]); // do the addition of the next inputs glUseProgram(progid); glUniform1i(DoDot, 0); glUniform1i(DoAdd, 1); glUniform1i(uniformTex, 0); glUniform1i(uniformTex2, 1); draw_quad(1.0); glUseProgram(0); print_texture_vector(output_tex[j], "OutputTex%d: ", j); //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } glBindTexture(GL_TEXTURE_2D, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT,0); return;}voiddisplay ( void ){ GLfloat buffer[1000596]; int j; glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(0, 0, 1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glDisable(GL_SCISSOR_TEST); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); // Render to FBO our dot product do_dot(); glViewport(0, 0, (GLsizei)window_width, (GLsizei)window_height); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glEnable(GL_TEXTURE_2D); // Draw the rendered textures // Tell the shader to RENDER a texture, not dot mult or add // DoDot=0 and DoAdd=0 for (j = 0; j <= num_levels; j++) { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex[2*j]); glUseProgram(progid); glUniform1i(DoDot, 0); glUniform1i(DoAdd, 0); glUniform1i(uniformTex, 0); draw_quad(0.2); glUseProgram(0); glPushMatrix(); glTranslatef(0.3, 0, 0); glBindTexture(GL_TEXTURE_2D, tex[2*j+1]); glUseProgram(progid); glUniform1i(DoDot, 0); glUniform1i(DoAdd, 0); glUniform1i(uniformTex, 0); draw_quad(0.2); glUseProgram(0); glPopMatrix(); glTranslatef(0, 0.3, 0); print_texture_vector(tex[2*j], "DISP Tex%d: ", 2*j); print_texture_vector(tex[2*j + 1], "DISP Tex%d: ", 2*j+1); } glTranslatef(0.6, -0.6, 0); glBindTexture(GL_TEXTURE_2D, output_tex[num_levels]); glUseProgram(progid); glUniform1i(DoDot, 0); glUniform1i(DoAdd, 0); glUniform1i(uniformTex, 0); draw_quad(0.2); glUseProgram(0); glutSwapBuffers(); return;}voidreshape ( int w, int h ){ window_width = w; window_height = h; glViewport(0, 0, (GLsizei)w, (GLsizei)h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); /* glOrtho( 0.0, 10.0, 0.0, 10.0, 0.1, 100.0); */ /* glFrustum(-5.0, 100.0, -5.0, 100.0, 1.0, 1000.0); */ gluPerspective(40.0, 1.0, 1.0, 200.0); glMatrixMode(GL_MODELVIEW); return;}voidshader_print_log ( GLuint shader ){ GLint logLength; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar* log = (GLchar*)malloc(logLength); glGetShaderInfoLog(shader, logLength, &logLength, log); printf("Shader compile log:\n%s\n", log); free(log); } return;}voidinit_shaders ( void ){ glewInit(); GLuint vid = glCreateShader(GL_VERTEX_SHADER); GLuint fid = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(vid, 1, &vertex, NULL); glShaderSource(fid, 1, &fragment, NULL); glCompileShader(vid); shader_print_log(vid); glCompileShader(fid); shader_print_log(fid); progid = glCreateProgram(); glAttachShader(progid, vid); glAttachShader(progid, fid); glLinkProgram(progid); uniformTex = glGetUniformLocation(progid, "tex"); uniformTex2 = glGetUniformLocation(progid, "tex2"); DoDot = glGetUniformLocation(progid, "enabledot"); DoAdd = glGetUniformLocation(progid, "enableadd");}GLfloat *create_matrix ( GLint n ){ GLfloat *array; int i; array = (GLfloat *)malloc(sizeof(GLfloat) * n * 4); for (i = 0; i < 4*n; i) { /* array[i] = -50.0 + 1.0 * (rand() % 100); */ /* array[i+1] = -50.0 + 1.0 * (rand() % 100); */ /* array[i+2] = -50.0 + 1.0 * (rand() % 100); */ array[i] = 1.0 * (random() % 100) / 100.0; array[i+1] = 0; array[i+2] = 0; //array[i+1] = 1.0 * (rand() % 100)/ 100.0; //array[i+2] = 1.0 * (rand() % 100)/ 100.0; array[i+3] = 1.0; printf("%f ", array[i]); i = i + 4; } printf("\n"); return(array);}voidinit_fbo ( ){ glGenFramebuffersEXT(1, &fb); CHECK_ERROR; // glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb); //CHECK_ERROR; return;}voidinit_textures ( GLint w, GLint h ){ if (!glewIsSupported("GL_ARB_texture_float")) printf("Warning! GL_ARB_texture_float not supported!\n"); // TODO: temp hack; make sure it's the next highest power of 2 real_n = n; // Need 2*log2(size) textures with an extra for final...?! // Need 2*(log2(n)+1) INPUT textures // Need HALF as many OUTPUT textures num_levels = log2(real_n); num_tex = 2*(num_levels + 1); printf("N = %d REAL_N = %d with %d number of levels\n", n, real_n, num_levels); printf("Creating %d INPUT textures and %d OUTPUT textures\n", num_tex, num_tex / 2); vectors[0] = create_matrix(n); vectors[1] = create_matrix(n); level_n = malloc(sizeof(GLint) * num_levels); level_n[0] = real_n; glGenTextures(num_tex, tex); CHECK_ERROR; glGenTextures(num_tex / 2, output_tex); CHECK_ERROR; glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex[0]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, level_n[0], 1, 0, GL_RGBA, GL_FLOAT, vectors[0]); glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex[1]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, level_n[0], 1, 0, GL_RGBA, GL_FLOAT, vectors[1]); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE2); glEnable(GL_TEXTURE_2D); // Create the rest of the input and output textures int i; for (i = 0; i <= num_levels; i++) { if (i > 0) level_n[i] = level_n[i-1] / 2; glBindTexture(GL_TEXTURE_2D, tex[2*i]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, level_n[i], 1, 0, GL_RGBA, GL_FLOAT, vectors[0]); glBindTexture(GL_TEXTURE_2D, tex[2*i+1]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, level_n[i], 1, 0, GL_RGBA, GL_FLOAT, vectors[1]); printf("Inputs: Level %d: %d by 1\n", i, level_n[i]); } for (i = 0; i <= num_levels; i++) { glBindTexture(GL_TEXTURE_2D, output_tex[i]); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, level_n[i], 1, 0, GL_RGBA, GL_FLOAT, NULL); printf("Outputs: Level %d: %d by 1\n", i, level_n[i]); } glBindTexture(GL_TEXTURE_2D, 0); return;}intmain ( int argc, char **argv ){ int fullscreen = 0; usage(); if (argc > 1) { if ((argv[1][0] == '-') && (argv[1][1] == 'f')) fullscreen = 1; else n = atoi(argv[1]); } printf("*** Generating %dD vectors\n", n); srandom(time(NULL)); glutInit(&argc, argv); glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_ALPHA | GLUT_STENCIL); if (!fullscreen) { glutInitWindowSize(1024, 1024); glutInitWindowPosition(0, 0); glutCreateWindow(argv[0]); } else { glutGameModeString("1024x768:32@75"); glutEnterGameMode(); } /* * GLEW and Shader Init */ init_shaders(); /* * Print Version info for OpenGL */ printf("OpenGL Version: %s\n", glGetString(GL_VERSION)); printf("GLEW Version: %s\n", glewGetString(GLEW_VERSION)); //printf("Extensions: %s\n", glGetString(GL_EXTENSIONS)); /* * FBO and Texture Init */ init_fbo(); init_textures(startsize_w, startsize_h); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); /* * Enable Depth Buffering */ glDepthFunc(GL_LESS); glEnable(GL_DEPTH_TEST); glShadeModel(GL_SMOOTH); glutKeyboardFunc(kb_cb); glutSpecialFunc(special_cb); glutDisplayFunc(display); glutReshapeFunc(reshape); //glutIdleFunc(display); glutMainLoop(); return(0);}