GPUOffScreen *GPU_offscreen_create(int width, int height, int samples, char err_out[256]) { GPUOffScreen *ofs; ofs = MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); ofs->fb = GPU_framebuffer_create(); if (!ofs->fb) { GPU_offscreen_free(ofs); return NULL; } if (samples) { if (!GLEW_EXT_framebuffer_multisample || !GLEW_ARB_texture_multisample || /* Only needed for GPU_offscreen_read_pixels. * We could add an arg if we intend to use multi-sample * offscreen buffers w/o reading their pixels */ !GLEW_EXT_framebuffer_blit || /* This is required when blitting from a multi-sampled buffers, * even though we're not scaling. */ !GLEW_EXT_framebuffer_multisample_blit_scaled) { samples = 0; } } ofs->depth = GPU_texture_create_depth_multisample(width, height, samples, err_out); if (!ofs->depth) { GPU_offscreen_free(ofs); return NULL; } if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, 0, err_out)) { GPU_offscreen_free(ofs); return NULL; } ofs->color = GPU_texture_create_2D_multisample(width, height, NULL, GPU_HDR_NONE, samples, err_out); if (!ofs->color) { GPU_offscreen_free(ofs); return NULL; } if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, 0, err_out)) { GPU_offscreen_free(ofs); return NULL; } /* check validity at the very end! */ if (!GPU_framebuffer_check_valid(ofs->fb, err_out)) { GPU_offscreen_free(ofs); return NULL; } GPU_framebuffer_restore(); return ofs; }
GPUOffScreen *GPU_offscreen_create(int *width, int *height, char err_out[256]) { GPUOffScreen *ofs; ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); ofs->fb = GPU_framebuffer_create(); if(!ofs->fb) { GPU_offscreen_free(ofs); return NULL; } ofs->depth = GPU_texture_create_depth(*width, *height, err_out); if(!ofs->depth) { GPU_offscreen_free(ofs); return NULL; } if(*width!=ofs->depth->w || *height!=ofs->depth->h) { *width= ofs->depth->w; *height= ofs->depth->h; printf("Offscreen size differs from given size!\n"); } if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) { GPU_offscreen_free(ofs); return NULL; } ofs->color = GPU_texture_create_2D(*width, *height, NULL, err_out); if(!ofs->color) { GPU_offscreen_free(ofs); return NULL; } if(!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) { GPU_offscreen_free(ofs); return NULL; } GPU_framebuffer_restore(); return ofs; }
/* TODO: Creating, attaching texture, and destroying a framebuffer is quite slow. * Calling this function should be avoided during interactive drawing. */ static void view3d_opengl_read_Z_pixels(GPUViewport *viewport, rcti *rect, void *data) { DefaultTextureList *dtxl = (DefaultTextureList *)GPU_viewport_texture_list_get(viewport); GPUFrameBuffer *tmp_fb = GPU_framebuffer_create(); GPU_framebuffer_texture_attach(tmp_fb, dtxl->depth, 0, 0); GPU_framebuffer_bind(tmp_fb); glReadPixels(rect->xmin, rect->ymin, BLI_rcti_size_x(rect), BLI_rcti_size_y(rect), GL_DEPTH_COMPONENT, GL_FLOAT, data); GPU_framebuffer_restore(); GPU_framebuffer_free(tmp_fb); }
GPUOffScreen *GPU_offscreen_create(int width, int height, char err_out[256]) { GPUOffScreen *ofs; ofs= MEM_callocN(sizeof(GPUOffScreen), "GPUOffScreen"); ofs->w= width; ofs->h= height; ofs->fb = GPU_framebuffer_create(); if (!ofs->fb) { GPU_offscreen_free(ofs); return NULL; } ofs->depth = GPU_texture_create_depth(width, height, err_out); if (!ofs->depth) { GPU_offscreen_free(ofs); return NULL; } if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->depth, err_out)) { GPU_offscreen_free(ofs); return NULL; } ofs->color = GPU_texture_create_2D(width, height, NULL, err_out); if (!ofs->color) { GPU_offscreen_free(ofs); return NULL; } if (!GPU_framebuffer_texture_attach(ofs->fb, ofs->color, err_out)) { GPU_offscreen_free(ofs); return NULL; } GPU_framebuffer_restore(); return ofs; }
bool GPU_fx_compositor_initialize_passes( GPUFX *fx, const rcti *rect, const rcti *scissor_rect, const GPUFXSettings *fx_settings) { int w = BLI_rcti_size_x(rect), h = BLI_rcti_size_y(rect); char err_out[256]; int num_passes = 0; char fx_flag; fx->effects = 0; if (!fx_settings) { cleanup_fx_gl_data(fx, true); return false; } fx_flag = fx_settings->fx_flag; /* disable effects if no options passed for them */ if (!fx_settings->dof) { fx_flag &= ~GPU_FX_FLAG_DOF; } if (!fx_settings->ssao || fx_settings->ssao->samples < 1) { fx_flag &= ~GPU_FX_FLAG_SSAO; } if (!fx_flag) { cleanup_fx_gl_data(fx, true); return false; } /* scissor is missing when drawing offscreen, in that case, dimensions match exactly. In opposite case * add one to match viewport dimensions */ if (scissor_rect) { w++, h++; } fx->num_passes = 0; /* dof really needs a ping-pong buffer to work */ if (fx_flag & GPU_FX_FLAG_DOF) num_passes++; if (fx_flag & GPU_FX_FLAG_SSAO) num_passes++; if (!fx->gbuffer) fx->gbuffer = GPU_framebuffer_create(); /* try creating the jitter texture */ if (!fx->jitter_buffer) fx->jitter_buffer = create_jitter_texture(); if (!fx->gbuffer) return false; /* check if color buffers need recreation */ if (!fx->color_buffer || !fx->depth_buffer || w != fx->gbuffer_dim[0] || h != fx->gbuffer_dim[1]) { cleanup_fx_gl_data(fx, false); if (!(fx->color_buffer = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->depth_buffer = GPU_texture_create_depth(w, h, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } if (fx_flag & GPU_FX_FLAG_SSAO) { if (fx_settings->ssao->samples != fx->ssao_sample_count || !fx->ssao_concentric_samples_tex) { if (fx_settings->ssao->samples < 1) fx_settings->ssao->samples = 1; fx->ssao_sample_count = fx_settings->ssao->samples; if (fx->ssao_concentric_samples_tex) { GPU_texture_free(fx->ssao_concentric_samples_tex); } fx->ssao_concentric_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples); } } else { if (fx->ssao_concentric_samples_tex) { GPU_texture_free(fx->ssao_concentric_samples_tex); fx->ssao_concentric_samples_tex = NULL; } } /* create textures for dof effect */ if (fx_flag & GPU_FX_FLAG_DOF) { if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) { fx->dof_downsampled_w = w / 4; fx->dof_downsampled_h = h / 4; if (!(fx->dof_near_coc_buffer = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_coc_blurred_buffer = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } if (!(fx->dof_near_coc_final_buffer = GPU_texture_create_2D( fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_NONE, err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } } else { /* cleanup unnecessary buffers */ cleanup_fx_dof_buffers(fx); } /* we need to pass data between shader stages, allocate an extra color buffer */ if (num_passes > 1) { if(!fx->color_buffer_sec) { if (!(fx->color_buffer_sec = GPU_texture_create_2D(w, h, NULL, GPU_HDR_NONE, err_out))) { printf(".256%s\n", err_out); cleanup_fx_gl_data(fx, true); return false; } } } else { if (fx->color_buffer_sec) { GPU_framebuffer_texture_detach(fx->color_buffer_sec); GPU_texture_free(fx->color_buffer_sec); fx->color_buffer_sec = NULL; } } /* bind the buffers */ /* first depth buffer, because system assumes read/write buffers */ if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer, 0, err_out)) printf("%.256s\n", err_out); if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->color_buffer, 0, err_out)) printf("%.256s\n", err_out); if(!GPU_framebuffer_check_valid(fx->gbuffer, err_out)) printf("%.256s\n", err_out); GPU_texture_bind_as_framebuffer(fx->color_buffer); /* enable scissor test. It's needed to ensure sculpting works correctly */ if (scissor_rect) { int w_sc = BLI_rcti_size_x(scissor_rect) + 1; int h_sc = BLI_rcti_size_y(scissor_rect) + 1; glPushAttrib(GL_SCISSOR_BIT); glEnable(GL_SCISSOR_TEST); glScissor(scissor_rect->xmin - rect->xmin, scissor_rect->ymin - rect->ymin, w_sc, h_sc); fx->restore_stencil = true; } else { fx->restore_stencil = false; } fx->effects = fx_flag; if (fx_settings) fx->settings = *fx_settings; fx->gbuffer_dim[0] = w; fx->gbuffer_dim[1] = h; fx->num_passes = num_passes; return true; }