Eevee: Implement Overscan option

This option make the internal render size larger than the output size in
order to minimize screenspace effects disapearing at the render edges.

The overscan size added around the render is the maximum dimension
multiplied by the overscan percentage.
This commit is contained in:
Clément Foucault 2018-10-31 18:31:14 +01:00
parent c6466ed0d2
commit cde64619ca
9 changed files with 105 additions and 15 deletions

View File

@ -956,13 +956,21 @@ class RENDER_PT_eevee_film(RenderButtonsPanel, Panel):
layout.use_property_split = True
scene = context.scene
props = scene.eevee
rd = scene.render
split = layout.split()
split.prop(props, "use_overscan")
row = split.row()
row.active = props.use_overscan
row.prop(props, "overscan_size", text="")
col = layout.column()
col.prop(rd, "filter_size")
col.prop(rd, "alpha_mode", text="Alpha")
class RENDER_PT_eevee_hair(RenderButtonsPanel, Panel):
bl_label = "Hair"
bl_options = {'DEFAULT_CLOSED'}

View File

@ -919,6 +919,8 @@ void BKE_scene_init(Scene *sce)
sce->eevee.light_cache = NULL;
sce->eevee.overscan = 0.3f;
sce->eevee.flag =
SCE_EEVEE_VOLUMETRIC_LIGHTS |
SCE_EEVEE_GTAO_BENT_NORMALS |

View File

@ -2226,4 +2226,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
| OB_EMPTY_IMAGE_VISIBLE_ORTHOGRAPHIC);
}
}
{
if (!DNA_struct_elem_find(fd->filesdna, "SceneEEVEE", "float", "overscan")) {
for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
scene->eevee.overscan = 3.0f;
}
}
}
}

View File

