static GPUTexture * create_jitter_texture(void)
{
	float jitter [64 * 64][2];
	int i;

	for (i = 0; i < 64 * 64; i++) {
		jitter[i][0] = 2.0f * BLI_frand() - 1.0f;
		jitter[i][1] = 2.0f * BLI_frand() - 1.0f;
		normalize_v2(jitter[i]);
	}

	return GPU_texture_create_2D_procedural(64, 64, &jitter[0][0], NULL);
}
Exemple #2
0
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 (!GLEW_EXT_framebuffer_object)
		return false;

	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();

		if (!fx->gbuffer) {
			return false;
		}
	}

	/* try creating the jitter texture */
	if (!fx->jitter_buffer)
		fx->jitter_buffer = create_jitter_texture();

	/* 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_cache || !fx->ssao_spiral_samples_tex) {
			if (fx_settings->ssao->samples < 1)
				fx_settings->ssao->samples = 1;

			fx->ssao_sample_count_cache = fx_settings->ssao->samples;

			if (fx->ssao_spiral_samples_tex) {
				GPU_texture_free(fx->ssao_spiral_samples_tex);
			}

			fx->ssao_spiral_samples_tex = create_spiral_sample_texture(fx_settings->ssao->samples);
		}
	}
	else {
		if (fx->ssao_spiral_samples_tex) {
			GPU_texture_free(fx->ssao_spiral_samples_tex);
			fx->ssao_spiral_samples_tex = NULL;
		}
	}

	/* create textures for dof effect */
	if (fx_flag & GPU_FX_FLAG_DOF) {
		bool dof_high_quality = (fx_settings->dof->high_quality != 0) &&
		                        GPU_geometry_shader_support() && GPU_instanced_drawing_support();

		/* cleanup buffers if quality setting has changed (no need to keep more buffers around than necessary ) */
		if (dof_high_quality != fx->dof_high_quality)
			cleanup_fx_dof_buffers(fx);

		if (dof_high_quality) {
			fx->dof_downsampled_w = w / 2;
			fx->dof_downsampled_h = h / 2;

			if (!fx->dof_half_downsampled_near || !fx->dof_nearfar_coc || !fx->dof_near_blur ||
			    !fx->dof_far_blur || !fx->dof_half_downsampled_far)
			{

				if (!(fx->dof_half_downsampled_near = 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_half_downsampled_far = 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_nearfar_coc = GPU_texture_create_2D_procedural(
				      fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, false, err_out)))
				{
					printf("%.256s\n", err_out);
					cleanup_fx_gl_data(fx, true);
					return false;
				}


				if (!(fx->dof_near_blur = GPU_texture_create_2D(
				    fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
				{
					printf("%.256s\n", err_out);
					cleanup_fx_gl_data(fx, true);
					return false;
				}

				if (!(fx->dof_far_blur = GPU_texture_create_2D(
				    fx->dof_downsampled_w, fx->dof_downsampled_h, NULL, GPU_HDR_HALF_FLOAT, err_out)))
				{
					printf("%.256s\n", err_out);
					cleanup_fx_gl_data(fx, true);
					return false;
				}
			}
		}
		else {
			fx->dof_downsampled_w = w / 4;
			fx->dof_downsampled_h = h / 4;

			if (!fx->dof_near_coc_buffer || !fx->dof_near_coc_blurred_buffer || !fx->dof_near_coc_final_buffer) {

				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;
				}
			}
		}

		fx->dof_high_quality = dof_high_quality;
	}
	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;
}