2017-05-04 17:36:40 +02:00
|
|
|
/*
|
|
|
|
* Copyright 2016, Blender Foundation.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* Contributor(s): Blender Institute
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Gather all screen space effects technique such as Bloom, Motion Blur, DoF, SSAO, SSR, ...
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** \file eevee_effects.c
|
|
|
|
* \ingroup draw_engine
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "DRW_render.h"
|
|
|
|
|
|
|
|
#include "DNA_anim_types.h"
|
2017-05-09 21:57:13 +02:00
|
|
|
#include "DNA_camera_types.h"
|
2017-05-04 17:36:40 +02:00
|
|
|
#include "DNA_view3d_types.h"
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
#include "BKE_camera.h"
|
2017-05-04 17:36:40 +02:00
|
|
|
#include "BKE_object.h"
|
|
|
|
#include "BKE_animsys.h"
|
|
|
|
|
|
|
|
#include "eevee_private.h"
|
|
|
|
#include "GPU_texture.h"
|
|
|
|
|
|
|
|
typedef struct EEVEE_ProbeData {
|
|
|
|
short probe_id, shadow_id;
|
|
|
|
} EEVEE_ProbeData;
|
|
|
|
|
|
|
|
/* TODO Option */
|
2017-05-04 19:11:20 +02:00
|
|
|
#define ENABLE_EFFECT_MOTION_BLUR 1
|
2017-05-07 14:27:43 +02:00
|
|
|
#define ENABLE_EFFECT_BLOOM 1
|
2017-05-09 21:57:13 +02:00
|
|
|
#define ENABLE_EFFECT_DOF 1
|
2017-05-04 17:36:40 +02:00
|
|
|
|
|
|
|
static struct {
|
2017-05-09 21:57:13 +02:00
|
|
|
/* Motion Blur */
|
2017-05-04 17:36:40 +02:00
|
|
|
struct GPUShader *motion_blur_sh;
|
2017-05-07 14:27:43 +02:00
|
|
|
|
|
|
|
/* Bloom */
|
|
|
|
struct GPUShader *bloom_blit_sh[2];
|
|
|
|
struct GPUShader *bloom_downsample_sh[2];
|
|
|
|
struct GPUShader *bloom_upsample_sh[2];
|
|
|
|
struct GPUShader *bloom_resolve_sh[2];
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
/* Depth Of Field */
|
|
|
|
struct GPUShader *dof_downsample_sh;
|
|
|
|
struct GPUShader *dof_scatter_sh;
|
|
|
|
struct GPUShader *dof_resolve_sh;
|
|
|
|
|
2017-05-04 17:36:40 +02:00
|
|
|
struct GPUShader *tonemap_sh;
|
|
|
|
} e_data = {NULL}; /* Engine data */
|
|
|
|
|
|
|
|
extern char datatoc_effect_motion_blur_frag_glsl[];
|
2017-05-07 14:27:43 +02:00
|
|
|
extern char datatoc_effect_bloom_frag_glsl[];
|
2017-05-09 21:57:13 +02:00
|
|
|
extern char datatoc_effect_dof_vert_glsl[];
|
|
|
|
extern char datatoc_effect_dof_geom_glsl[];
|
|
|
|
extern char datatoc_effect_dof_frag_glsl[];
|
2017-05-04 17:36:40 +02:00
|
|
|
extern char datatoc_tonemap_frag_glsl[];
|
|
|
|
|
|
|
|
void EEVEE_effects_init(EEVEE_Data *vedata)
|
|
|
|
{
|
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
|
|
EEVEE_TextureList *txl = vedata->txl;
|
2017-05-09 21:57:13 +02:00
|
|
|
EEVEE_EffectsInfo *effects;
|
2017-05-04 17:36:40 +02:00
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
|
|
Scene *scene = draw_ctx->scene;
|
|
|
|
View3D *v3d = draw_ctx->v3d;
|
|
|
|
RegionView3D *rv3d = draw_ctx->rv3d;
|
2017-05-04 17:36:40 +02:00
|
|
|
|
|
|
|
const float *viewport_size = DRW_viewport_size_get();
|
|
|
|
|
|
|
|
if (!e_data.motion_blur_sh) {
|
|
|
|
e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL);
|
|
|
|
}
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
if (!e_data.dof_downsample_sh) {
|
|
|
|
e_data.dof_downsample_sh = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL,
|
|
|
|
datatoc_effect_dof_frag_glsl, "#define STEP_DOWNSAMPLE\n");
|
|
|
|
e_data.dof_scatter_sh = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL,
|
|
|
|
datatoc_effect_dof_frag_glsl, "#define STEP_SCATTER\n");
|
|
|
|
e_data.dof_resolve_sh = DRW_shader_create(datatoc_effect_dof_vert_glsl, NULL,
|
|
|
|
datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n");
|
|
|
|
}
|
|
|
|
|
2017-05-07 14:27:43 +02:00
|
|
|
if (!e_data.bloom_blit_sh[0]) {
|
|
|
|
e_data.bloom_blit_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_BLIT\n");
|
|
|
|
e_data.bloom_blit_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_BLIT\n"
|
|
|
|
"#define HIGH_QUALITY\n");
|
|
|
|
|
|
|
|
e_data.bloom_downsample_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_DOWNSAMPLE\n");
|
|
|
|
e_data.bloom_downsample_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_DOWNSAMPLE\n"
|
|
|
|
"#define HIGH_QUALITY\n");
|
|
|
|
|
|
|
|
e_data.bloom_upsample_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_UPSAMPLE\n");
|
|
|
|
e_data.bloom_upsample_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_UPSAMPLE\n"
|
|
|
|
"#define HIGH_QUALITY\n");
|
|
|
|
|
|
|
|
e_data.bloom_resolve_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_RESOLVE\n");
|
|
|
|
e_data.bloom_resolve_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_bloom_frag_glsl, "#define STEP_RESOLVE\n"
|
|
|
|
"#define HIGH_QUALITY\n");
|
|
|
|
}
|
|
|
|
|
2017-05-04 17:36:40 +02:00
|
|
|
if (!e_data.tonemap_sh) {
|
|
|
|
e_data.tonemap_sh = DRW_shader_create_fullscreen(datatoc_tonemap_frag_glsl, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!stl->effects) {
|
|
|
|
stl->effects = MEM_callocN(sizeof(EEVEE_EffectsInfo), "EEVEE_EffectsInfo");
|
|
|
|
}
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
effects = stl->effects;
|
|
|
|
|
|
|
|
effects->enabled_effects = 0;
|
|
|
|
|
2017-05-07 14:27:43 +02:00
|
|
|
#if ENABLE_EFFECT_MOTION_BLUR
|
2017-05-04 17:36:40 +02:00
|
|
|
{
|
|
|
|
/* Update Motion Blur Matrices */
|
|
|
|
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
|
|
|
float ctime = BKE_scene_frame_get(scene);
|
|
|
|
float past_obmat[4][4], future_obmat[4][4], winmat[4][4];
|
|
|
|
|
|
|
|
DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
|
|
|
|
|
|
|
|
/* HACK */
|
|
|
|
Object cam_cpy;
|
|
|
|
memcpy(&cam_cpy, v3d->camera, sizeof(cam_cpy));
|
|
|
|
|
|
|
|
/* Past matrix */
|
|
|
|
/* FIXME : This is a temporal solution that does not take care of parent animations */
|
|
|
|
/* Recalc Anim manualy */
|
|
|
|
BKE_animsys_evaluate_animdata(scene, &cam_cpy.id, cam_cpy.adt, ctime - 1.0, ADT_RECALC_ANIM);
|
|
|
|
BKE_object_where_is_calc_time(scene, &cam_cpy, ctime - 1.0);
|
|
|
|
|
|
|
|
normalize_m4_m4(past_obmat, cam_cpy.obmat);
|
|
|
|
invert_m4(past_obmat);
|
|
|
|
mul_m4_m4m4(effects->past_world_to_ndc, winmat, past_obmat);
|
|
|
|
|
|
|
|
#if 0 /* for future high quality blur */
|
|
|
|
/* Future matrix */
|
|
|
|
/* Recalc Anim manualy */
|
|
|
|
BKE_animsys_evaluate_animdata(scene, &cam_cpy.id, cam_cpy.adt, ctime + 1.0, ADT_RECALC_ANIM);
|
|
|
|
BKE_object_where_is_calc_time(scene, &cam_cpy, ctime + 1.0);
|
|
|
|
|
|
|
|
normalize_m4_m4(past_obmat, cam_cpy.obmat);
|
|
|
|
invert_m4(past_obmat);
|
|
|
|
mul_m4_m4m4(effects->past_world_to_ndc, winmat, past_obmat);
|
|
|
|
#else
|
|
|
|
UNUSED_VARS(future_obmat);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Current matrix */
|
|
|
|
DRW_viewport_matrix_get(effects->current_ndc_to_world, DRW_MAT_PERSINV);
|
|
|
|
|
|
|
|
effects->blur_amount = 0.5f;
|
|
|
|
effects->enabled_effects |= EFFECT_MOTION_BLUR;
|
|
|
|
}
|
2017-05-07 14:27:43 +02:00
|
|
|
}
|
2017-05-04 17:36:40 +02:00
|
|
|
#endif /* ENABLE_EFFECT_MOTION_BLUR */
|
2017-05-07 14:27:43 +02:00
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
#if ENABLE_EFFECT_BLOOM
|
2017-05-07 14:27:43 +02:00
|
|
|
{
|
|
|
|
/* Bloom */
|
|
|
|
int blitsize[2], texsize[2];
|
|
|
|
|
|
|
|
/* Blit Buffer */
|
|
|
|
effects->source_texel_size[0] = 1.0f / viewport_size[0];
|
|
|
|
effects->source_texel_size[1] = 1.0f / viewport_size[1];
|
|
|
|
|
|
|
|
blitsize[0] = (int)viewport_size[0];
|
|
|
|
blitsize[1] = (int)viewport_size[1];
|
|
|
|
|
|
|
|
effects->blit_texel_size[0] = 1.0f / (float)blitsize[0];
|
|
|
|
effects->blit_texel_size[1] = 1.0f / (float)blitsize[1];
|
|
|
|
|
|
|
|
DRWFboTexture tex_blit = {&txl->bloom_blit, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
|
|
|
DRW_framebuffer_init(&fbl->bloom_blit_fb,
|
|
|
|
(int)blitsize[0], (int)blitsize[1],
|
|
|
|
&tex_blit, 1);
|
|
|
|
|
|
|
|
/* Parameters */
|
|
|
|
/* TODO UI Options */
|
|
|
|
float threshold = 0.8f;
|
|
|
|
float knee = 0.5f;
|
|
|
|
float intensity = 0.8f;
|
|
|
|
float radius = 8.5f;
|
|
|
|
|
|
|
|
/* determine the iteration count */
|
|
|
|
const float minDim = (float)MIN2(blitsize[0], blitsize[1]);
|
|
|
|
const float maxIter = (radius - 8.0f) + log(minDim) / log(2);
|
|
|
|
const int maxIterInt = effects->bloom_iteration_ct = (int)maxIter;
|
|
|
|
|
|
|
|
CLAMP(effects->bloom_iteration_ct, 1, MAX_BLOOM_STEP);
|
|
|
|
|
|
|
|
effects->bloom_sample_scale = 0.5f + maxIter - (float)maxIterInt;
|
|
|
|
effects->bloom_curve_threshold[0] = threshold - knee;
|
|
|
|
effects->bloom_curve_threshold[1] = knee * 2.0f;
|
|
|
|
effects->bloom_curve_threshold[2] = 0.25f / knee;
|
|
|
|
effects->bloom_curve_threshold[3] = threshold;
|
|
|
|
effects->bloom_intensity = intensity;
|
|
|
|
|
|
|
|
/* Downsample buffers */
|
|
|
|
copy_v2_v2_int(texsize, blitsize);
|
|
|
|
for (int i = 0; i < effects->bloom_iteration_ct; ++i) {
|
|
|
|
texsize[0] /= 2; texsize[1] /= 2;
|
|
|
|
texsize[0] = MAX2(texsize[0], 2);
|
|
|
|
texsize[1] = MAX2(texsize[1], 2);
|
|
|
|
|
|
|
|
effects->downsamp_texel_size[i][0] = 1.0f / (float)texsize[0];
|
|
|
|
effects->downsamp_texel_size[i][1] = 1.0f / (float)texsize[1];
|
|
|
|
|
|
|
|
DRWFboTexture tex_bloom = {&txl->bloom_downsample[i], DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
|
|
|
DRW_framebuffer_init(&fbl->bloom_down_fb[i],
|
|
|
|
(int)texsize[0], (int)texsize[1],
|
|
|
|
&tex_bloom, 1);
|
2017-05-04 17:36:40 +02:00
|
|
|
}
|
2017-05-07 14:27:43 +02:00
|
|
|
|
|
|
|
/* Upsample buffers */
|
|
|
|
copy_v2_v2_int(texsize, blitsize);
|
|
|
|
for (int i = 0; i < effects->bloom_iteration_ct - 1; ++i) {
|
|
|
|
texsize[0] /= 2; texsize[1] /= 2;
|
|
|
|
texsize[0] = MAX2(texsize[0], 2);
|
|
|
|
texsize[1] = MAX2(texsize[1], 2);
|
|
|
|
|
|
|
|
DRWFboTexture tex_bloom = {&txl->bloom_upsample[i], DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
|
|
|
DRW_framebuffer_init(&fbl->bloom_accum_fb[i],
|
|
|
|
(int)texsize[0], (int)texsize[1],
|
|
|
|
&tex_bloom, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
effects->enabled_effects |= EFFECT_BLOOM;
|
|
|
|
}
|
2017-05-09 21:57:13 +02:00
|
|
|
#endif /* ENABLE_EFFECT_BLOOM */
|
|
|
|
|
|
|
|
#if ENABLE_EFFECT_DOF
|
|
|
|
{
|
|
|
|
/* Depth Of Field */
|
|
|
|
if (rv3d->persp == RV3D_CAMOB && v3d->camera) {
|
|
|
|
Camera *cam = (Camera *)v3d->camera->data;
|
|
|
|
|
|
|
|
/* Retreive Near and Far distance */
|
|
|
|
effects->dof_near_far[0] = -cam->clipsta;
|
|
|
|
effects->dof_near_far[1] = -cam->clipend;
|
|
|
|
|
|
|
|
int buffer_size[2] = {(int)viewport_size[0] / 2, (int)viewport_size[1] / 2};
|
|
|
|
|
|
|
|
/* Setup buffers */
|
|
|
|
DRWFboTexture tex_down[3] = {{&txl->dof_down_near, DRW_BUF_RGBA_16, 0},
|
|
|
|
{&txl->dof_down_far, DRW_BUF_RGBA_16, 0},
|
|
|
|
{&txl->dof_coc, DRW_BUF_RG_16, 0}};
|
|
|
|
DRW_framebuffer_init(&fbl->dof_down_fb, buffer_size[0], buffer_size[1], tex_down, 3);
|
|
|
|
|
|
|
|
DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
|
|
|
DRW_framebuffer_init(&fbl->dof_scatter_far_fb, buffer_size[0], buffer_size[1], &tex_scatter_far, 1);
|
|
|
|
|
|
|
|
DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
|
|
|
DRW_framebuffer_init(&fbl->dof_scatter_near_fb, buffer_size[0], buffer_size[1], &tex_scatter_near, 1);
|
|
|
|
|
|
|
|
/* Parameters */
|
|
|
|
/* TODO UI Options */
|
|
|
|
float fstop = cam->gpu_dof.fstop;
|
|
|
|
float blades = cam->gpu_dof.num_blades;
|
|
|
|
float rotation = 0.0f;
|
|
|
|
float ratio = 1.0f;
|
|
|
|
float sensor = BKE_camera_sensor_size(cam->sensor_fit, cam->sensor_x, cam->sensor_y);
|
|
|
|
float focus_dist = BKE_camera_object_dof_distance(v3d->camera);
|
|
|
|
float focal_len = cam->lens;
|
|
|
|
|
|
|
|
UNUSED_VARS(rotation, ratio);
|
|
|
|
|
|
|
|
/* this is factor that converts to the scene scale. focal length and sensor are expressed in mm
|
|
|
|
* unit.scale_length is how many meters per blender unit we have. We want to convert to blender units though
|
|
|
|
* because the shader reads coordinates in world space, which is in blender units.
|
|
|
|
* Note however that focus_distance is already in blender units and shall not be scaled here (see T48157). */
|
|
|
|
float scale = (scene->unit.system) ? scene->unit.scale_length : 1.0f;
|
|
|
|
float scale_camera = 0.001f / scale;
|
|
|
|
/* we want radius here for the aperture number */
|
|
|
|
float aperture = 0.5f * scale_camera * focal_len / fstop;
|
|
|
|
float focal_len_scaled = scale_camera * focal_len;
|
|
|
|
float sensor_scaled = scale_camera * sensor;
|
|
|
|
|
|
|
|
effects->dof_params[0] = aperture * fabsf(focal_len_scaled / (focus_dist - focal_len_scaled));
|
|
|
|
effects->dof_params[1] = -focus_dist;
|
|
|
|
effects->dof_params[2] = viewport_size[0] / sensor_scaled;
|
|
|
|
effects->dof_bokeh[0] = blades;
|
|
|
|
effects->dof_bokeh[1] = rotation;
|
|
|
|
effects->dof_bokeh[2] = ratio;
|
|
|
|
|
|
|
|
effects->enabled_effects |= EFFECT_DOF;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* ENABLE_EFFECT_DOF */
|
|
|
|
|
|
|
|
/* Only allocate if at least one effect is activated */
|
|
|
|
if (effects->enabled_effects != 0) {
|
|
|
|
/* Ping Pong buffer */
|
|
|
|
DRWFboTexture tex = {&txl->color_post, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
|
|
|
|
|
|
|
DRW_framebuffer_init(&fbl->effect_fb,
|
|
|
|
(int)viewport_size[0], (int)viewport_size[1],
|
|
|
|
&tex, 1);
|
|
|
|
}
|
2017-05-07 14:27:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
|
|
|
|
{
|
|
|
|
struct Batch *quad = DRW_cache_fullscreen_quad_get();
|
|
|
|
|
|
|
|
*pass = DRW_pass_create(name, DRW_STATE_WRITE_COLOR);
|
|
|
|
|
|
|
|
DRWShadingGroup *grp = DRW_shgroup_create(sh, *pass);
|
|
|
|
DRW_shgroup_call_add(grp, quad, NULL);
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "sourceBuffer", &effects->unf_source_buffer);
|
2017-05-07 14:27:43 +02:00
|
|
|
DRW_shgroup_uniform_vec2(grp, "sourceBufferTexelSize", effects->unf_source_texel_size, 1);
|
|
|
|
if (upsample) {
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "baseBuffer", &effects->unf_base_buffer);
|
2017-05-07 14:27:43 +02:00
|
|
|
DRW_shgroup_uniform_float(grp, "sampleScale", &effects->bloom_sample_scale, 1);
|
2017-05-04 17:36:40 +02:00
|
|
|
}
|
2017-05-07 14:27:43 +02:00
|
|
|
|
|
|
|
return grp;
|
2017-05-04 17:36:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
|
|
|
{
|
|
|
|
EEVEE_PassList *psl = vedata->psl;
|
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
EEVEE_TextureList *txl = vedata->txl;
|
|
|
|
EEVEE_EffectsInfo *effects = stl->effects;
|
|
|
|
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
|
|
|
|
|
|
|
struct Batch *quad = DRW_cache_fullscreen_quad_get();
|
|
|
|
|
|
|
|
{
|
|
|
|
psl->motion_blur = DRW_pass_create("Motion Blur", DRW_STATE_WRITE_COLOR);
|
|
|
|
|
|
|
|
DRWShadingGroup *grp = DRW_shgroup_create(e_data.motion_blur_sh, psl->motion_blur);
|
|
|
|
DRW_shgroup_uniform_float(grp, "blurAmount", &effects->blur_amount, 1);
|
|
|
|
DRW_shgroup_uniform_mat4(grp, "currInvViewProjMatrix", (float *)effects->current_ndc_to_world);
|
|
|
|
DRW_shgroup_uniform_mat4(grp, "pastViewProjMatrix", (float *)effects->past_world_to_ndc);
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
|
|
|
|
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
|
2017-05-04 17:36:40 +02:00
|
|
|
DRW_shgroup_call_add(grp, quad, NULL);
|
|
|
|
}
|
|
|
|
|
2017-05-07 14:27:43 +02:00
|
|
|
{
|
|
|
|
/** Bloom algorithm
|
|
|
|
*
|
|
|
|
* Overview :
|
|
|
|
* - Downsample the color buffer doing a small blur during each step.
|
|
|
|
* - Accumulate bloom color using previously downsampled color buffers
|
|
|
|
* and do an upsample blur for each new accumulated layer.
|
|
|
|
* - Finally add accumulation buffer onto the source color buffer.
|
|
|
|
*
|
|
|
|
* [1/1] is original copy resolution (can be half or quater res for performance)
|
|
|
|
*
|
|
|
|
* [DOWNSAMPLE CHAIN] [UPSAMPLE CHAIN]
|
|
|
|
*
|
|
|
|
* Source Color ── [Blit] ──> Bright Color Extract [1/1] Final Color
|
|
|
|
* | Λ
|
|
|
|
* [Downsample First] Source Color ─> + [Resolve]
|
|
|
|
* v |
|
|
|
|
* Color Downsampled [1/2] ────────────> + Accumulation Buffer [1/2]
|
|
|
|
* | Λ
|
|
|
|
* ─── ───
|
|
|
|
* Repeat Repeat
|
|
|
|
* ─── ───
|
|
|
|
* v |
|
|
|
|
* Color Downsampled [1/N-1] ──────────> + Accumulation Buffer [1/N-1]
|
|
|
|
* | Λ
|
|
|
|
* [Downsample] [Upsample]
|
|
|
|
* v |
|
|
|
|
* Color Downsampled [1/N] ─────────────────────────┘
|
|
|
|
**/
|
|
|
|
DRWShadingGroup *grp;
|
|
|
|
const bool use_highres = true;
|
|
|
|
const bool use_antiflicker = true;
|
|
|
|
eevee_create_bloom_pass("Bloom Downsample First", effects, e_data.bloom_downsample_sh[use_antiflicker], &psl->bloom_downsample_first, false);
|
|
|
|
eevee_create_bloom_pass("Bloom Downsample", effects, e_data.bloom_downsample_sh[0], &psl->bloom_downsample, false);
|
|
|
|
eevee_create_bloom_pass("Bloom Upsample", effects, e_data.bloom_upsample_sh[use_highres], &psl->bloom_upsample, true);
|
|
|
|
grp = eevee_create_bloom_pass("Bloom Blit", effects, e_data.bloom_blit_sh[use_antiflicker], &psl->bloom_blit, false);
|
|
|
|
DRW_shgroup_uniform_vec4(grp, "curveThreshold", effects->bloom_curve_threshold, 1);
|
|
|
|
grp = eevee_create_bloom_pass("Bloom Resolve", effects, e_data.bloom_resolve_sh[use_highres], &psl->bloom_resolve, true);
|
|
|
|
DRW_shgroup_uniform_float(grp, "bloomIntensity", &effects->bloom_intensity, 1);
|
|
|
|
}
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
{
|
|
|
|
/** Depth of Field algorithm
|
|
|
|
*
|
|
|
|
* Overview :
|
|
|
|
* - Downsample the color buffer into 2 buffers weighted with
|
|
|
|
* CoC values. Also output CoC into a texture.
|
|
|
|
* - Shoot quads for every pixel and expand it depending on the CoC.
|
|
|
|
* Do one pass for near Dof and one pass for far Dof.
|
|
|
|
* - Finally composite the 2 blurred buffers with the original render.
|
|
|
|
**/
|
|
|
|
DRWShadingGroup *grp;
|
|
|
|
|
|
|
|
psl->dof_down = DRW_pass_create("DoF Downsample", DRW_STATE_WRITE_COLOR);
|
|
|
|
|
|
|
|
grp = DRW_shgroup_create(e_data.dof_downsample_sh, psl->dof_down);
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
|
|
|
|
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
|
2017-05-09 21:57:13 +02:00
|
|
|
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
|
|
|
|
DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
|
|
|
|
DRW_shgroup_call_add(grp, quad, NULL);
|
|
|
|
|
|
|
|
psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE);
|
|
|
|
|
|
|
|
/* This create an empty batch of N triangles to be positioned
|
|
|
|
* by the vertex shader 0.4ms against 6ms with instancing */
|
|
|
|
const float *viewport_size = DRW_viewport_size_get();
|
|
|
|
const int sprite_ct = ((int)viewport_size[0]/2) * ((int)viewport_size[1]/2); /* brackets matters */
|
|
|
|
grp = DRW_shgroup_empty_tri_batch_create(e_data.dof_scatter_sh, psl->dof_scatter, sprite_ct);
|
|
|
|
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->unf_source_buffer);
|
|
|
|
DRW_shgroup_uniform_buffer(grp, "cocBuffer", &txl->dof_coc);
|
2017-05-09 21:57:13 +02:00
|
|
|
DRW_shgroup_uniform_vec2(grp, "layerSelection", effects->dof_layer_select, 1);
|
|
|
|
DRW_shgroup_uniform_vec3(grp, "bokehParams", effects->dof_bokeh, 1);
|
|
|
|
|
|
|
|
psl->dof_resolve = DRW_pass_create("DoF Resolve", DRW_STATE_WRITE_COLOR);
|
|
|
|
|
|
|
|
grp = DRW_shgroup_create(e_data.dof_resolve_sh, psl->dof_resolve);
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer);
|
|
|
|
DRW_shgroup_uniform_buffer(grp, "nearBuffer", &txl->dof_near_blur);
|
|
|
|
DRW_shgroup_uniform_buffer(grp, "farBuffer", &txl->dof_far_blur);
|
|
|
|
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth);
|
2017-05-09 21:57:13 +02:00
|
|
|
DRW_shgroup_uniform_vec2(grp, "nearFar", effects->dof_near_far, 1);
|
|
|
|
DRW_shgroup_uniform_vec3(grp, "dofParams", effects->dof_params, 1);
|
|
|
|
DRW_shgroup_call_add(grp, quad, NULL);
|
|
|
|
}
|
|
|
|
|
2017-05-04 17:36:40 +02:00
|
|
|
{
|
|
|
|
/* Final pass : Map HDR color to LDR color.
|
|
|
|
* Write result to the default color buffer */
|
|
|
|
psl->tonemap = DRW_pass_create("Tone Mapping", DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND);
|
|
|
|
|
|
|
|
DRWShadingGroup *grp = DRW_shgroup_create(e_data.tonemap_sh, psl->tonemap);
|
2017-05-09 22:08:25 +02:00
|
|
|
DRW_shgroup_uniform_buffer(grp, "hdrColorBuf", &effects->source_buffer);
|
2017-05-04 17:36:40 +02:00
|
|
|
DRW_shgroup_call_add(grp, quad, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
#define SWAP_BUFFERS() { \
|
|
|
|
if (effects->source_buffer == txl->color) { \
|
|
|
|
effects->source_buffer = txl->color_post; \
|
|
|
|
effects->target_buffer = fbl->main; \
|
|
|
|
} \
|
|
|
|
else { \
|
|
|
|
effects->source_buffer = txl->color; \
|
|
|
|
effects->target_buffer = fbl->effect_fb; \
|
|
|
|
} \
|
|
|
|
} ((void)0)
|
2017-05-07 14:27:43 +02:00
|
|
|
|
2017-05-04 17:36:40 +02:00
|
|
|
void EEVEE_draw_effects(EEVEE_Data *vedata)
|
|
|
|
{
|
|
|
|
EEVEE_PassList *psl = vedata->psl;
|
2017-05-07 14:27:43 +02:00
|
|
|
EEVEE_TextureList *txl = vedata->txl;
|
2017-05-04 17:36:40 +02:00
|
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
|
|
EEVEE_StorageList *stl = vedata->stl;
|
|
|
|
EEVEE_EffectsInfo *effects = stl->effects;
|
|
|
|
|
|
|
|
/* Default framebuffer and texture */
|
|
|
|
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
|
|
|
|
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
|
|
|
|
2017-05-07 14:27:43 +02:00
|
|
|
/* Init pointers */
|
|
|
|
effects->source_buffer = txl->color; /* latest updated texture */
|
|
|
|
effects->target_buffer = fbl->effect_fb; /* next target to render to */
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
/* Detach depth for effects to use it */
|
|
|
|
DRW_framebuffer_texture_detach(dtxl->depth);
|
|
|
|
|
2017-05-07 14:27:43 +02:00
|
|
|
/* Motion Blur */
|
2017-05-04 17:36:40 +02:00
|
|
|
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
|
2017-05-09 21:57:13 +02:00
|
|
|
DRW_framebuffer_bind(effects->target_buffer);
|
2017-05-04 17:36:40 +02:00
|
|
|
DRW_draw_pass(psl->motion_blur);
|
2017-05-09 21:57:13 +02:00
|
|
|
SWAP_BUFFERS();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Depth Of Field */
|
|
|
|
if ((effects->enabled_effects & EFFECT_DOF) != 0) {
|
|
|
|
float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f};
|
|
|
|
|
|
|
|
/* Downsample */
|
|
|
|
DRW_framebuffer_bind(fbl->dof_down_fb);
|
|
|
|
DRW_draw_pass(psl->dof_down);
|
|
|
|
|
|
|
|
/* Scatter Far */
|
|
|
|
effects->unf_source_buffer = txl->dof_down_far;
|
|
|
|
copy_v2_fl2(effects->dof_layer_select, 0.0f, 1.0f);
|
|
|
|
DRW_framebuffer_bind(fbl->dof_scatter_far_fb);
|
|
|
|
DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
|
|
|
|
DRW_draw_pass(psl->dof_scatter);
|
|
|
|
|
|
|
|
/* Scatter Near */
|
|
|
|
effects->unf_source_buffer = txl->dof_down_near;
|
|
|
|
copy_v2_fl2(effects->dof_layer_select, 1.0f, 0.0f);
|
|
|
|
DRW_framebuffer_bind(fbl->dof_scatter_near_fb);
|
|
|
|
DRW_framebuffer_clear(true, false, false, clear_col, 0.0f);
|
|
|
|
DRW_draw_pass(psl->dof_scatter);
|
|
|
|
|
|
|
|
/* Resolve */
|
|
|
|
DRW_framebuffer_bind(effects->target_buffer);
|
|
|
|
DRW_draw_pass(psl->dof_resolve);
|
|
|
|
SWAP_BUFFERS();
|
2017-05-04 17:36:40 +02:00
|
|
|
}
|
|
|
|
|
2017-05-07 14:27:43 +02:00
|
|
|
/* Bloom */
|
|
|
|
if ((effects->enabled_effects & EFFECT_BLOOM) != 0) {
|
|
|
|
struct GPUTexture *last;
|
|
|
|
|
|
|
|
/* Extract bright pixels */
|
|
|
|
copy_v2_v2(effects->unf_source_texel_size, effects->source_texel_size);
|
|
|
|
effects->unf_source_buffer = effects->source_buffer;
|
|
|
|
|
|
|
|
DRW_framebuffer_bind(fbl->bloom_blit_fb);
|
|
|
|
DRW_draw_pass(psl->bloom_blit);
|
|
|
|
|
|
|
|
/* Downsample */
|
|
|
|
copy_v2_v2(effects->unf_source_texel_size, effects->blit_texel_size);
|
|
|
|
effects->unf_source_buffer = txl->bloom_blit;
|
|
|
|
|
|
|
|
DRW_framebuffer_bind(fbl->bloom_down_fb[0]);
|
|
|
|
DRW_draw_pass(psl->bloom_downsample_first);
|
|
|
|
|
|
|
|
last = txl->bloom_downsample[0];
|
|
|
|
|
|
|
|
for (int i = 1; i < effects->bloom_iteration_ct; ++i) {
|
|
|
|
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i-1]);
|
|
|
|
effects->unf_source_buffer = last;
|
|
|
|
|
|
|
|
DRW_framebuffer_bind(fbl->bloom_down_fb[i]);
|
|
|
|
DRW_draw_pass(psl->bloom_downsample);
|
|
|
|
|
|
|
|
/* Used in next loop */
|
|
|
|
last = txl->bloom_downsample[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Upsample and accumulate */
|
|
|
|
for (int i = effects->bloom_iteration_ct - 2; i >= 0; --i) {
|
|
|
|
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[i]);
|
|
|
|
effects->unf_source_buffer = txl->bloom_downsample[i];
|
|
|
|
effects->unf_base_buffer = last;
|
|
|
|
|
|
|
|
DRW_framebuffer_bind(fbl->bloom_accum_fb[i]);
|
|
|
|
DRW_draw_pass(psl->bloom_upsample);
|
|
|
|
|
|
|
|
last = txl->bloom_upsample[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Resolve */
|
|
|
|
copy_v2_v2(effects->unf_source_texel_size, effects->downsamp_texel_size[0]);
|
|
|
|
effects->unf_source_buffer = last;
|
|
|
|
effects->unf_base_buffer = effects->source_buffer;
|
|
|
|
|
2017-05-09 21:57:13 +02:00
|
|
|
DRW_framebuffer_bind(effects->target_buffer);
|
2017-05-07 14:27:43 +02:00
|
|
|
DRW_draw_pass(psl->bloom_resolve);
|
2017-05-09 21:57:13 +02:00
|
|
|
SWAP_BUFFERS();
|
2017-05-07 14:27:43 +02:00
|
|
|
}
|
|
|
|
|
2017-05-04 17:36:40 +02:00
|
|
|
/* Restore default framebuffer */
|
|
|
|
DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
|
|
|
|
DRW_framebuffer_bind(dfbl->default_fb);
|
|
|
|
|
|
|
|
/* Tonemapping */
|
2017-05-07 14:27:43 +02:00
|
|
|
/* TODO : use OCIO */
|
2017-05-04 17:36:40 +02:00
|
|
|
DRW_draw_pass(psl->tonemap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EEVEE_effects_free(void)
|
|
|
|
{
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.tonemap_sh);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh);
|
2017-05-09 21:57:13 +02:00
|
|
|
DRW_SHADER_FREE_SAFE(e_data.dof_downsample_sh);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.dof_scatter_sh);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.dof_resolve_sh);
|
2017-05-07 14:27:43 +02:00
|
|
|
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[0]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[0]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_upsample_sh[0]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_resolve_sh[0]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[1]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[1]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_upsample_sh[1]);
|
|
|
|
DRW_SHADER_FREE_SAFE(e_data.bloom_resolve_sh[1]);
|
2017-05-04 17:36:40 +02:00
|
|
|
}
|