Eevee: Initial Depth Of Field commit.
This commit is contained in:
parent
435f5017fa
commit
9075f934aa
|
@ -37,7 +37,7 @@ class CAMERA_MT_presets(Menu):
|
|||
bl_label = "Camera Presets"
|
||||
preset_subdir = "camera"
|
||||
preset_operator = "script.execute_preset"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
|
@ -45,14 +45,14 @@ class SAFE_AREAS_MT_presets(Menu):
|
|||
bl_label = "Camera Presets"
|
||||
preset_subdir = "safe_areas"
|
||||
preset_operator = "script.execute_preset"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
draw = Menu.draw_preset
|
||||
|
||||
|
||||
class DATA_PT_context_camera(CameraButtonsPanel, Panel):
|
||||
bl_label = ""
|
||||
bl_options = {'HIDE_HEADER'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -72,7 +72,7 @@ class DATA_PT_context_camera(CameraButtonsPanel, Panel):
|
|||
|
||||
class DATA_PT_lens(CameraButtonsPanel, Panel):
|
||||
bl_label = "Lens"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -183,7 +183,7 @@ class DATA_PT_camera_stereoscopy(CameraButtonsPanel, Panel):
|
|||
|
||||
class DATA_PT_camera(CameraButtonsPanel, Panel):
|
||||
bl_label = "Camera"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -217,7 +217,7 @@ class DATA_PT_camera(CameraButtonsPanel, Panel):
|
|||
|
||||
class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
|
||||
bl_label = "Depth of Field"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -247,7 +247,7 @@ class DATA_PT_camera_dof(CameraButtonsPanel, Panel):
|
|||
|
||||
class DATA_PT_camera_display(CameraButtonsPanel, Panel):
|
||||
bl_label = "Display"
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
@ -277,7 +277,7 @@ class DATA_PT_camera_display(CameraButtonsPanel, Panel):
|
|||
class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
|
||||
bl_label = "Safe Areas"
|
||||
bl_options = {'DEFAULT_CLOSED'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
|
||||
def draw_header(self, context):
|
||||
cam = context.camera
|
||||
|
@ -293,7 +293,7 @@ class DATA_PT_camera_safe_areas(CameraButtonsPanel, Panel):
|
|||
|
||||
|
||||
class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel):
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY'}
|
||||
COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME', 'BLENDER_CLAY', 'BLENDER_EEVEE'}
|
||||
_context_path = "object.data"
|
||||
_property_type = bpy.types.Camera
|
||||
|
||||
|
|
|
@ -115,6 +115,9 @@ data_to_c_simple(engines/eevee/shaders/background_vert.glsl SRC)
|
|||
data_to_c_simple(engines/eevee/shaders/lit_surface_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/lit_surface_vert.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/effect_bloom_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/effect_dof_vert.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/effect_dof_geom.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/effect_dof_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/probe_filter_frag.glsl SRC)
|
||||
data_to_c_simple(engines/eevee/shaders/probe_sh_frag.glsl SRC)
|
||||
|
|
|
@ -29,8 +29,10 @@
|
|||
#include "DRW_render.h"
|
||||
|
||||
#include "DNA_anim_types.h"
|
||||
#include "DNA_camera_types.h"
|
||||
#include "DNA_view3d_types.h"
|
||||
|
||||
#include "BKE_camera.h"
|
||||
#include "BKE_object.h"
|
||||
#include "BKE_animsys.h"
|
||||
|
||||
|
@ -44,8 +46,10 @@ typedef struct EEVEE_ProbeData {
|
|||
/* TODO Option */
|
||||
#define ENABLE_EFFECT_MOTION_BLUR 1
|
||||
#define ENABLE_EFFECT_BLOOM 1
|
||||
#define ENABLE_EFFECT_DOF 1
|
||||
|
||||
static struct {
|
||||
/* Motion Blur */
|
||||
struct GPUShader *motion_blur_sh;
|
||||
|
||||
/* Bloom */
|
||||
|
@ -54,11 +58,19 @@ static struct {
|
|||
struct GPUShader *bloom_upsample_sh[2];
|
||||
struct GPUShader *bloom_resolve_sh[2];
|
||||
|
||||
/* Depth Of Field */
|
||||
struct GPUShader *dof_downsample_sh;
|
||||
struct GPUShader *dof_scatter_sh;
|
||||
struct GPUShader *dof_resolve_sh;
|
||||
|
||||
struct GPUShader *tonemap_sh;
|
||||
} e_data = {NULL}; /* Engine data */
|
||||
|
||||
extern char datatoc_effect_motion_blur_frag_glsl[];
|
||||
extern char datatoc_effect_bloom_frag_glsl[];
|
||||
extern char datatoc_effect_dof_vert_glsl[];
|
||||
extern char datatoc_effect_dof_geom_glsl[];
|
||||
extern char datatoc_effect_dof_frag_glsl[];
|
||||
extern char datatoc_tonemap_frag_glsl[];
|
||||
|
||||
void EEVEE_effects_init(EEVEE_Data *vedata)
|
||||
|
@ -66,19 +78,28 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
EEVEE_StorageList *stl = vedata->stl;
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_TextureList *txl = vedata->txl;
|
||||
EEVEE_EffectsInfo *effects;
|
||||
|
||||
/* Ping Pong buffer */
|
||||
DRWFboTexture tex = {&txl->color_post, DRW_BUF_RGBA_16, DRW_TEX_FILTER};
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
Scene *scene = draw_ctx->scene;
|
||||
View3D *v3d = draw_ctx->v3d;
|
||||
RegionView3D *rv3d = draw_ctx->rv3d;
|
||||
|
||||
const float *viewport_size = DRW_viewport_size_get();
|
||||
DRW_framebuffer_init(&fbl->effect_fb,
|
||||
(int)viewport_size[0], (int)viewport_size[1],
|
||||
&tex, 1);
|
||||
|
||||
if (!e_data.motion_blur_sh) {
|
||||
e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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"
|
||||
|
@ -103,18 +124,15 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
|
||||
if (!stl->effects) {
|
||||
stl->effects = MEM_callocN(sizeof(EEVEE_EffectsInfo), "EEVEE_EffectsInfo");
|
||||
stl->effects->enabled_effects = 0;
|
||||
}
|
||||
|
||||
effects = stl->effects;
|
||||
|
||||
effects->enabled_effects = 0;
|
||||
|
||||
#if ENABLE_EFFECT_MOTION_BLUR
|
||||
{
|
||||
/* Update Motion Blur Matrices */
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
const DRWContextState *draw_ctx = DRW_context_state_get();
|
||||
Scene *scene = draw_ctx->scene;
|
||||
View3D *v3d = draw_ctx->v3d;
|
||||
RegionView3D *rv3d = draw_ctx->rv3d;
|
||||
|
||||
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];
|
||||
|
@ -157,9 +175,9 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
}
|
||||
#endif /* ENABLE_EFFECT_MOTION_BLUR */
|
||||
|
||||
#if ENABLE_EFFECT_BLOOM
|
||||
{
|
||||
/* Bloom */
|
||||
EEVEE_EffectsInfo *effects = stl->effects;
|
||||
int blitsize[2], texsize[2];
|
||||
|
||||
/* Blit Buffer */
|
||||
|
@ -229,6 +247,76 @@ void EEVEE_effects_init(EEVEE_Data *vedata)
|
|||
|
||||
effects->enabled_effects |= EFFECT_BLOOM;
|
||||
}
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
static DRWShadingGroup *eevee_create_bloom_pass(const char *name, EEVEE_EffectsInfo *effects, struct GPUShader *sh, DRWPass **pass, bool upsample)
|
||||
|
@ -266,7 +354,7 @@ void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
|||
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);
|
||||
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &txl->color, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth, 1);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
}
|
||||
|
@ -312,6 +400,52 @@ void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
|||
DRW_shgroup_uniform_float(grp, "bloomIntensity", &effects->bloom_intensity, 1);
|
||||
}
|
||||
|
||||
{
|
||||
/** 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);
|
||||
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth, 1);
|
||||
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);
|
||||
|
||||
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->unf_source_buffer, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "cocBuffer", &txl->dof_coc, 1);
|
||||
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);
|
||||
DRW_shgroup_uniform_buffer(grp, "colorBuffer", &effects->source_buffer, 0);
|
||||
DRW_shgroup_uniform_buffer(grp, "nearBuffer", &txl->dof_near_blur, 1);
|
||||
DRW_shgroup_uniform_buffer(grp, "farBuffer", &txl->dof_far_blur, 2);
|
||||
DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth, 3);
|
||||
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);
|
||||
}
|
||||
|
||||
{
|
||||
/* Final pass : Map HDR color to LDR color.
|
||||
* Write result to the default color buffer */
|
||||
|
@ -323,24 +457,16 @@ void EEVEE_effects_cache_init(EEVEE_Data *vedata)
|
|||
}
|
||||
}
|
||||
|
||||
/* Ping pong between 2 buffers */
|
||||
static void eevee_effect_framebuffer_bind(EEVEE_Data *vedata)
|
||||
{
|
||||
EEVEE_TextureList *txl = vedata->txl;
|
||||
EEVEE_FramebufferList *fbl = vedata->fbl;
|
||||
EEVEE_EffectsInfo *effects = vedata->stl->effects;
|
||||
|
||||
DRW_framebuffer_bind(effects->target_buffer);
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
#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)
|
||||
|
||||
void EEVEE_draw_effects(EEVEE_Data *vedata)
|
||||
{
|
||||
|
@ -358,10 +484,42 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
|
|||
effects->source_buffer = txl->color; /* latest updated texture */
|
||||
effects->target_buffer = fbl->effect_fb; /* next target to render to */
|
||||
|
||||
/* Detach depth for effects to use it */
|
||||
DRW_framebuffer_texture_detach(dtxl->depth);
|
||||
|
||||
/* Motion Blur */
|
||||
if ((effects->enabled_effects & EFFECT_MOTION_BLUR) != 0) {
|
||||
eevee_effect_framebuffer_bind(vedata);
|
||||
DRW_framebuffer_bind(effects->target_buffer);
|
||||
DRW_draw_pass(psl->motion_blur);
|
||||
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();
|
||||
}
|
||||
|
||||
/* Bloom */
|
||||
|
@ -412,12 +570,12 @@ void EEVEE_draw_effects(EEVEE_Data *vedata)
|
|||
effects->unf_source_buffer = last;
|
||||
effects->unf_base_buffer = effects->source_buffer;
|
||||
|
||||
eevee_effect_framebuffer_bind(vedata);
|
||||
DRW_framebuffer_bind(effects->target_buffer);
|
||||
DRW_draw_pass(psl->bloom_resolve);
|
||||
SWAP_BUFFERS();
|
||||
}
|
||||
|
||||
/* Restore default framebuffer */
|
||||
DRW_framebuffer_texture_detach(dtxl->depth);
|
||||
DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0);
|
||||
DRW_framebuffer_bind(dfbl->default_fb);
|
||||
|
||||
|
@ -430,6 +588,9 @@ void EEVEE_effects_free(void)
|
|||
{
|
||||
DRW_SHADER_FREE_SAFE(e_data.tonemap_sh);
|
||||
DRW_SHADER_FREE_SAFE(e_data.motion_blur_sh);
|
||||
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);
|
||||
|
||||
DRW_SHADER_FREE_SAFE(e_data.bloom_blit_sh[0]);
|
||||
DRW_SHADER_FREE_SAFE(e_data.bloom_downsample_sh[0]);
|
||||
|
|
|
@ -54,6 +54,9 @@ typedef struct EEVEE_PassList {
|
|||
struct DRWPass *bloom_downsample;
|
||||
struct DRWPass *bloom_upsample;
|
||||
struct DRWPass *bloom_resolve;
|
||||
struct DRWPass *dof_down;
|
||||
struct DRWPass *dof_scatter;
|
||||
struct DRWPass *dof_resolve;
|
||||
struct DRWPass *tonemap;
|
||||
|
||||
struct DRWPass *depth_pass;
|
||||
|
@ -77,6 +80,9 @@ typedef struct EEVEE_FramebufferList {
|
|||
struct GPUFrameBuffer *bloom_blit_fb; /* HDR */
|
||||
struct GPUFrameBuffer *bloom_down_fb[MAX_BLOOM_STEP]; /* HDR */
|
||||
struct GPUFrameBuffer *bloom_accum_fb[MAX_BLOOM_STEP-1]; /* HDR */
|
||||
struct GPUFrameBuffer *dof_down_fb;
|
||||
struct GPUFrameBuffer *dof_scatter_far_fb;
|
||||
struct GPUFrameBuffer *dof_scatter_near_fb;
|
||||
|
||||
struct GPUFrameBuffer *main; /* HDR */
|
||||
} EEVEE_FramebufferList;
|
||||
|
@ -93,6 +99,11 @@ typedef struct EEVEE_TextureList {
|
|||
struct GPUTexture *probe_sh; /* R16_G16_B16 */
|
||||
/* Effects */
|
||||
struct GPUTexture *color_post; /* R16_G16_B16 */
|
||||
struct GPUTexture *dof_down_near; /* R16_G16_B16_A16 */
|
||||
struct GPUTexture *dof_down_far; /* R16_G16_B16_A16 */
|
||||
struct GPUTexture *dof_coc; /* R16_G16 */
|
||||
struct GPUTexture *dof_near_blur; /* R16_G16_B16_A16 */
|
||||
struct GPUTexture *dof_far_blur; /* R16_G16_B16_A16 */
|
||||
struct GPUTexture *bloom_blit; /* R16_G16_B16 */
|
||||
struct GPUTexture *bloom_downsample[MAX_BLOOM_STEP]; /* R16_G16_B16 */
|
||||
struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP-1]; /* R16_G16_B16 */
|
||||
|
@ -193,6 +204,13 @@ typedef struct EEVEE_EffectsInfo {
|
|||
float tmp_mat[4][4];
|
||||
float blur_amount;
|
||||
|
||||
/* Depth Of Field */
|
||||
float dof_near_far[2];
|
||||
float dof_params[3];
|
||||
float dof_bokeh[3];
|
||||
float dof_layer_select[2];
|
||||
int dof_target_size[2];
|
||||
|
||||
/* Bloom */
|
||||
int bloom_iteration_ct;
|
||||
float source_texel_size[2];
|
||||
|
@ -213,6 +231,7 @@ typedef struct EEVEE_EffectsInfo {
|
|||
enum {
|
||||
EFFECT_MOTION_BLUR = (1 << 0),
|
||||
EFFECT_BLOOM = (1 << 1),
|
||||
EFFECT_DOF = (1 << 2),
|
||||
};
|
||||
|
||||
/* *********************************** */
|
||||
|
|
|
@ -0,0 +1,222 @@
|
|||
|
||||
uniform mat4 ProjectionMatrix;
|
||||
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D depthBuffer;
|
||||
|
||||
uniform vec3 dofParams;
|
||||
|
||||
#define dof_aperturesize dofParams.x
|
||||
#define dof_distance dofParams.y
|
||||
#define dof_invsensorsize dofParams.z
|
||||
|
||||
uniform vec3 bokehParams;
|
||||
|
||||
#define bokeh_sides bokehParams.x /* Polygon Bokeh shape number of sides */
|
||||
#define bokeh_rotation bokehParams.y
|
||||
|
||||
uniform vec2 nearFar; /* Near & far view depths values */
|
||||
|
||||
/* initial uv coordinate */
|
||||
in vec2 uvcoord;
|
||||
|
||||
layout(location = 0) out vec4 fragData0;
|
||||
layout(location = 1) out vec4 fragData1;
|
||||
layout(location = 2) out vec4 fragData2;
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#define M_2PI 6.2831853071795864769252868
|
||||
|
||||
/* -------------- Utils ------------- */
|
||||
|
||||
/* calculate 4 samples at once */
|
||||
float calculate_coc(in float zdepth)
|
||||
{
|
||||
float coc = dof_aperturesize * (dof_distance / zdepth - 1.0);
|
||||
|
||||
/* multiply by 1.0 / sensor size to get the normalized size */
|
||||
return coc * dof_invsensorsize;
|
||||
}
|
||||
|
||||
vec4 calculate_coc(in vec4 zdepth)
|
||||
{
|
||||
vec4 coc = dof_aperturesize * (vec4(dof_distance) / zdepth - vec4(1.0));
|
||||
|
||||
/* multiply by 1.0 / sensor size to get the normalized size */
|
||||
return coc * dof_invsensorsize;
|
||||
}
|
||||
|
||||
float max4(vec4 x)
|
||||
{
|
||||
return max(max(x.x, x.y), max(x.z, x.w));
|
||||
}
|
||||
|
||||
float linear_depth(float z)
|
||||
{
|
||||
/* if persp */
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
return (nearFar.x * nearFar.y) / (z * (nearFar.x - nearFar.y) + nearFar.y);
|
||||
}
|
||||
else {
|
||||
return (z * 2.0 - 1.0) * nearFar.y;
|
||||
}
|
||||
}
|
||||
|
||||
vec4 linear_depth(vec4 z)
|
||||
{
|
||||
/* if persp */
|
||||
if (ProjectionMatrix[3][3] == 0.0) {
|
||||
return (nearFar.xxxx * nearFar.yyyy) / (z * (nearFar.xxxx - nearFar.yyyy) + nearFar.yyyy);
|
||||
}
|
||||
else {
|
||||
return (z * 2.0 - 1.0) * nearFar.yyyy;
|
||||
}
|
||||
}
|
||||
|
||||
#define THRESHOLD 0.0
|
||||
|
||||
/* ----------- Steps ----------- */
|
||||
|
||||
/* Downsample the color buffer to half resolution.
|
||||
* Weight color samples by
|
||||
* Compute maximum CoC for near and far blur. */
|
||||
void step_downsample(void)
|
||||
{
|
||||
ivec4 uvs = ivec4(gl_FragCoord.xyxy) * 2 + ivec4(0, 0, 1, 1);
|
||||
|
||||
/* custom downsampling */
|
||||
vec4 color1 = texelFetch(colorBuffer, uvs.xy, 0);
|
||||
vec4 color2 = texelFetch(colorBuffer, uvs.zw, 0);
|
||||
vec4 color3 = texelFetch(colorBuffer, uvs.zy, 0);
|
||||
vec4 color4 = texelFetch(colorBuffer, uvs.xw, 0);
|
||||
|
||||
/* Leverage SIMD by combining 4 depth samples into a vec4 */
|
||||
vec4 depth;
|
||||
depth.r = texelFetch(depthBuffer, uvs.xy, 0).r;
|
||||
depth.g = texelFetch(depthBuffer, uvs.zw, 0).r;
|
||||
depth.b = texelFetch(depthBuffer, uvs.zy, 0).r;
|
||||
depth.a = texelFetch(depthBuffer, uvs.xw, 0).r;
|
||||
|
||||
vec4 zdepth = linear_depth(depth);
|
||||
|
||||
/* Compute signed CoC for each depth samples */
|
||||
vec4 coc_near = calculate_coc(zdepth);
|
||||
vec4 coc_far = -coc_near;
|
||||
|
||||
/* now we need to write the near-far fields premultiplied by the coc */
|
||||
vec4 near_weights = step(THRESHOLD, coc_near);
|
||||
vec4 far_weights = step(THRESHOLD, coc_far);
|
||||
|
||||
/* now write output to weighted buffers. */
|
||||
fragData0 = color1 * near_weights.x +
|
||||
color2 * near_weights.y +
|
||||
color3 * near_weights.z +
|
||||
color4 * near_weights.w;
|
||||
|
||||
fragData1 = color1 * far_weights.x +
|
||||
color2 * far_weights.y +
|
||||
color3 * far_weights.z +
|
||||
color4 * far_weights.w;
|
||||
|
||||
float norm_near = dot(near_weights, near_weights);
|
||||
float norm_far = dot(far_weights, far_weights);
|
||||
|
||||
if (norm_near > 0.0) {
|
||||
fragData0 /= norm_near;
|
||||
}
|
||||
|
||||
if (norm_far > 0.0) {
|
||||
fragData1 /= norm_far;
|
||||
}
|
||||
|
||||
float max_near_coc = max(max4(coc_near), 0.0);
|
||||
float max_far_coc = max(max4(coc_far), 0.0);
|
||||
|
||||
fragData2 = vec4(max_near_coc, max_far_coc, 0.0, 1.0);
|
||||
}
|
||||
|
||||
/* coordinate used for calculating radius et al set in geometry shader */
|
||||
in vec2 particlecoord;
|
||||
flat in vec4 color;
|
||||
|
||||
/* accumulate color in the near/far blur buffers */
|
||||
void step_scatter(void)
|
||||
{
|
||||
/* Early out */
|
||||
float dist_sqrd = dot(particlecoord, particlecoord);
|
||||
|
||||
/* Circle Dof */
|
||||
if (dist_sqrd > 1.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
/* Regular Polygon Dof */
|
||||
if (bokeh_sides > 0.0) {
|
||||
/* Circle parametrization */
|
||||
float theta = atan(particlecoord.y, particlecoord.x) + bokeh_rotation;
|
||||
float r;
|
||||
|
||||
r = cos(M_PI / bokeh_sides) /
|
||||
(cos(theta - (M_2PI / bokeh_sides) * floor((bokeh_sides * theta + M_PI) / M_2PI)));
|
||||
|
||||
if (dist_sqrd > r * r) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
||||
fragData0 = color;
|
||||
}
|
||||
|
||||
#define MERGE_THRESHOLD 4.0
|
||||
|
||||
uniform sampler2D farBuffer;
|
||||
uniform sampler2D nearBuffer;
|
||||
|
||||
/* Combine the Far and Near color buffers */
|
||||
void step_resolve(void)
|
||||
{
|
||||
/* Recompute Near / Far CoC */
|
||||
float depth = texture(depthBuffer, uvcoord).r;
|
||||
float zdepth = linear_depth(depth);
|
||||
float coc_signed = calculate_coc(zdepth);
|
||||
float coc_far = max(-coc_signed, 0.0);
|
||||
float coc_near = max(coc_signed, 0.0);
|
||||
|
||||
/* Recompute Near / Far CoC */
|
||||
vec4 srccolor = texture(colorBuffer, uvcoord);
|
||||
vec4 farcolor = texture(farBuffer, uvcoord);
|
||||
vec4 nearcolor = texture(nearBuffer, uvcoord);
|
||||
|
||||
float farweight = farcolor.a;
|
||||
if (farweight > 0.0)
|
||||
farcolor /= farweight;
|
||||
|
||||
float mixfac = smoothstep(1.0, MERGE_THRESHOLD, coc_far);
|
||||
|
||||
farweight = mix(1.0, farweight, mixfac);
|
||||
|
||||
float nearweight = nearcolor.a;
|
||||
if (nearweight > 0.0) {
|
||||
nearcolor /= nearweight;
|
||||
}
|
||||
|
||||
if (coc_near > 1.0) {
|
||||
fragData0 = nearcolor;
|
||||
}
|
||||
else {
|
||||
float totalweight = nearweight + farweight;
|
||||
vec4 finalcolor = mix(srccolor, farcolor, mixfac);
|
||||
fragData0 = mix(finalcolor, nearcolor, nearweight / totalweight);
|
||||
}
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#ifdef STEP_DOWNSAMPLE
|
||||
step_downsample();
|
||||
#elif defined(STEP_SCATTER)
|
||||
step_scatter();
|
||||
#elif defined(STEP_RESOLVE)
|
||||
step_resolve();
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
uniform ivec2 targetBufferSize;
|
||||
|
||||
uniform vec2 layerSelection;
|
||||
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D cocBuffer;
|
||||
|
||||
layout(points) in;
|
||||
layout(triangle_strip, max_vertices = 4) out;
|
||||
|
||||
#define POS gl_in[0].gl_Position
|
||||
|
||||
in vec2 uvcoord[];
|
||||
out vec2 particlecoord;
|
||||
flat out vec4 color;
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 coc = textureLod(cocBuffer, uvcoord[0], 0.0);
|
||||
|
||||
float offset_val = dot(coc.rg, layerSelection);
|
||||
if (offset_val < 1.0)
|
||||
return;
|
||||
|
||||
vec4 colortex = textureLod(colorBuffer, uvcoord[0], 0.0);
|
||||
|
||||
/* find the area the pixel will cover and divide the color by it */
|
||||
float alpha = 1.0 / (offset_val * offset_val * M_PI);
|
||||
colortex *= alpha;
|
||||
colortex.a = alpha;
|
||||
|
||||
vec2 offset_far = vec2(offset_val * 0.5) / vec2(targetBufferSize.x, targetBufferSize.y);
|
||||
|
||||
color = colortex;
|
||||
|
||||
gl_Position = POS + vec4(-offset_far.x, -offset_far.y, 0.0, 0.0);
|
||||
particlecoord = vec2(-1.0, -1.0);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = POS + vec4(-offset_far.x, offset_far.y, 0.0, 0.0);
|
||||
particlecoord = vec2(-1.0, 1.0);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = POS + vec4(offset_far.x, -offset_far.y, 0.0, 0.0);
|
||||
particlecoord = vec2(1.0, -1.0);
|
||||
EmitVertex();
|
||||
|
||||
gl_Position = POS + vec4(offset_far.x, offset_far.y, 0.0, 0.0);
|
||||
particlecoord = vec2(1.0, 1.0);
|
||||
EmitVertex();
|
||||
|
||||
EndPrimitive();
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
|
||||
in vec2 pos;
|
||||
in vec2 uvs;
|
||||
|
||||
uniform vec2 layerSelection;
|
||||
|
||||
uniform sampler2D colorBuffer;
|
||||
uniform sampler2D cocBuffer;
|
||||
|
||||
flat out vec4 color;
|
||||
out vec2 particlecoord;
|
||||
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
|
||||
/* geometry shading pass, calculate a texture coordinate based on the indexed id */
|
||||
void step_scatter()
|
||||
{
|
||||
ivec2 tex_size = textureSize(cocBuffer, 0);
|
||||
vec2 texel_size = 1.0 / vec2(tex_size);
|
||||
|
||||
int t_id = gl_VertexID / 3; /* Triangle Id */
|
||||
|
||||
ivec2 texelco = ivec2(0);
|
||||
/* some math to get the target pixel */
|
||||
texelco.x = t_id % tex_size.x;
|
||||
texelco.y = t_id / tex_size.x;
|
||||
|
||||
float coc = dot(layerSelection, texelFetch(cocBuffer, texelco, 0).rg);
|
||||
|
||||
/* Clamp to max size for performance */
|
||||
coc = min(coc, 100.0);
|
||||
|
||||
if (coc >= 1.0) {
|
||||
color = texelFetch(colorBuffer, texelco, 0);
|
||||
/* find the area the pixel will cover and divide the color by it */
|
||||
float alpha = 1.0 / (coc * coc * M_PI);
|
||||
color *= alpha;
|
||||
color.a = alpha;
|
||||
}
|
||||
else {
|
||||
color = vec4(0.0);
|
||||
}
|
||||
|
||||
/* Generate Triangle : less memory fetches from a VBO */
|
||||
int v_id = gl_VertexID % 3; /* Vertex Id */
|
||||
|
||||
/* Extend to cover at least the unit circle */
|
||||
const float extend = (cos(M_PI / 4.0) + 1.0) * 2.0;
|
||||
/* Crappy diagram
|
||||
* ex 1
|
||||
* | \
|
||||
* | \
|
||||
* 1 | \
|
||||
* | \
|
||||
* | \
|
||||
* 0 | x \
|
||||
* | Circle \
|
||||
* | Origin \
|
||||
* -1 0 --------------- 2
|
||||
* -1 0 1 ex
|
||||
**/
|
||||
gl_Position.x = float(v_id / 2) * extend - 1.0; /* int divisor round down */
|
||||
gl_Position.y = float(v_id % 2) * extend - 1.0;
|
||||
gl_Position.z = 0.0;
|
||||
gl_Position.w = 1.0;
|
||||
|
||||
/* Generate Triangle */
|
||||
particlecoord = gl_Position.xy;
|
||||
|
||||
gl_Position.xy *= coc * texel_size;
|
||||
gl_Position.xy -= 1.0 - 0.5 * texel_size; /* NDC Bottom left */
|
||||
gl_Position.xy += (0.5 + vec2(texelco) * 2.0) * texel_size;
|
||||
}
|
||||
|
||||
out vec2 uvcoord;
|
||||
|
||||
void passthrough()
|
||||
{
|
||||
uvcoord = uvs;
|
||||
gl_Position = vec4(pos, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
#if defined(STEP_DOWNSAMPLE)
|
||||
passthrough();
|
||||
#elif defined(STEP_SCATTER)
|
||||
step_scatter();
|
||||
#elif defined(STEP_RESOLVE)
|
||||
passthrough();
|
||||
#endif
|
||||
}
|
Loading…
Reference in New Issue