static void split_width(int x, int n, int *splitx, int *nx) { int a, newnx, waste; /* if already power of two just use it */ if(is_pow2(x)) { splitx[0]= x; (*nx)++; return; } if(n == 1) { /* last part, we have to go larger */ splitx[0]= larger_pow2(x); (*nx)++; } else { /* two or more parts to go, use smaller part */ splitx[0]= smaller_pow2(x); newnx= ++(*nx); split_width(x-splitx[0], n-1, splitx+1, &newnx); for(waste=0, a=0; a<n; a++) waste += splitx[a]; /* if we waste more space or use the same amount, * revert deeper splits and just use larger */ if(waste >= larger_pow2(x)) { splitx[0]= larger_pow2(x); memset(splitx+1, 0, sizeof(int)*(n-1)); } else *nx= newnx; } }
static void checker_board_color_fill(unsigned char *rect, float *rect_float, int width, int height) { int hue_step, y, x; float hue, val, sat, r, g, b; sat= 1.0; hue_step= larger_pow2(width / 8); if(hue_step < 8) hue_step= 8; for(y= 0; y < height; y++) { val= 0.1 + (y * (0.4 / height)); /* use a number lower then 1.0 else its too bright */ for(x= 0; x < width; x++) { hue= (float)((double)(x/hue_step) * 1.0 / width * hue_step); hsv_to_rgb(hue, sat, val, &r, &g, &b); if (rect) { rect[0]= (char)(r * 255.0f); rect[1]= (char)(g * 255.0f); rect[2]= (char)(b * 255.0f); rect[3]= 255; rect += 4; } if (rect_float) { rect_float[0]= r; rect_float[1]= g; rect_float[2]= b; rect_float[3]= 1.0f; rect_float += 4; } } } }
void draw_volume(ARegion *ar, GPUTexture *tex, float *min, float *max, int res[3], float dx, GPUTexture *tex_shadow) { RegionView3D *rv3d= ar->regiondata; float viewnormal[3]; int i, j, n, good_index; float d /*, d0 */ /* UNUSED */, dd, ds; float *points = NULL; int numpoints = 0; float cor[3] = {1.,1.,1.}; int gl_depth = 0, gl_blend = 0; /* draw slices of smoke is adapted from c++ code authored by: Johannes Schmid and Ingemar Rask, 2006, [email protected] */ float cv[][3] = { {1.0f, 1.0f, 1.0f}, {-1.0f, 1.0f, 1.0f}, {-1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, 1.0f}, {1.0f, 1.0f, -1.0f}, {-1.0f, 1.0f, -1.0f}, {-1.0f, -1.0f, -1.0f}, {1.0f, -1.0f, -1.0f} }; // edges have the form edges[n][0][xyz] + t*edges[n][1][xyz] float edges[12][2][3] = { {{1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{-1.0f, 1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 0.0f, 2.0f}}, {{1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 2.0f, 0.0f}}, {{-1.0f, 1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}}, {{-1.0f, 1.0f, -1.0f}, {2.0f, 0.0f, 0.0f}} }; /* Fragment program to calculate the view3d of smoke */ /* using 2 textures, density and shadow */ const char *text = "!!ARBfp1.0\n" "PARAM dx = program.local[0];\n" "PARAM darkness = program.local[1];\n" "PARAM f = {1.442695041, 1.442695041, 1.442695041, 0.01};\n" "TEMP temp, shadow, value;\n" "TEX temp, fragment.texcoord[0], texture[0], 3D;\n" "TEX shadow, fragment.texcoord[0], texture[1], 3D;\n" "MUL value, temp, darkness;\n" "MUL value, value, dx;\n" "MUL value, value, f;\n" "EX2 temp, -value.r;\n" "SUB temp.a, 1.0, temp.r;\n" "MUL temp.r, temp.r, shadow.r;\n" "MUL temp.g, temp.g, shadow.r;\n" "MUL temp.b, temp.b, shadow.r;\n" "MOV result.color, temp;\n" "END\n"; GLuint prog; float size[3]; if(!tex) { printf("Could not allocate 3D texture for 3D View smoke drawing.\n"); return; } tstart(); sub_v3_v3v3(size, max, min); // maxx, maxy, maxz cv[0][0] = max[0]; cv[0][1] = max[1]; cv[0][2] = max[2]; // minx, maxy, maxz cv[1][0] = min[0]; cv[1][1] = max[1]; cv[1][2] = max[2]; // minx, miny, maxz cv[2][0] = min[0]; cv[2][1] = min[1]; cv[2][2] = max[2]; // maxx, miny, maxz cv[3][0] = max[0]; cv[3][1] = min[1]; cv[3][2] = max[2]; // maxx, maxy, minz cv[4][0] = max[0]; cv[4][1] = max[1]; cv[4][2] = min[2]; // minx, maxy, minz cv[5][0] = min[0]; cv[5][1] = max[1]; cv[5][2] = min[2]; // minx, miny, minz cv[6][0] = min[0]; cv[6][1] = min[1]; cv[6][2] = min[2]; // maxx, miny, minz cv[7][0] = max[0]; cv[7][1] = min[1]; cv[7][2] = min[2]; copy_v3_v3(edges[0][0], cv[4]); // maxx, maxy, minz copy_v3_v3(edges[1][0], cv[5]); // minx, maxy, minz copy_v3_v3(edges[2][0], cv[6]); // minx, miny, minz copy_v3_v3(edges[3][0], cv[7]); // maxx, miny, minz copy_v3_v3(edges[4][0], cv[3]); // maxx, miny, maxz copy_v3_v3(edges[5][0], cv[2]); // minx, miny, maxz copy_v3_v3(edges[6][0], cv[6]); // minx, miny, minz copy_v3_v3(edges[7][0], cv[7]); // maxx, miny, minz copy_v3_v3(edges[8][0], cv[1]); // minx, maxy, maxz copy_v3_v3(edges[9][0], cv[2]); // minx, miny, maxz copy_v3_v3(edges[10][0], cv[6]); // minx, miny, minz copy_v3_v3(edges[11][0], cv[5]); // minx, maxy, minz // printf("size x: %f, y: %f, z: %f\n", size[0], size[1], size[2]); // printf("min[2]: %f, max[2]: %f\n", min[2], max[2]); edges[0][1][2] = size[2]; edges[1][1][2] = size[2]; edges[2][1][2] = size[2]; edges[3][1][2] = size[2]; edges[4][1][1] = size[1]; edges[5][1][1] = size[1]; edges[6][1][1] = size[1]; edges[7][1][1] = size[1]; edges[8][1][0] = size[0]; edges[9][1][0] = size[0]; edges[10][1][0] = size[0]; edges[11][1][0] = size[0]; glGetBooleanv(GL_BLEND, (GLboolean *)&gl_blend); glGetBooleanv(GL_DEPTH_TEST, (GLboolean *)&gl_depth); glLoadMatrixf(rv3d->viewmat); // glMultMatrixf(ob->obmat); glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); /* printf("Viewinv:\n"); printf("%f, %f, %f\n", rv3d->viewinv[0][0], rv3d->viewinv[0][1], rv3d->viewinv[0][2]); printf("%f, %f, %f\n", rv3d->viewinv[1][0], rv3d->viewinv[1][1], rv3d->viewinv[1][2]); printf("%f, %f, %f\n", rv3d->viewinv[2][0], rv3d->viewinv[2][1], rv3d->viewinv[2][2]); */ // get view vector copy_v3_v3(viewnormal, rv3d->viewinv[2]); normalize_v3(viewnormal); // find cube vertex that is closest to the viewer for (i=0; i<8; i++) { float x,y,z; x = cv[i][0] - viewnormal[0]; y = cv[i][1] - viewnormal[1]; z = cv[i][2] - viewnormal[2]; if ((x>=min[0])&&(x<=max[0]) &&(y>=min[1])&&(y<=max[1]) &&(z>=min[2])&&(z<=max[2])) { break; } } if(i >= 8) { /* fallback, avoid using buffer over-run */ i= 0; } // printf("i: %d\n", i); // printf("point %f, %f, %f\n", cv[i][0], cv[i][1], cv[i][2]); if (GL_TRUE == glewIsSupported("GL_ARB_fragment_program")) { glEnable(GL_FRAGMENT_PROGRAM_ARB); glGenProgramsARB(1, &prog); glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, prog); glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei)strlen(text), text); // cell spacing glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, dx, dx, dx, 1.0); // custom parameter for smoke style (higher = thicker) glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 1, 7.0, 7.0, 7.0, 1.0); } else printf("Your gfx card does not support 3D View smoke drawing.\n"); GPU_texture_bind(tex, 0); if(tex_shadow) GPU_texture_bind(tex_shadow, 1); else printf("No volume shadow\n"); if (!GPU_non_power_of_two_support()) { cor[0] = (float)res[0]/(float)larger_pow2(res[0]); cor[1] = (float)res[1]/(float)larger_pow2(res[1]); cor[2] = (float)res[2]/(float)larger_pow2(res[2]); } // our slices are defined by the plane equation a*x + b*y +c*z + d = 0 // (a,b,c), the plane normal, are given by viewdir // d is the parameter along the view direction. the first d is given by // inserting previously found vertex into the plane equation /* d0 = (viewnormal[0]*cv[i][0] + viewnormal[1]*cv[i][1] + viewnormal[2]*cv[i][2]); */ /* UNUSED */ ds = (ABS(viewnormal[0])*size[0] + ABS(viewnormal[1])*size[1] + ABS(viewnormal[2])*size[2]); dd = 0.05; // ds/512.0f; n = 0; good_index = i; // printf("d0: %f, dd: %f, ds: %f\n\n", d0, dd, ds); points = MEM_callocN(sizeof(float)*12*3, "smoke_points_preview"); while(1) { float p0[3]; float tmp_point[3], tmp_point2[3]; if(dd*(float)n > ds) break; copy_v3_v3(tmp_point, viewnormal); mul_v3_fl(tmp_point, -dd*((ds/dd)-(float)n)); add_v3_v3v3(tmp_point2, cv[good_index], tmp_point); d = dot_v3v3(tmp_point2, viewnormal); // printf("my d: %f\n", d); // intersect_edges returns the intersection points of all cube edges with // the given plane that lie within the cube numpoints = intersect_edges(points, viewnormal[0], viewnormal[1], viewnormal[2], -d, edges); // printf("points: %d\n", numpoints); if (numpoints > 2) { copy_v3_v3(p0, points); // sort points to get a convex polygon for(i = 1; i < numpoints - 1; i++) { for(j = i + 1; j < numpoints; j++) { if(!convex(p0, viewnormal, &points[j * 3], &points[i * 3])) { float tmp2[3]; copy_v3_v3(tmp2, &points[j * 3]); copy_v3_v3(&points[j * 3], &points[i * 3]); copy_v3_v3(&points[i * 3], tmp2); } } } // printf("numpoints: %d\n", numpoints); glBegin(GL_POLYGON); glColor3f(1.0, 1.0, 1.0); for (i = 0; i < numpoints; i++) { glTexCoord3d((points[i * 3 + 0] - min[0] )*cor[0]/size[0], (points[i * 3 + 1] - min[1])*cor[1]/size[1], (points[i * 3 + 2] - min[2])*cor[2]/size[2]); glVertex3f(points[i * 3 + 0], points[i * 3 + 1], points[i * 3 + 2]); } glEnd(); } n++; } tend(); // printf ( "Draw Time: %f\n",( float ) tval() ); if(tex_shadow) GPU_texture_unbind(tex_shadow); GPU_texture_unbind(tex); if(GLEW_ARB_fragment_program) { glDisable(GL_FRAGMENT_PROGRAM_ARB); glDeleteProgramsARB(1, &prog); } MEM_freeN(points); if(!gl_blend) glDisable(GL_BLEND); if(gl_depth) { glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); } }
GPUTexture *GPU_texture_create_3D(int w, int h, int depth, float *fpixels) { GPUTexture *tex; GLenum type, format, internalformat; void *pixels = NULL; float vfBorderColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; if(!GLEW_VERSION_1_2) return NULL; tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; tex->depth = depth; tex->number = -1; tex->refcount = 1; tex->target = GL_TEXTURE_3D; glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { fprintf(stderr, "GPUTexture: texture create failed: %d\n", (int)glGetError()); GPU_texture_free(tex); return NULL; } if (!GPU_non_power_of_two_support()) { tex->w = larger_pow2(tex->w); tex->h = larger_pow2(tex->h); tex->depth = larger_pow2(tex->depth); } tex->number = 0; glBindTexture(tex->target, tex->bindcode); GPU_print_error("3D glBindTexture"); type = GL_FLOAT; // GL_UNSIGNED_BYTE format = GL_RED; internalformat = GL_INTENSITY; //if (fpixels) // pixels = GPU_texture_convert_pixels(w*h*depth, fpixels); glTexImage3D(tex->target, 0, internalformat, tex->w, tex->h, tex->depth, 0, format, type, NULL); GPU_print_error("3D glTexImage3D"); if (fpixels) { if(!GPU_non_power_of_two_support() && (w != tex->w || h != tex->h || depth != tex->depth)) { /* clear first to avoid unitialized pixels */ float *zero= MEM_callocN(sizeof(float)*tex->w*tex->h*tex->depth, "zero"); glTexSubImage3D(tex->target, 0, 0, 0, 0, tex->w, tex->h, tex->depth, format, type, zero); MEM_freeN(zero); } glTexSubImage3D(tex->target, 0, 0, 0, 0, w, h, depth, format, type, fpixels); GPU_print_error("3D glTexSubImage3D"); } glTexParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, vfBorderColor); GPU_print_error("3D GL_TEXTURE_BORDER_COLOR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); GPU_print_error("3D GL_LINEAR"); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); GPU_print_error("3D GL_CLAMP_TO_BORDER"); if (pixels) MEM_freeN(pixels); if (tex) GPU_texture_unbind(tex); return tex; }
static GPUTexture *GPU_texture_create_nD(int w, int h, int n, float *fpixels, int depth, char err_out[256]) { GPUTexture *tex; GLenum type, format, internalformat; void *pixels = NULL; if(depth && !GLEW_ARB_depth_texture) return NULL; tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture"); tex->w = w; tex->h = h; tex->number = -1; tex->refcount = 1; tex->target = (n == 1)? GL_TEXTURE_1D: GL_TEXTURE_2D; tex->depth = depth; glGenTextures(1, &tex->bindcode); if (!tex->bindcode) { if(err_out) { BLI_snprintf(err_out, 256, "GPUTexture: texture create failed: %d", (int)glGetError()); } else { fprintf(stderr, "GPUTexture: texture create failed: %d\n", (int)glGetError()); } GPU_texture_free(tex); return NULL; } if (!GPU_non_power_of_two_support()) { tex->w = larger_pow2(tex->w); tex->h = larger_pow2(tex->h); } tex->number = 0; glBindTexture(tex->target, tex->bindcode); if(depth) { type = GL_UNSIGNED_BYTE; format = GL_DEPTH_COMPONENT; internalformat = GL_DEPTH_COMPONENT; } else { type = GL_UNSIGNED_BYTE; format = GL_RGBA; internalformat = GL_RGBA8; if (fpixels) pixels = GPU_texture_convert_pixels(w*h, fpixels); } if (tex->target == GL_TEXTURE_1D) { glTexImage1D(tex->target, 0, internalformat, tex->w, 0, format, type, NULL); if (fpixels) { glTexSubImage1D(tex->target, 0, 0, w, format, type, pixels? pixels: fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, 1); } } else { glTexImage2D(tex->target, 0, internalformat, tex->w, tex->h, 0, format, type, NULL); if (fpixels) { glTexSubImage2D(tex->target, 0, 0, 0, w, h, format, type, pixels? pixels: fpixels); if (tex->w > w) GPU_glTexSubImageEmpty(tex->target, format, w, 0, tex->w-w, tex->h); if (tex->h > h) GPU_glTexSubImageEmpty(tex->target, format, 0, h, w, tex->h-h); } } if (pixels) MEM_freeN(pixels); if(depth) { glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tex->target, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE); glTexParameteri(tex->target, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL); glTexParameteri(tex->target, GL_DEPTH_TEXTURE_MODE_ARB, GL_INTENSITY); } else { glTexParameteri(tex->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(tex->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); } if (tex->target != GL_TEXTURE_1D) { /* CLAMP_TO_BORDER is an OpenGL 1.3 core feature */ GLenum wrapmode = (depth)? GL_CLAMP_TO_EDGE: GL_CLAMP_TO_BORDER; glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, wrapmode); glTexParameteri(tex->target, GL_TEXTURE_WRAP_T, wrapmode); #if 0 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f }; glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); #endif } else glTexParameteri(tex->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); return tex; }
void Blur_init(){ blur=Blur_basic; sw=larger_pow2(screen->w); sh=larger_pow2(screen->h); GLint mx; glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mx); consoleLog("Blur_init: required texture size is %dx%d\n", sw, sh); if(sw>mx || sh>mx){ consoleLog("Blur_init: too big texture, disabling blur\n"); blur=Blur_none; return; } consoleLog("Blur_init: allocating screen buffer\n"); glGenTextures(1, &tex_screen); glBindTexture(GL_TEXTURE_2D, tex_screen); #if GL_EXT_framebuffer_object if(use_hdr){ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, sw,sh, 0, GL_RGB, GL_HALF_FLOAT_ARB, NULL); }else{ #endif glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, sw,sh, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); #if GL_EXT_framebuffer_object } #endif glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClearColor(0.f, 0.f, 0.0f, 1.f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screen->w, screen->h); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); clearTexture(sw, sh); #if GL_ARB_shader_objects #if GL_ARB_depth_texture if(cap_glsl){ consoleLog("Blur_init: allocating depth buffer\n"); glGenTextures(1, &tex_depth); glBindTexture(GL_TEXTURE_2D, tex_depth); int comp; GLint i; glGetIntegerv(GL_DEPTH_BITS, &i); switch(i){ case 16: comp=GL_DEPTH_COMPONENT16_ARB; break; case 24: comp=GL_DEPTH_COMPONENT24_ARB; break; case 32: comp=GL_DEPTH_COMPONENT32_ARB; break; default: comp=GL_DEPTH_COMPONENT; break; } comp=GL_DEPTH_COMPONENT; if(use_hdr) comp=GL_DEPTH_COMPONENT24_ARB; glTexImage2D(GL_TEXTURE_2D, 0, comp, sw,sh, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); } #endif #endif #if GL_ARB_shader_objects if(cap_glsl){ prg_blurSimple=create_program("res/shaders/blur1.vs", "res/shaders/blur1.fs"); if(prg_blurSimple) consoleLog("Blur_init: compiled program \"blur1\"\n"); else consoleLog("Blur_init: couldn't compile program \"blur1\"\n"); #if GL_ARB_depth_texture prg_blurDepth=create_program("res/shaders/blur2.vs", "res/shaders/blur2.fs"); if(prg_blurDepth) consoleLog("Blur_init: compiled program \"blur2\"\n"); else consoleLog("Blur_init: couldn't compile program \"blur2\"\n"); #endif }else{ #endif consoleLog("Blur_init: no programs to compile\n"); #if GL_ARB_shader_objects } #endif #if GL_ARB_shader_objects if(cap_glsl){ blur=Blur_glsl_simple; #if GL_ARB_depth_texture blur=Blur_glsl_depth; #endif } #endif }