This means we have less overall noise for rendered image. SSR, AO, and Refraction are affected by this change. SSR still exhibit artifacts because the reconstruction pattern needs to change every frame (TODO).
340 lines
11 KiB
C
340 lines
11 KiB
C
/*
|
|
* 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
|
|
*
|
|
*/
|
|
|
|
/** \file eevee_engine.c
|
|
* \ingroup draw_engine
|
|
*/
|
|
|
|
#include "DNA_world_types.h"
|
|
#include "DRW_render.h"
|
|
|
|
#include "BLI_dynstr.h"
|
|
#include "BLI_rand.h"
|
|
|
|
#include "GPU_material.h"
|
|
#include "GPU_glew.h"
|
|
|
|
#include "eevee_engine.h"
|
|
#include "eevee_private.h"
|
|
|
|
#define EEVEE_ENGINE "BLENDER_EEVEE"
|
|
|
|
extern GlobalsUboStorage ts;
|
|
|
|
/* *********** FUNCTIONS *********** */
|
|
|
|
static void EEVEE_engine_init(void *ved)
|
|
{
|
|
EEVEE_Data *vedata = (EEVEE_Data *)ved;
|
|
EEVEE_TextureList *txl = vedata->txl;
|
|
EEVEE_FramebufferList *fbl = vedata->fbl;
|
|
EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
|
|
EEVEE_SceneLayerData *sldata = EEVEE_scene_layer_data_get();
|
|
|
|
if (!stl->g_data) {
|
|
/* Alloc transient pointers */
|
|
stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__);
|
|
}
|
|
stl->g_data->background_alpha = 1.0f;
|
|
stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL);
|
|
|
|
DRWFboTexture tex = {&txl->color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
|
|
|
|
const float *viewport_size = DRW_viewport_size_get();
|
|
DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type,
|
|
(int)viewport_size[0], (int)viewport_size[1],
|
|
&tex, 1);
|
|
|
|
EEVEE_materials_init(stl);
|
|
EEVEE_lights_init(sldata);
|
|
EEVEE_lightprobes_init(sldata, vedata);
|
|
EEVEE_effects_init(sldata, vedata);
|
|
}
|
|
|
|
static void EEVEE_cache_init(void *vedata)
|
|
{
|
|
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
|
|
EEVEE_SceneLayerData *sldata = EEVEE_scene_layer_data_get();
|
|
|
|
EEVEE_materials_cache_init(vedata);
|
|
EEVEE_lights_cache_init(sldata, psl);
|
|
EEVEE_lightprobes_cache_init(sldata, vedata);
|
|
EEVEE_effects_cache_init(sldata, vedata);
|
|
}
|
|
|
|
static void EEVEE_cache_populate(void *vedata, Object *ob)
|
|
{
|
|
EEVEE_SceneLayerData *sldata = EEVEE_scene_layer_data_get();
|
|
|
|
const DRWContextState *draw_ctx = DRW_context_state_get();
|
|
const bool is_active = (ob == draw_ctx->obact);
|
|
if (is_active) {
|
|
if (DRW_object_is_mode_shade(ob) == true) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (ELEM(ob->type, OB_MESH)) {
|
|
EEVEE_materials_cache_populate(vedata, sldata, ob);
|
|
|
|
const bool cast_shadow = true;
|
|
|
|
if (cast_shadow) {
|
|
if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
|
|
/* TODO: Special case for dupli objects because we cannot save the object pointer. */
|
|
}
|
|
else {
|
|
BLI_addtail(&sldata->shadow_casters, BLI_genericNodeN(ob));
|
|
EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(ob);
|
|
oedata->need_update = ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0);
|
|
}
|
|
}
|
|
}
|
|
else if (ob->type == OB_LIGHTPROBE) {
|
|
if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
|
|
/* TODO: Special case for dupli objects because we cannot save the object pointer. */
|
|
}
|
|
else {
|
|
EEVEE_lightprobes_cache_add(sldata, ob);
|
|
}
|
|
}
|
|
else if (ob->type == OB_LAMP) {
|
|
if ((ob->base_flag & BASE_FROMDUPLI) != 0) {
|
|
/* TODO: Special case for dupli objects because we cannot save the object pointer. */
|
|
}
|
|
else {
|
|
EEVEE_lights_cache_add(sldata, ob);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void EEVEE_cache_finish(void *vedata)
|
|
{
|
|
EEVEE_SceneLayerData *sldata = EEVEE_scene_layer_data_get();
|
|
|
|
EEVEE_materials_cache_finish(vedata);
|
|
EEVEE_lights_cache_finish(sldata);
|
|
EEVEE_lightprobes_cache_finish(sldata, vedata);
|
|
}
|
|
|
|
static void EEVEE_draw_scene(void *vedata)
|
|
{
|
|
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
|
|
EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl;
|
|
EEVEE_SceneLayerData *sldata = EEVEE_scene_layer_data_get();
|
|
|
|
/* Default framebuffer and texture */
|
|
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
|
|
|
|
/* Number of iteration: needed for all temporal effect (SSR, TAA)
|
|
* when using opengl render. */
|
|
int loop_ct = DRW_state_is_image_render() ? 4 : 1;
|
|
|
|
static float rand = 0.0f;
|
|
|
|
/* XXX temp for denoising render. TODO plug number of samples here */
|
|
if (DRW_state_is_image_render()) {
|
|
rand += 1.0f / 16.0f;
|
|
rand = rand - floorf(rand);
|
|
|
|
/* Set jitter offset */
|
|
EEVEE_update_util_texture(rand);
|
|
}
|
|
|
|
while (loop_ct--) {
|
|
|
|
/* Refresh shadows */
|
|
DRW_stats_group_start("Shadows");
|
|
EEVEE_draw_shadows(sldata, psl);
|
|
DRW_stats_group_end();
|
|
|
|
/* Refresh Probes */
|
|
DRW_stats_group_start("Probes Refresh");
|
|
EEVEE_lightprobes_refresh(sldata, vedata);
|
|
DRW_stats_group_end();
|
|
|
|
/* Attach depth to the hdr buffer and bind it */
|
|
DRW_framebuffer_texture_detach(dtxl->depth);
|
|
DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0);
|
|
DRW_framebuffer_bind(fbl->main);
|
|
DRW_framebuffer_clear(false, true, false, NULL, 1.0f);
|
|
|
|
/* Depth prepass */
|
|
DRW_stats_group_start("Prepass");
|
|
DRW_draw_pass(psl->depth_pass);
|
|
DRW_draw_pass(psl->depth_pass_cull);
|
|
DRW_stats_group_end();
|
|
|
|
/* Create minmax texture */
|
|
DRW_stats_group_start("Main MinMax buffer");
|
|
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
|
|
DRW_stats_group_end();
|
|
|
|
/* Compute GTAO Horizons */
|
|
EEVEE_effects_do_gtao(sldata, vedata);
|
|
|
|
/* Restore main FB */
|
|
DRW_framebuffer_bind(fbl->main);
|
|
|
|
/* Shading pass */
|
|
DRW_stats_group_start("Shading");
|
|
DRW_draw_pass(psl->background_pass);
|
|
EEVEE_draw_default_passes(psl);
|
|
DRW_draw_pass(psl->material_pass);
|
|
DRW_stats_group_end();
|
|
|
|
/* Screen Space Reflections */
|
|
DRW_stats_group_start("SSR");
|
|
EEVEE_effects_do_ssr(sldata, vedata);
|
|
DRW_stats_group_end();
|
|
|
|
DRW_draw_pass(psl->probe_display);
|
|
|
|
/* Prepare Refraction */
|
|
EEVEE_effects_do_refraction(sldata, vedata);
|
|
|
|
/* Restore main FB */
|
|
DRW_framebuffer_bind(fbl->main);
|
|
|
|
/* Opaque refraction */
|
|
DRW_stats_group_start("Opaque Refraction");
|
|
DRW_draw_pass(psl->refract_depth_pass);
|
|
DRW_draw_pass(psl->refract_depth_pass_cull);
|
|
DRW_draw_pass(psl->refract_pass);
|
|
DRW_stats_group_end();
|
|
|
|
/* Transparent */
|
|
DRW_pass_sort_shgroup_z(psl->transparent_pass);
|
|
DRW_stats_group_start("Transparent");
|
|
DRW_draw_pass(psl->transparent_pass);
|
|
DRW_stats_group_end();
|
|
|
|
/* Volumetrics */
|
|
DRW_stats_group_start("Volumetrics");
|
|
EEVEE_effects_do_volumetrics(sldata, vedata);
|
|
DRW_stats_group_end();
|
|
|
|
/* Post Process */
|
|
DRW_stats_group_start("Post FX");
|
|
EEVEE_draw_effects(vedata);
|
|
DRW_stats_group_end();
|
|
}
|
|
}
|
|
|
|
static void EEVEE_engine_free(void)
|
|
{
|
|
EEVEE_materials_free();
|
|
EEVEE_effects_free();
|
|
EEVEE_lights_free();
|
|
EEVEE_lightprobes_free();
|
|
}
|
|
|
|
static void EEVEE_layer_collection_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
|
|
{
|
|
BLI_assert(props &&
|
|
props->type == IDP_GROUP &&
|
|
props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
|
|
// BKE_collection_engine_property_add_int(props, "high_quality_sphere_lamps", false);
|
|
UNUSED_VARS_NDEBUG(props);
|
|
}
|
|
|
|
static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDProperty *props)
|
|
{
|
|
BLI_assert(props &&
|
|
props->type == IDP_GROUP &&
|
|
props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
|
|
|
|
|
|
BKE_collection_engine_property_add_bool(props, "ssr_enable", false);
|
|
BKE_collection_engine_property_add_bool(props, "ssr_refraction", false);
|
|
BKE_collection_engine_property_add_bool(props, "ssr_halfres", true);
|
|
BKE_collection_engine_property_add_int(props, "ssr_ray_count", 1);
|
|
BKE_collection_engine_property_add_float(props, "ssr_quality", 0.25f);
|
|
BKE_collection_engine_property_add_float(props, "ssr_max_roughness", 0.5f);
|
|
BKE_collection_engine_property_add_float(props, "ssr_thickness", 0.2f);
|
|
BKE_collection_engine_property_add_float(props, "ssr_border_fade", 0.075f);
|
|
BKE_collection_engine_property_add_float(props, "ssr_firefly_fac", 10.0f);
|
|
|
|
BKE_collection_engine_property_add_bool(props, "volumetric_enable", false);
|
|
BKE_collection_engine_property_add_float(props, "volumetric_start", 0.1f);
|
|
BKE_collection_engine_property_add_float(props, "volumetric_end", 100.0f);
|
|
BKE_collection_engine_property_add_int(props, "volumetric_samples", 64);
|
|
BKE_collection_engine_property_add_float(props, "volumetric_sample_distribution", 0.8f);
|
|
BKE_collection_engine_property_add_bool(props, "volumetric_lights", true);
|
|
BKE_collection_engine_property_add_float(props, "volumetric_light_clamp", 0.0f);
|
|
BKE_collection_engine_property_add_bool(props, "volumetric_shadows", false);
|
|
BKE_collection_engine_property_add_int(props, "volumetric_shadow_samples", 16);
|
|
BKE_collection_engine_property_add_bool(props, "volumetric_colored_transmittance", true);
|
|
|
|
BKE_collection_engine_property_add_bool(props, "gtao_enable", false);
|
|
BKE_collection_engine_property_add_bool(props, "gtao_use_bent_normals", true);
|
|
BKE_collection_engine_property_add_bool(props, "gtao_denoise", true);
|
|
BKE_collection_engine_property_add_bool(props, "gtao_bounce", true);
|
|
BKE_collection_engine_property_add_float(props, "gtao_distance", 0.2f);
|
|
BKE_collection_engine_property_add_float(props, "gtao_factor", 1.0f);
|
|
BKE_collection_engine_property_add_float(props, "gtao_quality", 0.25f);
|
|
BKE_collection_engine_property_add_int(props, "gtao_samples", 2);
|
|
|
|
BKE_collection_engine_property_add_bool(props, "dof_enable", false);
|
|
BKE_collection_engine_property_add_float(props, "bokeh_max_size", 100.0f);
|
|
BKE_collection_engine_property_add_float(props, "bokeh_threshold", 1.0f);
|
|
|
|
float default_bloom_color[3] = {1.0f, 1.0f, 1.0f};
|
|
BKE_collection_engine_property_add_bool(props, "bloom_enable", false);
|
|
BKE_collection_engine_property_add_float_array(props, "bloom_color", default_bloom_color, 3);
|
|
BKE_collection_engine_property_add_float(props, "bloom_threshold", 0.8f);
|
|
BKE_collection_engine_property_add_float(props, "bloom_knee", 0.5f);
|
|
BKE_collection_engine_property_add_float(props, "bloom_intensity", 0.8f);
|
|
BKE_collection_engine_property_add_float(props, "bloom_radius", 6.5f);
|
|
BKE_collection_engine_property_add_float(props, "bloom_clamp", 1.0f);
|
|
|
|
BKE_collection_engine_property_add_bool(props, "motion_blur_enable", false);
|
|
BKE_collection_engine_property_add_int(props, "motion_blur_samples", 8);
|
|
BKE_collection_engine_property_add_float(props, "motion_blur_shutter", 1.0f);
|
|
}
|
|
|
|
static const DrawEngineDataSize EEVEE_data_size = DRW_VIEWPORT_DATA_SIZE(EEVEE_Data);
|
|
|
|
DrawEngineType draw_engine_eevee_type = {
|
|
NULL, NULL,
|
|
N_("Eevee"),
|
|
&EEVEE_data_size,
|
|
&EEVEE_engine_init,
|
|
&EEVEE_engine_free,
|
|
&EEVEE_cache_init,
|
|
&EEVEE_cache_populate,
|
|
&EEVEE_cache_finish,
|
|
&EEVEE_draw_scene,
|
|
NULL//&EEVEE_draw_scene
|
|
};
|
|
|
|
RenderEngineType DRW_engine_viewport_eevee_type = {
|
|
NULL, NULL,
|
|
EEVEE_ENGINE, N_("Eevee"), RE_INTERNAL | RE_USE_SHADING_NODES,
|
|
NULL, NULL, NULL, NULL, NULL, NULL, NULL,
|
|
&EEVEE_layer_collection_settings_create, &EEVEE_scene_layer_settings_create,
|
|
&draw_engine_eevee_type,
|
|
{NULL, NULL, NULL}
|
|
};
|
|
|
|
|
|
#undef EEVEE_ENGINE
|