@ -797,6 +797,8 @@ typedef struct EEVEE_PrivateData {
float viewmat[4][4], viewinv[4][4];
float winmat[4][4], wininv[4][4];
float studiolight_matrix[3][3];
float overscan, overscan_pixels;
float size_orig[2];
/* Mist Settings */
float mist_start, mist_inv_dist, mist_falloff;

View File

@ -33,6 +33,8 @@
#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "BKE_camera.h"
#include "BLI_rand.h"
#include "BLI_rect.h"
@ -54,6 +56,7 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
Scene *scene = DEG_get_evaluated_scene(depsgraph);
const float *size_orig = DRW_viewport_size_get();
/* Init default FB and render targets:
* In render mode the default framebuffer is not generated
@ -62,6 +65,28 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get();
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
/* Alloc transient data. */
if (!stl->g_data) {
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
EEVEE_PrivateData *g_data = stl->g_data;
g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
g_data->valid_double_buffer = 0;
copy_v2_v2(g_data->size_orig, size_orig);
if (scene->eevee.flag & SCE_EEVEE_OVERSCAN) {
g_data->overscan = scene->eevee.overscan / 100.0f;
g_data->overscan_pixels = roundf(max_ff(size_orig[0], size_orig[1]) * g_data->overscan);
}
else {
g_data->overscan = 0.0f;
g_data->overscan_pixels = 0.0f;
}
/* XXX overiding viewport size. Simplify things but is not really 100% safe. */
DRW_render_viewport_size_set((int[2]){size_orig[0] + g_data->overscan_pixels * 2.0f,
size_orig[1] + g_data->overscan_pixels * 2.0f});
/* TODO 32 bit depth */
DRW_texture_ensure_fullscreen_2D(&dtxl->depth, GPU_DEPTH24_STENCIL8, 0);
DRW_texture_ensure_fullscreen_2D(&txl->color, GPU_RGBA32F, DRW_TEX_FILTER | DRW_TEX_MIPMAP);
@ -79,14 +104,6 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
GPU_ATTACHMENT_TEXTURE(txl->color)
});
/* Alloc transient data. */
if (!stl->g_data) {
stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__);
}
EEVEE_PrivateData *g_data = stl->g_data;
g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f;
g_data->valid_double_buffer = 0;
/* Alloc common ubo data. */
if (sldata->common_ubo == NULL) {
sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data);
@ -102,6 +119,8 @@ void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
RE_GetCameraWindow(engine->re, ob_camera_eval, frame, g_data->winmat);
RE_GetCameraModelMatrix(engine->re, ob_camera_eval, g_data->viewinv);
RE_GetCameraWindowWithOverscan(engine->re, g_data->winmat, g_data->overscan);
invert_m4_m4(g_data->viewmat, g_data->viewinv);
mul_m4_m4m4(g_data->persmat, g_data->winmat, g_data->viewmat);
invert_m4_m4(g_data->persinv, g_data->persmat);
@ -189,7 +208,8 @@ static void eevee_render_result_combined(
GPU_framebuffer_bind(vedata->stl->effects->final_fb);
GPU_framebuffer_read_color(vedata->stl->effects->final_fb,
rect->xmin, rect->ymin,
vedata->stl->g_data->overscan_pixels + rect->xmin,
vedata->stl->g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
4, 0, rp->rect);
@ -217,7 +237,8 @@ static void eevee_render_result_subsurface(
GPU_framebuffer_bind(vedata->fbl->sss_accum_fb);
GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb,
rect->xmin, rect->ymin,
vedata->stl->g_data->overscan_pixels + rect->xmin,
vedata->stl->g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
3, 1, rp->rect);
@ -232,7 +253,8 @@ static void eevee_render_result_subsurface(
GPU_framebuffer_bind(vedata->fbl->sss_accum_fb);
GPU_framebuffer_read_color(vedata->fbl->sss_accum_fb,
rect->xmin, rect->ymin,
vedata->stl->g_data->overscan_pixels + rect->xmin,
vedata->stl->g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
3, 0, rp->rect);
@ -266,7 +288,8 @@ static void eevee_render_result_normal(
GPU_framebuffer_bind(vedata->fbl->main_fb);
GPU_framebuffer_read_color(vedata->fbl->main_fb,
rect->xmin, rect->ymin,
g_data->overscan_pixels + rect->xmin,
g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
3, 1, rp->rect);
@ -312,7 +335,8 @@ static void eevee_render_result_z(
GPU_framebuffer_bind(vedata->fbl->main_fb);
GPU_framebuffer_read_depth(vedata->fbl->main_fb,
rect->xmin, rect->ymin,
g_data->overscan_pixels + rect->xmin,
g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
rp->rect);
@ -348,7 +372,8 @@ static void eevee_render_result_mist(
GPU_framebuffer_bind(vedata->fbl->mist_accum_fb);
GPU_framebuffer_read_color(vedata->fbl->mist_accum_fb,
rect->xmin, rect->ymin,
vedata->stl->g_data->overscan_pixels + rect->xmin,
vedata->stl->g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
1, 0, rp->rect);
@ -376,7 +401,8 @@ static void eevee_render_result_occlusion(
GPU_framebuffer_bind(vedata->fbl->ao_accum_fb);
GPU_framebuffer_read_color(vedata->fbl->ao_accum_fb,
rect->xmin, rect->ymin,
vedata->stl->g_data->overscan_pixels + rect->xmin,
vedata->stl->g_data->overscan_pixels + rect->ymin,
BLI_rcti_size_x(rect), BLI_rcti_size_y(rect),
3, 0, rp->rect);
@ -561,6 +587,9 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
eevee_render_result_subsurface(rl, viewname, rect, vedata, sldata, render_samples);
eevee_render_result_mist(rl, viewname, rect, vedata, sldata, render_samples);
eevee_render_result_occlusion(rl, viewname, rect, vedata, sldata, render_samples);
/* Restore original viewport size. */
DRW_render_viewport_size_set((int[2]){g_data->size_orig[0], g_data->size_orig[1]});
}
void EEVEE_render_update_passes(RenderEngine *engine, Scene *scene, ViewLayer *view_layer)

View File

@ -1485,6 +1485,9 @@ typedef struct SceneEEVEE {
struct LightCache *light_cache;
char light_cache_info[64];
float overscan;
float pad;
} SceneEEVEE;
/* *************************************************************** */
@ -2192,6 +2195,7 @@ enum {
SCE_EEVEE_SHOW_CUBEMAPS = (1 << 18),
SCE_EEVEE_GI_AUTOBAKE = (1 << 19),
SCE_EEVEE_SHADOW_SOFT = (1 << 20),
SCE_EEVEE_OVERSCAN = (1 << 21),
};
/* SceneEEVEE->shadow_method */

View File

@ -6022,6 +6022,23 @@ static void rna_def_scene_eevee(BlenderRNA *brna)
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_ui_text(prop, "Soft Shadows", "Randomize shadowmaps origin to create soft shadows");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
/* Overscan */
prop = RNA_def_property(srna, "use_overscan", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SCE_EEVEE_OVERSCAN);
RNA_def_property_boolean_default(prop, 0);
RNA_def_property_ui_text(prop, "Overscan", "Internally render past the image border to avoid "
"screen-space effects disapearing");
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
prop = RNA_def_property(srna, "overscan_size", PROP_FLOAT, PROP_PERCENTAGE);
RNA_def_property_float_sdna(prop, NULL, "overscan");
RNA_def_property_float_default(prop, 3.0f);
RNA_def_property_ui_text(prop, "Overscan Size", "Percentage of render size to add as overscan to the "
"internal render buffers");
RNA_def_property_range(prop, 0.0f, 50.0f);
RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 2);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_STATIC);
}
void RNA_def_scene(BlenderRNA *brna)

View File

@ -335,6 +335,7 @@ struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int pas
#define RE_BAKE_AO 2
void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]);
void RE_GetCameraWindowWithOverscan(struct Render *re, float mat[4][4], float overscan);
void RE_GetCameraModelMatrix(struct Render *re, struct Object *camera, float r_mat[4][4]);
struct Scene *RE_GetScene(struct Render *re);
void RE_SetScene(struct Render *re, struct Scene *sce);

View File

@ -195,6 +195,25 @@ void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, flo
copy_m4_m4(mat, re->winmat);
}
/* Must be called after RE_GetCameraWindow(), does not change re->winmat. */
void RE_GetCameraWindowWithOverscan(struct Render *re, float mat[4][4], float overscan)
{
CameraParams params;
params.is_ortho = re->winmat[3][3] != 0.0f;
params.clipsta = re->clipsta;
params.clipend = re->clipend;
params.viewplane = re->viewplane;
overscan *= max_ff(BLI_rctf_size_x(&params.viewplane), BLI_rctf_size_y(&params.viewplane));
params.viewplane.xmin -= overscan;
params.viewplane.xmax += overscan;
params.viewplane.ymin -= overscan;
params.viewplane.ymax += overscan;
BKE_camera_params_compute_matrix(&params);
copy_m4_m4(mat, params.winmat);
}
void RE_GetCameraModelMatrix(Render *re, struct Object *camera, float r_mat[4][4])
{
BKE_camera_multiview_model_matrix(&re->r, camera, re->viewname, r_mat);