void GPU_fx_compositor_setup_XRay_pass(GPUFX *fx, bool do_xray) { char err_out[256]; if (do_xray) { if (!fx->depth_buffer_xray && !(fx->depth_buffer_xray = GPU_texture_create_depth(fx->gbuffer_dim[0], fx->gbuffer_dim[1], err_out))) { printf("%.256s\n", err_out); cleanup_fx_gl_data(fx, true); return; } } else { if (fx->depth_buffer_xray) { GPU_framebuffer_texture_detach(fx->depth_buffer_xray); GPU_texture_free(fx->depth_buffer_xray); fx->depth_buffer_xray = NULL; } return; } GPU_framebuffer_texture_detach(fx->depth_buffer); /* first depth buffer, because system assumes read/write buffers */ if(!GPU_framebuffer_texture_attach(fx->gbuffer, fx->depth_buffer_xray, 0, err_out)) printf("%.256s\n", err_out); }
/* destroy a text compositor */ void GPU_fx_compositor_destroy(GPUFX *fx) { cleanup_fx_gl_data(fx, true); MEM_freeN(fx); }
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; }
/* destroy a text compositor */ void GPU_fx_compositor_destroy(GPUFX *fx) { cleanup_fx_gl_data(fx, true); glDeleteBuffers(1, &fx->vbuffer); MEM_freeN(fx); }