diff options
Diffstat (limited to 'source/blender/draw/engines')
45 files changed, 3118 insertions, 1833 deletions
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c index 10dfe7b5996..31a431e3001 100644 --- a/source/blender/draw/engines/basic/basic_engine.c +++ b/source/blender/draw/engines/basic/basic_engine.c @@ -264,6 +264,7 @@ DrawEngineType draw_engine_basic_type = { &basic_draw_scene, NULL, NULL, + NULL, }; /* Note: currently unused, we may want to register so we can see this when debugging the view. */ diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c index 01f89ae6b1c..d2bf164efdc 100644 --- a/source/blender/draw/engines/clay/clay_engine.c +++ b/source/blender/draw/engines/clay/clay_engine.c @@ -183,6 +183,7 @@ typedef struct CLAY_PrivateData { DRWShadingGroup *depth_shgrp_cull; DRWShadingGroup *depth_shgrp_cull_select; DRWShadingGroup *depth_shgrp_cull_active; + bool enable_ao; } CLAY_PrivateData; /* Transient data */ /* Functions */ @@ -317,7 +318,7 @@ static struct GPUTexture *create_jitter_texture(int num_samples) jitter[i][2] = bn * num_samples_inv; } - UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx); + UNUSED_VARS(bsdf_split_sum_ggx, btdf_split_sum_ggx, ltc_mag_ggx, ltc_mat_ggx, ltc_disk_integral); return DRW_texture_create_2D(64, 64, DRW_TEX_RGB_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]); } @@ -607,7 +608,7 @@ static int hair_mat_in_ubo(CLAY_Storage *storage, const CLAY_HAIR_UBO_Material * return id; } -static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo) +static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo, bool *r_needs_ao) { IDProperty *props = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_CLAY); @@ -622,6 +623,12 @@ static void ubo_mat_from_object(Object *ob, CLAY_UBO_Material *r_ubo) float ssao_attenuation = BKE_collection_engine_property_value_get_float(props, "ssao_attenuation"); int matcap_icon = BKE_collection_engine_property_value_get_int(props, "matcap_icon"); + if (((ssao_factor_cavity > 0.0) || (ssao_factor_edge > 0.0)) && + (ssao_distance > 0.0)) + { + *r_needs_ao = true; + } + memset(r_ubo, 0x0, sizeof(*r_ubo)); r_ubo->matcap_rot[0] = cosf(matcap_rot * 3.14159f * 2.0f); @@ -667,7 +674,7 @@ static DRWShadingGroup *CLAY_object_shgrp_get( DRWShadingGroup **shgrps = use_flat ? stl->storage->shgrps_flat : stl->storage->shgrps; CLAY_UBO_Material mat_ubo_test; - ubo_mat_from_object(ob, &mat_ubo_test); + ubo_mat_from_object(ob, &mat_ubo_test, &stl->g_data->enable_ao); int id = mat_in_ubo(stl->storage, &mat_ubo_test); @@ -712,6 +719,9 @@ static void clay_cache_init(void *vedata) stl->g_data = MEM_mallocN(sizeof(*stl->g_data), __func__); } + /* Disable AO unless a material needs it. */ + stl->g_data->enable_ao = false; + /* Depth Pass */ { psl->depth_pass = DRW_pass_create("Depth Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); @@ -746,12 +756,45 @@ static void clay_cache_init(void *vedata) } } +static void clay_cache_populate_particles(void *vedata, Object *ob) +{ + CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; + const DRWContextState *draw_ctx = DRW_context_state_get(); + + + Scene *scene = draw_ctx->scene; + Object *obedit = scene->obedit; + + if (ob != obedit) { + for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { + if (psys_check_enabled(ob, psys, false)) { + ParticleSettings *part = psys->part; + int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; + + if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) { + draw_as = PART_DRAW_DOT; + } + + static float mat[4][4]; + unit_m4(mat); + + if (draw_as == PART_DRAW_PATH) { + struct Gwn_Batch *geom = DRW_cache_particles_get_hair(psys, NULL); + DRWShadingGroup *hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl); + DRW_shgroup_call_add(hair_shgrp, geom, mat); + } + } + } + } +} + static void clay_cache_populate(void *vedata, Object *ob) { CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; - DRWShadingGroup *clay_shgrp, *hair_shgrp; + DRWShadingGroup *clay_shgrp; if (!DRW_object_is_renderable(ob)) return; @@ -764,6 +807,15 @@ static void clay_cache_populate(void *vedata, Object *ob) } } + /* Handle particles first in case the emitter itself shouldn't be rendered. */ + if (ob->type == OB_MESH) { + clay_cache_populate_particles(vedata, ob); + } + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + struct Gwn_Batch *geom = DRW_cache_object_surface_get(ob); if (geom) { IDProperty *ces_mode_ob = BKE_layer_collection_engine_evaluated_get(ob, COLLECTION_MODE_OBJECT, ""); @@ -797,33 +849,6 @@ static void clay_cache_populate(void *vedata, Object *ob) DRW_shgroup_call_add(clay_shgrp, geom, ob->obmat); } } - - if (ob->type == OB_MESH) { - Scene *scene = draw_ctx->scene; - Object *obedit = scene->obedit; - - if (ob != obedit) { - for (ParticleSystem *psys = ob->particlesystem.first; psys; psys = psys->next) { - if (psys_check_enabled(ob, psys, false)) { - ParticleSettings *part = psys->part; - int draw_as = (part->draw_as == PART_DRAW_REND) ? part->ren_as : part->draw_as; - - if (draw_as == PART_DRAW_PATH && !psys->pathcache && !psys->childcache) { - draw_as = PART_DRAW_DOT; - } - - static float mat[4][4]; - unit_m4(mat); - - if (draw_as == PART_DRAW_PATH) { - geom = DRW_cache_particles_get_hair(psys, NULL); - hair_shgrp = CLAY_hair_shgrp_get(vedata, ob, stl, psl); - DRW_shgroup_call_add(hair_shgrp, geom, mat); - } - } - } - } - } } static void clay_cache_finish(void *vedata) @@ -836,18 +861,25 @@ static void clay_cache_finish(void *vedata) static void clay_draw_scene(void *vedata) { - + CLAY_StorageList *stl = ((CLAY_Data *)vedata)->stl; CLAY_PassList *psl = ((CLAY_Data *)vedata)->psl; CLAY_FramebufferList *fbl = ((CLAY_Data *)vedata)->fbl; DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); /* Pass 1 : Depth pre-pass */ - DRW_draw_pass(psl->depth_pass); - DRW_draw_pass(psl->depth_pass_cull); + if (stl->g_data->enable_ao) { + DRW_draw_pass(psl->depth_pass); + DRW_draw_pass(psl->depth_pass_cull); + } + else { + DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS; + DRW_pass_state_set(psl->clay_pass, state); + DRW_pass_state_set(psl->clay_pass_flat, state); + } /* Pass 2 : Duplicate depth */ /* Unless we go for deferred shading we need this to avoid manual depth test and artifacts */ - if (DRW_state_is_fbo()) { + if (DRW_state_is_fbo() && stl->g_data->enable_ao) { /* attach temp textures */ DRW_framebuffer_texture_attach(fbl->dupli_depth, e_data.depth_dup, 0, 0); @@ -917,6 +949,7 @@ DrawEngineType draw_engine_clay_type = { &clay_draw_scene, NULL, NULL, + NULL, }; RenderEngineType DRW_engine_viewport_clay_type = { diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c index d5582a498a4..c6e5f645f10 100644 --- a/source/blender/draw/engines/eevee/eevee_data.c +++ b/source/blender/draw/engines/eevee/eevee_data.c @@ -45,13 +45,17 @@ static void eevee_view_layer_data_free(void *storage) DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_target); DRW_TEXTURE_FREE_SAFE(sldata->shadow_cascade_blur); DRW_TEXTURE_FREE_SAFE(sldata->shadow_pool); - BLI_freelistN(&sldata->shadow_casters); + MEM_SAFE_FREE(sldata->shcasters_buffers[0].shadow_casters); + MEM_SAFE_FREE(sldata->shcasters_buffers[0].flags); + MEM_SAFE_FREE(sldata->shcasters_buffers[1].shadow_casters); + MEM_SAFE_FREE(sldata->shcasters_buffers[1].flags); /* Probes */ MEM_SAFE_FREE(sldata->probes); DRW_UBO_FREE_SAFE(sldata->probe_ubo); DRW_UBO_FREE_SAFE(sldata->grid_ubo); DRW_UBO_FREE_SAFE(sldata->planar_ubo); + DRW_UBO_FREE_SAFE(sldata->common_ubo); DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb); DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb); DRW_TEXTURE_FREE_SAFE(sldata->probe_rt); @@ -59,24 +63,6 @@ static void eevee_view_layer_data_free(void *storage) DRW_TEXTURE_FREE_SAFE(sldata->probe_pool); DRW_TEXTURE_FREE_SAFE(sldata->irradiance_pool); DRW_TEXTURE_FREE_SAFE(sldata->irradiance_rt); - - /* Volumetrics */ - MEM_SAFE_FREE(sldata->volumetrics); -} - -static void eevee_lamp_data_free(void *storage) -{ - EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)storage; - - MEM_SAFE_FREE(led->storage); - BLI_freelistN(&led->shadow_caster_list); -} - -static void eevee_lightprobe_data_free(void *storage) -{ - EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)storage; - - BLI_freelistN(&ped->captured_object_list); } EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void) @@ -97,59 +83,95 @@ EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void) return *sldata; } +/* Object data. */ + +static void eevee_object_data_init(ObjectEngineData *engine_data) +{ + EEVEE_ObjectEngineData *eevee_data = (EEVEE_ObjectEngineData *)engine_data; + eevee_data->shadow_caster_id = -1; +} + EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob) { + if (ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP)) { + return NULL; + } return (EEVEE_ObjectEngineData *)DRW_object_engine_data_get( ob, &draw_engine_eevee_type); } EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob) { - EEVEE_ObjectEngineData **oedata = (EEVEE_ObjectEngineData **)DRW_object_engine_data_ensure( - ob, &draw_engine_eevee_type, NULL); + BLI_assert(!ELEM(ob->type, OB_LIGHTPROBE, OB_LAMP)); + return (EEVEE_ObjectEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_eevee_type, + sizeof(EEVEE_ObjectEngineData), + eevee_object_data_init, + NULL); +} - if (*oedata == NULL) { - *oedata = MEM_callocN(sizeof(**oedata), "EEVEE_ObjectEngineData"); - } +/* Light probe data. */ + +static void eevee_lightprobe_data_init(ObjectEngineData *engine_data) +{ + EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data; + ped->need_full_update = true; + ped->need_update = true; +} - return *oedata; +static void eevee_lightprobe_data_free(ObjectEngineData *engine_data) +{ + EEVEE_LightProbeEngineData *ped = (EEVEE_LightProbeEngineData *)engine_data; + + BLI_freelistN(&ped->captured_object_list); } EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob) { + if (ob->type != OB_LIGHTPROBE) { + return NULL; + } return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_get( ob, &draw_engine_eevee_type); } EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob) { - EEVEE_LightProbeEngineData **pedata = (EEVEE_LightProbeEngineData **)DRW_object_engine_data_ensure( - ob, &draw_engine_eevee_type, &eevee_lightprobe_data_free); + BLI_assert(ob->type == OB_LIGHTPROBE); + return (EEVEE_LightProbeEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_eevee_type, + sizeof(EEVEE_LightProbeEngineData), + &eevee_lightprobe_data_init, + &eevee_lightprobe_data_free); +} - if (*pedata == NULL) { - *pedata = MEM_callocN(sizeof(**pedata), "EEVEE_LightProbeEngineData"); - (*pedata)->need_full_update = true; - (*pedata)->need_update = true; - } +/* Lamp data. */ - return *pedata; +static void eevee_lamp_data_init(ObjectEngineData *engine_data) +{ + EEVEE_LampEngineData *led = (EEVEE_LampEngineData *)engine_data; + led->need_update = true; + led->prev_cube_shadow_id = -1; } EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob) { + if (ob->type != OB_LAMP) { + return NULL; + } return (EEVEE_LampEngineData *)DRW_object_engine_data_get( ob, &draw_engine_eevee_type); } EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob) { - EEVEE_LampEngineData **ledata = (EEVEE_LampEngineData **)DRW_object_engine_data_ensure( - ob, &draw_engine_eevee_type, &eevee_lamp_data_free); - - if (*ledata == NULL) { - *ledata = MEM_callocN(sizeof(**ledata), "EEVEE_LampEngineData"); - (*ledata)->need_update = true; - } - - return *ledata; + BLI_assert(ob->type == OB_LAMP); + return (EEVEE_LampEngineData *)DRW_object_engine_data_ensure( + ob, + &draw_engine_eevee_type, + sizeof(EEVEE_LampEngineData), + eevee_lamp_data_init, + NULL); } diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c index ef7e6412fc4..f5fc79aba4f 100644 --- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c +++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c @@ -45,6 +45,7 @@ #include "BKE_screen.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "eevee_private.h" #include "GPU_extensions.h" @@ -74,7 +75,7 @@ static void eevee_create_shader_depth_of_field(void) datatoc_effect_dof_frag_glsl, "#define STEP_RESOLVE\n"); } -int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera) { EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; @@ -87,16 +88,15 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v if (BKE_collection_engine_property_value_get_bool(props, "dof_enable")) { Scene *scene = draw_ctx->scene; - View3D *v3d = draw_ctx->v3d; RegionView3D *rv3d = draw_ctx->rv3d; if (!e_data.dof_downsample_sh) { eevee_create_shader_depth_of_field(); } - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + if (camera) { const float *viewport_size = DRW_viewport_size_get(); - Camera *cam = (Camera *)v3d->camera->data; + Camera *cam = (Camera *)camera->data; /* Retreive Near and Far distance */ effects->dof_near_far[0] = -cam->clipsta; @@ -125,12 +125,15 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v &fbl->dof_down_fb, &draw_engine_eevee_type, buffer_size[0], buffer_size[1], tex_down, 3); - DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER}; + /* Go full 32bits for rendering and reduce the color artifacts. */ + DRWTextureFormat fb_format = DRW_state_is_image_render() ? DRW_TEX_RGBA_32 : DRW_TEX_RGBA_16; + + DRWFboTexture tex_scatter_far = {&txl->dof_far_blur, fb_format, DRW_TEX_FILTER}; DRW_framebuffer_init( &fbl->dof_scatter_far_fb, &draw_engine_eevee_type, buffer_size[0], buffer_size[1], &tex_scatter_far, 1); - DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, DRW_TEX_RGBA_16, DRW_TEX_FILTER}; + DRWFboTexture tex_scatter_near = {&txl->dof_near_blur, fb_format, DRW_TEX_FILTER}; DRW_framebuffer_init( &fbl->dof_scatter_near_fb, &draw_engine_eevee_type, buffer_size[0], buffer_size[1], &tex_scatter_near, 1); @@ -142,7 +145,7 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v float rotation = cam->gpu_dof.rotation; float ratio = 1.0f / cam->gpu_dof.ratio; 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 focus_dist = BKE_camera_object_dof_distance(camera); float focal_len = cam->lens; UNUSED_VARS(rotation, ratio); @@ -158,9 +161,13 @@ int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v float focal_len_scaled = scale_camera * focal_len; float sensor_scaled = scale_camera * sensor; + if (rv3d != NULL) { + sensor_scaled *= rv3d->viewcamtexcofac[0]; + } + 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] / (rv3d->viewcamtexcofac[0] * sensor_scaled); + effects->dof_params[2] = viewport_size[0] / sensor_scaled; effects->dof_bokeh[0] = blades; effects->dof_bokeh[1] = rotation; effects->dof_bokeh[2] = ratio; @@ -213,7 +220,7 @@ void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_ 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); + psl->dof_scatter = DRW_pass_create("DoF Scatter", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE_FULL); /* This create an empty batch of N triangles to be positioned * by the vertex shader 0.4ms against 6ms with instancing */ diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 703369a86ee..c1ac085230e 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -27,10 +27,9 @@ #include "DRW_render.h" -#include "BKE_global.h" /* for G.debug_value */ - #include "eevee_private.h" #include "GPU_texture.h" +#include "GPU_extensions.h" static struct { /* Downsample Depth */ @@ -77,36 +76,31 @@ static void eevee_create_shader_downsample(void) "#define MAX_PASS\n"); e_data.minz_downdepth_sh = DRW_shader_create_fullscreen( datatoc_effect_minmaxz_frag_glsl, - "#define MIN_PASS\n" - "#define INPUT_DEPTH\n"); + "#define MIN_PASS\n"); e_data.maxz_downdepth_sh = DRW_shader_create_fullscreen( datatoc_effect_minmaxz_frag_glsl, - "#define MAX_PASS\n" - "#define INPUT_DEPTH\n"); + "#define MAX_PASS\n"); e_data.minz_downdepth_layer_sh = DRW_shader_create_fullscreen( datatoc_effect_minmaxz_frag_glsl, "#define MIN_PASS\n" - "#define LAYERED\n" - "#define INPUT_DEPTH\n"); + "#define LAYERED\n"); e_data.maxz_downdepth_layer_sh = DRW_shader_create_fullscreen( datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n" - "#define LAYERED\n" - "#define INPUT_DEPTH\n"); + "#define LAYERED\n"); e_data.minz_copydepth_sh = DRW_shader_create_fullscreen( datatoc_effect_minmaxz_frag_glsl, "#define MIN_PASS\n" - "#define INPUT_DEPTH\n" "#define COPY_DEPTH\n"); e_data.maxz_copydepth_sh = DRW_shader_create_fullscreen( datatoc_effect_minmaxz_frag_glsl, "#define MAX_PASS\n" - "#define INPUT_DEPTH\n" "#define COPY_DEPTH\n"); } -void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -126,9 +120,9 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) effects = stl->effects; effects->enabled_effects = 0; - effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata); + effects->enabled_effects |= EEVEE_motion_blur_init(sldata, vedata, camera); effects->enabled_effects |= EEVEE_bloom_init(sldata, vedata); - effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata); + effects->enabled_effects |= EEVEE_depth_of_field_init(sldata, vedata, camera); effects->enabled_effects |= EEVEE_temporal_sampling_init(sldata, vedata); effects->enabled_effects |= EEVEE_occlusion_init(sldata, vedata); effects->enabled_effects |= EEVEE_subsurface_init(sldata, vedata); @@ -154,10 +148,17 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) * MinMax Pyramid */ DRWFboTexture texmax = {&txl->maxzbuffer, DRW_TEX_DEPTH_24, DRW_TEX_MIPMAP}; + + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + /* Intel gpu seems to have problem rendering to only depth format */ + texmax.format = DRW_TEX_R_32; + } + DRW_framebuffer_init(&fbl->downsample_fb, &draw_engine_eevee_type, - (int)viewport_size[0] / 2, (int)viewport_size[1] / 2, + max_ii((int)viewport_size[0] / 2, 1), max_ii((int)viewport_size[1] / 2, 1), &texmax, 1); + /** * Compute Mipmap texel alignement. */ @@ -167,8 +168,8 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) mip_size[0] = floorf(fmaxf(1.0f, mip_size[0] / 2.0f)); mip_size[1] = floorf(fmaxf(1.0f, mip_size[1] / 2.0f)); } - stl->g_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0]))))); - stl->g_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1]))))); + common_data->mip_ratio[i][0] = viewport_size[0] / (mip_size[0] * powf(2.0f, floorf(log2f(floorf(viewport_size[0] / mip_size[0]))))); + common_data->mip_ratio[i][1] = viewport_size[1] / (mip_size[1] * powf(2.0f, floorf(log2f(floorf(viewport_size[1] / mip_size[1]))))); } @@ -207,12 +208,17 @@ void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } } -void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; - EEVEE_StorageList *stl = vedata->stl; EEVEE_TextureList *txl = vedata->txl; - EEVEE_EffectsInfo *effects = stl->effects; + int downsample_write = DRW_STATE_WRITE_DEPTH; + + /* Intel gpu seems to have problem rendering to only depth format. + * Use color texture instead. */ + if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_ANY, GPU_DRIVER_ANY)) { + downsample_write = DRW_STATE_WRITE_COLOR; + } struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); @@ -220,7 +226,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v psl->color_downsample_ps = DRW_pass_create("Downsample", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.downsample_sh, psl->color_downsample_ps); DRW_shgroup_uniform_buffer(grp, "source", &e_data.color_src); - DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1); + DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); DRW_shgroup_call_add(grp, quad, NULL); } @@ -239,39 +245,39 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v DRWShadingGroup *grp; #if 0 /* Not used for now */ - psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->minz_downlevel_ps = DRW_pass_create("HiZ Min Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.minz_downlevel_sh, psl->minz_downlevel_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &stl->g_data->minzbuffer); DRW_shgroup_call_add(grp, quad, NULL); #endif - psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downlevel_ps = DRW_pass_create("HiZ Max Down Level", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downlevel_sh, psl->maxz_downlevel_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &txl->maxzbuffer); DRW_shgroup_call_add(grp, quad, NULL); /* Copy depth buffer to halfres top level of HiZ */ #if 0 /* Not used for now */ - psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->minz_downdepth_ps = DRW_pass_create("HiZ Min Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.minz_downdepth_sh, psl->minz_downdepth_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); #endif - psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downdepth_ps = DRW_pass_create("HiZ Max Copy Depth Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downdepth_sh, psl->maxz_downdepth_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); #if 0 /* Not used for now */ - psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->minz_downdepth_layer_ps = DRW_pass_create("HiZ Min Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.minz_downdepth_layer_sh, psl->minz_downdepth_layer_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1); DRW_shgroup_call_add(grp, quad, NULL); #endif - psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_downdepth_layer_ps = DRW_pass_create("HiZ Max Copy DepthLayer Halfres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_downdepth_layer_sh, psl->maxz_downdepth_layer_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_int(grp, "depthLayer", &e_data.depth_src_layer, 1); @@ -279,13 +285,13 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v /* Copy depth buffer to halfres top level of HiZ */ #if 0 /* Not used for now */ - psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->minz_copydepth_ps = DRW_pass_create("HiZ Min Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.minz_copydepth_sh, psl->minz_copydepth_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); #endif - psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS); + psl->maxz_copydepth_ps = DRW_pass_create("HiZ Max Copy Depth Fullres", downsample_write | DRW_STATE_DEPTH_ALWAYS); grp = DRW_shgroup_create(e_data.maxz_copydepth_sh, psl->maxz_copydepth_ps); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_call_add(grp, quad, NULL); @@ -392,13 +398,12 @@ void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_ DRW_stats_group_end(); } -void EEVEE_draw_effects(EEVEE_Data *vedata) +void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; - DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); /* only once per frame after the first post process */ @@ -419,39 +424,9 @@ void EEVEE_draw_effects(EEVEE_Data *vedata) EEVEE_depth_of_field_draw(vedata); EEVEE_bloom_draw(vedata); - /* Restore default framebuffer */ - DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); - DRW_framebuffer_bind(dfbl->default_fb); - - /* Tonemapping */ - DRW_transform_to_display(effects->source_buffer); - - /* Debug : Ouput buffer to view. */ - switch (G.debug_value) { - case 1: - if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer); - break; - case 2: - if (stl->g_data->ssr_hit_output[0]) DRW_transform_to_display(stl->g_data->ssr_hit_output[0]); - break; - case 3: - if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input); - break; - case 4: - if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input); - break; - case 5: - if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer); - break; - case 6: - if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug); - break; - case 7: - if (txl->sss_data) DRW_transform_to_display(txl->sss_data); - break; - default: - break; - } + /* Save the final texture and framebuffer for final transformation or read. */ + effects->final_tx = effects->source_buffer; + effects->final_fb = (effects->target_buffer != fbl->main) ? fbl->main : fbl->effect_fb; /* If no post processes is enabled, buffers are still not swapped, do it now. */ SWAP_DOUBLE_BUFFERS(); @@ -466,7 +441,7 @@ void EEVEE_draw_effects(EEVEE_Data *vedata) } /* Record pers matrix for the next frame. */ - DRW_viewport_matrix_get(stl->g_data->prev_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_get(sldata->common_data.prev_persmat, DRW_MAT_PERS); /* Update double buffer status if render mode. */ if (DRW_state_is_image_render()) { diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index a20b1afe3d4..8e74f3344dd 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -29,9 +29,13 @@ #include "BLI_rand.h" #include "BKE_object.h" +#include "BKE_global.h" /* for G.debug_value */ +#include "BKE_screen.h" #include "DNA_world_types.h" +#include "ED_screen.h" + #include "GPU_material.h" #include "GPU_glew.h" @@ -52,11 +56,16 @@ static void eevee_engine_init(void *ved) EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + const DRWContextState *draw_ctx = DRW_context_state_get(); + View3D *v3d = draw_ctx->v3d; + RegionView3D *rv3d = draw_ctx->rv3d; + Object *camera = (rv3d->persp == RV3D_CAMOB) ? v3d->camera : NULL; + if (!stl->g_data) { /* Alloc transient pointers */ stl->g_data = MEM_callocN(sizeof(*stl->g_data), __func__); } - stl->g_data->background_alpha = 1.0f; + stl->g_data->background_alpha = DRW_state_draw_background() ? 1.0f : 0.0f; stl->g_data->valid_double_buffer = (txl->color_double_buffer != NULL); DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}; @@ -66,14 +75,17 @@ static void eevee_engine_init(void *ved) (int)viewport_size[0], (int)viewport_size[1], &tex, 1); - /* EEVEE_effects_init needs to go first for TAA */ - EEVEE_effects_init(sldata, vedata); + if (sldata->common_ubo == NULL) { + sldata->common_ubo = DRW_uniformbuffer_create(sizeof(sldata->common_data), &sldata->common_data); + } - EEVEE_materials_init(stl); + /* EEVEE_effects_init needs to go first for TAA */ + EEVEE_effects_init(sldata, vedata, camera); + EEVEE_materials_init(sldata, stl, fbl); EEVEE_lights_init(sldata); EEVEE_lightprobes_init(sldata, vedata); - if (stl->effects->taa_current_sample > 1) { + if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) { /* XXX otherwise it would break the other engines. */ DRW_viewport_matrix_override_unset(DRW_MAT_PERS); DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV); @@ -113,22 +125,17 @@ static void eevee_cache_populate(void *vedata, Object *ob) } } - if (ELEM(ob->type, OB_MESH)) { - if (!BKE_object_is_visible(ob)) { - return; - } + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { 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_lights_cache_shcaster_object_add(sldata, ob); } } else if (ob->type == OB_LIGHTPROBE) { @@ -140,12 +147,7 @@ static void eevee_cache_populate(void *vedata, Object *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); - } + EEVEE_lights_cache_add(sldata, ob); } } @@ -158,46 +160,47 @@ static void eevee_cache_finish(void *vedata) EEVEE_lightprobes_cache_finish(sldata, vedata); } -static void eevee_draw_scene(void *vedata) +/* As renders in an HDR offscreen buffer, we need draw everything once + * during the background pass. This way the other drawing callback between + * the background and the scene pass are visible. + * Note: we could break it up in two passes using some depth test + * to reduce the fillrate */ +static void eevee_draw_background(void *vedata) { EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; + EEVEE_TextureList *txl = ((EEVEE_Data *)vedata)->txl; EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; EEVEE_FramebufferList *fbl = ((EEVEE_Data *)vedata)->fbl; EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); /* Default framebuffer and texture */ DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_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); - } - else if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && (stl->effects->taa_current_sample > 1)) { - double r; - BLI_halton_1D(2, 0.0, stl->effects->taa_current_sample - 1, &r); - - /* Set jitter offset */ - /* PERF This is killing perf ! */ - EEVEE_update_util_texture((float)r); - } - while (loop_ct--) { + unsigned int primes[3] = {2, 3, 7}; + double offset[3] = {0.0, 0.0, 0.0}; + double r[3]; + + if (DRW_state_is_image_render() || + ((stl->effects->enabled_effects & EFFECT_TAA) != 0)) + { + BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r); + EEVEE_update_noise(psl, fbl, r); + } /* Refresh Probes */ DRW_stats_group_start("Probes Refresh"); EEVEE_lightprobes_refresh(sldata, vedata); DRW_stats_group_end(); + /* Update common buffer after probe rendering. */ + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + /* Refresh shadows */ DRW_stats_group_start("Shadows"); EEVEE_draw_shadows(sldata, psl); @@ -207,9 +210,19 @@ static void eevee_draw_scene(void *vedata) 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, true, NULL, 1.0f); + if (DRW_state_draw_background()) { + DRW_framebuffer_clear(false, true, true, NULL, 1.0f); + } + else { + /* We need to clear the alpha chanel in this case. */ + float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + DRW_framebuffer_clear(true, true, true, clear_col, 1.0f); + } - if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && stl->effects->taa_current_sample > 1) { + if (((stl->effects->enabled_effects & EFFECT_TAA) != 0) && + (stl->effects->taa_current_sample > 1) && + !DRW_state_is_image_render()) + { DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS); DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV); DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN); @@ -227,12 +240,14 @@ static void eevee_draw_scene(void *vedata) EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); DRW_stats_group_end(); - EEVEE_occlusion_compute(sldata, vedata); + EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); EEVEE_volumes_compute(sldata, vedata); /* Shading pass */ DRW_stats_group_start("Shading"); - DRW_draw_pass(psl->background_pass); + if (DRW_state_draw_background()) { + DRW_draw_pass(psl->background_pass); + } EEVEE_draw_default_passes(psl); DRW_draw_pass(psl->material_pass); EEVEE_subsurface_data_render(sldata, vedata); @@ -261,10 +276,10 @@ static void eevee_draw_scene(void *vedata) /* Post Process */ DRW_stats_group_start("Post FX"); - EEVEE_draw_effects(vedata); + EEVEE_draw_effects(sldata, vedata); DRW_stats_group_end(); - if (stl->effects->taa_current_sample > 1) { + if ((stl->effects->taa_current_sample > 1) && !DRW_state_is_image_render()) { DRW_viewport_matrix_override_unset(DRW_MAT_PERS); DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV); DRW_viewport_matrix_override_unset(DRW_MAT_WIN); @@ -272,6 +287,43 @@ static void eevee_draw_scene(void *vedata) } } + /* Restore default framebuffer */ + DRW_framebuffer_texture_attach(dfbl->default_fb, dtxl->depth, 0, 0); + DRW_framebuffer_bind(dfbl->default_fb); + + /* Tonemapping */ + DRW_transform_to_display(stl->effects->final_tx); + + /* Debug : Ouput buffer to view. */ + switch (G.debug_value) { + case 1: + if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer); + break; + case 2: + if (stl->g_data->ssr_pdf_output) DRW_transform_to_display(stl->g_data->ssr_pdf_output); + break; + case 3: + if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input); + break; + case 4: + if (txl->ssr_specrough_input) DRW_transform_to_display(txl->ssr_specrough_input); + break; + case 5: + if (txl->color_double_buffer) DRW_transform_to_display(txl->color_double_buffer); + break; + case 6: + if (stl->g_data->gtao_horizons_debug) DRW_transform_to_display(stl->g_data->gtao_horizons_debug); + break; + case 7: + if (txl->gtao_horizons) DRW_transform_to_display(txl->gtao_horizons); + break; + case 8: + if (txl->sss_data) DRW_transform_to_display(txl->sss_data); + break; + default: + break; + } + EEVEE_volumes_free_smoke_textures(); stl->g_data->view_updated = false; @@ -285,24 +337,50 @@ static void eevee_view_update(void *vedata) } } -static void eevee_id_update(void *UNUSED(vedata), ID *id) +static void eevee_id_object_update(void *UNUSED(vedata), Object *object) { - const ID_Type id_type = GS(id->name); - if (id_type == ID_OB) { - Object *object = (Object *)id; - EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object); - if (ped != NULL) { - ped->need_full_update = true; - } - EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object); - if (led != NULL) { - led->need_update = true; - } - EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object); - if (oedata != NULL) { - oedata->need_update = true; - } + /* This is a bit mask of components which update is to be ignored. */ + const int ignore_updates = ID_RECALC_COLLECTIONS; + const int allowed_updates = ~ignore_updates; + EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(object); + if (ped != NULL && (ped->engine_data.recalc & allowed_updates) != 0) { + ped->need_full_update = true; + ped->engine_data.recalc = 0; } + EEVEE_LampEngineData *led = EEVEE_lamp_data_get(object); + if (led != NULL && (led->engine_data.recalc & allowed_updates) != 0) { + led->need_update = true; + led->engine_data.recalc = 0; + } + EEVEE_ObjectEngineData *oedata = EEVEE_object_data_get(object); + if (oedata != NULL && (oedata->engine_data.recalc & allowed_updates) != 0) { + oedata->need_update = true; + oedata->engine_data.recalc = 0; + } +} + +static void eevee_id_update(void *vedata, ID *id) +{ + /* Handle updates based on ID type. */ + switch (GS(id->name)) { + case ID_OB: + eevee_id_object_update(vedata, (Object *)id); + break; + default: + /* pass */ + break; + } +} + +static void eevee_render_to_image(void *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph) +{ + EEVEE_render_init(vedata, engine, depsgraph); + + DRW_render_object_iter(vedata, engine, depsgraph, EEVEE_render_cache); + /* Actually do the rendering. */ + EEVEE_render_draw(vedata, engine, depsgraph); + /* Write outputs to RenderResult. */ + EEVEE_render_output(vedata, engine, depsgraph); } static void eevee_engine_free(void) @@ -340,7 +418,8 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro BKE_collection_engine_property_add_int(props, "gi_cubemap_resolution", 512); BKE_collection_engine_property_add_int(props, "gi_visibility_resolution", 32); - BKE_collection_engine_property_add_int(props, "taa_samples", 8); + BKE_collection_engine_property_add_int(props, "taa_samples", 16); + BKE_collection_engine_property_add_int(props, "taa_render_samples", 64); BKE_collection_engine_property_add_bool(props, "sss_enable", false); BKE_collection_engine_property_add_int(props, "sss_samples", 7); @@ -350,7 +429,6 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro 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); @@ -371,12 +449,10 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro 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); @@ -411,16 +487,17 @@ DrawEngineType draw_engine_eevee_type = { &eevee_cache_init, &eevee_cache_populate, &eevee_cache_finish, - &eevee_draw_scene, - NULL, //&EEVEE_draw_scene + &eevee_draw_background, + NULL, /* Everything is drawn in the background pass (see comment on function) */ &eevee_view_update, &eevee_id_update, + &eevee_render_to_image, }; 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, + NULL, &DRW_render_to_image, NULL, NULL, NULL, NULL, NULL, &eevee_layer_collection_settings_create, &eevee_view_layer_settings_create, &draw_engine_eevee_type, diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c index d7ccc1a5336..7403da737dd 100644 --- a/source/blender/draw/engines/eevee/eevee_lightprobes.c +++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c @@ -26,7 +26,7 @@ #include "DRW_render.h" #include "BLI_utildefines.h" -#include "BLI_dynstr.h" +#include "BLI_string_utils.h" #include "BLI_rand.h" #include "DNA_world_types.h" @@ -83,7 +83,6 @@ static struct { struct GPUTexture *cube_face_minmaxz; int update_world; - bool world_ready_to_shade; } e_data = {NULL}; /* Engine data */ extern char datatoc_background_vert_glsl[]; @@ -107,6 +106,7 @@ extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_lightprobe_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_bsdf_sampling_lib_glsl[]; extern GlobalsUboStorage ts; @@ -204,12 +204,11 @@ static void lightprobe_shaders_init(void) char *shader_str = NULL; - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_glossy_frag_glsl); - shader_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + shader_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_lightprobe_filter_glossy_frag_glsl); e_data.probe_filter_glossy_sh = DRW_shader_create( datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, shader_str, filter_defines); @@ -219,36 +218,33 @@ static void lightprobe_shaders_init(void) MEM_freeN(shader_str); - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_diffuse_frag_glsl); - shader_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + shader_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_lightprobe_filter_diffuse_frag_glsl); e_data.probe_filter_diffuse_sh = DRW_shader_create_fullscreen(shader_str, filter_defines); MEM_freeN(shader_str); - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_filter_visibility_frag_glsl); - shader_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + shader_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_lightprobe_filter_visibility_frag_glsl); e_data.probe_filter_visibility_sh = DRW_shader_create_fullscreen(shader_str, filter_defines); MEM_freeN(shader_str); - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_grid_display_frag_glsl); - shader_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + shader_str = BLI_string_joinN( + datatoc_octahedron_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_lightprobe_grid_display_frag_glsl); e_data.probe_grid_display_sh = DRW_shader_create( datatoc_lightprobe_grid_display_vert_glsl, NULL, shader_str, filter_defines); @@ -258,13 +254,12 @@ static void lightprobe_shaders_init(void) e_data.probe_grid_fill_sh = DRW_shader_create_fullscreen( datatoc_lightprobe_grid_fill_frag_glsl, filter_defines); - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_cube_display_frag_glsl); - shader_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + shader_str = BLI_string_joinN( + datatoc_octahedron_lib_glsl, + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_lightprobe_cube_display_frag_glsl); e_data.probe_cube_display_sh = DRW_shader_create( datatoc_lightprobe_cube_display_vert_glsl, NULL, shader_str, NULL); @@ -286,6 +281,7 @@ static void lightprobe_shaders_init(void) void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(vedata)) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; bool update_all = false; const DRWContextState *draw_ctx = DRW_context_state_get(); ViewLayer *view_layer = draw_ctx->view_layer; @@ -298,15 +294,16 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda if (!sldata->probes) { sldata->probes = MEM_callocN(sizeof(EEVEE_LightProbesInfo), "EEVEE_LightProbesInfo"); - sldata->probes->specular_toggle = true; - sldata->probes->ssr_toggle = true; - sldata->probes->sss_toggle = true; sldata->probes->grid_initialized = false; sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightProbe) * MAX_PROBE, NULL); sldata->grid_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_LightGrid) * MAX_GRID, NULL); sldata->planar_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_PlanarReflection) * MAX_PLANAR, NULL); } + common_data->spec_toggle = true; + common_data->ssr_toggle = true; + common_data->sss_toggle = true; + int prop_bounce_num = BKE_collection_engine_property_value_get_int(props, "gi_diffuse_bounces"); if (sldata->probes->num_bounce != prop_bounce_num) { sldata->probes->num_bounce = prop_bounce_num; @@ -325,8 +322,8 @@ void EEVEE_lightprobes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *UNUSED(veda } int visibility_res = BKE_collection_engine_property_value_get_int(props, "gi_visibility_resolution"); - if (sldata->probes->irradiance_vis_size != visibility_res) { - sldata->probes->irradiance_vis_size = visibility_res; + if (common_data->prb_irradiance_vis_size != visibility_res) { + common_data->prb_irradiance_vis_size = visibility_res; update_all = true; } @@ -370,6 +367,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat EEVEE_StorageList *stl = vedata->stl; EEVEE_LightProbesInfo *pinfo = sldata->probes; + pinfo->do_cube_update = false; pinfo->num_cube = 1; /* at least one for the world */ pinfo->num_grid = 1; pinfo->num_planar = 0; @@ -391,7 +389,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat float *col = ts.colorBackground; if (wo) { col = &wo->horr; - if (wo->update_flag != 0) { + if (wo->update_flag != 0 || pinfo->prev_world != wo) { e_data.update_world |= PROBE_UPDATE_ALL; pinfo->updated_bounce = 0; pinfo->grid_initialized = false; @@ -413,6 +411,14 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat col = pink; } } + + pinfo->prev_world = wo; + } + else if (pinfo->prev_world) { + pinfo->prev_world = NULL; + e_data.update_world |= PROBE_UPDATE_ALL; + pinfo->updated_bounce = 0; + pinfo->grid_initialized = false; } /* Fallback if shader fails or if not using nodetree. */ @@ -430,14 +436,15 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = DRW_shgroup_instance_create(e_data.probe_filter_glossy_sh, psl->probe_glossy_compute, geom); - DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1); - DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1); - DRW_shgroup_uniform_float(grp, "roughnessSquared", &sldata->probes->roughness, 1); - DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1); - DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1); - DRW_shgroup_uniform_float(grp, "texelSize", &sldata->probes->texel_size, 1); - DRW_shgroup_uniform_float(grp, "paddingSize", &sldata->probes->padding_size, 1); - DRW_shgroup_uniform_int(grp, "Layer", &sldata->probes->layer, 1); + DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); + DRW_shgroup_uniform_float(grp, "roughnessSquared", &pinfo->roughness, 1); + DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1); + DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1); + DRW_shgroup_uniform_float(grp, "texelSize", &pinfo->texel_size, 1); + DRW_shgroup_uniform_float(grp, "paddingSize", &pinfo->padding_size, 1); + DRW_shgroup_uniform_int(grp, "Layer", &pinfo->layer, 1); DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); // DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter); DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt); @@ -450,14 +457,15 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_diffuse_sh, psl->probe_diffuse_compute); #ifdef IRRADIANCE_SH_L2 - DRW_shgroup_uniform_int(grp, "probeSize", &sldata->probes->shres, 1); + DRW_shgroup_uniform_int(grp, "probeSize", &pinfo->shres, 1); #else - DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1); - DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1); - DRW_shgroup_uniform_float(grp, "lodFactor", &sldata->probes->lodfactor, 1); - DRW_shgroup_uniform_float(grp, "lodMax", &sldata->probes->lod_rt_max, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); + DRW_shgroup_uniform_float(grp, "lodFactor", &pinfo->lodfactor, 1); + DRW_shgroup_uniform_float(grp, "lodMax", &pinfo->lod_rt_max, 1); DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); #endif + DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1); DRW_shgroup_uniform_texture(grp, "probeHdr", sldata->probe_rt); struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); @@ -468,14 +476,14 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat psl->probe_visibility_compute = DRW_pass_create("LightProbe Visibility Compute", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.probe_filter_visibility_sh, psl->probe_visibility_compute); - DRW_shgroup_uniform_int(grp, "outputSize", &sldata->probes->shres, 1); - DRW_shgroup_uniform_float(grp, "visibilityRange", &sldata->probes->visibility_range, 1); - DRW_shgroup_uniform_float(grp, "visibilityBlur", &sldata->probes->visibility_blur, 1); - DRW_shgroup_uniform_float(grp, "sampleCount", &sldata->probes->samples_ct, 1); - DRW_shgroup_uniform_float(grp, "invSampleCount", &sldata->probes->invsamples_ct, 1); - DRW_shgroup_uniform_float(grp, "storedTexelSize", &sldata->probes->texel_size, 1); - DRW_shgroup_uniform_float(grp, "nearClip", &sldata->probes->near_clip, 1); - DRW_shgroup_uniform_float(grp, "farClip", &sldata->probes->far_clip, 1); + DRW_shgroup_uniform_int(grp, "outputSize", &pinfo->shres, 1); + DRW_shgroup_uniform_float(grp, "visibilityRange", &pinfo->visibility_range, 1); + DRW_shgroup_uniform_float(grp, "visibilityBlur", &pinfo->visibility_blur, 1); + DRW_shgroup_uniform_float(grp, "sampleCount", &pinfo->samples_ct, 1); + DRW_shgroup_uniform_float(grp, "invSampleCount", &pinfo->invsamples_ct, 1); + DRW_shgroup_uniform_float(grp, "storedTexelSize", &pinfo->texel_size, 1); + DRW_shgroup_uniform_float(grp, "nearClip", &pinfo->near_clip, 1); + DRW_shgroup_uniform_float(grp, "farClip", &pinfo->far_clip, 1); DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley); DRW_shgroup_uniform_texture(grp, "probeDepth", sldata->probe_depth_rt); @@ -502,8 +510,8 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat DRW_shgroup_attrib_float(grp, "probe_id", 1); /* XXX this works because we are still uploading 4bytes and using the right stride */ DRW_shgroup_attrib_float(grp, "probe_location", 3); DRW_shgroup_attrib_float(grp, "sphere_size", 1); - DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1); DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); geom = DRW_cache_quad_get(); grp = stl->g_data->planar_display_shgrp = DRW_shgroup_instance_create(e_data.probe_planar_display_sh, psl->probe_display, geom); @@ -518,7 +526,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = stl->g_data->planar_downsample = DRW_shgroup_instance_create(e_data.probe_planar_downsample_sh, psl->probe_planar_downsample_ps, geom); DRW_shgroup_uniform_buffer(grp, "source", &txl->planar_pool); - DRW_shgroup_uniform_float(grp, "fireflyFactor", &stl->effects->ssr_firefly_fac, 1); + DRW_shgroup_uniform_float(grp, "fireflyFactor", &sldata->common_data.ssr_firefly_fac, 1); } } @@ -551,7 +559,6 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) ped->need_update = true; ped->probe_id = 0; - if (probe->type == LIGHTPROBE_TYPE_GRID) { ped->updated_cells = 0; ped->updated_lvl = 0; @@ -567,6 +574,8 @@ void EEVEE_lightprobes_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) ped->probe_id = 0; } + pinfo->do_cube_update |= ped->need_update; + if (probe->type == LIGHTPROBE_TYPE_CUBE) { pinfo->probes_cube_ref[pinfo->num_cube] = ob; pinfo->num_cube++; @@ -685,8 +694,7 @@ static void EEVEE_planar_reflections_updates(EEVEE_ViewLayerData *sldata, EEVEE_ eplanar->attenuation_bias = max_dist * -eplanar->attenuation_scale; /* Debug Display */ - if (BKE_object_is_visible(ob) && - DRW_state_draw_support() && + if (DRW_state_draw_support() && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { DRW_shgroup_call_dynamic_add(stl->g_data->planar_display_shgrp, &ped->probe_id, ob->obmat); @@ -734,8 +742,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis invert_m4(eprobe->parallaxmat); /* Debug Display */ - if (BKE_object_is_visible(ob) && - DRW_state_draw_support() && + if (DRW_state_draw_support() && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { ped->probe_size = probe->data_draw_size * 0.1f; @@ -816,8 +823,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis len_v3(egrid->increment_z)) + 1.0f; /* Debug Display */ - if (BKE_object_is_visible(ob) && - DRW_state_draw_support() && + if (DRW_state_draw_support() && (probe->flag & LIGHTPROBE_FLAG_SHOW_DATA)) { struct Gwn_Batch *geom = DRW_cache_sphere_get(); @@ -837,6 +843,7 @@ static void EEVEE_lightprobes_updates(EEVEE_ViewLayerData *sldata, EEVEE_PassLis void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_StorageList *stl = vedata->stl; EEVEE_LightProbesInfo *pinfo = sldata->probes; Object *ob; @@ -854,7 +861,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved } int irr_size[3]; - irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, irr_size); + irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, irr_size); if ((irr_size[0] != pinfo->cache_irradiance_size[0]) || (irr_size[1] != pinfo->cache_irradiance_size[1]) || @@ -880,8 +887,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved /* Tag probes to refresh */ e_data.update_world |= PROBE_UPDATE_CUBE; - e_data.world_ready_to_shade = false; - pinfo->num_render_cube = 0; + common_data->prb_num_render_cube = 0; pinfo->cache_num_cube = pinfo->num_cube; for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); i++) { @@ -913,7 +919,7 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved sldata->irradiance_rt = DRW_texture_create_2D_array(irr_size[0], irr_size[1], irr_size[2], irradiance_format, DRW_TEX_FILTER, NULL); } - pinfo->num_render_grid = 0; + common_data->prb_num_render_grid = 0; pinfo->updated_bounce = 0; pinfo->grid_initialized = false; e_data.update_world |= PROBE_UPDATE_GRID; @@ -925,9 +931,9 @@ void EEVEE_lightprobes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved } } - if (pinfo->num_render_grid > pinfo->num_grid) { + if (common_data->prb_num_render_grid > pinfo->num_grid) { /* This can happen when deleting a probe. */ - pinfo->num_render_grid = pinfo->num_grid; + common_data->prb_num_render_grid = pinfo->num_grid; } EEVEE_lightprobes_updates(sldata, vedata->psl, vedata->stl); @@ -944,23 +950,26 @@ static void downsample_planar(void *vedata, int level) EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; const float *size = DRW_viewport_size_get(); - copy_v2_v2(stl->g_data->texel_size, size); + copy_v2_v2(stl->g_data->planar_texel_size, size); for (int i = 0; i < level - 1; ++i) { - stl->g_data->texel_size[0] /= 2.0f; - stl->g_data->texel_size[1] /= 2.0f; - min_ff(floorf(stl->g_data->texel_size[0]), 1.0f); - min_ff(floorf(stl->g_data->texel_size[1]), 1.0f); + stl->g_data->planar_texel_size[0] /= 2.0f; + stl->g_data->planar_texel_size[1] /= 2.0f; + min_ff(floorf(stl->g_data->planar_texel_size[0]), 1.0f); + min_ff(floorf(stl->g_data->planar_texel_size[1]), 1.0f); } - invert_v2(stl->g_data->texel_size); + invert_v2(stl->g_data->planar_texel_size); DRW_draw_pass(psl->probe_planar_downsample_ps); } /* Glossy filter probe_rt to probe_pool at index probe_idx */ -static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx) +static void glossy_filter_probe( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int probe_idx, float intensity) { EEVEE_LightProbesInfo *pinfo = sldata->probes; + pinfo->intensity_fac = intensity; + /* Max lod used from the render target probe */ pinfo->lod_rt_max = floorf(log2f(pinfo->target_size)) - 2.0f; @@ -1023,7 +1032,7 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, CLAMP_MIN(mipsize, 1); } /* For shading, save max level of the octahedron map */ - pinfo->lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f; + sldata->common_data.prb_lod_cube_max = (float)(maxlevel - min_lod_level) - 1.0f; /* reattach to have a valid framebuffer. */ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); @@ -1032,12 +1041,15 @@ static void glossy_filter_probe(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, /* Diffuse filter probe_rt to irradiance_pool at index probe_idx */ static void diffuse_filter_probe( EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, EEVEE_PassList *psl, int offset, - float clipsta, float clipend, float vis_range, float vis_blur) + float clipsta, float clipend, float vis_range, float vis_blur, float intensity) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_LightProbesInfo *pinfo = sldata->probes; + pinfo->intensity_fac = intensity; + int pool_size[3]; - irradiance_pool_size_get(pinfo->irradiance_vis_size, pinfo->total_irradiance_samples, pool_size); + irradiance_pool_size_get(common_data->prb_irradiance_vis_size, pinfo->total_irradiance_samples, pool_size); /* find cell position on the virtual 3D texture */ /* NOTE : Keep in sync with load_irradiance_cell() */ @@ -1081,23 +1093,24 @@ static void diffuse_filter_probe( /* Compute visibility */ pinfo->samples_ct = 512.0f; /* TODO refine */ pinfo->invsamples_ct = 1.0f / pinfo->samples_ct; - pinfo->shres = pinfo->irradiance_vis_size; + pinfo->shres = common_data->prb_irradiance_vis_size; pinfo->visibility_range = vis_range; pinfo->visibility_blur = vis_blur; pinfo->near_clip = -clipsta; pinfo->far_clip = -clipend; - pinfo->texel_size = 1.0f / (float)pinfo->irradiance_vis_size; + pinfo->texel_size = 1.0f / (float)common_data->prb_irradiance_vis_size; - int cell_per_col = pool_size[1] / pinfo->irradiance_vis_size; - cell_per_row = pool_size[0] / pinfo->irradiance_vis_size; - x = pinfo->irradiance_vis_size * (offset % cell_per_row); - y = pinfo->irradiance_vis_size * ((offset / cell_per_row) % cell_per_col); + int cell_per_col = pool_size[1] / common_data->prb_irradiance_vis_size; + cell_per_row = pool_size[0] / common_data->prb_irradiance_vis_size; + x = common_data->prb_irradiance_vis_size * (offset % cell_per_row); + y = common_data->prb_irradiance_vis_size * ((offset / cell_per_row) % cell_per_col); int layer = 1 + ((offset / cell_per_row) / cell_per_col); DRW_framebuffer_texture_detach(sldata->irradiance_rt); DRW_framebuffer_texture_layer_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, layer, 0); - DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, pinfo->irradiance_vis_size, sldata->probes->irradiance_vis_size); + DRW_framebuffer_viewport_size(sldata->probe_filter_fb, x, y, common_data->prb_irradiance_vis_size, + common_data->prb_irradiance_vis_size); DRW_draw_pass(psl->probe_visibility_compute); } @@ -1116,24 +1129,13 @@ static void render_scene_to_probe( EEVEE_StorageList *stl = vedata->stl; EEVEE_LightProbesInfo *pinfo = sldata->probes; - float winmat[4][4], wininv[4][4], posmat[4][4], tmp_ao_dist, tmp_ao_samples, tmp_ao_settings; + float winmat[4][4], wininv[4][4], posmat[4][4]; unit_m4(posmat); /* Move to capture position */ negate_v3_v3(posmat[3], pos); - /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */ - sldata->probes->specular_toggle = false; - sldata->probes->ssr_toggle = false; - sldata->probes->sss_toggle = false; - - /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */ - tmp_ao_dist = stl->effects->ao_dist; - tmp_ao_samples = stl->effects->ao_samples; - tmp_ao_settings = stl->effects->ao_settings; - stl->effects->ao_settings = 0.0f; /* Disable AO */ - /* 1 - Render to each cubeface individually. * We do this instead of using geometry shader because a) it's faster, * b) it's easier than fixing the nodetree shaders (for view dependant effects). */ @@ -1149,6 +1151,9 @@ static void render_scene_to_probe( stl->g_data->minzbuffer = e_data.depth_placeholder; txl->maxzbuffer = e_data.depth_placeholder; + /* Update common uniforms */ + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + /* Detach to rebind the right cubeface. */ DRW_framebuffer_bind(sldata->probe_fb); DRW_framebuffer_texture_detach(sldata->probe_rt); @@ -1210,15 +1215,9 @@ static void render_scene_to_probe( DRW_viewport_matrix_override_unset(DRW_MAT_WININV); /* Restore */ - pinfo->specular_toggle = true; - pinfo->ssr_toggle = true; - pinfo->sss_toggle = true; txl->planar_pool = tmp_planar_pool; stl->g_data->minzbuffer = tmp_minz; txl->maxzbuffer = tmp_maxz; - stl->effects->ao_dist = tmp_ao_dist; - stl->effects->ao_samples = tmp_ao_samples; - stl->effects->ao_settings = tmp_ao_settings; } static void render_scene_to_planar( @@ -1257,11 +1256,6 @@ static void render_scene_to_planar( DRW_framebuffer_clear(false, true, false, NULL, 1.0); - /* Turn off ssr to avoid black specular */ - /* TODO : Enable SSR in planar reflections? (Would be very heavy) */ - sldata->probes->ssr_toggle = false; - sldata->probes->sss_toggle = false; - /* Avoid using the texture attached to framebuffer when rendering. */ /* XXX */ GPUTexture *tmp_planar_pool = txl->planar_pool; @@ -1279,7 +1273,7 @@ static void render_scene_to_planar( EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer); /* Compute GTAO Horizons */ - EEVEE_occlusion_compute(sldata, vedata); + EEVEE_occlusion_compute(sldata, vedata, tmp_planar_depth, layer); /* Rebind Planar FB */ DRW_framebuffer_bind(fbl->planarref_fb); @@ -1293,8 +1287,6 @@ static void render_scene_to_planar( DRW_state_clip_planes_reset(); /* Restore */ - sldata->probes->ssr_toggle = true; - sldata->probes->sss_toggle = true; txl->planar_pool = tmp_planar_pool; txl->planar_depth = tmp_planar_depth; DRW_viewport_matrix_override_unset(DRW_MAT_PERS); @@ -1380,27 +1372,25 @@ static void lightprobe_cell_world_location_get(EEVEE_LightGrid *egrid, float loc static void lightprobes_refresh_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_PassList *psl = vedata->psl; - EEVEE_LightProbesInfo *pinfo = sldata->probes; + render_world_to_probe(sldata, psl); if (e_data.update_world & PROBE_UPDATE_CUBE) { - glossy_filter_probe(sldata, vedata, psl, 0); + glossy_filter_probe(sldata, vedata, psl, 0, 1.0); + common_data->prb_num_render_cube = 1; } if (e_data.update_world & PROBE_UPDATE_GRID) { - diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0); + diffuse_filter_probe(sldata, vedata, psl, 0, 0.0, 0.0, 0.0, 0.0, 1.0); SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); DRW_framebuffer_texture_detach(sldata->probe_pool); DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->irradiance_rt, 0, 0); DRW_draw_pass(psl->probe_grid_fill); DRW_framebuffer_texture_detach(sldata->irradiance_rt); DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); + common_data->prb_num_render_grid = 1; } e_data.update_world = 0; - if (!e_data.world_ready_to_shade) { - e_data.world_ready_to_shade = true; - pinfo->num_render_cube = 1; - pinfo->num_render_grid = 1; - } DRW_viewport_request_redraw(); } @@ -1432,36 +1422,53 @@ static void lightprobes_refresh_initialize_grid(EEVEE_ViewLayerData *sldata, EEV static void lightprobes_refresh_planar(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_TextureList *txl = vedata->txl; Object *ob; EEVEE_LightProbesInfo *pinfo = sldata->probes; + + if (pinfo->num_planar == 0) { + return; + } + + /* Temporary Remove all planar reflections (avoid lag effect). */ + common_data->prb_num_planar = 0; + /* Turn off ssr to avoid black specular */ + /* TODO : Enable SSR in planar reflections? (Would be very heavy) */ + common_data->ssr_toggle = false; + common_data->sss_toggle = false; + + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); i++) { EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); if (!ped->need_update) { continue; } - /* Temporary Remove all planar reflections (avoid lag effect). */ - int tmp_num_planar = pinfo->num_planar; - pinfo->num_planar = 0; render_scene_to_planar(sldata, vedata, i, ped->viewmat, ped->persmat, ped->planer_eq_offset); - /* Restore */ - pinfo->num_planar = tmp_num_planar; ped->need_update = false; ped->probe_id = i; } + + /* Restore */ + common_data->prb_num_planar = pinfo->num_planar; + common_data->ssr_toggle = true; + common_data->sss_toggle = true; + /* If there is at least one planar probe */ if (pinfo->num_planar > 0 && (vedata->stl->effects->enabled_effects & EFFECT_SSR) != 0) { const int max_lod = 9; DRW_stats_group_start("Planar Probe Downsample"); DRW_framebuffer_recursive_downsample(vedata->fbl->downsample_fb, txl->planar_pool, max_lod, &downsample_planar, vedata); /* For shading, save max level of the planar map */ - pinfo->lod_planar_max = (float)(max_lod); + common_data->prb_lod_planar_max = (float)(max_lod); DRW_stats_group_end(); } } static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; EEVEE_LightProbesInfo *pinfo = sldata->probes; @@ -1473,11 +1480,11 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve } LightProbe *prb = (LightProbe *)ob->data; render_scene_to_probe(sldata, vedata, ob->obmat[3], prb->clipsta, prb->clipend); - glossy_filter_probe(sldata, vedata, psl, i); + glossy_filter_probe(sldata, vedata, psl, i, prb->intensity); ped->need_update = false; ped->probe_id = i; if (!ped->ready_to_shade) { - pinfo->num_render_cube++; + common_data->prb_num_render_cube++; ped->ready_to_shade = true; } #if 0 @@ -1488,13 +1495,13 @@ static void lightprobes_refresh_cube(EEVEE_ViewLayerData *sldata, EEVEE_Data *ve stl->effects->taa_current_sample = 1; /* Only do one probe per frame */ - lightprobes_refresh_planar(sldata, vedata); return; } } static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; EEVEE_LightProbesInfo *pinfo = sldata->probes; @@ -1506,7 +1513,6 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_ /* Only compute probes if not navigating or in playback */ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C); if (((rv3d->rflag & RV3D_NAVIGATING) != 0) || ED_screen_animation_no_scrub(wm) != NULL) { - lightprobes_refresh_planar(sldata, vedata); return; } } @@ -1515,7 +1521,7 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_ /* Reflection probes depend on diffuse lighting thus on irradiance grid, * so update them first. */ while (pinfo->updated_bounce < pinfo->num_bounce) { - pinfo->num_render_grid = pinfo->num_grid; + common_data->prb_num_render_grid = pinfo->num_grid; /* TODO(sergey): This logic can be split into smaller functions. */ for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); i++) { EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_ensure(ob); @@ -1559,16 +1565,16 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_ lightprobe_cell_world_location_get(egrid, grid_loc, pos); SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); /* Temporary Remove all probes. */ - int tmp_num_render_grid = pinfo->num_render_grid; - int tmp_num_render_cube = pinfo->num_render_cube; - int tmp_num_planar = pinfo->num_planar; + int tmp_num_render_grid = common_data->prb_num_render_grid; + int tmp_num_render_cube = common_data->prb_num_render_cube; + int tmp_num_planar = common_data->prb_num_planar; float tmp_level_bias = egrid->level_bias; - pinfo->num_render_cube = 0; - pinfo->num_planar = 0; + common_data->prb_num_render_cube = 0; + common_data->prb_num_planar = 0; /* Use light from previous bounce when capturing radiance. */ if (pinfo->updated_bounce == 0) { /* But not on first bounce. */ - pinfo->num_render_grid = 0; + common_data->prb_num_render_grid = 0; } else { /* Remove bias */ @@ -1577,14 +1583,15 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_ } render_scene_to_probe(sldata, vedata, pos, prb->clipsta, prb->clipend); diffuse_filter_probe(sldata, vedata, psl, egrid->offset + cell_id, - prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur); + prb->clipsta, prb->clipend, egrid->visibility_range, prb->vis_blur, + prb->intensity); /* To see what is going on. */ SWAP(GPUTexture *, sldata->irradiance_pool, sldata->irradiance_rt); /* Restore */ - pinfo->num_render_cube = tmp_num_render_cube; + common_data->prb_num_render_cube = tmp_num_render_cube; pinfo->num_planar = tmp_num_planar; if (pinfo->updated_bounce == 0) { - pinfo->num_render_grid = tmp_num_render_grid; + common_data->prb_num_render_grid = tmp_num_render_grid; } else { egrid->level_bias = tmp_level_bias; @@ -1608,12 +1615,11 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_ DRW_viewport_request_redraw(); /* Do not let this frame accumulate. */ stl->effects->taa_current_sample = 1; - lightprobes_refresh_planar(sldata, vedata); return; } pinfo->updated_bounce++; - pinfo->num_render_grid = pinfo->num_grid; + common_data->prb_num_render_grid = pinfo->num_grid; if (pinfo->updated_bounce < pinfo->num_bounce) { /* Retag all grids to update for next bounce */ @@ -1641,13 +1647,39 @@ static void lightprobes_refresh_all_no_world(EEVEE_ViewLayerData *sldata, EEVEE_ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_LightProbesInfo *pinfo = sldata->probes; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + + /* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */ + common_data->spec_toggle = false; + common_data->ssr_toggle = false; + common_data->sss_toggle = false; + + /* Disable AO until we find a way to hide really bad discontinuities between cubefaces. */ + float tmp_ao_dist = common_data->ao_dist; + float tmp_ao_settings = common_data->ao_settings; + common_data->ao_settings = 0.0f; + common_data->ao_dist = 0.0f; + /* Render world in priority */ if (e_data.update_world) { lightprobes_refresh_world(sldata, vedata); } - else if (true) { /* TODO if at least one probe needs refresh */ + else if (pinfo->do_cube_update || (pinfo->updated_bounce < pinfo->num_bounce)) { lightprobes_refresh_all_no_world(sldata, vedata); } + + /* Restore */ + common_data->spec_toggle = true; + common_data->ssr_toggle = true; + common_data->sss_toggle = true; + common_data->ao_dist = tmp_ao_dist; + common_data->ao_settings = tmp_ao_settings; + + lightprobes_refresh_planar(sldata, vedata); + + /* Disable SSR if we cannot read previous frame */ + common_data->ssr_toggle = vedata->stl->g_data->valid_double_buffer; } void EEVEE_lightprobes_free(void) diff --git a/source/blender/draw/engines/eevee/eevee_lights.c b/source/blender/draw/engines/eevee/eevee_lights.c index 22465c04cfa..69b58bf9670 100644 --- a/source/blender/draw/engines/eevee/eevee_lights.c +++ b/source/blender/draw/engines/eevee/eevee_lights.c @@ -32,28 +32,7 @@ #include "eevee_engine.h" #include "eevee_private.h" -/* Theses are the structs stored inside Objects. - * It works with even if the object is in multiple layers - * because we don't get the same "Object *" for each layer. */ -typedef struct EEVEE_LightData { - short light_id, shadow_id; -} EEVEE_LightData; - -typedef struct EEVEE_ShadowCubeData { - short light_id, shadow_id, cube_id, layer_id; -} EEVEE_ShadowCubeData; - -typedef struct EEVEE_ShadowCascadeData { - short light_id, shadow_id, cascade_id, layer_id; - float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ - float radius[MAX_CASCADE_NUM]; -} EEVEE_ShadowCascadeData; - -typedef struct ShadowCaster { - struct ShadowCaster *next, *prev; - void *ob; - bool prune; -} ShadowCaster; +#define SHADOW_CASTER_ALLOC_CHUNK 16 static struct { struct GPUShader *shadow_sh; @@ -70,6 +49,48 @@ extern char datatoc_shadow_store_frag_glsl[]; extern char datatoc_shadow_copy_frag_glsl[]; extern char datatoc_concentric_samples_lib_glsl[]; +/* Prototype */ +static void eevee_light_setup(Object *ob, EEVEE_Light *evli); + +/* *********** LIGHT BITS *********** */ +static void lightbits_set_single(EEVEE_LightBits *bitf, unsigned int idx, bool val) +{ + if (val) { + bitf->fields[idx / 8] |= (1 << (idx % 8)); + } + else { + bitf->fields[idx / 8] &= ~(1 << (idx % 8)); + } +} + +static void lightbits_set_all(EEVEE_LightBits *bitf, bool val) +{ + memset(bitf, (val) ? 0xFF : 0x00, sizeof(EEVEE_LightBits)); +} + +static void lightbits_or(EEVEE_LightBits *r, const EEVEE_LightBits *v) +{ + for (int i = 0; i < MAX_LIGHTBITS_FIELDS; ++i) { + r->fields[i] |= v->fields[i]; + } +} + +static bool lightbits_get(const EEVEE_LightBits *r, unsigned int idx) +{ + return r->fields[idx / 8] & (1 << (idx % 8)); +} + +static void lightbits_convert(EEVEE_LightBits *r, const EEVEE_LightBits *bitf, const int *light_bit_conv_table, unsigned int table_length) +{ + for (int i = 0; i < table_length; ++i) { + if (lightbits_get(bitf, i) != 0) { + if (light_bit_conv_table[i] >= 0) { + r->fields[i / 8] |= (1 << (i % 8)); + } + } + } +} + /* *********** FUNCTIONS *********** */ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata) @@ -96,7 +117,8 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata) store_shadow_shader_str, "#define ESM\n"); e_data.shadow_store_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen( - store_shadow_shader_str, "#define ESM\n" + store_shadow_shader_str, + "#define ESM\n" "#define CSM\n"); e_data.shadow_store_cube_sh[SHADOW_VSM] = DRW_shader_create_fullscreen( @@ -114,7 +136,8 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata) "#define ESM\n" "#define COPY\n"); e_data.shadow_copy_cascade_sh[SHADOW_ESM] = DRW_shader_create_fullscreen( - datatoc_shadow_copy_frag_glsl, "#define ESM\n" + datatoc_shadow_copy_frag_glsl, + "#define ESM\n" "#define COPY\n" "#define CSM\n"); @@ -134,8 +157,21 @@ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata) sldata->light_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Light) * MAX_LIGHT, NULL); sldata->shadow_ubo = DRW_uniformbuffer_create(shadow_ubo_size, NULL); sldata->shadow_render_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_ShadowRender), NULL); + + for (int i = 0; i < 2; ++i) { + sldata->shcasters_buffers[i].shadow_casters = MEM_callocN(sizeof(EEVEE_ShadowCaster) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_ShadowCaster buf"); + sldata->shcasters_buffers[i].flags = MEM_callocN(sizeof(sldata->shcasters_buffers[0].flags) * SHADOW_CASTER_ALLOC_CHUNK, "EEVEE_shcast_buffer flags buf"); + sldata->shcasters_buffers[i].alloc_count = SHADOW_CASTER_ALLOC_CHUNK; + sldata->shcasters_buffers[i].count = 0; + } + + sldata->lamps->shcaster_frontbuffer = &sldata->shcasters_buffers[0]; + sldata->lamps->shcaster_backbuffer = &sldata->shcasters_buffers[1]; } + /* Flip buffers */ + SWAP(EEVEE_ShadowCasterBuffer *, sldata->lamps->shcaster_frontbuffer, sldata->lamps->shcaster_backbuffer); + int sh_method = BKE_collection_engine_property_value_get_int(props, "shadow_method"); int sh_size = BKE_collection_engine_property_value_get_int(props, "shadow_size"); int sh_high_bitdepth = BKE_collection_engine_property_value_get_int(props, "shadow_high_bitdepth"); @@ -173,6 +209,7 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) { EEVEE_LampsInfo *linfo = sldata->lamps; + linfo->shcaster_frontbuffer->count = 0; linfo->num_light = 0; linfo->num_layer = 0; linfo->gpu_cube_ct = linfo->gpu_cascade_ct = linfo->gpu_shadow_ct = 0; @@ -180,6 +217,11 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) memset(linfo->light_ref, 0, sizeof(linfo->light_ref)); memset(linfo->shadow_cube_ref, 0, sizeof(linfo->shadow_cube_ref)); memset(linfo->shadow_cascade_ref, 0, sizeof(linfo->shadow_cascade_ref)); + memset(linfo->new_shadow_id, -1, sizeof(linfo->new_shadow_id)); + + /* Shadow Casters: Reset flags. */ + memset(linfo->shcaster_backbuffer->flags, (char)SHADOW_CASTER_PRUNED, linfo->shcaster_backbuffer->alloc_count); + memset(linfo->shcaster_frontbuffer->flags, 0x00, linfo->shcaster_frontbuffer->alloc_count); { psl->shadow_cube_store_pass = DRW_pass_create("Shadow Storage Pass", DRW_STATE_WRITE_COLOR); @@ -239,9 +281,6 @@ void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) "Shadow Cascade Pass", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS); } - - /* Reset shadow casters list */ - BLI_freelistN(&sldata->shadow_casters); } void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) @@ -250,14 +289,27 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) /* Step 1 find all lamps in the scene and setup them */ if (linfo->num_light >= MAX_LIGHT) { - printf("Too much lamps in the scene !!!\n"); - linfo->num_light = MAX_LIGHT - 1; + printf("Too many lamps in the scene !!!\n"); } else { Lamp *la = (Lamp *)ob->data; + EEVEE_Light *evli = linfo->light_data + linfo->num_light; + eevee_light_setup(ob, evli); + + /* We do not support shadowmaps for dupli lamps. */ + if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + linfo->num_light++; + return; + } + EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); - MEM_SAFE_FREE(led->storage); + /* Save previous shadow id. */ + int prev_cube_sh_id = led->prev_cube_shadow_id; + + /* Default light without shadows */ + led->data.ld.shadow_id = -1; + led->prev_cube_shadow_id = -1; if (la->mode & (LA_SHAD_BUF | LA_SHAD_RAY)) { if (la->type == LA_SUN) { @@ -268,13 +320,11 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) /* Save Light object. */ linfo->shadow_cascade_ref[linfo->cpu_cascade_ct] = ob; - /* Create storage and store indices. */ - EEVEE_ShadowCascadeData *data = MEM_mallocN( - sizeof(EEVEE_ShadowCascadeData), "EEVEE_ShadowCascadeData"); + /* Store indices. */ + EEVEE_ShadowCascadeData *data = &led->data.scad; data->shadow_id = linfo->gpu_shadow_ct; data->cascade_id = linfo->gpu_cascade_ct; data->layer_id = linfo->num_layer; - led->storage = data; /* Increment indices. */ linfo->gpu_shadow_ct += 1; @@ -291,13 +341,24 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) /* Save Light object. */ linfo->shadow_cube_ref[linfo->cpu_cube_ct] = ob; - /* Create storage and store indices. */ - EEVEE_ShadowCubeData *data = MEM_mallocN( - sizeof(EEVEE_ShadowCubeData), "EEVEE_ShadowCubeData"); + /* For light update tracking. */ + if ((prev_cube_sh_id >= 0) && + (prev_cube_sh_id < linfo->shcaster_backbuffer->count)) + { + linfo->new_shadow_id[prev_cube_sh_id] = linfo->cpu_cube_ct; + } + led->prev_cube_shadow_id = linfo->cpu_cube_ct; + + /* Saving lamp bounds for later. */ + BLI_assert(linfo->cpu_cube_ct >= 0 && linfo->cpu_cube_ct < MAX_LIGHT); + copy_v3_v3(linfo->shadow_bounds[linfo->cpu_cube_ct].center, ob->obmat[3]); + linfo->shadow_bounds[linfo->cpu_cube_ct].radius = la->clipend; + + EEVEE_ShadowCubeData *data = &led->data.scd; + /* Store indices. */ data->shadow_id = linfo->gpu_shadow_ct; data->cube_id = linfo->gpu_cube_ct; data->layer_id = linfo->num_layer; - led->storage = data; /* Increment indices. */ linfo->gpu_shadow_ct += 1; @@ -309,13 +370,7 @@ void EEVEE_lights_cache_add(EEVEE_ViewLayerData *sldata, Object *ob) } } - /* Default light without shadows */ - if (!led->storage) { - led->storage = MEM_mallocN(sizeof(EEVEE_LightData), "EEVEE_LightData"); - ((EEVEE_LightData *)led->storage)->shadow_id = -1; - } - - ((EEVEE_LightData *)led->storage)->light_id = linfo->num_light; + led->data.ld.light_id = linfo->num_light; linfo->light_ref[linfo->num_light] = ob; linfo->num_light++; } @@ -362,11 +417,75 @@ void EEVEE_lights_cache_shcaster_material_add( DRW_shgroup_set_instance_count(grp, MAX_CASCADE_NUM); } +/* Make that object update shadow casting lamps inside its influence bounding box. */ +void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, Object *ob) +{ + if ((ob->base_flag & BASE_FROMDUPLI) != 0) { + /* TODO: Special case for dupli objects because we cannot save the object pointer. */ + return; + } + + EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); + EEVEE_LampsInfo *linfo = sldata->lamps; + EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer; + EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer; + int past_id = oedata->shadow_caster_id; + + /* Update flags in backbuffer. */ + if (past_id > -1 && past_id < backbuffer->count) { + backbuffer->flags[past_id] &= ~SHADOW_CASTER_PRUNED; + + if (oedata->need_update) { + backbuffer->flags[past_id] |= SHADOW_CASTER_UPDATED; + } + } + + /* Update id. */ + oedata->shadow_caster_id = frontbuffer->count++; + + /* Make sure shadow_casters is big enough. */ + if (oedata->shadow_caster_id >= frontbuffer->alloc_count) { + frontbuffer->alloc_count += SHADOW_CASTER_ALLOC_CHUNK; + frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + } + + EEVEE_ShadowCaster *shcaster = frontbuffer->shadow_casters + oedata->shadow_caster_id; + + if (oedata->need_update) { + frontbuffer->flags[oedata->shadow_caster_id] = SHADOW_CASTER_UPDATED; + } + + /* Update World AABB in frontbuffer. */ + BoundBox *bb = BKE_object_boundbox_get(ob); + float min[3], max[3]; + INIT_MINMAX(min, max); + for (int i = 0; i < 8; ++i) { + float vec[3]; + copy_v3_v3(vec, bb->vec[i]); + mul_m4_v3(ob->obmat, vec); + minmax_v3v3_v3(min, max, vec); + } + + EEVEE_BoundBox *aabb = &shcaster->bbox; + add_v3_v3v3(aabb->center, min, max); + mul_v3_fl(aabb->center, 0.5f); + sub_v3_v3v3(aabb->halfdim, aabb->center, max); + + aabb->halfdim[0] = fabsf(aabb->halfdim[0]); + aabb->halfdim[1] = fabsf(aabb->halfdim[1]); + aabb->halfdim[2] = fabsf(aabb->halfdim[2]); + + oedata->need_update = false; +} + void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata) { EEVEE_LampsInfo *linfo = sldata->lamps; DRWTextureFormat shadow_pool_format = DRW_TEX_R_32; + sldata->common_data.la_num_light = linfo->num_light; + /* Setup enough layers. */ /* Free textures if number mismatch. */ if (linfo->num_layer != linfo->cache_num_layer) { @@ -428,11 +547,8 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata) } /* Update buffer with lamp data */ -static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led) +static void eevee_light_setup(Object *ob, EEVEE_Light *evli) { - /* TODO only update if data changes */ - EEVEE_LightData *evld = led->storage; - EEVEE_Light *evli = linfo->light_data + evld->light_id; Lamp *la = (Lamp *)ob->data; float mat[4][4], scale[3], power; @@ -485,13 +601,14 @@ static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngi } else if (la->type == LA_SPOT || la->type == LA_LOCAL) { power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(4*r²*Pi²) */ - M_PI * M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */ + M_PI * M_PI * 10.0; /* XXX : Empirical, Fit cycles power */ /* for point lights (a.k.a radius == 0.0) */ // power = M_PI * M_PI * 0.78; /* XXX : Empirical, Fit cycles power */ } else { - power = 1.0f; + power = 1.0f / (4.0f * evli->radius * evli->radius * M_PI * M_PI) * /* 1/(r²*Pi) */ + 12.5f; /* XXX : Empirical, Fit cycles power */ } mul_v3_fl(evli->color, power * la->energy); @@ -504,7 +621,7 @@ static void eevee_light_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngi static void eevee_shadow_cube_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE_LampEngineData *led) { - EEVEE_ShadowCubeData *sh_data = (EEVEE_ShadowCubeData *)led->storage; + EEVEE_ShadowCubeData *sh_data = &led->data.scd; EEVEE_Light *evli = linfo->light_data + sh_data->light_id; EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id; EEVEE_ShadowCube *cube_data = linfo->shadow_cube_data + sh_data->cube_id; @@ -598,7 +715,7 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE int sh_nbr = 1; /* TODO : MSM */ int cascade_nbr = la->cascade_count; - EEVEE_ShadowCascadeData *sh_data = (EEVEE_ShadowCascadeData *)led->storage; + EEVEE_ShadowCascadeData *sh_data = &led->data.scad; EEVEE_Light *evli = linfo->light_data + sh_data->light_id; EEVEE_Shadow *ubo_data = linfo->shadow_data + sh_data->shadow_id; EEVEE_ShadowCascade *cascade_data = linfo->shadow_cascade_data + sh_data->cascade_id; @@ -783,128 +900,86 @@ static void eevee_shadow_cascade_setup(Object *ob, EEVEE_LampsInfo *linfo, EEVEE } /* Used for checking if object is inside the shadow volume. */ -static bool cube_bbox_intersect(const float cube_center[3], float cube_half_dim, const BoundBox *bb, float (*obmat)[4]) +static bool sphere_bbox_intersect(const EEVEE_BoundSphere *bs, const EEVEE_BoundBox *bb) { - float min[3], max[4], tmp[4][4]; - unit_m4(tmp); - translate_m4(tmp, -cube_center[0], -cube_center[1], -cube_center[2]); - mul_m4_m4m4(tmp, tmp, obmat); - - /* Just simple AABB intersection test in world space. */ - INIT_MINMAX(min, max); - for (int i = 0; i < 8; ++i) { - float vec[3]; - copy_v3_v3(vec, bb->vec[i]); - mul_m4_v3(tmp, vec); - minmax_v3v3_v3(min, max, vec); - } + /* We are testing using a rougher AABB vs AABB test instead of full AABB vs Sphere. */ + /* TODO test speed with AABB vs Sphere. */ + bool x = fabsf(bb->center[0] - bs->center[0]) <= (bb->halfdim[0] + bs->radius); + bool y = fabsf(bb->center[1] - bs->center[1]) <= (bb->halfdim[1] + bs->radius); + bool z = fabsf(bb->center[2] - bs->center[2]) <= (bb->halfdim[2] + bs->radius); - if (MAX3(max[0], max[1], max[2]) < -cube_half_dim) return false; - if (MIN3(min[0], min[1], min[2]) > cube_half_dim) return false; - - return true; + return x && y && z; } -static ShadowCaster *search_object_in_list(ListBase *list, Object *ob) +void EEVEE_lights_update(EEVEE_ViewLayerData *sldata) { - for (ShadowCaster *ldata = list->first; ldata; ldata = ldata->next) { - if (ldata->ob == ob) - return ldata; + EEVEE_LampsInfo *linfo = sldata->lamps; + Object *ob; + int i; + char *flag; + EEVEE_ShadowCaster *shcaster; + EEVEE_BoundSphere *bsphere; + EEVEE_ShadowCasterBuffer *frontbuffer = linfo->shcaster_frontbuffer; + EEVEE_ShadowCasterBuffer *backbuffer = linfo->shcaster_backbuffer; + + EEVEE_LightBits update_bits = {{0}}; + if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) { + /* Update all lights. */ + lightbits_set_all(&update_bits, true); } - - return NULL; -} - -static void delete_pruned_shadowcaster(EEVEE_LampEngineData *led) -{ - ShadowCaster *next; - for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = next) { - next = ldata->next; - if (ldata->prune == true) { - led->need_update = true; - BLI_freelinkN(&led->shadow_caster_list, ldata); + else { + /* Search for deleted shadow casters and if shcaster WAS in shadow radius. */ + /* No need to run this if we already update all lamps. */ + EEVEE_LightBits past_bits = {{0}}; + EEVEE_LightBits curr_bits = {{0}}; + shcaster = backbuffer->shadow_casters; + flag = backbuffer->flags; + for (i = 0; i < backbuffer->count; ++i, ++flag, ++shcaster) { + /* If the shadowcaster has been deleted or updated. */ + if (*flag != 0) { + /* Add the lamps that were intersecting with its BBox. */ + lightbits_or(&past_bits, &shcaster->bits); + } } + /* Convert old bits to new bits and add result to final update bits. */ + /* NOTE: This might be overkill since all lights are tagged to refresh if + * the light count changes. */ + lightbits_convert(&curr_bits, &past_bits, linfo->new_shadow_id, MAX_LIGHT); + lightbits_or(&update_bits, &curr_bits); } -} -static void light_tag_shadow_update(Object *lamp, Object *ob) -{ - Lamp *la = lamp->data; - EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(lamp); - - bool is_inside_range = cube_bbox_intersect(lamp->obmat[3], la->clipend, BKE_object_boundbox_get(ob), ob->obmat); - ShadowCaster *ldata = search_object_in_list(&led->shadow_caster_list, ob); - - if (is_inside_range) { - if (ldata == NULL) { - /* Object was not a shadow caster previously but is now. Add it. */ - ldata = MEM_callocN(sizeof(ShadowCaster), "ShadowCaster"); - ldata->ob = ob; - BLI_addtail(&led->shadow_caster_list, ldata); - led->need_update = true; + /* Search for updates in current shadow casters. */ + shcaster = frontbuffer->shadow_casters; + flag = frontbuffer->flags; + for (i = 0; i < frontbuffer->count; i++, flag++, shcaster++) { + /* Run intersection checks to fill the bitfields. */ + bsphere = linfo->shadow_bounds; + for (int j = 0; j < linfo->cpu_cube_ct; j++, bsphere++) { + bool iter = sphere_bbox_intersect(bsphere, &shcaster->bbox); + lightbits_set_single(&shcaster->bits, j, iter); } - else { - EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); - if (oedata->need_update) { - led->need_update = true; - } + /* Only add to final bits if objects has been updated. */ + if (*flag != 0) { + lightbits_or(&update_bits, &shcaster->bits); } - ldata->prune = false; } - else if (ldata != NULL) { - /* Object was a shadow caster previously and is not anymore. Remove it. */ - led->need_update = true; - BLI_freelinkN(&led->shadow_caster_list, ldata); - } -} - -static void eevee_lights_shcaster_updated(EEVEE_ViewLayerData *sldata, Object *ob) -{ - Object *lamp; - EEVEE_LampsInfo *linfo = sldata->lamps; - - /* Iterate over all shadow casting lamps to see if - * each of them needs update because of this object */ - for (int i = 0; (lamp = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) { - light_tag_shadow_update(lamp, ob); - } - EEVEE_ObjectEngineData *oedata = EEVEE_object_data_ensure(ob); - oedata->need_update = false; -} - -void EEVEE_lights_update(EEVEE_ViewLayerData *sldata) -{ - EEVEE_LampsInfo *linfo = sldata->lamps; - Object *ob; - int i; - /* Prune shadow casters to remove if object does not exists anymore (unprune them if object exists) */ - Object *lamp; - for (i = 0; (lamp = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) { - EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(lamp); + /* Setup shadow cube in UBO and tag for update if necessary. */ + for (i = 0; (i < MAX_SHADOW_CUBE) && (ob = linfo->shadow_cube_ref[i]); i++) { + EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); - if ((linfo->update_flag & LIGHT_UPDATE_SHADOW_CUBE) != 0) { + eevee_shadow_cube_setup(ob, linfo, led); + if (lightbits_get(&update_bits, i) != 0) { led->need_update = true; } - - for (ShadowCaster *ldata = led->shadow_caster_list.first; ldata; ldata = ldata->next) { - ldata->prune = true; - } } - for (LinkData *ldata = sldata->shadow_casters.first; ldata; ldata = ldata->next) { - eevee_lights_shcaster_updated(sldata, ldata->data); - } - - for (i = 0; (ob = linfo->light_ref[i]) && (i < MAX_LIGHT); i++) { - EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); - eevee_light_setup(ob, linfo, led); - } - - for (i = 0; (ob = linfo->shadow_cube_ref[i]) && (i < MAX_SHADOW_CUBE); i++) { - EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); - eevee_shadow_cube_setup(ob, linfo, led); - delete_pruned_shadowcaster(led); + /* Resize shcasters buffers if too big. */ + if (frontbuffer->alloc_count - frontbuffer->count > SHADOW_CASTER_ALLOC_CHUNK) { + frontbuffer->alloc_count = (frontbuffer->count / SHADOW_CASTER_ALLOC_CHUNK) * SHADOW_CASTER_ALLOC_CHUNK; + frontbuffer->alloc_count += (frontbuffer->count % SHADOW_CASTER_ALLOC_CHUNK != 0) ? SHADOW_CASTER_ALLOC_CHUNK : 0; + frontbuffer->shadow_casters = MEM_reallocN(frontbuffer->shadow_casters, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); + frontbuffer->flags = MEM_reallocN(frontbuffer->flags, sizeof(EEVEE_ShadowCaster) * frontbuffer->alloc_count); } } @@ -932,7 +1007,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) } EEVEE_ShadowRender *srd = &linfo->shadow_render_data; - EEVEE_ShadowCubeData *evscd = (EEVEE_ShadowCubeData *)led->storage; + EEVEE_ShadowCubeData *evscd = &led->data.scd; srd->clip_near = la->clipsta; srd->clip_far = la->clipend; @@ -1010,7 +1085,7 @@ void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl) EEVEE_LampEngineData *led = EEVEE_lamp_data_ensure(ob); Lamp *la = (Lamp *)ob->data; - EEVEE_ShadowCascadeData *evscd = (EEVEE_ShadowCascadeData *)led->storage; + EEVEE_ShadowCascadeData *evscd = &led->data.scad; EEVEE_ShadowRender *srd = &linfo->shadow_render_data; eevee_shadow_cascade_setup(ob, linfo, led); diff --git a/source/blender/draw/engines/eevee/eevee_lut.h b/source/blender/draw/engines/eevee/eevee_lut.h index d706110351e..3c2ffeb11a7 100644 --- a/source/blender/draw/engines/eevee/eevee_lut.h +++ b/source/blender/draw/engines/eevee/eevee_lut.h @@ -3345,6 +3345,521 @@ static float bsdf_split_sum_ggx[64 * 64 * 2] = { 0.626953f, 0.023544f, 0.616699f, 0.022186f, 0.605957f, 0.020920f, 0.594727f, 0.019730f }; +static float ltc_disk_integral[64 * 64] = { + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.015873f, 0.047619f, 0.079365f, 0.111111f, 0.142857f, 0.174603f, 0.206349f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000148f, 0.002454f, 0.008675f, 0.019560f, + 0.035433f, 0.056294f, 0.081819f, 0.111259f, 0.142857f, 0.174603f, 0.206349f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000002f, 0.000761f, 0.003673f, 0.009403f, 0.018333f, 0.030683f, + 0.046556f, 0.065952f, 0.088768f, 0.114784f, 0.143618f, 0.174606f, 0.206349f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000039f, 0.000969f, 0.003703f, 0.008684f, 0.016189f, 0.026395f, 0.039409f, + 0.055282f, 0.074014f, 0.095554f, 0.119795f, 0.146560f, 0.175573f, 0.206388f, 0.238095f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000047f, 0.000895f, 0.003265f, 0.007514f, 0.013873f, 0.022495f, 0.033483f, 0.046897f, + 0.062770f, 0.081102f, 0.101860f, 0.124985f, 0.150372f, 0.177868f, 0.207245f, 0.238143f, + 0.269841f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000028f, + 0.000695f, 0.002655f, 0.006230f, 0.011623f, 0.018976f, 0.028384f, 0.039915f, 0.053606f, + 0.069479f, 0.087534f, 0.107749f, 0.130087f, 0.154481f, 0.180833f, 0.209005f, 0.238791f, + 0.269869f, 0.301587f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000465f, + 0.002017f, 0.004975f, 0.009533f, 0.015821f, 0.023934f, 0.033937f, 0.045874f, 0.059772f, + 0.075645f, 0.093493f, 0.113302f, 0.135045f, 0.158678f, 0.184136f, 0.211325f, 0.240113f, + 0.270306f, 0.301594f, 0.333333f, 0.365079f, 0.396825f, 0.428571f, 0.460317f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000260f, 0.001426f, + 0.003823f, 0.007642f, 0.013012f, 0.020025f, 0.028745f, 0.039218f, 0.051475f, 0.065535f, + 0.081408f, 0.099094f, 0.118583f, 0.139856f, 0.162882f, 0.187615f, 0.213991f, 0.241918f, + 0.271267f, 0.301847f, 0.333333f, 0.365079f, 0.396826f, 0.428572f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000109f, 0.000921f, 0.002807f, + 0.005966f, 0.010528f, 0.016585f, 0.024200f, 0.033420f, 0.044278f, 0.056796f, 0.070988f, + 0.086861f, 0.104415f, 0.123643f, 0.144531f, 0.167057f, 0.191188f, 0.216878f, 0.244062f, + 0.272649f, 0.302509f, 0.333442f, 0.365079f, 0.396826f, 0.428572f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000024f, 0.000524f, 0.001947f, 0.004511f, + 0.008351f, 0.013561f, 0.020206f, 0.028332f, 0.037974f, 0.049155f, 0.061892f, 0.076194f, + 0.092067f, 0.109511f, 0.128520f, 0.149085f, 0.171189f, 0.194809f, 0.219910f, 0.246447f, + 0.274352f, 0.303535f, 0.333857f, 0.365104f, 0.396826f, 0.428572f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000242f, 0.001250f, 0.003275f, 0.006463f, + 0.010913f, 0.016693f, 0.023849f, 0.032418f, 0.042423f, 0.053881f, 0.066805f, 0.081201f, + 0.097074f, 0.114424f, 0.133246f, 0.153534f, 0.175275f, 0.198453f, 0.223042f, 0.249009f, + 0.276304f, 0.304862f, 0.334584f, 0.365322f, 0.396826f, 0.428571f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000074f, 0.000716f, 0.002252f, 0.004848f, 0.008610f, + 0.013608f, 0.019894f, 0.027502f, 0.036458f, 0.046780f, 0.058480f, 0.071567f, 0.086045f, + 0.101918f, 0.119186f, 0.137845f, 0.157891f, 0.179316f, 0.202106f, 0.226243f, 0.251704f, + 0.278451f, 0.306436f, 0.335586f, 0.365796f, 0.396900f, 0.428571f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000006f, 0.000342f, 0.001437f, 0.003492f, 0.006624f, 0.010911f, + 0.016406f, 0.023146f, 0.031157f, 0.040457f, 0.051059f, 0.062972f, 0.076203f, 0.090753f, + 0.106626f, 0.123822f, 0.142337f, 0.162170f, 0.183314f, 0.205760f, 0.229496f, 0.254502f, + 0.280753f, 0.308212f, 0.336825f, 0.366517f, 0.397167f, 0.428578f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000114f, 0.000820f, 0.002381f, 0.004935f, 0.008569f, 0.013339f, + 0.019286f, 0.026437f, 0.034810f, 0.044418f, 0.055271f, 0.067375f, 0.080733f, 0.095348f, + 0.111221f, 0.128352f, 0.146740f, 0.166382f, 0.187276f, 0.209413f, 0.232786f, 0.257382f, + 0.283181f, 0.310156f, 0.338269f, 0.367461f, 0.397646f, 0.428685f, 0.460318f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000014f, 0.000390f, 0.001503f, 0.003525f, 0.006554f, 0.010655f, 0.015872f, + 0.022233f, 0.029758f, 0.038460f, 0.048347f, 0.059427f, 0.071702f, 0.085175f, 0.099848f, + 0.115721f, 0.132794f, 0.151067f, 0.170538f, 0.191204f, 0.213063f, 0.236107f, 0.260329f, + 0.285714f, 0.312243f, 0.339887f, 0.368604f, 0.398329f, 0.428961f, 0.460331f, 0.492064f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000130f, 0.000845f, 0.002376f, 0.004845f, 0.008325f, 0.012864f, 0.018495f, + 0.025237f, 0.033105f, 0.042107f, 0.052249f, 0.063534f, 0.075965f, 0.089543f, 0.104269f, + 0.120142f, 0.137163f, 0.155330f, 0.174645f, 0.195106f, 0.216710f, 0.239454f, 0.263332f, + 0.288336f, 0.314451f, 0.341658f, 0.369924f, 0.399202f, 0.429416f, 0.460447f, 0.492064f, + 0.523809f, 0.555555f, 0.587301f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000016f, 0.000391f, 0.001475f, 0.003423f, 0.006322f, 0.010230f, 0.015179f, 0.021195f, + 0.028290f, 0.036474f, 0.045752f, 0.056128f, 0.067602f, 0.080176f, 0.093850f, 0.108623f, + 0.124496f, 0.141469f, 0.159541f, 0.178713f, 0.198985f, 0.220355f, 0.242823f, 0.266385f, + 0.291036f, 0.316767f, 0.343563f, 0.371402f, 0.400248f, 0.430047f, 0.460709f, 0.492079f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000123f, 0.000807f, 0.002272f, 0.004628f, 0.007942f, 0.012253f, 0.017589f, 0.023963f, + 0.031387f, 0.039864f, 0.049398f, 0.059990f, 0.071638f, 0.084344f, 0.098106f, 0.112923f, + 0.128796f, 0.145725f, 0.163709f, 0.182749f, 0.202847f, 0.224001f, 0.246214f, 0.269482f, + 0.293805f, 0.319176f, 0.345587f, 0.373021f, 0.401454f, 0.430844f, 0.461125f, 0.492187f, + 0.523810f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, + 0.000356f, 0.001378f, 0.003225f, 0.005979f, 0.009689f, 0.014384f, 0.020083f, 0.026795f, + 0.034525f, 0.043276f, 0.053047f, 0.063839f, 0.075649f, 0.088476f, 0.102320f, 0.117178f, + 0.133051f, 0.149939f, 0.167841f, 0.186760f, 0.206696f, 0.227650f, 0.249625f, 0.272620f, + 0.296636f, 0.321671f, 0.347718f, 0.374768f, 0.402804f, 0.431796f, 0.461695f, 0.492420f, + 0.523822f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000100f, + 0.000725f, 0.002097f, 0.004323f, 0.007463f, 0.011553f, 0.016613f, 0.022655f, 0.029684f, + 0.037702f, 0.046708f, 0.056701f, 0.067680f, 0.079640f, 0.092581f, 0.106501f, 0.121397f, + 0.137270f, 0.154120f, 0.171946f, 0.190751f, 0.210537f, 0.231305f, 0.253057f, 0.275797f, + 0.299525f, 0.324242f, 0.349947f, 0.376633f, 0.404289f, 0.432895f, 0.462415f, 0.492788f, + 0.523909f, 0.555556f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000005f, 0.000296f, + 0.001231f, 0.002960f, 0.005558f, 0.009072f, 0.013526f, 0.018933f, 0.025299f, 0.032627f, + 0.040916f, 0.050162f, 0.060364f, 0.071517f, 0.083619f, 0.096666f, 0.110656f, 0.125588f, + 0.141461f, 0.158275f, 0.176031f, 0.194730f, 0.214374f, 0.234967f, 0.256512f, 0.279011f, + 0.302468f, 0.326887f, 0.352266f, 0.378605f, 0.405897f, 0.434130f, 0.463277f, 0.493295f, + 0.524106f, 0.555561f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000068f, 0.000613f, + 0.001874f, 0.003958f, 0.006921f, 0.010796f, 0.015599f, 0.021336f, 0.028011f, 0.035623f, + 0.044167f, 0.053640f, 0.064038f, 0.075355f, 0.087589f, 0.100736f, 0.114793f, 0.129759f, + 0.145632f, 0.162412f, 0.180101f, 0.198700f, 0.218213f, 0.238641f, 0.259989f, 0.282262f, + 0.305464f, 0.329599f, 0.354670f, 0.380678f, 0.407622f, 0.435493f, 0.464275f, 0.493938f, + 0.524422f, 0.555624f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000223f, 0.001054f, + 0.002649f, 0.005086f, 0.008406f, 0.012629f, 0.017766f, 0.023820f, 0.030789f, 0.038669f, + 0.047455f, 0.057143f, 0.067726f, 0.079199f, 0.091558f, 0.104798f, 0.118918f, 0.133915f, + 0.149788f, 0.166537f, 0.184164f, 0.202669f, 0.222056f, 0.242329f, 0.263492f, 0.285551f, + 0.308510f, 0.332376f, 0.357153f, 0.382845f, 0.409454f, 0.436977f, 0.465404f, 0.494713f, + 0.524864f, 0.555779f, 0.587302f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000037f, 0.000486f, 0.001621f, + 0.003553f, 0.006338f, 0.010004f, 0.014565f, 0.020024f, 0.026380f, 0.033629f, 0.041765f, + 0.050782f, 0.060673f, 0.071431f, 0.083052f, 0.095529f, 0.108859f, 0.123038f, 0.138065f, + 0.153938f, 0.170657f, 0.188224f, 0.206640f, 0.225909f, 0.246035f, 0.267022f, 0.288878f, + 0.311607f, 0.335216f, 0.359713f, 0.385103f, 0.411390f, 0.438576f, 0.466656f, 0.495617f, + 0.525431f, 0.556041f, 0.587338f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000149f, 0.000861f, 0.002312f, + 0.004581f, 0.007709f, 0.011713f, 0.016599f, 0.022367f, 0.029014f, 0.036531f, 0.044912f, + 0.054148f, 0.064233f, 0.075158f, 0.086918f, 0.099507f, 0.112922f, 0.127157f, 0.142212f, + 0.158085f, 0.174776f, 0.192287f, 0.210619f, 0.229775f, 0.249761f, 0.270582f, 0.292243f, + 0.314753f, 0.338118f, 0.362347f, 0.387447f, 0.413424f, 0.440284f, 0.468027f, 0.496645f, + 0.526122f, 0.556417f, 0.587451f, 0.619048f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000012f, 0.000355f, 0.001353f, 0.003126f, + 0.005730f, 0.009194f, 0.013526f, 0.018728f, 0.024795f, 0.031720f, 0.039494f, 0.048109f, + 0.057555f, 0.067824f, 0.078909f, 0.090802f, 0.103499f, 0.116993f, 0.131282f, 0.146364f, + 0.162237f, 0.178902f, 0.196358f, 0.214610f, 0.233660f, 0.253512f, 0.274174f, 0.295650f, + 0.317950f, 0.341081f, 0.365053f, 0.389874f, 0.415553f, 0.442098f, 0.469512f, 0.497794f, + 0.526935f, 0.556908f, 0.587657f, 0.619060f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000083f, 0.000665f, 0.001962f, 0.004059f, + 0.006997f, 0.010790f, 0.015442f, 0.020949f, 0.027304f, 0.034497f, 0.042518f, 0.051358f, + 0.061005f, 0.071451f, 0.082688f, 0.094709f, 0.107507f, 0.121078f, 0.135419f, 0.150526f, + 0.166399f, 0.183038f, 0.200443f, 0.218618f, 0.237566f, 0.257291f, 0.277800f, 0.299100f, + 0.321199f, 0.344106f, 0.367830f, 0.392383f, 0.417774f, 0.444013f, 0.471107f, 0.499060f, + 0.527869f, 0.557517f, 0.587966f, 0.619130f, 0.650794f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000001f, 0.000233f, 0.001082f, 0.002688f, 0.005111f, + 0.008377f, 0.012493f, 0.017456f, 0.023260f, 0.029893f, 0.037345f, 0.045604f, 0.054659f, + 0.064499f, 0.075115f, 0.086498f, 0.098641f, 0.111537f, 0.125182f, 0.139571f, 0.154703f, + 0.170576f, 0.187190f, 0.204547f, 0.222648f, 0.241498f, 0.261101f, 0.281465f, 0.302595f, + 0.324501f, 0.347192f, 0.370679f, 0.394973f, 0.420085f, 0.446027f, 0.472810f, 0.500441f, + 0.528921f, 0.558244f, 0.588384f, 0.619281f, 0.650795f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000033f, 0.000477f, 0.001611f, 0.003532f, 0.006280f, + 0.009869f, 0.014301f, 0.019568f, 0.025659f, 0.032563f, 0.040265f, 0.048753f, 0.058016f, + 0.068042f, 0.078821f, 0.090344f, 0.102604f, 0.115594f, 0.129309f, 0.143745f, 0.158901f, + 0.174774f, 0.191365f, 0.208674f, 0.226705f, 0.245461f, 0.264947f, 0.285170f, 0.306137f, + 0.327857f, 0.350341f, 0.373598f, 0.397642f, 0.422485f, 0.448139f, 0.474619f, 0.501933f, + 0.530089f, 0.559087f, 0.588913f, 0.619525f, 0.650826f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000130f, 0.000821f, 0.002252f, 0.004491f, 0.007562f, + 0.011472f, 0.016213f, 0.021776f, 0.028147f, 0.035312f, 0.043256f, 0.051966f, 0.061430f, + 0.071635f, 0.082571f, 0.094229f, 0.106602f, 0.119682f, 0.133465f, 0.147947f, 0.163125f, + 0.178998f, 0.195566f, 0.212830f, 0.230793f, 0.249459f, 0.268832f, 0.288920f, 0.309730f, + 0.331271f, 0.353554f, 0.376590f, 0.400391f, 0.424973f, 0.450347f, 0.476531f, 0.503535f, + 0.531372f, 0.560047f, 0.589554f, 0.619869f, 0.650923f, 0.682540f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000005f, 0.000309f, 0.001270f, 0.003008f, 0.005566f, 0.008959f, + 0.013183f, 0.018228f, 0.024080f, 0.030723f, 0.038142f, 0.046321f, 0.055246f, 0.064903f, + 0.075281f, 0.086369f, 0.098158f, 0.110639f, 0.123806f, 0.137655f, 0.152180f, 0.167380f, + 0.183253f, 0.199799f, 0.217020f, 0.234918f, 0.253496f, 0.272761f, 0.292719f, 0.313377f, + 0.334745f, 0.356833f, 0.379654f, 0.403221f, 0.427548f, 0.452651f, 0.478545f, 0.505246f, + 0.532768f, 0.561122f, 0.590309f, 0.620318f, 0.651102f, 0.682545f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000053f, 0.000579f, 0.001828f, 0.003878f, 0.006757f, 0.010468f, + 0.015002f, 0.020344f, 0.026479f, 0.033388f, 0.041054f, 0.049461f, 0.058594f, 0.068440f, + 0.078985f, 0.090220f, 0.102134f, 0.114721f, 0.127972f, 0.141884f, 0.156451f, 0.171672f, + 0.187545f, 0.204070f, 0.221249f, 0.239083f, 0.257578f, 0.276738f, 0.296569f, 0.317080f, + 0.338281f, 0.360181f, 0.382794f, 0.406133f, 0.430213f, 0.455050f, 0.480662f, 0.507065f, + 0.534278f, 0.562313f, 0.591180f, 0.620875f, 0.651373f, 0.682593f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000000f, 0.000169f, 0.000949f, 0.002497f, 0.004864f, 0.008063f, 0.012089f, + 0.016929f, 0.022563f, 0.028974f, 0.036142f, 0.044049f, 0.052678f, 0.062014f, 0.072042f, + 0.082750f, 0.094127f, 0.106164f, 0.118852f, 0.132185f, 0.146157f, 0.160766f, 0.176007f, + 0.191880f, 0.208385f, 0.225523f, 0.243296f, 0.261709f, 0.280767f, 0.300476f, 0.320845f, + 0.341883f, 0.363601f, 0.386011f, 0.409128f, 0.432967f, 0.457545f, 0.482881f, 0.508992f, + 0.535899f, 0.563619f, 0.592165f, 0.621544f, 0.651743f, 0.682709f, 0.714286f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000010f, 0.000368f, 0.001423f, 0.003279f, 0.005966f, 0.009485f, 0.013824f, + 0.018964f, 0.024886f, 0.031567f, 0.038988f, 0.047130f, 0.055975f, 0.065508f, 0.075714f, + 0.086580f, 0.098095f, 0.110251f, 0.123038f, 0.136450f, 0.150482f, 0.165129f, 0.180390f, + 0.196263f, 0.212748f, 0.229847f, 0.247561f, 0.265895f, 0.284854f, 0.304445f, 0.324675f, + 0.345555f, 0.367095f, 0.389309f, 0.412210f, 0.435814f, 0.460138f, 0.485203f, 0.511028f, + 0.537634f, 0.565041f, 0.593268f, 0.622327f, 0.652217f, 0.682907f, 0.714296f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000068f, 0.000658f, 0.002006f, 0.004178f, 0.007186f, 0.011024f, 0.015672f, + 0.021109f, 0.027312f, 0.034259f, 0.041928f, 0.050300f, 0.059356f, 0.069081f, 0.079460f, + 0.090480f, 0.102130f, 0.114400f, 0.127284f, 0.140772f, 0.154862f, 0.169548f, 0.184828f, + 0.200701f, 0.217167f, 0.234227f, 0.251884f, 0.270141f, 0.289004f, 0.308479f, 0.328575f, + 0.349301f, 0.370668f, 0.392689f, 0.415379f, 0.438754f, 0.462830f, 0.487630f, 0.513173f, + 0.539482f, 0.566579f, 0.594488f, 0.623226f, 0.652800f, 0.683198f, 0.714354f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000000f, 0.000196f, 0.001048f, 0.002702f, 0.005194f, 0.008526f, 0.012680f, 0.017635f, + 0.023365f, 0.029846f, 0.037053f, 0.044965f, 0.053561f, 0.062824f, 0.072737f, 0.083284f, + 0.094454f, 0.106236f, 0.118619f, 0.131595f, 0.145159f, 0.159305f, 0.174028f, 0.189327f, + 0.205200f, 0.221647f, 0.238670f, 0.256270f, 0.274453f, 0.293222f, 0.312585f, 0.332550f, + 0.353126f, 0.374324f, 0.396158f, 0.418641f, 0.441790f, 0.465624f, 0.490163f, 0.515429f, + 0.541445f, 0.568236f, 0.595828f, 0.624242f, 0.653496f, 0.683588f, 0.714482f, 0.746032f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000012f, 0.000407f, 0.001545f, 0.003514f, 0.006332f, 0.009987f, 0.014457f, 0.019715f, + 0.025734f, 0.032488f, 0.039952f, 0.048102f, 0.056919f, 0.066384f, 0.076480f, 0.087193f, + 0.098509f, 0.110419f, 0.122912f, 0.135980f, 0.149617f, 0.163817f, 0.178577f, 0.193894f, + 0.209767f, 0.226196f, 0.243182f, 0.260728f, 0.278837f, 0.297515f, 0.316768f, 0.336605f, + 0.357034f, 0.378067f, 0.399717f, 0.421998f, 0.444928f, 0.468523f, 0.492806f, 0.517798f, + 0.543525f, 0.570012f, 0.597288f, 0.625379f, 0.654307f, 0.684084f, 0.714693f, 0.746044f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000074f, 0.000713f, 0.002152f, 0.004446f, 0.007592f, 0.011571f, 0.016356f, 0.021915f, + 0.028220f, 0.035243f, 0.042959f, 0.051344f, 0.060377f, 0.070040f, 0.080316f, 0.091191f, + 0.102651f, 0.114686f, 0.127286f, 0.140443f, 0.154151f, 0.168405f, 0.183201f, 0.198536f, + 0.214409f, 0.230820f, 0.247770f, 0.265263f, 0.283301f, 0.301889f, 0.321035f, 0.340746f, + 0.361032f, 0.381904f, 0.403374f, 0.425457f, 0.448169f, 0.471530f, 0.495561f, 0.520284f, + 0.545725f, 0.571911f, 0.598873f, 0.626640f, 0.655239f, 0.684692f, 0.714999f, 0.746106f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, + 0.000208f, 0.001121f, 0.002877f, 0.005501f, 0.008979f, 0.013283f, 0.018380f, 0.024238f, + 0.030826f, 0.038115f, 0.046079f, 0.054695f, 0.063941f, 0.073799f, 0.084252f, 0.095285f, + 0.106886f, 0.119044f, 0.131749f, 0.144994f, 0.158772f, 0.173078f, 0.187908f, 0.203261f, + 0.219134f, 0.235527f, 0.252443f, 0.269883f, 0.287851f, 0.306352f, 0.325393f, 0.344981f, + 0.365126f, 0.385839f, 0.407132f, 0.429020f, 0.451520f, 0.474651f, 0.498433f, 0.522890f, + 0.548048f, 0.573936f, 0.600584f, 0.628027f, 0.656295f, 0.685417f, 0.715406f, 0.746240f, + 0.777778f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000011f, + 0.000427f, 0.001638f, 0.003724f, 0.006685f, 0.010497f, 0.015125f, 0.020534f, 0.026688f, + 0.033557f, 0.041109f, 0.049318f, 0.058161f, 0.067617f, 0.077666f, 0.088293f, 0.099482f, + 0.111221f, 0.123499f, 0.136308f, 0.149639f, 0.163485f, 0.177843f, 0.192707f, 0.208077f, + 0.223950f, 0.240326f, 0.257208f, 0.274596f, 0.292496f, 0.310911f, 0.329849f, 0.349316f, + 0.369323f, 0.389880f, 0.410999f, 0.432696f, 0.454987f, 0.477890f, 0.501426f, 0.525620f, + 0.550498f, 0.576089f, 0.602427f, 0.629544f, 0.657479f, 0.686264f, 0.715924f, 0.746459f, + 0.777789f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000071f, + 0.000744f, 0.002274f, 0.004698f, 0.008002f, 0.012149f, 0.017102f, 0.022822f, 0.029271f, + 0.036417f, 0.044229f, 0.052681f, 0.061749f, 0.071411f, 0.081649f, 0.092447f, 0.103790f, + 0.115665f, 0.128062f, 0.140972f, 0.154387f, 0.168301f, 0.182709f, 0.197608f, 0.212994f, + 0.228867f, 0.245227f, 0.262074f, 0.279412f, 0.297244f, 0.315575f, 0.334412f, 0.353760f, + 0.373631f, 0.394034f, 0.414983f, 0.436491f, 0.458575f, 0.481253f, 0.504547f, 0.528481f, + 0.553081f, 0.578377f, 0.604404f, 0.631197f, 0.658795f, 0.687238f, 0.716559f, 0.746776f, + 0.777849f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000205f, + 0.001168f, 0.003033f, 0.005806f, 0.009456f, 0.013942f, 0.019220f, 0.025250f, 0.031992f, + 0.039414f, 0.047484f, 0.056176f, 0.065466f, 0.075333f, 0.085757f, 0.096724f, 0.108218f, + 0.120227f, 0.132741f, 0.145751f, 0.159249f, 0.173230f, 0.187687f, 0.202619f, 0.218021f, + 0.233894f, 0.250238f, 0.267052f, 0.284341f, 0.302106f, 0.320354f, 0.339090f, 0.358322f, + 0.378059f, 0.398311f, 0.419090f, 0.440412f, 0.462292f, 0.484748f, 0.507802f, 0.531477f, + 0.555802f, 0.580805f, 0.606522f, 0.632990f, 0.660250f, 0.688346f, 0.717319f, 0.747200f, + 0.777982f, 0.809524f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000007f, 0.000427f, + 0.001710f, 0.003925f, 0.007054f, 0.011055f, 0.015881f, 0.021485f, 0.027824f, 0.034859f, + 0.042554f, 0.050881f, 0.059811f, 0.069321f, 0.079390f, 0.089998f, 0.101132f, 0.112775f, + 0.124917f, 0.137547f, 0.150655f, 0.164236f, 0.178281f, 0.192788f, 0.207752f, 0.223171f, + 0.239044f, 0.255371f, 0.272153f, 0.289393f, 0.307093f, 0.325259f, 0.343896f, 0.363012f, + 0.382617f, 0.402719f, 0.423332f, 0.444469f, 0.466146f, 0.488383f, 0.511199f, 0.534618f, + 0.558668f, 0.583380f, 0.608787f, 0.634929f, 0.661849f, 0.689594f, 0.718211f, 0.747742f, + 0.778205f, 0.809530f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000059f, 0.000754f, + 0.002379f, 0.004956f, 0.008449f, 0.012806f, 0.017974f, 0.023905f, 0.030553f, 0.037879f, + 0.045847f, 0.054429f, 0.063595f, 0.073323f, 0.083592f, 0.094384f, 0.105682f, 0.117474f, + 0.129747f, 0.142491f, 0.155697f, 0.169358f, 0.183469f, 0.198024f, 0.213020f, 0.228455f, + 0.244329f, 0.260639f, 0.277389f, 0.294580f, 0.312216f, 0.330300f, 0.348840f, 0.367842f, + 0.387315f, 0.407270f, 0.427717f, 0.448671f, 0.470149f, 0.492167f, 0.514746f, 0.537911f, + 0.561688f, 0.586108f, 0.611206f, 0.637022f, 0.663599f, 0.690989f, 0.719242f, 0.748411f, + 0.778531f, 0.809583f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000187f, 0.001196f, + 0.003184f, 0.006136f, 0.010000f, 0.014716f, 0.020230f, 0.026488f, 0.033445f, 0.041062f, + 0.049303f, 0.058138f, 0.067540f, 0.077485f, 0.087953f, 0.098926f, 0.110388f, 0.122327f, + 0.134729f, 0.147587f, 0.160889f, 0.174631f, 0.188806f, 0.203409f, 0.218437f, 0.233888f, + 0.249761f, 0.266056f, 0.282774f, 0.299917f, 0.317488f, 0.335493f, 0.353936f, 0.372825f, + 0.392168f, 0.411976f, 0.432259f, 0.453032f, 0.474310f, 0.496111f, 0.518456f, 0.541367f, + 0.564872f, 0.589001f, 0.613789f, 0.639277f, 0.665510f, 0.692539f, 0.720422f, 0.749216f, + 0.778974f, 0.809711f, 0.841270f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000002f, 0.000409f, 0.001767f, + 0.004137f, 0.007474f, 0.011716f, 0.016797f, 0.022657f, 0.029244f, 0.036512f, 0.044420f, + 0.052933f, 0.062021f, 0.071657f, 0.081819f, 0.092485f, 0.103638f, 0.115263f, 0.127348f, + 0.139880f, 0.152849f, 0.166248f, 0.180070f, 0.194308f, 0.208958f, 0.224018f, 0.239485f, + 0.255359f, 0.271638f, 0.288324f, 0.305419f, 0.322927f, 0.340851f, 0.359199f, 0.377975f, + 0.397189f, 0.416851f, 0.436971f, 0.457564f, 0.478644f, 0.500229f, 0.522339f, 0.544997f, + 0.568230f, 0.592068f, 0.616546f, 0.641705f, 0.667590f, 0.694255f, 0.721760f, 0.750168f, + 0.779545f, 0.809933f, 0.841272f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000041f, 0.000744f, 0.002481f, + 0.005248f, 0.008982f, 0.013608f, 0.019058f, 0.025269f, 0.032188f, 0.039767f, 0.047967f, + 0.056752f, 0.066093f, 0.075963f, 0.086340f, 0.097203f, 0.108537f, 0.120325f, 0.132554f, + 0.145215f, 0.158296f, 0.171790f, 0.185691f, 0.199993f, 0.214691f, 0.229782f, 0.245265f, + 0.261138f, 0.277401f, 0.294056f, 0.311104f, 0.328548f, 0.346394f, 0.364645f, 0.383310f, + 0.402396f, 0.421912f, 0.441870f, 0.462283f, 0.483165f, 0.504535f, 0.526410f, 0.548816f, + 0.571776f, 0.595323f, 0.619489f, 0.644317f, 0.669852f, 0.696148f, 0.723267f, 0.751280f, + 0.780258f, 0.810268f, 0.841311f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000156f, 0.001209f, 0.003349f, + 0.006531f, 0.010672f, 0.015691f, 0.021515f, 0.028080f, 0.035332f, 0.043225f, 0.051717f, + 0.060775f, 0.070370f, 0.080474f, 0.091067f, 0.102128f, 0.113641f, 0.125591f, 0.137965f, + 0.150754f, 0.163947f, 0.177537f, 0.191516f, 0.205881f, 0.220626f, 0.235749f, 0.251248f, + 0.267121f, 0.283368f, 0.299992f, 0.316992f, 0.334374f, 0.352140f, 0.370296f, 0.388849f, + 0.407807f, 0.427178f, 0.446974f, 0.467207f, 0.487892f, 0.509046f, 0.530687f, 0.552839f, + 0.575527f, 0.598780f, 0.622634f, 0.647128f, 0.672308f, 0.698231f, 0.724958f, 0.752563f, + 0.781127f, 0.810733f, 0.841426f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000374f, 0.001821f, 0.004389f, + 0.008001f, 0.012559f, 0.017979f, 0.024182f, 0.031106f, 0.038695f, 0.046903f, 0.055690f, + 0.065023f, 0.074872f, 0.085211f, 0.096020f, 0.107279f, 0.118971f, 0.131084f, 0.143604f, + 0.156521f, 0.169825f, 0.183510f, 0.197569f, 0.211997f, 0.226789f, 0.241944f, 0.257458f, + 0.273331f, 0.289563f, 0.306154f, 0.323108f, 0.340426f, 0.358113f, 0.376175f, 0.394616f, + 0.413445f, 0.432671f, 0.452305f, 0.472358f, 0.492845f, 0.513783f, 0.535189f, 0.557087f, + 0.579500f, 0.602459f, 0.625997f, 0.650154f, 0.674976f, 0.700518f, 0.726845f, 0.754032f, + 0.782167f, 0.811344f, 0.841644f, 0.873016f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000020f, 0.000719f, 0.002598f, 0.005618f, + 0.009675f, 0.014663f, 0.020490f, 0.027080f, 0.034367f, 0.042297f, 0.050824f, 0.059909f, + 0.069517f, 0.079622f, 0.090198f, 0.101224f, 0.112682f, 0.124555f, 0.136831f, 0.149496f, + 0.162542f, 0.175958f, 0.189739f, 0.203877f, 0.218368f, 0.233208f, 0.248393f, 0.263923f, + 0.279796f, 0.296012f, 0.312573f, 0.329479f, 0.346734f, 0.364342f, 0.382307f, 0.400637f, + 0.419337f, 0.438418f, 0.457889f, 0.477761f, 0.498050f, 0.518770f, 0.539940f, 0.561581f, + 0.583718f, 0.606380f, 0.629599f, 0.653415f, 0.677874f, 0.703030f, 0.728948f, 0.755706f, + 0.783396f, 0.812121f, 0.841989f, 0.873035f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000114f, 0.001215f, 0.003561f, 0.007056f, + 0.011574f, 0.017003f, 0.023248f, 0.030232f, 0.037888f, 0.046164f, 0.055014f, 0.064399f, + 0.074287f, 0.084650f, 0.095464f, 0.106709f, 0.118367f, 0.130423f, 0.142862f, 0.155674f, + 0.168849f, 0.182378f, 0.196255f, 0.210473f, 0.225027f, 0.239915f, 0.255132f, 0.270678f, + 0.286551f, 0.302751f, 0.319280f, 0.336138f, 0.353330f, 0.370858f, 0.388728f, 0.406944f, + 0.425515f, 0.444449f, 0.463756f, 0.483447f, 0.503535f, 0.524036f, 0.544968f, 0.566350f, + 0.588208f, 0.610569f, 0.633466f, 0.656936f, 0.681025f, 0.705788f, 0.731289f, 0.757606f, + 0.784834f, 0.813085f, 0.842485f, 0.873130f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000000f, 0.000324f, 0.001887f, 0.004735f, 0.008727f, + 0.013724f, 0.019607f, 0.026280f, 0.033666f, 0.041699f, 0.050326f, 0.059504f, 0.069194f, + 0.079365f, 0.089989f, 0.101045f, 0.112512f, 0.124372f, 0.136611f, 0.149216f, 0.162176f, + 0.175482f, 0.189125f, 0.203098f, 0.217396f, 0.232015f, 0.246950f, 0.262200f, 0.277761f, + 0.293634f, 0.309819f, 0.326315f, 0.343126f, 0.360254f, 0.377701f, 0.395474f, 0.413577f, + 0.432018f, 0.450804f, 0.469944f, 0.489451f, 0.509337f, 0.529617f, 0.550307f, 0.571428f, + 0.593003f, 0.615059f, 0.637628f, 0.660746f, 0.684460f, 0.708820f, 0.733893f, 0.759756f, + 0.786505f, 0.814259f, 0.843157f, 0.873340f, 0.904762f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000003f, 0.000683f, 0.002764f, 0.006148f, 0.010661f, + 0.016155f, 0.022506f, 0.029620f, 0.037417f, 0.045835f, 0.054821f, 0.064333f, 0.074333f, + 0.084792f, 0.095683f, 0.106984f, 0.118675f, 0.130741f, 0.143166f, 0.155939f, 0.169049f, + 0.182487f, 0.196245f, 0.210317f, 0.224697f, 0.239380f, 0.254364f, 0.269646f, 0.285223f, + 0.301096f, 0.317265f, 0.333729f, 0.350491f, 0.367554f, 0.384920f, 0.402594f, 0.420582f, + 0.438891f, 0.457527f, 0.476499f, 0.495820f, 0.515500f, 0.535555f, 0.556000f, 0.576855f, + 0.598143f, 0.619888f, 0.642123f, 0.664883f, 0.688211f, 0.712160f, 0.736792f, 0.762186f, + 0.788439f, 0.815672f, 0.844034f, 0.873699f, 0.904765f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000066f, 0.001228f, 0.003880f, 0.007835f, 0.012895f, + 0.018905f, 0.025742f, 0.033309f, 0.041530f, 0.050342f, 0.059696f, 0.069550f, 0.079868f, + 0.090620f, 0.101783f, 0.113333f, 0.125254f, 0.137529f, 0.150144f, 0.163088f, 0.176351f, + 0.189924f, 0.203799f, 0.217970f, 0.232433f, 0.247182f, 0.262216f, 0.277530f, 0.293124f, + 0.308997f, 0.325149f, 0.341581f, 0.358294f, 0.375290f, 0.392573f, 0.410148f, 0.428019f, + 0.446192f, 0.464676f, 0.483478f, 0.502608f, 0.522079f, 0.541905f, 0.562100f, 0.582684f, + 0.603677f, 0.625106f, 0.646998f, 0.669390f, 0.692324f, 0.715849f, 0.740028f, 0.764937f, + 0.790673f, 0.817358f, 0.845150f, 0.874244f, 0.904828f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000260f, 0.002001f, 0.005278f, 0.009840f, 0.015475f, + 0.022025f, 0.029365f, 0.037402f, 0.046060f, 0.055280f, 0.065013f, 0.075218f, 0.085861f, + 0.096916f, 0.108356f, 0.120163f, 0.132319f, 0.144808f, 0.157618f, 0.170737f, 0.184155f, + 0.197866f, 0.211861f, 0.226134f, 0.240682f, 0.255499f, 0.270583f, 0.285931f, 0.301542f, + 0.317415f, 0.333550f, 0.349948f, 0.366610f, 0.383539f, 0.400738f, 0.418210f, 0.435961f, + 0.453997f, 0.472324f, 0.490951f, 0.509887f, 0.529144f, 0.548735f, 0.568674f, 0.588979f, + 0.609671f, 0.630773f, 0.652314f, 0.674328f, 0.696854f, 0.719942f, 0.743651f, 0.768057f, + 0.793253f, 0.819363f, 0.846547f, 0.875017f, 0.905021f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000000f, 0.000642f, 0.003053f, 0.007010f, 0.012219f, 0.018462f, + 0.025577f, 0.033444f, 0.041970f, 0.051082f, 0.060724f, 0.070849f, 0.081417f, 0.092397f, + 0.103763f, 0.115491f, 0.127562f, 0.139960f, 0.152670f, 0.165679f, 0.178979f, 0.192558f, + 0.206410f, 0.220529f, 0.234907f, 0.249542f, 0.264428f, 0.279564f, 0.294947f, 0.310575f, + 0.326448f, 0.342566f, 0.358929f, 0.375540f, 0.392399f, 0.409511f, 0.426878f, 0.444506f, + 0.462400f, 0.480566f, 0.499013f, 0.517749f, 0.536785f, 0.556134f, 0.575809f, 0.595827f, + 0.616207f, 0.636973f, 0.658150f, 0.679772f, 0.701876f, 0.724509f, 0.747730f, 0.771609f, + 0.796240f, 0.821743f, 0.848280f, 0.876069f, 0.905404f, 0.936508f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000020f, 0.001278f, 0.004450f, 0.009147f, 0.015050f, 0.021937f, + 0.029649f, 0.038068f, 0.047106f, 0.056694f, 0.066777f, 0.077310f, 0.088257f, 0.099588f, + 0.111277f, 0.123304f, 0.135650f, 0.148299f, 0.161237f, 0.174455f, 0.187941f, 0.201687f, + 0.215687f, 0.229933f, 0.244420f, 0.259145f, 0.274103f, 0.289293f, 0.304711f, 0.320357f, + 0.336230f, 0.352330f, 0.368658f, 0.385214f, 0.402002f, 0.419023f, 0.436282f, 0.453782f, + 0.471529f, 0.489528f, 0.507788f, 0.526317f, 0.545124f, 0.564221f, 0.583621f, 0.603341f, + 0.623397f, 0.643812f, 0.664611f, 0.685824f, 0.707488f, 0.729646f, 0.752354f, 0.775680f, + 0.799715f, 0.824574f, 0.850417f, 0.877466f, 0.906040f, 0.936528f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000183f, 0.002253f, 0.006282f, 0.011786f, 0.018436f, 0.026011f, + 0.034358f, 0.043364f, 0.052944f, 0.063033f, 0.073580f, 0.084544f, 0.095889f, 0.107588f, + 0.119617f, 0.131957f, 0.144591f, 0.157503f, 0.170682f, 0.184117f, 0.197799f, 0.211720f, + 0.225873f, 0.240253f, 0.254854f, 0.269673f, 0.284707f, 0.299953f, 0.315408f, 0.331073f, + 0.346946f, 0.363028f, 0.379318f, 0.395818f, 0.412530f, 0.429457f, 0.446602f, 0.463968f, + 0.481561f, 0.499386f, 0.517450f, 0.535761f, 0.554328f, 0.573162f, 0.592275f, 0.611681f, + 0.631398f, 0.651445f, 0.671845f, 0.692628f, 0.713827f, 0.735484f, 0.757650f, 0.780390f, + 0.803789f, 0.827960f, 0.853056f, 0.879298f, 0.907014f, 0.936691f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.000617f, 0.003679f, 0.008674f, 0.015068f, 0.022531f, 0.030851f, + 0.039880f, 0.049515f, 0.059675f, 0.070300f, 0.081343f, 0.092764f, 0.104533f, 0.116624f, + 0.129015f, 0.141687f, 0.154626f, 0.167818f, 0.181252f, 0.194918f, 0.208807f, 0.222913f, + 0.237229f, 0.251750f, 0.266473f, 0.281392f, 0.296505f, 0.311811f, 0.327306f, 0.342991f, + 0.358864f, 0.374925f, 0.391176f, 0.407616f, 0.424249f, 0.441076f, 0.458100f, 0.475324f, + 0.492754f, 0.510394f, 0.528251f, 0.546331f, 0.564644f, 0.583198f, 0.602005f, 0.621078f, + 0.640434f, 0.660089f, 0.680066f, 0.700390f, 0.721094f, 0.742215f, 0.763800f, 0.785912f, + 0.808628f, 0.832055f, 0.856338f, 0.881690f, 0.908441f, 0.937125f, 0.968254f, 1.000000f, + 0.000000f, 0.000000f, 0.001477f, 0.005732f, 0.011826f, 0.019212f, 0.027573f, 0.036710f, + 0.046487f, 0.056807f, 0.067598f, 0.078806f, 0.090386f, 0.102304f, 0.114532f, 0.127047f, + 0.139828f, 0.152861f, 0.166130f, 0.179624f, 0.193332f, 0.207247f, 0.221360f, 0.235666f, + 0.250158f, 0.264832f, 0.279684f, 0.294711f, 0.309911f, 0.325280f, 0.340819f, 0.356524f, + 0.372397f, 0.388438f, 0.404645f, 0.421022f, 0.437569f, 0.454287f, 0.471181f, 0.488253f, + 0.505507f, 0.522947f, 0.540580f, 0.558412f, 0.576449f, 0.594701f, 0.613178f, 0.631892f, + 0.650856f, 0.670088f, 0.689606f, 0.709434f, 0.729600f, 0.750138f, 0.771093f, 0.792519f, + 0.814488f, 0.837097f, 0.860481f, 0.884842f, 0.910494f, 0.937985f, 0.968254f, 1.000000f, + 0.000000f, 0.000096f, 0.003012f, 0.008704f, 0.016071f, 0.024590f, 0.033968f, 0.044025f, + 0.054641f, 0.065728f, 0.077225f, 0.089081f, 0.101260f, 0.113731f, 0.126469f, 0.139454f, + 0.152670f, 0.166101f, 0.179736f, 0.193565f, 0.207578f, 0.221769f, 0.236130f, 0.250656f, + 0.265343f, 0.280187f, 0.295183f, 0.310330f, 0.325624f, 0.341065f, 0.356650f, 0.372380f, + 0.388253f, 0.404269f, 0.420430f, 0.436735f, 0.453187f, 0.469786f, 0.486536f, 0.503439f, + 0.520498f, 0.537717f, 0.555102f, 0.572657f, 0.590390f, 0.608307f, 0.626419f, 0.644733f, + 0.663264f, 0.682025f, 0.701032f, 0.720308f, 0.739875f, 0.759764f, 0.780014f, 0.800673f, + 0.821803f, 0.843492f, 0.865860f, 0.889087f, 0.913466f, 0.939520f, 0.968350f, 1.000000f, + 0.000000f, 0.000727f, 0.005696f, 0.013170f, 0.022074f, 0.031940f, 0.042520f, 0.053660f, + 0.065258f, 0.077243f, 0.089562f, 0.102175f, 0.115050f, 0.128164f, 0.141495f, 0.155026f, + 0.168745f, 0.182639f, 0.196699f, 0.210915f, 0.225282f, 0.239792f, 0.254440f, 0.269223f, + 0.284135f, 0.299174f, 0.314337f, 0.329622f, 0.345026f, 0.360549f, 0.376189f, 0.391946f, + 0.407819f, 0.423808f, 0.439914f, 0.456137f, 0.472479f, 0.488940f, 0.505523f, 0.522230f, + 0.539064f, 0.556028f, 0.573125f, 0.590361f, 0.607741f, 0.625270f, 0.642957f, 0.660809f, + 0.678836f, 0.697050f, 0.715465f, 0.734098f, 0.752968f, 0.772101f, 0.791529f, 0.811290f, + 0.831438f, 0.852044f, 0.873210f, 0.895090f, 0.917932f, 0.942204f, 0.968981f, 1.000000f, + 0.000000f, 0.002796f, 0.010764f, 0.020645f, 0.031576f, 0.043202f, 0.055340f, 0.067877f, + 0.080740f, 0.093877f, 0.107250f, 0.120832f, 0.134598f, 0.148533f, 0.162620f, 0.176849f, + 0.191210f, 0.205694f, 0.220294f, 0.235005f, 0.249820f, 0.264737f, 0.279751f, 0.294859f, + 0.310058f, 0.325346f, 0.340721f, 0.356181f, 0.371725f, 0.387353f, 0.403063f, 0.418854f, + 0.434727f, 0.450682f, 0.466718f, 0.482837f, 0.499038f, 0.515324f, 0.531695f, 0.548153f, + 0.564700f, 0.581338f, 0.598070f, 0.614900f, 0.631830f, 0.648865f, 0.666011f, 0.683273f, + 0.700659f, 0.718176f, 0.735834f, 0.753646f, 0.771625f, 0.789790f, 0.808162f, 0.826771f, + 0.845654f, 0.864863f, 0.884472f, 0.904592f, 0.925407f, 0.947271f, 0.971050f, 1.000000f, + 0.000000f, 0.015873f, 0.031746f, 0.047619f, 0.063492f, 0.079365f, 0.095238f, 0.111111f, + 0.126984f, 0.142857f, 0.158730f, 0.174603f, 0.190476f, 0.206349f, 0.222222f, 0.238095f, + 0.253968f, 0.269841f, 0.285714f, 0.301587f, 0.317460f, 0.333333f, 0.349206f, 0.365079f, + 0.380952f, 0.396825f, 0.412698f, 0.428571f, 0.444444f, 0.460317f, 0.476190f, 0.492063f, + 0.507937f, 0.523810f, 0.539683f, 0.555556f, 0.571429f, 0.587302f, 0.603175f, 0.619048f, + 0.634921f, 0.650794f, 0.666667f, 0.682540f, 0.698413f, 0.714286f, 0.730159f, 0.746032f, + 0.761905f, 0.777778f, 0.793651f, 0.809524f, 0.825397f, 0.841270f, 0.857143f, 0.873016f, + 0.888889f, 0.904762f, 0.920635f, 0.936508f, 0.952381f, 0.968254f, 0.984127f, 1.000000f +}; + static float btdf_split_sum_ggx[32][64 * 64] = { { 0.000000f, 1.000000f, 0.999512f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 1.000000f, 0.999512f, 1.000000f, diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index c25ab1e7859..84627e03137 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -28,6 +28,8 @@ #include "BLI_dynstr.h" #include "BLI_ghash.h" #include "BLI_alloca.h" +#include "BLI_rand.h" +#include "BLI_string_utils.h" #include "BKE_particle.h" #include "BKE_paint.h" @@ -51,16 +53,18 @@ static struct { struct GPUShader *default_prepass_sh; struct GPUShader *default_prepass_clip_sh; struct GPUShader *default_lit[VAR_MAT_MAX]; - struct GPUShader *default_background; + struct GPUShader *update_noise_sh; /* 64*64 array texture containing all LUTs and other utilitarian arrays. * Packing enables us to same precious textures slots. */ struct GPUTexture *util_tex; + struct GPUTexture *noise_tex; unsigned int sss_count; - float viewvecs[2][4]; + float alpha_hash_offset; + float noise_offsets[3]; } e_data = {NULL}; /* Engine data */ extern char datatoc_lamps_lib_glsl[]; @@ -76,6 +80,7 @@ extern char datatoc_btdf_lut_frag_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; extern char datatoc_bsdf_direct_lib_glsl[]; extern char datatoc_bsdf_sampling_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_lit_surface_frag_glsl[]; @@ -87,6 +92,7 @@ extern char datatoc_shadow_geom_glsl[]; extern char datatoc_lightprobe_geom_glsl[]; extern char datatoc_lightprobe_vert_glsl[]; extern char datatoc_background_vert_glsl[]; +extern char datatoc_update_noise_frag_glsl[]; extern char datatoc_volumetric_vert_glsl[]; extern char datatoc_volumetric_geom_glsl[]; extern char datatoc_volumetric_frag_glsl[]; @@ -105,13 +111,9 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h)) static float samples_ct = 8192.0f; static float inv_samples_ct = 1.0f / 8192.0f; - char *lib_str = NULL; - - DynStr *ds_vert = BLI_dynstr_new(); - BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl); - lib_str = BLI_dynstr_get_cstring(ds_vert); - BLI_dynstr_free(ds_vert); + char *lib_str = BLI_string_joinN( + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl); struct GPUShader *sh = DRW_shader_create_with_lib( datatoc_lightprobe_vert_glsl, datatoc_lightprobe_geom_glsl, datatoc_bsdf_lut_frag_glsl, lib_str, @@ -167,14 +169,10 @@ static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h) static float a2 = 0.0f; static float inv_samples_ct = 1.0f / 8192.0f; - char *frag_str = NULL; - - DynStr *ds_vert = BLI_dynstr_new(); - BLI_dynstr_append(ds_vert, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_vert, datatoc_bsdf_sampling_lib_glsl); - BLI_dynstr_append(ds_vert, datatoc_btdf_lut_frag_glsl); - frag_str = BLI_dynstr_get_cstring(ds_vert); - BLI_dynstr_free(ds_vert); + char *frag_str = BLI_string_joinN( + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_btdf_lut_frag_glsl); struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str, "#define HAMMERSLEY_SIZE 8192\n" @@ -352,77 +350,67 @@ static char *eevee_get_volume_defines(int options) **/ static void add_standard_uniforms( DRWShadingGroup *shgrp, EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, - int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend, bool use_sss) + int *ssr_id, float *refract_depth, bool use_ssrefraction, bool use_alpha_blend) { - if (ssr_id == NULL || !vedata->stl->g_data->valid_double_buffer) { + if (ssr_id == NULL) { static int no_ssr = -1.0f; ssr_id = &no_ssr; } + DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo); DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_int(shgrp, "light_count", &sldata->lamps->num_light, 1); - DRW_shgroup_uniform_int(shgrp, "probe_count", &sldata->probes->num_render_cube, 1); - DRW_shgroup_uniform_int(shgrp, "grid_count", &sldata->probes->num_render_grid, 1); - DRW_shgroup_uniform_int(shgrp, "planar_count", &sldata->probes->num_planar, 1); - DRW_shgroup_uniform_bool(shgrp, "specToggle", &sldata->probes->specular_toggle, 1); - DRW_shgroup_uniform_bool(shgrp, "ssrToggle", &sldata->probes->ssr_toggle, 1); - DRW_shgroup_uniform_float(shgrp, "lodCubeMax", &sldata->probes->lod_cube_max, 1); - DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); - DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool); - DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool); - DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool); - DRW_shgroup_uniform_int(shgrp, "irradianceVisibilitySize", &sldata->probes->irradiance_vis_size, 1); - DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool); - DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1); - DRW_shgroup_uniform_vec4(shgrp, "aoParameters[0]", &vedata->stl->effects->ao_dist, 2); - DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer); - DRW_shgroup_uniform_vec2(shgrp, "mipRatio[0]", (float *)vedata->stl->g_data->mip_ratio, 10); - DRW_shgroup_uniform_vec4(shgrp, "ssrParameters", &vedata->stl->effects->ssr_quality, 1); - - if (refract_depth != NULL) { - DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1); + DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo); + + /* TODO if glossy or diffuse bsdf */ + if (true) { + DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); + DRW_shgroup_uniform_buffer(shgrp, "shadowTexture", &sldata->shadow_pool); + DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer); + + if ((vedata->stl->effects->enabled_effects & EFFECT_GTAO) != 0) { + DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons); + } + else { + /* Use maxzbuffer as fallback to avoid sampling problem on certain platform, see: T52593 */ + DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->maxzbuffer); + } } - if (use_ssrefraction) { - DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color); - DRW_shgroup_uniform_float(shgrp, "borderFadeFactor", &vedata->stl->effects->ssr_border_fac, 1); - DRW_shgroup_uniform_float(shgrp, "maxRoughness", &vedata->stl->effects->ssr_max_roughness, 1); - DRW_shgroup_uniform_int(shgrp, "rayCount", &vedata->stl->effects->ssr_ray_count, 1); + /* TODO if diffuse bsdf */ + if (true) { + DRW_shgroup_uniform_buffer(shgrp, "irradianceGrid", &sldata->irradiance_pool); } - if (vedata->stl->effects->use_ao) { - DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &vedata->txl->gtao_horizons); - DRW_shgroup_uniform_ivec2(shgrp, "aoHorizonTexSize", (int *)vedata->stl->effects->ao_texsize, 1); + /* TODO if glossy bsdf */ + if (true) { + DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_buffer(shgrp, "probePlanars", &vedata->txl->planar_pool); + DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1); } - else { - /* Use shadow_pool as fallback to avoid sampling problem on certain platform, see: T52593 */ - DRW_shgroup_uniform_buffer(shgrp, "horizonBuffer", &sldata->shadow_pool); + + if (use_ssrefraction) { + BLI_assert(refract_depth != NULL); + DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1); + DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color); } - if (vedata->stl->effects->use_volumetrics && use_alpha_blend) { + if ((vedata->stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0 && + use_alpha_blend) + { /* Do not use history buffers as they already have been swapped */ DRW_shgroup_uniform_buffer(shgrp, "inScattering", &vedata->txl->volume_scatter); DRW_shgroup_uniform_buffer(shgrp, "inTransmittance", &vedata->txl->volume_transmittance); - DRW_shgroup_uniform_vec2(shgrp, "volume_uv_ratio", (float *)sldata->volumetrics->volume_coord_scale, 1); - DRW_shgroup_uniform_vec3(shgrp, "volume_param", (float *)sldata->volumetrics->depth_param, 1); - } - - if (use_sss) { - DRW_shgroup_uniform_bool(shgrp, "sssToggle", &sldata->probes->sss_toggle, 1); } } static void create_default_shader(int options) { - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, e_data.frag_shader_lib); - BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl); - char *frag_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + char *frag_str = BLI_string_joinN( + e_data.frag_shader_lib, + datatoc_default_frag_glsl); char *defines = eevee_get_defines(options); @@ -432,11 +420,13 @@ static void create_default_shader(int options) MEM_freeN(frag_str); } -void EEVEE_update_util_texture(float offset) +static void eevee_init_noise_texture(void) { + e_data.noise_tex = DRW_texture_create_2D(64, 64, DRW_TEX_RGBA_16, 0, (float *)blue_noise); +} - /* TODO: split this into 2 functions : one for init, - * and the other one that updates the noise with the offset. */ +static void eevee_init_util_texture(void) +{ const int layers = 3 + 16; float (*texels)[4] = MEM_mallocN(sizeof(float[4]) * 64 * 64 * layers, "utils texels"); float (*texels_layer)[4] = texels; @@ -451,19 +441,16 @@ void EEVEE_update_util_texture(float offset) texels_layer[i][0] = bsdf_split_sum_ggx[i * 2 + 0]; texels_layer[i][1] = bsdf_split_sum_ggx[i * 2 + 1]; texels_layer[i][2] = ltc_mag_ggx[i]; + texels_layer[i][3] = ltc_disk_integral[i]; } texels_layer += 64 * 64; /* Copy blue noise in 3rd layer */ for (int i = 0; i < 64 * 64; i++) { - float noise; - noise = fmod(blue_noise[i][0] + offset, 1.0f); - texels_layer[i][0] = noise; - - noise = fmod(blue_noise[i][1] + offset, 1.0f); - texels_layer[i][1] = noise * 0.5f + 0.5f; - texels_layer[i][2] = cosf(noise * 2.0f * M_PI); - texels_layer[i][3] = sinf(noise * 2.0f * M_PI); + texels_layer[i][0] = blue_noise[i][0]; + texels_layer[i][1] = blue_noise[i][1]; + texels_layer[i][2] = cosf(blue_noise[i][1] * 2.0f * M_PI); + texels_layer[i][3] = sinf(blue_noise[i][1] * 2.0f * M_PI); } texels_layer += 64 * 64; @@ -478,62 +465,72 @@ void EEVEE_update_util_texture(float offset) texels_layer += 64 * 64; } - if (e_data.util_tex == NULL) { - e_data.util_tex = DRW_texture_create_2D_array( - 64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels); - } - else { - DRW_texture_update(e_data.util_tex, (float *)texels); - } + e_data.util_tex = DRW_texture_create_2D_array( + 64, 64, layers, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_WRAP, (float *)texels); MEM_freeN(texels); } -void EEVEE_materials_init(EEVEE_StorageList *stl) +void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double offsets[3]) +{ + e_data.noise_offsets[0] = offsets[0]; + e_data.noise_offsets[1] = offsets[1]; + e_data.noise_offsets[2] = offsets[2]; + + /* Attach & detach because we don't currently support multiple FB per texture, + * and this would be the case for multiple viewport. */ + DRW_framebuffer_texture_layer_attach(fbl->update_noise_fb, e_data.util_tex, 0, 2, 0); + DRW_framebuffer_bind(fbl->update_noise_fb); + DRW_draw_pass(psl->update_noise_pass); + DRW_framebuffer_texture_detach(e_data.util_tex); +} + +void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl) { if (!e_data.frag_shader_lib) { char *frag_str = NULL; /* Shaders */ - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ssr_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl); - for (int i = 0; i < 7; ++i) { - /* Add one for each Closure */ - BLI_dynstr_append(ds_frag, datatoc_lit_surface_frag_glsl); - } - BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl); - e_data.frag_shader_lib = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); - - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ltc_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_volumetric_frag_glsl); - e_data.volume_shader_lib = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); - - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, e_data.frag_shader_lib); - BLI_dynstr_append(ds_frag, datatoc_default_frag_glsl); - frag_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + e_data.frag_shader_lib = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_ssr_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ltc_lib_glsl, + datatoc_bsdf_direct_lib_glsl, + datatoc_lamps_lib_glsl, + /* Add one for each Closure */ + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_lit_surface_frag_glsl, + datatoc_volumetric_lib_glsl); + + e_data.volume_shader_lib = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ltc_lib_glsl, + datatoc_bsdf_direct_lib_glsl, + datatoc_lamps_lib_glsl, + datatoc_volumetric_lib_glsl, + datatoc_volumetric_frag_glsl); + + frag_str = BLI_string_joinN( + e_data.frag_shader_lib, + datatoc_default_frag_glsl); e_data.default_background = DRW_shader_create( datatoc_background_vert_glsl, NULL, datatoc_default_world_frag_glsl, @@ -549,16 +546,32 @@ void EEVEE_materials_init(EEVEE_StorageList *stl) MEM_freeN(frag_str); - EEVEE_update_util_texture(0.0f); + e_data.update_noise_sh = DRW_shader_create_fullscreen( + datatoc_update_noise_frag_glsl, NULL); + + eevee_init_util_texture(); + eevee_init_noise_texture(); } + /* Alpha hash scale: Non-flickering size if we are not refining the render. */ + if (!DRW_state_is_image_render() && + (((stl->effects->enabled_effects & EFFECT_TAA) == 0) || + (stl->effects->taa_current_sample == 1))) { - /* Update viewvecs */ - const bool is_persp = DRW_viewport_is_persp_get(); + e_data.alpha_hash_offset = 0.0f; + } + else { + double r; + BLI_halton_1D(5, 0.0, stl->effects->taa_current_sample, &r); + e_data.alpha_hash_offset = (float)r; + } + + { + /* Update view_vecs */ float invproj[4][4], winmat[4][4]; /* view vectors for the corners of the view frustum. * Can be used to recreate the world space position easily */ - float viewvecs[3][4] = { + float view_vecs[3][4] = { {-1.0f, -1.0f, -1.0f, 1.0f}, {1.0f, -1.0f, -1.0f, 1.0f}, {-1.0f, 1.0f, -1.0f, 1.0f} @@ -567,31 +580,39 @@ void EEVEE_materials_init(EEVEE_StorageList *stl) /* invert the view matrix */ DRW_viewport_matrix_get(winmat, DRW_MAT_WIN); invert_m4_m4(invproj, winmat); + const bool is_persp = (winmat[3][3] == 0.0f); /* convert the view vectors to view space */ for (int i = 0; i < 3; i++) { - mul_m4_v4(invproj, viewvecs[i]); + mul_m4_v4(invproj, view_vecs[i]); /* normalized trick see: * http://www.derschmale.com/2014/01/26/reconstructing-positions-from-the-depth-buffer */ - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][3]); + mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][3]); if (is_persp) - mul_v3_fl(viewvecs[i], 1.0f / viewvecs[i][2]); - viewvecs[i][3] = 1.0; + mul_v3_fl(view_vecs[i], 1.0f / view_vecs[i][2]); + view_vecs[i][3] = 1.0; } - copy_v4_v4(stl->g_data->viewvecs[0], viewvecs[0]); - copy_v4_v4(stl->g_data->viewvecs[1], viewvecs[1]); + copy_v4_v4(sldata->common_data.view_vecs[0], view_vecs[0]); + copy_v4_v4(sldata->common_data.view_vecs[1], view_vecs[1]); /* we need to store the differences */ - stl->g_data->viewvecs[1][0] -= viewvecs[0][0]; - stl->g_data->viewvecs[1][1] = viewvecs[2][1] - viewvecs[0][1]; + sldata->common_data.view_vecs[1][0] -= view_vecs[0][0]; + sldata->common_data.view_vecs[1][1] = view_vecs[2][1] - view_vecs[0][1]; /* calculate a depth offset as well */ if (!is_persp) { float vec_far[] = {-1.0f, -1.0f, 1.0f, 1.0f}; mul_m4_v4(invproj, vec_far); mul_v3_fl(vec_far, 1.0f / vec_far[3]); - stl->g_data->viewvecs[1][2] = vec_far[2] - viewvecs[0][2]; + sldata->common_data.view_vecs[1][2] = vec_far[2] - view_vecs[0][2]; + } + } + + { + /* Update noise Framebuffer. */ + if (fbl->update_noise_fb == NULL) { + fbl->update_noise_fb = DRW_framebuffer_create(); } } } @@ -652,6 +673,7 @@ struct GPUMaterial *EEVEE_material_mesh_get( struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_multiply, bool use_refract, bool use_sss, bool use_translucency, int shadow_method) { + EEVEE_EffectsInfo *effects = vedata->stl->effects; const void *engine = &DRW_engine_viewport_eevee_type; int options = VAR_MAT_MESH; @@ -659,9 +681,9 @@ struct GPUMaterial *EEVEE_material_mesh_get( if (use_multiply) options |= VAR_MAT_MULT; if (use_refract) options |= VAR_MAT_REFRACT; if (use_sss) options |= VAR_MAT_SSS; - if (use_sss && vedata->stl->effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED; + if (use_sss && effects->sss_separate_albedo) options |= VAR_MAT_SSSALBED; if (use_translucency) options |= VAR_MAT_TRANSLUC; - if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME; + if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME; options |= eevee_material_shadow_option(shadow_method); @@ -728,11 +750,9 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get( char *defines = eevee_get_defines(options); - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, e_data.frag_shader_lib); - BLI_dynstr_append(ds_frag, datatoc_prepass_frag_glsl); - char *frag_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + char *frag_str = BLI_string_joinN( + e_data.frag_shader_lib, + datatoc_prepass_frag_glsl); mat = GPU_material_from_nodetree( scene, ma->nodetree, &ma->gpumaterial, engine, options, @@ -779,6 +799,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create( EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, DRWPass *pass, bool is_hair, bool is_flat_normal, bool use_blend, bool use_ssr, int shadow_method) { + EEVEE_EffectsInfo *effects = vedata->stl->effects; static int ssr_id; ssr_id = (use_ssr) ? 1 : -1; int options = VAR_MAT_MESH; @@ -786,7 +807,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create( if (is_hair) options |= VAR_MAT_HAIR; if (is_flat_normal) options |= VAR_MAT_FLAT; if (use_blend) options |= VAR_MAT_BLEND; - if (vedata->stl->effects->use_volumetrics && use_blend) options |= VAR_MAT_VOLUME; + if (((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_blend) options |= VAR_MAT_VOLUME; options |= eevee_material_shadow_option(shadow_method); @@ -795,7 +816,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create( } DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass); - add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend, false); + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, use_blend); return shgrp; } @@ -825,7 +846,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get( vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state); DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); - add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false, false); + add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false, false); } return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]); @@ -836,19 +857,6 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl; EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; - { - const DRWContextState *draw_ctx = DRW_context_state_get(); - ViewLayer *view_layer = draw_ctx->view_layer; - IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); - /* Global AO Switch*/ - stl->effects->use_ao = BKE_collection_engine_property_value_get_bool(props, "gtao_enable"); - stl->effects->use_bent_normals = BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals"); - /* SSR switch */ - stl->effects->use_ssr = BKE_collection_engine_property_value_get_bool(props, "ssr_enable"); - /* Volumetrics */ - stl->effects->use_volumetrics = BKE_collection_engine_property_value_get_bool(props, "volumetric_enable"); - } - /* Create Material Ghash */ { stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash"); @@ -951,6 +959,15 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS | DRW_STATE_CLIP_PLANES | DRW_STATE_WIRE; psl->transparent_pass = DRW_pass_create("Material Transparent Pass", state); } + + { + psl->update_noise_pass = DRW_pass_create("Update Noise Pass", DRW_STATE_WRITE_COLOR); + DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass); + DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex); + DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1); + DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); + } + } #define ADD_SHGROUP_CALL(shgrp, ob, geom) do { \ @@ -979,6 +996,7 @@ static void material_opaque( bool do_cull, bool use_flat_nor, struct GPUMaterial **gpumat, struct GPUMaterial **gpumat_depth, struct DRWShadingGroup **shgrp, struct DRWShadingGroup **shgrp_depth, struct DRWShadingGroup **shgrp_depth_clip) { + EEVEE_EffectsInfo *effects = vedata->stl->effects; const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl; @@ -991,9 +1009,11 @@ static void material_opaque( float *rough_p = &ma->gloss_mir; const bool use_gpumat = (ma->use_nodes && ma->nodetree); - const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0); - const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0); - const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0) && ((stl->effects->enabled_effects & EFFECT_SSS) != 0); + const bool use_refract = ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) && + ((effects->enabled_effects & EFFECT_REFRACT) != 0); + const bool use_sss = ((ma->blend_flag & MA_BL_SS_SUBSURFACE) != 0) && + ((effects->enabled_effects & EFFECT_SSS) != 0); + const bool use_translucency = use_sss && ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0); EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma); @@ -1021,8 +1041,8 @@ static void material_opaque( if (*shgrp) { static int no_ssr = -1; static int first_ssr = 1; - int *ssr_id = (stl->effects->use_ssr && !use_refract) ? &first_ssr : &no_ssr; - add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false, use_sss); + int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_refract) ? &first_ssr : &no_ssr; + add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract, false); if (use_sss) { struct GPUTexture *sss_tex_profile = NULL; @@ -1037,7 +1057,7 @@ static void material_opaque( } DRW_shgroup_stencil_mask(*shgrp, e_data.sss_count + 1); - EEVEE_subsurface_add_pass(vedata, e_data.sss_count + 1, sss_profile); + EEVEE_subsurface_add_pass(sldata, vedata, e_data.sss_count + 1, sss_profile); e_data.sss_count++; } } @@ -1067,19 +1087,24 @@ static void material_opaque( } if (*shgrp_depth != NULL) { - add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false, false); + add_standard_uniforms(*shgrp_depth, sldata, vedata, NULL, NULL, false, false); if (ma->blend_method == MA_BM_CLIP) { DRW_shgroup_uniform_float(*shgrp_depth, "alphaThreshold", &ma->alpha_threshold, 1); DRW_shgroup_uniform_float(*shgrp_depth_clip, "alphaThreshold", &ma->alpha_threshold, 1); } + else if (ma->blend_method == MA_BM_HASHED) { + DRW_shgroup_uniform_float(*shgrp_depth, "hashAlphaOffset", &e_data.alpha_hash_offset, 1); + DRW_shgroup_uniform_float(*shgrp_depth_clip, "hashAlphaOffset", &e_data.alpha_hash_offset, 1); + } } } } /* Fallback to default shader */ if (*shgrp == NULL) { - *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, use_flat_nor, stl->effects->use_ssr, linfo->shadow_method); + bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0); + *shgrp = EEVEE_default_shading_group_get(sldata, vedata, false, use_flat_nor, use_ssr, linfo->shadow_method); DRW_shgroup_uniform_vec3(*shgrp, "basecol", color_p, 1); DRW_shgroup_uniform_float(*shgrp, "metallic", metal_p, 1); DRW_shgroup_uniform_float(*shgrp, "specular", spec_p, 1); @@ -1131,7 +1156,7 @@ static void material_transparent( if (*shgrp) { static int ssr_id = -1; /* TODO transparent SSR */ bool use_blend = (ma->blend_method & MA_BM_BLEND) != 0; - add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend, false); + add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract, use_blend); } else { /* Shader failed : pink color */ @@ -1217,7 +1242,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld const bool is_default_mode_shader = is_sculpt_mode; /* First get materials for this mesh. */ - if (ELEM(ob->type, OB_MESH)) { + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { const int materials_len = MAX2(1, (is_sculpt_mode_draw ? 1 : ob->totcol)); struct DRWShadingGroup **shgrp_array = BLI_array_alloca(shgrp_array, materials_len); @@ -1335,7 +1360,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld } /* Volumetrics */ - if (vedata->stl->effects->use_volumetrics && use_volume_material) { + if (((stl->effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) && use_volume_material) { EEVEE_volumes_cache_object_add(sldata, vedata, scene, ob); } } @@ -1383,7 +1408,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass); if (shgrp) { - add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false, false); + add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false, false); BLI_ghash_insert(material_hash, ma, shgrp); @@ -1401,7 +1426,9 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sld /* Fallback to default shader */ if (shgrp == NULL) { - shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, stl->effects->use_ssr, sldata->lamps->shadow_method); + bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0); + shgrp = EEVEE_default_shading_group_get(sldata, vedata, true, false, use_ssr, + sldata->lamps->shadow_method); DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1); DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1); DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); @@ -1438,7 +1465,9 @@ void EEVEE_materials_free(void) DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh); DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh); DRW_SHADER_FREE_SAFE(e_data.default_background); + DRW_SHADER_FREE_SAFE(e_data.update_noise_sh); DRW_TEXTURE_FREE_SAFE(e_data.util_tex); + DRW_TEXTURE_FREE_SAFE(e_data.noise_tex); } void EEVEE_draw_default_passes(EEVEE_PassList *psl) diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c index d5e0a05f9ed..037bbe3b6c9 100644 --- a/source/blender/draw/engines/eevee/eevee_motion_blur.c +++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c @@ -40,6 +40,7 @@ #include "ED_screen.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "eevee_private.h" #include "GPU_texture.h" @@ -52,7 +53,11 @@ static struct { extern char datatoc_effect_motion_blur_frag_glsl[]; static void eevee_motion_blur_camera_get_matrix_at_time( - const bContext *C, Scene *scene, ARegion *ar, RegionView3D *rv3d, View3D *v3d, Object *camera, float time, float r_mat[4][4]) + Scene *scene, + ARegion *ar, RegionView3D *rv3d, View3D *v3d, + Object *camera, + float time, + float r_mat[4][4]) { EvaluationContext eval_ctx; float obmat[4][4]; @@ -63,7 +68,19 @@ static void eevee_motion_blur_camera_get_matrix_at_time( memcpy(&camdata_cpy, camera->data, sizeof(camdata_cpy)); cam_cpy.data = &camdata_cpy; - CTX_data_eval_ctx(C, &eval_ctx); + /* NOTE: Mode corresponds to old usage of eval_ctx from viewport (which was + * actually coming from bmain). It was always DAG_EVAL_VIEWPORT. For F12 + * render this should be DAG_EVAL_RENDER, but the whole hack is to be + * reconsidered first anyway. + */ + const DRWContextState *draw_ctx = DRW_context_state_get(); + DEG_evaluation_context_init_from_scene( + &eval_ctx, + scene, + draw_ctx->view_layer, + draw_ctx->engine_type, + DAG_EVAL_VIEWPORT); + eval_ctx.ctime = time; /* Past matrix */ /* FIXME : This is a temporal solution that does not take care of parent animations */ @@ -76,27 +93,15 @@ static void eevee_motion_blur_camera_get_matrix_at_time( CameraParams params; BKE_camera_params_init(¶ms); - /* copy of BKE_camera_params_from_view3d */ - { - params.lens = v3d->lens; - params.clipsta = v3d->near; - params.clipend = v3d->far; - - /* camera view */ + if (v3d != NULL) { + BKE_camera_params_from_view3d(¶ms, draw_ctx->depsgraph, v3d, rv3d); + BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); + } + else { BKE_camera_params_from_object(¶ms, &cam_cpy); - - params.zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); - - params.offsetx = 2.0f * rv3d->camdx * params.zoom; - params.offsety = 2.0f * rv3d->camdy * params.zoom; - - params.shiftx *= params.zoom; - params.shifty *= params.zoom; - - params.zoom = CAMERA_PARAM_ZOOM_INIT_CAMOB / params.zoom; + BKE_camera_params_compute_viewplane(¶ms, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp); } - BKE_camera_params_compute_viewplane(¶ms, ar->winx, ar->winy, 1.0f, 1.0f); BKE_camera_params_compute_matrix(¶ms); /* FIXME Should be done per view (MULTIVIEW) */ @@ -110,7 +115,7 @@ static void eevee_create_shader_motion_blur(void) e_data.motion_blur_sh = DRW_shader_create_fullscreen(datatoc_effect_motion_blur_frag_glsl, NULL); } -int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, Object *camera) { EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; @@ -121,34 +126,51 @@ int EEVEE_motion_blur_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *veda View3D *v3d = draw_ctx->v3d; RegionView3D *rv3d = draw_ctx->rv3d; ARegion *ar = draw_ctx->ar; - IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, + COLLECTION_MODE_NONE, + RE_engine_id_BLENDER_EEVEE); - if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable") && (draw_ctx->evil_C != NULL)) { + if (BKE_collection_engine_property_value_get_bool(props, "motion_blur_enable")) { /* Update Motion Blur Matrices */ - if (rv3d->persp == RV3D_CAMOB && v3d->camera) { + if (camera) { float persmat[4][4]; float ctime = BKE_scene_frame_get(scene); float delta = BKE_collection_engine_property_value_get_float(props, "motion_blur_shutter"); + Object *camera_object = DEG_get_evaluated_object(draw_ctx->depsgraph, camera); /* Current matrix */ - eevee_motion_blur_camera_get_matrix_at_time(draw_ctx->evil_C, scene, ar, rv3d, v3d, v3d->camera, ctime, effects->current_ndc_to_world); + eevee_motion_blur_camera_get_matrix_at_time(scene, + ar, rv3d, v3d, + camera_object, + ctime, + effects->current_ndc_to_world); /* Viewport Matrix */ DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); /* Only continue if camera is not being keyed */ - if (compare_m4m4(persmat, effects->current_ndc_to_world, 0.0001f)) { - + if (DRW_state_is_image_render() || + compare_m4m4(persmat, effects->current_ndc_to_world, 0.0001f)) + { /* Past matrix */ - eevee_motion_blur_camera_get_matrix_at_time(draw_ctx->evil_C, scene, ar, rv3d, v3d, v3d->camera, ctime - delta, effects->past_world_to_ndc); + eevee_motion_blur_camera_get_matrix_at_time(scene, + ar, rv3d, v3d, + camera_object, + ctime - delta, + effects->past_world_to_ndc); #if 0 /* for future high quality blur */ /* Future matrix */ - eevee_motion_blur_camera_get_matrix_at_time(scene, ar, rv3d, v3d, v3d->camera, ctime + delta, effects->future_world_to_ndc); + eevee_motion_blur_camera_get_matrix_at_time(scene, + ar, rv3d, v3d, + camera_object, + ctime + delta, + effects->future_world_to_ndc); #endif invert_m4(effects->current_ndc_to_world); - effects->motion_blur_samples = BKE_collection_engine_property_value_get_int(props, "motion_blur_samples"); + effects->motion_blur_samples = BKE_collection_engine_property_value_get_int(props, + "motion_blur_samples"); if (!e_data.motion_blur_sh) { eevee_create_shader_motion_blur(); diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c index c1dde385284..9da438e825f 100644 --- a/source/blender/draw/engines/eevee/eevee_occlusion.c +++ b/source/blender/draw/engines/eevee/eevee_occlusion.c @@ -27,7 +27,7 @@ #include "DRW_render.h" -#include "BLI_dynstr.h" +#include "BLI_string_utils.h" #include "DNA_anim_types.h" @@ -38,38 +38,43 @@ static struct { /* Ground Truth Ambient Occlusion */ struct GPUShader *gtao_sh; + struct GPUShader *gtao_layer_sh; struct GPUShader *gtao_debug_sh; + struct GPUTexture *src_depth; } e_data = {NULL}; /* Engine data */ extern char datatoc_ambient_occlusion_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; extern char datatoc_effect_gtao_frag_glsl[]; static void eevee_create_shader_occlusion(void) { - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_effect_gtao_frag_glsl); - char *frag_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + char *frag_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_effect_gtao_frag_glsl); e_data.gtao_sh = DRW_shader_create_fullscreen(frag_str, NULL); + e_data.gtao_layer_sh = DRW_shader_create_fullscreen(frag_str, "#define LAYERED_DEPTH\n"); e_data.gtao_debug_sh = DRW_shader_create_fullscreen(frag_str, "#define DEBUG_AO\n"); MEM_freeN(frag_str); } -int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; - EEVEE_EffectsInfo *effects = stl->effects; const DRWContextState *draw_ctx = DRW_context_state_get(); ViewLayer *view_layer = draw_ctx->view_layer; - IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, + COLLECTION_MODE_NONE, + RE_engine_id_BLENDER_EEVEE); if (BKE_collection_engine_property_value_get_bool(props, "gtao_enable")) { const float *viewport_size = DRW_viewport_size_get(); @@ -79,48 +84,24 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata eevee_create_shader_occlusion(); } - effects->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance"); - effects->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor"); - effects->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality"); - effects->ao_samples = BKE_collection_engine_property_value_get_int(props, "gtao_samples"); - effects->ao_samples_inv = 1.0f / effects->ao_samples; + common_data->ao_dist = BKE_collection_engine_property_value_get_float(props, "gtao_distance"); + common_data->ao_factor = BKE_collection_engine_property_value_get_float(props, "gtao_factor"); + common_data->ao_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "gtao_quality"); - effects->ao_settings = 1.0; /* USE_AO */ + common_data->ao_settings = 1.0; /* USE_AO */ if (BKE_collection_engine_property_value_get_bool(props, "gtao_use_bent_normals")) { - effects->ao_settings += 2.0; /* USE_BENT_NORMAL */ + common_data->ao_settings += 2.0; /* USE_BENT_NORMAL */ } if (BKE_collection_engine_property_value_get_bool(props, "gtao_denoise")) { - effects->ao_settings += 4.0; /* USE_DENOISE */ - } - - effects->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce"); - - effects->ao_texsize[0] = ((int)viewport_size[0]); - effects->ao_texsize[1] = ((int)viewport_size[1]); - - /* Round up to multiple of 2 */ - if ((effects->ao_texsize[0] & 0x1) != 0) { - effects->ao_texsize[0] += 1; + common_data->ao_settings += 4.0; /* USE_DENOISE */ } - if ((effects->ao_texsize[1] & 0x1) != 0) { - effects->ao_texsize[1] += 1; - } - - CLAMP(effects->ao_samples, 1, 32); - if (effects->hori_tex_layers != effects->ao_samples) { - DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons); - } - - if (txl->gtao_horizons == NULL) { - effects->hori_tex_layers = effects->ao_samples; - txl->gtao_horizons = DRW_texture_create_2D_array((int)viewport_size[0], (int)viewport_size[1], effects->hori_tex_layers, DRW_TEX_RG_8, 0, NULL); - } + common_data->ao_bounce_fac = (float)BKE_collection_engine_property_value_get_bool(props, "gtao_bounce"); - DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RG_8, 0}; + DRWFboTexture tex = {&txl->gtao_horizons, DRW_TEX_RGBA_8, 0}; DRW_framebuffer_init(&fbl->gtao_fb, &draw_engine_eevee_type, - effects->ao_texsize[0], effects->ao_texsize[1], + (int)viewport_size[0], (int)viewport_size[1], &tex, 1); if (G.debug_value == 6) { @@ -137,12 +118,12 @@ int EEVEE_occlusion_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata /* Cleanup */ DRW_TEXTURE_FREE_SAFE(txl->gtao_horizons); DRW_FRAMEBUFFER_FREE_SAFE(fbl->gtao_fb); - effects->ao_settings = 0.0f; + common_data->ao_settings = 0.0f; return 0; } -void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; EEVEE_StorageList *stl = vedata->stl; @@ -166,51 +147,54 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data **/ psl->ao_horizon_search = DRW_pass_create("GTAO Horizon Search", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.gtao_sh, psl->ao_horizon_search); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer); - DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10); - DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2); - DRW_shgroup_uniform_float(grp, "sampleNbr", &stl->effects->ao_sample_nbr, 1); - DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)stl->effects->ao_texsize, 1); + DRW_shgroup_uniform_buffer(grp, "depthBuffer", &effects->ao_src_depth); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_call_add(grp, quad, NULL); + + psl->ao_horizon_search_layer = DRW_pass_create("GTAO Horizon Search Layer", DRW_STATE_WRITE_COLOR); + grp = DRW_shgroup_create(e_data.gtao_layer_sh, psl->ao_horizon_search_layer); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer); + DRW_shgroup_uniform_buffer(grp, "depthBufferLayered", &effects->ao_src_depth); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1); DRW_shgroup_call_add(grp, quad, NULL); if (G.debug_value == 6) { psl->ao_horizon_debug = DRW_pass_create("GTAO Horizon Debug", DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(e_data.gtao_debug_sh, psl->ao_horizon_debug); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &txl->gtao_horizons); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10); - DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &stl->effects->ao_dist, 2); - DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)stl->effects->ao_texsize, 1); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_call_add(grp, quad, NULL); } } } -void EEVEE_occlusion_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +void EEVEE_occlusion_compute( + EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer) { EEVEE_PassList *psl = vedata->psl; - EEVEE_TextureList *txl = vedata->txl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; if ((effects->enabled_effects & EFFECT_GTAO) != 0) { DRW_stats_group_start("GTAO Horizon Scan"); - for (effects->ao_sample_nbr = 0.0; - effects->ao_sample_nbr < effects->ao_samples; - ++effects->ao_sample_nbr) - { - DRW_framebuffer_texture_detach(txl->gtao_horizons); - DRW_framebuffer_texture_layer_attach(fbl->gtao_fb, txl->gtao_horizons, 0, (int)effects->ao_sample_nbr, 0); - DRW_framebuffer_bind(fbl->gtao_fb); + effects->ao_src_depth = depth_src; + effects->ao_depth_layer = layer; + DRW_framebuffer_bind(fbl->gtao_fb); + + if (layer >= 0) { + DRW_draw_pass(psl->ao_horizon_search_layer); + } + else { DRW_draw_pass(psl->ao_horizon_search); } @@ -247,5 +231,6 @@ void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data void EEVEE_occlusion_free(void) { DRW_SHADER_FREE_SAFE(e_data.gtao_sh); + DRW_SHADER_FREE_SAFE(e_data.gtao_layer_sh); DRW_SHADER_FREE_SAFE(e_data.gtao_debug_sh); } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 98fc6d6a6e4..218de6ddd88 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -27,6 +27,8 @@ #define __EEVEE_PRIVATE_H__ struct Object; +struct EEVEE_BoundSphere; +struct EEVEE_ShadowCasterBuffer; extern struct DrawEngineType draw_engine_eevee_type; @@ -127,6 +129,14 @@ enum { SHADOW_METHOD_MAX = 3, }; +typedef struct EEVEE_BoundSphere { + float center[3], radius; +} EEVEE_BoundSphere; + +typedef struct EEVEE_BoundBox { + float center[3], halfdim[3]; +} EEVEE_BoundBox; + typedef struct EEVEE_PassList { /* Shadows */ struct DRWPass *shadow_pass; @@ -148,6 +158,7 @@ typedef struct EEVEE_PassList { /* Effects */ struct DRWPass *ao_horizon_search; + struct DRWPass *ao_horizon_search_layer; struct DRWPass *ao_horizon_debug; struct DRWPass *motion_blur; struct DRWPass *bloom_blit; @@ -195,6 +206,7 @@ typedef struct EEVEE_PassList { struct DRWPass *refract_pass; struct DRWPass *transparent_pass; struct DRWPass *background_pass; + struct DRWPass *update_noise_pass; } EEVEE_PassList; typedef struct EEVEE_FramebufferList { @@ -217,6 +229,8 @@ typedef struct EEVEE_FramebufferList { struct GPUFrameBuffer *screen_tracing_fb; struct GPUFrameBuffer *refract_fb; + struct GPUFrameBuffer *update_noise_fb; + struct GPUFrameBuffer *planarref_fb; struct GPUFrameBuffer *main; @@ -237,6 +251,7 @@ typedef struct EEVEE_TextureList { struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */ struct GPUTexture *ssr_normal_input; struct GPUTexture *ssr_specrough_input; + struct GPUTexture *ssr_hit_output; struct GPUTexture *refract_color; struct GPUTexture *volume_prop_scattering; @@ -310,17 +325,23 @@ typedef struct EEVEE_ShadowRender { float shadow_inv_samples_ct; } EEVEE_ShadowRender; -/* ************ VOLUME DATA ************ */ -typedef struct EEVEE_VolumetricsInfo { - float integration_step_count, shadow_step_count, sample_distribution, light_clamp; - float integration_start, integration_end; - float depth_param[3], history_alpha; - bool use_lights, use_volume_shadows; - int froxel_tex_size[3]; - float inv_tex_size[3]; - float volume_coord_scale[2]; - float jitter[3]; -} EEVEE_VolumetricsInfo; +/* This is just a really long bitflag with special function to access it. */ +#define MAX_LIGHTBITS_FIELDS (MAX_LIGHT / 8) +typedef struct EEVEE_LightBits { + unsigned char fields[MAX_LIGHTBITS_FIELDS]; +} EEVEE_LightBits; + +typedef struct EEVEE_ShadowCaster { + struct EEVEE_LightBits bits; + struct EEVEE_BoundBox bbox; +} EEVEE_ShadowCaster; + +typedef struct EEVEE_ShadowCasterBuffer { + struct EEVEE_ShadowCaster *shadow_casters; + char *flags; + unsigned int alloc_count; + unsigned int count; +} EEVEE_ShadowCasterBuffer; /* ************ LIGHT DATA ************* */ typedef struct EEVEE_LampsInfo { @@ -346,8 +367,20 @@ typedef struct EEVEE_LampsInfo { struct EEVEE_Shadow shadow_data[MAX_SHADOW]; struct EEVEE_ShadowCube shadow_cube_data[MAX_SHADOW_CUBE]; struct EEVEE_ShadowCascade shadow_cascade_data[MAX_SHADOW_CASCADE]; + /* Lights tracking */ + int new_shadow_id[MAX_LIGHT]; /* To be able to convert old bitfield to new bitfield */ + struct EEVEE_BoundSphere shadow_bounds[MAX_LIGHT]; /* Tighly packed light bounds */ + /* Pointers only. */ + struct EEVEE_ShadowCasterBuffer *shcaster_frontbuffer; + struct EEVEE_ShadowCasterBuffer *shcaster_backbuffer; } EEVEE_LampsInfo; +/* EEVEE_LampsInfo->shadow_casters_flag */ +enum { + SHADOW_CASTER_PRUNED = (1 << 0), + SHADOW_CASTER_UPDATED = (1 << 1), +}; + /* EEVEE_LampsInfo->update_flag */ enum { LIGHT_UPDATE_SHADOW_CUBE = (1 << 0), @@ -395,11 +428,9 @@ typedef struct EEVEE_LightProbesInfo { int num_bounce; int cubemap_res; int target_size; - int irradiance_vis_size; int grid_initialized; - /* Actual number of probes that have datas. */ - int num_render_cube; - int num_render_grid; + struct World *prev_world; + bool do_cube_update; /* For rendering probes */ float probemat[6][4][4]; int layer; @@ -414,11 +445,8 @@ typedef struct EEVEE_LightProbesInfo { float lod_rt_max, lod_cube_max, lod_planar_max; float visibility_range; float visibility_blur; + float intensity_fac; int shres; - int shnbr; - bool specular_toggle; - bool ssr_toggle; - bool sss_toggle; /* List of probes in the scene. */ /* XXX This is fragile, can get out of sync quickly. */ struct Object *probes_cube_ref[MAX_PROBE]; @@ -441,30 +469,18 @@ enum { typedef struct EEVEE_EffectsInfo { int enabled_effects; bool swap_double_buffer; - /* SSSS */ int sss_sample_count; - float sss_jitter_threshold; bool sss_separate_albedo; - /* Volumetrics */ - bool use_volumetrics; int volume_current_sample; - /* SSR */ - bool use_ssr; bool reflection_trace_full; - bool ssr_use_normalization; - int ssr_ray_count; - float ssr_firefly_fac; - float ssr_border_fac; - float ssr_max_roughness; - float ssr_quality; - float ssr_thickness; - float ssr_pixelsize[2]; - + int ssr_neighbor_ofs; + int ssr_halfres_ofs[2]; /* Temporal Anti Aliasing */ int taa_current_sample; + int taa_render_sample; int taa_total_sample; float taa_alpha; bool prev_drw_support; @@ -473,27 +489,19 @@ typedef struct EEVEE_EffectsInfo { float overide_persinv[4][4]; float overide_winmat[4][4]; float overide_wininv[4][4]; - /* Ambient Occlusion */ - bool use_ao, use_bent_normals; - float ao_dist, ao_samples, ao_factor, ao_samples_inv; - float ao_offset, ao_bounce_fac, ao_quality, ao_settings; - float ao_sample_nbr; - int ao_texsize[2], hori_tex_layers; - + int ao_depth_layer; + struct GPUTexture *ao_src_depth; /* pointer copy */ /* Motion Blur */ float current_ndc_to_world[4][4]; float past_world_to_ndc[4][4]; - float tmp_mat[4][4]; int motion_blur_samples; - /* Depth Of Field */ float dof_near_far[2]; float dof_params[3]; float dof_bokeh[4]; float dof_layer_select[2]; int dof_target_size[2]; - /* Bloom */ int bloom_iteration_ct; float source_texel_size[2]; @@ -506,10 +514,11 @@ typedef struct EEVEE_EffectsInfo { float unf_source_texel_size[2]; struct GPUTexture *unf_source_buffer; /* pointer copy */ struct GPUTexture *unf_base_buffer; /* pointer copy */ - /* Not alloced, just a copy of a *GPUtexture in EEVEE_TextureList. */ struct GPUTexture *source_buffer; /* latest updated texture */ struct GPUFrameBuffer *target_buffer; /* next target to render to */ + struct GPUTexture *final_tx; /* Final color to transform to display color space. */ + struct GPUFrameBuffer *final_fb; /* Framebuffer with final_tx as attachement. */ } EEVEE_EffectsInfo; enum { @@ -527,6 +536,58 @@ enum { EFFECT_SSS = (1 << 11), }; +/* ***************** COMMON DATA **************** */ + +/* Common uniform buffer containing all "constant" data over the whole drawing pipeline. */ +/* !! CAUTION !! + * - [i]vec3 need to be paded to [i]vec4 (even in ubo declaration). + * - Make sure that [i]vec4 start at a multiple of 16 bytes. + * - Arrays of vec2/vec3 are padded as arrays of vec4. + * - sizeof(bool) == sizeof(int) in GLSL so use int in C */ +typedef struct EEVEE_CommonUniformBuffer { + float prev_persmat[4][4]; /* mat4 */ + float view_vecs[2][4]; /* vec4[2] */ + float mip_ratio[10][4]; /* vec2[10] */ + /* Ambient Occlusion */ + /* -- 16 byte aligned -- */ + float ao_dist, pad1, ao_factor, pad2; /* vec4 */ + float ao_offset, ao_bounce_fac, ao_quality, ao_settings; /* vec4 */ + /* Volumetric */ + /* -- 16 byte aligned -- */ + int vol_tex_size[3], pad3; /* ivec3 */ + float vol_depth_param[3], pad4; /* vec3 */ + float vol_inv_tex_size[3], pad5; /* vec3 */ + float vol_jitter[3], pad6; /* vec3 */ + float vol_coord_scale[2], pad7[2]; /* vec2 */ + /* -- 16 byte aligned -- */ + float vol_history_alpha; /* float */ + float vol_light_clamp; /* float */ + float vol_shadow_steps; /* float */ + int vol_use_lights; /* bool */ + /* Screen Space Reflections */ + /* -- 16 byte aligned -- */ + float ssr_quality, ssr_thickness, ssr_pixelsize[2]; /* vec4 */ + float ssr_border_fac; /* float */ + float ssr_max_roughness; /* float */ + float ssr_firefly_fac; /* float */ + float ssr_brdf_bias; /* float */ + int ssr_toggle; /* bool */ + /* SubSurface Scattering */ + float sss_jitter_threshold; /* float */ + int sss_toggle; /* bool */ + /* Specular */ + int spec_toggle; /* bool */ + /* Lamps */ + int la_num_light; /* int */ + /* Probes */ + int prb_num_planar; /* int */ + int prb_num_render_cube; /* int */ + int prb_num_render_grid; /* int */ + int prb_irradiance_vis_size; /* int */ + float prb_lod_cube_max; /* float */ + float prb_lod_planar_max; /* float */ +} EEVEE_CommonUniformBuffer; + /* ************** SCENE LAYER DATA ************** */ typedef struct EEVEE_ViewLayerData { /* Lamps */ @@ -546,7 +607,7 @@ typedef struct EEVEE_ViewLayerData { struct GPUTexture *shadow_cascade_blur; struct GPUTexture *shadow_pool; - struct ListBase shadow_casters; /* Shadow casters gathered during cache iteration */ + struct EEVEE_ShadowCasterBuffer shcasters_buffers[2]; /* Probes */ struct EEVEE_LightProbesInfo *probes; @@ -564,20 +625,45 @@ typedef struct EEVEE_ViewLayerData { struct GPUTexture *irradiance_pool; struct GPUTexture *irradiance_rt; - struct ListBase probe_queue; /* List of probes to update */ - - /* Volumetrics */ - struct EEVEE_VolumetricsInfo *volumetrics; + /* Common Uniform Buffer */ + struct EEVEE_CommonUniformBuffer common_data; + struct GPUUniformBuffer *common_ubo; } EEVEE_ViewLayerData; /* ************ OBJECT DATA ************ */ +typedef struct EEVEE_LightData { + short light_id, shadow_id; +} EEVEE_LightData; + +typedef struct EEVEE_ShadowCubeData { + short light_id, shadow_id, cube_id, layer_id; +} EEVEE_ShadowCubeData; + +typedef struct EEVEE_ShadowCascadeData { + short light_id, shadow_id, cascade_id, layer_id; + float viewprojmat[MAX_CASCADE_NUM][4][4]; /* World->Lamp->NDC : used for rendering the shadow map. */ + float radius[MAX_CASCADE_NUM]; +} EEVEE_ShadowCascadeData; + +/* Theses are the structs stored inside Objects. + * It works with even if the object is in multiple layers + * because we don't get the same "Object *" for each layer. */ typedef struct EEVEE_LampEngineData { + ObjectEngineData engine_data; + bool need_update; - struct ListBase shadow_caster_list; - void *storage; /* either EEVEE_LightData, EEVEE_ShadowCubeData, EEVEE_ShadowCascadeData */ + /* This needs to be out of the union to avoid undefined behaviour. */ + short prev_cube_shadow_id; + union { + struct EEVEE_LightData ld; + struct EEVEE_ShadowCubeData scd; + struct EEVEE_ShadowCascadeData scad; + } data; } EEVEE_LampEngineData; typedef struct EEVEE_LightProbeEngineData { + ObjectEngineData engine_data; + /* NOTE: need_full_update is set by dependency graph when the probe or it's * object is updated. This triggers full probe update, including it's * "progressive" GI refresh. @@ -606,7 +692,10 @@ typedef struct EEVEE_LightProbeEngineData { } EEVEE_LightProbeEngineData; typedef struct EEVEE_ObjectEngineData { + ObjectEngineData engine_data; + bool need_update; + unsigned int shadow_caster_id; } EEVEE_ObjectEngineData; /* *********************************** */ @@ -635,18 +724,18 @@ typedef struct EEVEE_PrivateData { struct GHash *material_hash; struct GHash *hair_material_hash; struct GPUTexture *minzbuffer; - struct GPUTexture *ssr_hit_output[4]; + struct GPUTexture *ssr_pdf_output; struct GPUTexture *gtao_horizons_debug; float background_alpha; /* TODO find a better place for this. */ - float viewvecs[2][4]; /* For planar probes */ - float texel_size[2]; - /* To correct mip level texel mis-alignement */ - float mip_ratio[10][2]; /* TODO put in a UBO */ + float planar_texel_size[2]; /* For double buffering */ bool view_updated; bool valid_double_buffer; - float prev_persmat[4][4]; + /* Render Matrices */ + float persmat[4][4], persinv[4][4]; + float viewmat[4][4], viewinv[4][4]; + float winmat[4][4], wininv[4][4]; } EEVEE_PrivateData; /* Transient data */ /* eevee_data.c */ @@ -661,7 +750,7 @@ EEVEE_LampEngineData *EEVEE_lamp_data_ensure(Object *ob); /* eevee_materials.c */ struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */ -void EEVEE_materials_init(EEVEE_StorageList *stl); +void EEVEE_materials_init(EEVEE_ViewLayerData *sldata, EEVEE_StorageList *stl, EEVEE_FramebufferList *fbl); void EEVEE_materials_cache_init(EEVEE_Data *vedata); void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob); void EEVEE_materials_cache_finish(EEVEE_Data *vedata); @@ -676,7 +765,7 @@ struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene, Material struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma, int shadow_method); void EEVEE_materials_free(void); void EEVEE_draw_default_passes(EEVEE_PassList *psl); -void EEVEE_update_util_texture(float offset); +void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, double offsets[3]); /* eevee_lights.c */ void EEVEE_lights_init(EEVEE_ViewLayerData *sldata); @@ -688,6 +777,7 @@ void EEVEE_lights_cache_shcaster_material_add( EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl, struct GPUMaterial *gpumat, struct Gwn_Batch *geom, struct Object *ob, float (*obmat)[4], float *alpha_threshold); +void EEVEE_lights_cache_shcaster_object_add(EEVEE_ViewLayerData *sldata, struct Object *ob); void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata); void EEVEE_lights_update(EEVEE_ViewLayerData *sldata); void EEVEE_draw_shadows(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl); @@ -702,7 +792,7 @@ void EEVEE_lightprobes_refresh(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_lightprobes_free(void); /* eevee_depth_of_field.c */ -int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera); void EEVEE_depth_of_field_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_depth_of_field_draw(EEVEE_Data *vedata); void EEVEE_depth_of_field_free(void); @@ -716,7 +806,7 @@ void EEVEE_bloom_free(void); /* eevee_occlusion.c */ int EEVEE_occlusion_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_occlusion_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); void EEVEE_occlusion_draw_debug(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_occlusion_free(void); @@ -730,19 +820,22 @@ void EEVEE_screen_raytrace_free(void); /* eevee_subsurface.c */ int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile); +void EEVEE_subsurface_add_pass( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile); void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_subsurface_free(void); /* eevee_motion_blur.c */ -int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +int EEVEE_motion_blur_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera); void EEVEE_motion_blur_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_motion_blur_draw(EEVEE_Data *vedata); void EEVEE_motion_blur_free(void); /* eevee_temporal_sampling.c */ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_temporal_sampling_matrices_calc( + EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], double ht_point[2]); void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata); void EEVEE_temporal_sampling_free(void); @@ -757,15 +850,21 @@ void EEVEE_volumes_free_smoke_textures(void); void EEVEE_volumes_free(void); /* eevee_effects.c */ -void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); +void EEVEE_effects_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, Object *camera); void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_create_minmax_buffer(EEVEE_Data *vedata, struct GPUTexture *depth_src, int layer); void EEVEE_downsample_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level); void EEVEE_downsample_cube_buffer(EEVEE_Data *vedata, struct GPUFrameBuffer *fb_src, struct GPUTexture *texture_src, int level); void EEVEE_effects_do_gtao(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); -void EEVEE_draw_effects(EEVEE_Data *vedata); +void EEVEE_draw_effects(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata); void EEVEE_effects_free(void); +/* eevee_ */ +void EEVEE_render_init(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph); +void EEVEE_render_cache(void *vedata, struct Object *ob, struct RenderEngine *engine, struct Depsgraph *depsgraph); +void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph); +void EEVEE_render_output(EEVEE_Data *vedata, struct RenderEngine *engine, struct Depsgraph *depsgraph); + /* Shadow Matrix */ static const float texcomat[4][4] = { /* From NDC to TexCo */ {0.5f, 0.0f, 0.0f, 0.0f}, diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c new file mode 100644 index 00000000000..a020887e420 --- /dev/null +++ b/source/blender/draw/engines/eevee/eevee_render.c @@ -0,0 +1,278 @@ +/* + * 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_render.c + * \ingroup draw_engine + */ + +/** + * Render functions for final render outputs. + */ + +#include "DRW_engine.h" +#include "DRW_render.h" + +#include "BLI_rand.h" + +#include "DEG_depsgraph_query.h" + +#include "GPU_framebuffer.h" +#include "GPU_glew.h" + +#include "RE_pipeline.h" + +#include "eevee_private.h" + +void EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *depsgraph) +{ + EEVEE_Data *vedata = (EEVEE_Data *)ved; + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_TextureList *txl = vedata->txl; + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + Scene *scene = DEG_get_evaluated_scene(depsgraph); + const float *viewport_size = DRW_viewport_size_get(); + + /* Init default FB and render targets: + * In render mode the default framebuffer is not generated + * because there is no viewport. So we need to manually create it or + * not use it. For code clarity we just allocate it make use of it. */ + DefaultFramebufferList *dfbl = DRW_viewport_framebuffer_list_get(); + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + + /* NOTE : use 32 bit format for precision in render mode. */ + DRWFboTexture dtex = {&dtxl->depth, DRW_TEX_DEPTH_24_STENCIL_8, 0}; + DRW_framebuffer_init(&dfbl->default_fb, &draw_engine_eevee_type, + (int)viewport_size[0], (int)viewport_size[1], + &dtex, 1); + + DRWFboTexture tex = {&txl->color, DRW_TEX_RGBA_32, DRW_TEX_FILTER | DRW_TEX_MIPMAP}; + DRW_framebuffer_init(&fbl->main, &draw_engine_eevee_type, + (int)viewport_size[0], (int)viewport_size[1], + &tex, 1); + + /* 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 = 1.0f; /* TODO option */ + 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); + } + + /* Set the pers & view matrix. */ + struct Object *camera = RE_GetCamera(engine->re); + float frame = BKE_scene_frame_get(scene); + RE_GetCameraWindow(engine->re, camera, frame, g_data->winmat); + RE_GetCameraModelMatrix(engine->re, camera, g_data->viewinv); + + 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); + invert_m4_m4(g_data->wininv, g_data->winmat); + + DRW_viewport_matrix_override_set(g_data->persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(g_data->persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(g_data->winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(g_data->wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV); + + /* EEVEE_effects_init needs to go first for TAA */ + EEVEE_effects_init(sldata, vedata, camera); + EEVEE_materials_init(sldata, stl, fbl); + EEVEE_lights_init(sldata); + EEVEE_lightprobes_init(sldata, vedata); + + /* INIT CACHE */ + EEVEE_bloom_cache_init(sldata, vedata); + EEVEE_depth_of_field_cache_init(sldata, vedata); + EEVEE_effects_cache_init(sldata, vedata); + EEVEE_lightprobes_cache_init(sldata, vedata); + EEVEE_lights_cache_init(sldata, psl); + EEVEE_materials_cache_init(vedata); + EEVEE_motion_blur_cache_init(sldata, vedata); + EEVEE_occlusion_cache_init(sldata, vedata); + EEVEE_screen_raytrace_cache_init(sldata, vedata); + EEVEE_subsurface_cache_init(sldata, vedata); + EEVEE_temporal_sampling_cache_init(sldata, vedata); + EEVEE_volumes_cache_init(sldata, vedata); +} + +void EEVEE_render_cache( + void *vedata, struct Object *ob, + struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) +{ + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + + if (DRW_check_object_visible_within_active_context(ob) == false) { + return; + } + + if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT)) { + EEVEE_materials_cache_populate(vedata, sldata, ob); + + const bool cast_shadow = true; + + if (cast_shadow) { + EEVEE_lights_cache_shcaster_object_add(sldata, ob); + } + } + else if (ob->type == OB_LIGHTPROBE) { + EEVEE_lightprobes_cache_add(sldata, ob); + } + else if (ob->type == OB_LAMP) { + EEVEE_lights_cache_add(sldata, ob); + } +} + +void EEVEE_render_draw(EEVEE_Data *vedata, struct RenderEngine *UNUSED(engine), struct Depsgraph *UNUSED(depsgraph)) +{ + EEVEE_PassList *psl = vedata->psl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_FramebufferList *fbl = vedata->fbl; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_PrivateData *g_data = stl->g_data; + + /* FINISH CACHE */ + EEVEE_materials_cache_finish(vedata); + EEVEE_lights_cache_finish(sldata); + EEVEE_lightprobes_cache_finish(sldata, vedata); + + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + unsigned int render_samples = BKE_collection_engine_property_value_get_int(props, "taa_render_samples"); + + while (render_samples-- > 0) { + float clear_col[4] = {0.0f, 0.0f, 0.0f, 0.6f}; + unsigned int primes[3] = {2, 3, 7}; + double offset[3] = {0.0, 0.0, 0.0}; + double r[3]; + + BLI_halton_3D(primes, offset, stl->effects->taa_current_sample, r); + EEVEE_update_noise(psl, fbl, r); + EEVEE_temporal_sampling_matrices_calc(stl->effects, g_data->viewmat, g_data->persmat, r); + + /* Refresh Probes & shadows */ + EEVEE_lightprobes_refresh(sldata, vedata); + DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data); + EEVEE_draw_shadows(sldata, psl); + + DRW_viewport_matrix_override_set(stl->effects->overide_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(stl->effects->overide_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(stl->effects->overide_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(stl->effects->overide_wininv, DRW_MAT_WININV); + DRW_viewport_matrix_override_set(g_data->viewmat, DRW_MAT_VIEW); + DRW_viewport_matrix_override_set(g_data->viewinv, DRW_MAT_VIEWINV); + + DRW_framebuffer_texture_detach(dtxl->depth); + DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0); + DRW_framebuffer_bind(fbl->main); + DRW_framebuffer_clear(true, true, true, clear_col, 1.0f); + /* Depth prepass */ + DRW_draw_pass(psl->depth_pass); + DRW_draw_pass(psl->depth_pass_cull); + /* Create minmax texture */ + EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1); + EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1); + EEVEE_volumes_compute(sldata, vedata); + /* Shading pass */ + DRW_draw_pass(psl->background_pass); + EEVEE_draw_default_passes(psl); + DRW_draw_pass(psl->material_pass); + EEVEE_subsurface_data_render(sldata, vedata); + /* Effects pre-transparency */ + EEVEE_subsurface_compute(sldata, vedata); + EEVEE_reflection_compute(sldata, vedata); + EEVEE_occlusion_draw_debug(sldata, vedata); + DRW_draw_pass(psl->probe_display); + EEVEE_refraction_compute(sldata, vedata); + /* Opaque refraction */ + DRW_draw_pass(psl->refract_depth_pass); + DRW_draw_pass(psl->refract_depth_pass_cull); + DRW_draw_pass(psl->refract_pass); + /* Volumetrics Resolve Opaque */ + EEVEE_volumes_resolve(sldata, vedata); + /* Transparent */ + DRW_pass_sort_shgroup_z(psl->transparent_pass); + DRW_draw_pass(psl->transparent_pass); + /* Post Process */ + EEVEE_draw_effects(sldata, vedata); + } +} + +void EEVEE_render_output(EEVEE_Data *vedata, RenderEngine *engine, struct Depsgraph *UNUSED(depsgraph)) +{ + const DRWContextState *draw_ctx = DRW_context_state_get(); + ViewLayer *view_layer = draw_ctx->view_layer; + DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure(); + EEVEE_FramebufferList *fbl = vedata->fbl; + EEVEE_StorageList *stl = vedata->stl; + EEVEE_PrivateData *g_data = stl->g_data; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; + + const char *viewname = NULL; + const float *render_size = DRW_viewport_size_get(); + + /* Combined */ + RenderResult *rr = RE_engine_begin_result(engine, 0, 0, (int)render_size[0], (int)render_size[1], NULL, viewname); + RenderLayer *rl = rr->layers.first; + RenderPass *rp = RE_pass_find_by_name(rl, RE_PASSNAME_COMBINED, viewname); + + DRW_framebuffer_bind(stl->effects->final_fb); + DRW_framebuffer_read_data(0, 0, (int)render_size[0], (int)render_size[1], 4, 0, rp->rect); + + if (view_layer->passflag & SCE_PASS_Z) { + rp = RE_pass_find_by_name(rl, RE_PASSNAME_Z, viewname); + + DRW_framebuffer_texture_attach(fbl->main, dtxl->depth, 0, 0); + DRW_framebuffer_bind(fbl->main); + DRW_framebuffer_read_depth(0, 0, (int)render_size[0], (int)render_size[1], rp->rect); + + bool is_persp = DRW_viewport_is_persp_get(); + + /* Convert ogl depth [0..1] to view Z [near..far] */ + for (int i = 0; i < (int)render_size[0] * (int)render_size[1]; ++i) { + if (rp->rect[i] == 1.0f ) { + rp->rect[i] = 1e10f; /* Background */ + } + else { + if (is_persp) { + rp->rect[i] = rp->rect[i] * 2.0f - 1.0f; + rp->rect[i] = g_data->winmat[3][2] / (rp->rect[i] + g_data->winmat[2][2]); + } + else { + rp->rect[i] = -common_data->view_vecs[0][2] + rp->rect[i] * -common_data->view_vecs[1][2]; + } + } + } + } + + RE_engine_end_result(engine, rr, false, false, false); +}
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 35669968337..2917bfd1236 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -28,15 +28,16 @@ #include "DRW_render.h" #include "BLI_dynstr.h" +#include "BLI_string_utils.h" #include "eevee_private.h" #include "GPU_texture.h" /* SSR shader variations */ enum { - SSR_SAMPLES = (1 << 0) | (1 << 1), - SSR_RESOLVE = (1 << 2), - SSR_FULL_TRACE = (1 << 3), + SSR_RESOLVE = (1 << 0), + SSR_FULL_TRACE = (1 << 1), + SSR_AO = (1 << 3), SSR_MAX_SHADER = (1 << 4), }; @@ -50,6 +51,7 @@ static struct { } e_data = {NULL}; /* Engine data */ extern char datatoc_ambient_occlusion_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_bsdf_common_lib_glsl[]; extern char datatoc_bsdf_sampling_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; @@ -60,22 +62,18 @@ extern char datatoc_raytrace_lib_glsl[]; static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) { if (e_data.ssr_sh[options] == NULL) { - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_sampling_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_ambient_occlusion_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_raytrace_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_effect_ssr_frag_glsl); - char *ssr_shader_str = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); - - int samples = (SSR_SAMPLES & options) + 1; + char *ssr_shader_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_sampling_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_lightprobe_lib_glsl, + datatoc_ambient_occlusion_lib_glsl, + datatoc_raytrace_lib_glsl, + datatoc_effect_ssr_frag_glsl); DynStr *ds_defines = BLI_dynstr_new(); BLI_dynstr_appendf(ds_defines, SHADER_DEFINES); - BLI_dynstr_appendf(ds_defines, "#define RAY_COUNT %d\n", samples); if (options & SSR_RESOLVE) { BLI_dynstr_appendf(ds_defines, "#define STEP_RESOLVE\n"); } @@ -86,6 +84,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) if (options & SSR_FULL_TRACE) { BLI_dynstr_appendf(ds_defines, "#define FULLRES\n"); } + if (options & SSR_AO) { + BLI_dynstr_appendf(ds_defines, "#define SSR_AO\n"); + } char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines); BLI_dynstr_free(ds_defines); @@ -98,8 +99,9 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) return e_data.ssr_sh[options]; } -int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_StorageList *stl = vedata->stl; EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; @@ -108,11 +110,13 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * const DRWContextState *draw_ctx = DRW_context_state_get(); ViewLayer *view_layer = draw_ctx->view_layer; - IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, + COLLECTION_MODE_NONE, + RE_engine_id_BLENDER_EEVEE); /* Compute pixel size, (shared with contact shadows) */ - copy_v2_v2(effects->ssr_pixelsize, viewport_size); - invert_v2(effects->ssr_pixelsize); + copy_v2_v2(common_data->ssr_pixelsize, viewport_size); + invert_v2(common_data->ssr_pixelsize); if (BKE_collection_engine_property_value_get_bool(props, "ssr_enable")) { const bool use_refraction = BKE_collection_engine_property_value_get_bool(props, "ssr_refraction"); @@ -120,24 +124,27 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * if (use_refraction) { DRWFboTexture tex = {&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP}; - DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1], &tex, 1); + DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type, + (int)viewport_size[0], (int)viewport_size[1], + &tex, 1); } - effects->ssr_ray_count = BKE_collection_engine_property_value_get_int(props, "ssr_ray_count"); + bool prev_trace_full = effects->reflection_trace_full; effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres"); - effects->ssr_use_normalization = BKE_collection_engine_property_value_get_bool(props, "ssr_normalize_weight"); - effects->ssr_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "ssr_quality"); - effects->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness"); - effects->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade"); - effects->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac"); - effects->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness"); - - if (effects->ssr_firefly_fac < 1e-8f) { - effects->ssr_firefly_fac = FLT_MAX; + common_data->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness"); + common_data->ssr_border_fac = BKE_collection_engine_property_value_get_float(props, "ssr_border_fade"); + common_data->ssr_firefly_fac = BKE_collection_engine_property_value_get_float(props, "ssr_firefly_fac"); + common_data->ssr_max_roughness = BKE_collection_engine_property_value_get_float(props, "ssr_max_roughness"); + common_data->ssr_quality = 1.0f - 0.95f * BKE_collection_engine_property_value_get_float(props, "ssr_quality"); + common_data->ssr_brdf_bias = 0.1f + common_data->ssr_quality * 0.6f; /* Range [0.1, 0.7]. */ + + if (common_data->ssr_firefly_fac < 1e-8f) { + common_data->ssr_firefly_fac = FLT_MAX; } - /* Important, can lead to breakage otherwise. */ - CLAMP(effects->ssr_ray_count, 1, 4); + if (prev_trace_full != effects->reflection_trace_full) { + DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output); + } const int divisor = (effects->reflection_trace_full) ? 1 : 2; int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor}; @@ -147,7 +154,8 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * /* TODO create one texture layer per lobe */ if (txl->ssr_specrough_input == NULL) { DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8; - txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], specrough_format, 0, NULL); + txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], + specrough_format, 0, NULL); } /* Reattach textures to the right buffer (because we are alternating between buffers) */ @@ -156,15 +164,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0); /* Raytracing output */ - /* TODO try integer format for hit coord to increase precision */ - DRWFboTexture tex_output[4] = { - {&stl->g_data->ssr_hit_output[0], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - {&stl->g_data->ssr_hit_output[1], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - {&stl->g_data->ssr_hit_output[2], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - {&stl->g_data->ssr_hit_output[3], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - }; + /* (AMD or Intel) For some reason DRW_TEX_TEMP with DRW_TEX_RG_16I + * creates problems when toggling ssr_halfres. Texture is not read correctly (black output). + * So using a persistent buffer instead. */ + DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, DRW_TEX_RG_16I, 0}, + {&stl->g_data->ssr_pdf_output, DRW_TEX_R_16, DRW_TEX_TEMP}}; - DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, effects->ssr_ray_count); + DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, + tracing_res[0], tracing_res[1], + tex_output, 2); /* Enable double buffering to be able to read previous frame color */ return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0); @@ -172,10 +180,9 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * /* Cleanup to release memory */ DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input); + DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output); DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb); - for (int i = 0; i < 4; ++i) { - stl->g_data->ssr_hit_output[i] = NULL; - } + stl->g_data->ssr_pdf_output = NULL; return 0; } @@ -191,7 +198,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v if ((effects->enabled_effects & EFFECT_SSR) != 0) { int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0; - options |= (effects->ssr_ray_count - 1); + options |= ((effects->enabled_effects & EFFECT_GTAO) != 0) ? SSR_AO : 0; struct GPUShader *trace_shader = eevee_effects_screen_raytrace_shader_get(options); struct GPUShader *resolve_shader = eevee_effects_screen_raytrace_shader_get(SSR_RESOLVE | options); @@ -214,15 +221,14 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "maxzBuffer", &txl->maxzbuffer); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10); - DRW_shgroup_uniform_vec4(grp, "ssrParameters", &effects->ssr_quality, 1); - DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1); - DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1); DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth); + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + if (!effects->reflection_trace_full) { + DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1); + } DRW_shgroup_call_add(grp, quad, NULL); psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); @@ -230,41 +236,19 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input); - DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); + DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool); + DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth); + DRW_shgroup_uniform_buffer(grp, "hitBuffer", &vedata->txl->ssr_hit_output); + DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &stl->g_data->ssr_pdf_output); DRW_shgroup_uniform_buffer(grp, "prevColorBuffer", &txl->color_double_buffer); - DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_int(grp, "planar_count", &sldata->probes->num_planar, 1); - DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1); - DRW_shgroup_uniform_vec2(grp, "mipRatio[0]", (float *)stl->g_data->mip_ratio, 10); - DRW_shgroup_uniform_float(grp, "borderFadeFactor", &effects->ssr_border_fac, 1); - DRW_shgroup_uniform_float(grp, "maxRoughness", &effects->ssr_max_roughness, 1); - DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1); - DRW_shgroup_uniform_float(grp, "lodPlanarMax", &sldata->probes->lod_planar_max, 1); - DRW_shgroup_uniform_float(grp, "fireflyFactor", &effects->ssr_firefly_fac, 1); DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); - DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool); - DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool); - DRW_shgroup_uniform_buffer(grp, "hitBuffer0", &stl->g_data->ssr_hit_output[0]); - if (effects->ssr_ray_count > 1) { - DRW_shgroup_uniform_buffer(grp, "hitBuffer1", &stl->g_data->ssr_hit_output[1]); - } - if (effects->ssr_ray_count > 2) { - DRW_shgroup_uniform_buffer(grp, "hitBuffer2", &stl->g_data->ssr_hit_output[2]); - } - if (effects->ssr_ray_count > 3) { - DRW_shgroup_uniform_buffer(grp, "hitBuffer3", &stl->g_data->ssr_hit_output[3]); - } - - DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &effects->ao_dist, 2); - if (effects->use_ao) { + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); + DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1); + if ((effects->enabled_effects & EFFECT_GTAO) != 0) { + DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &vedata->txl->gtao_horizons); - DRW_shgroup_uniform_ivec2(grp, "aoHorizonTexSize", (int *)vedata->stl->effects->ao_texsize, 1); - } - else { - /* Use shadow_pool as fallback to avoid sampling problem on certain platform, see: T52593 */ - DRW_shgroup_uniform_buffer(grp, "horizonBuffer", &sldata->shadow_pool); } DRW_shgroup_call_add(grp, quad, NULL); @@ -301,22 +285,39 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v e_data.depth_src = dtxl->depth; DRW_stats_group_start("SSR"); - - for (int i = 0; i < effects->ssr_ray_count; ++i) { - DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_hit_output[i], i, 0); - } + DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_pdf_output, 1, 0); DRW_framebuffer_bind(fbl->screen_tracing_fb); /* Raytrace. */ DRW_draw_pass(psl->ssr_raytrace); - for (int i = 0; i < effects->ssr_ray_count; ++i) { - DRW_framebuffer_texture_detach(stl->g_data->ssr_hit_output[i]); - } + DRW_framebuffer_texture_detach(stl->g_data->ssr_pdf_output); EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->color_double_buffer, 9); /* Resolve at fullres */ + int sample = (DRW_state_is_image_render()) ? effects->taa_render_sample : effects->taa_current_sample; + /* Doing a neighbor shift only after a few iteration. We wait for a prime number of cycles to avoid + * noise correlation. This reduces variance faster. */ + effects->ssr_neighbor_ofs = ((sample / 5) % 8) * 4; + switch ((sample / 11) % 4) { + case 0: + effects->ssr_halfres_ofs[0] = 0; + effects->ssr_halfres_ofs[1] = 0; + break; + case 1: + effects->ssr_halfres_ofs[0] = 0; + effects->ssr_halfres_ofs[1] = 1; + break; + case 2: + effects->ssr_halfres_ofs[0] = 1; + effects->ssr_halfres_ofs[1] = 0; + break; + case 4: + effects->ssr_halfres_ofs[0] = 1; + effects->ssr_halfres_ofs[1] = 1; + break; + } DRW_framebuffer_texture_detach(dtxl->depth); DRW_framebuffer_texture_detach(txl->ssr_normal_input); DRW_framebuffer_texture_detach(txl->ssr_specrough_input); diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c index 4efdfb0fb84..17da4a18b78 100644 --- a/source/blender/draw/engines/eevee/eevee_subsurface.c +++ b/source/blender/draw/engines/eevee/eevee_subsurface.c @@ -27,7 +27,7 @@ #include "DRW_render.h" -#include "BLI_dynstr.h" +#include "BLI_string_utils.h" #include "eevee_private.h" #include "GPU_texture.h" @@ -36,18 +36,26 @@ static struct { struct GPUShader *sss_sh[3]; } e_data = {NULL}; /* Engine data */ +extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_effect_subsurface_frag_glsl[]; static void eevee_create_shader_subsurface(void) { - e_data.sss_sh[0] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define FIRST_PASS\n"); - e_data.sss_sh[1] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n"); - e_data.sss_sh[2] = DRW_shader_create_fullscreen(datatoc_effect_subsurface_frag_glsl, "#define SECOND_PASS\n" - "#define USE_SEP_ALBEDO\n"); + char *frag_str = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_effect_subsurface_frag_glsl); + + e_data.sss_sh[0] = DRW_shader_create_fullscreen(frag_str, "#define FIRST_PASS\n"); + e_data.sss_sh[1] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n"); + e_data.sss_sh[2] = DRW_shader_create_fullscreen(frag_str, "#define SECOND_PASS\n" + "#define USE_SEP_ALBEDO\n"); + + MEM_freeN(frag_str); } -int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) +int EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) { + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; EEVEE_StorageList *stl = vedata->stl; EEVEE_EffectsInfo *effects = stl->effects; EEVEE_FramebufferList *fbl = vedata->fbl; @@ -60,8 +68,8 @@ int EEVEE_subsurface_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedat if (BKE_collection_engine_property_value_get_bool(props, "sss_enable")) { effects->sss_sample_count = 1 + BKE_collection_engine_property_value_get_int(props, "sss_samples") * 2; - effects->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold"); effects->sss_separate_albedo = BKE_collection_engine_property_value_get_bool(props, "sss_separate_albedo"); + common_data->sss_jitter_threshold = BKE_collection_engine_property_value_get_float(props, "sss_jitter_threshold"); /* Shaders */ if (!e_data.sss_sh[0]) { @@ -117,7 +125,8 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data } } -void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile) +void EEVEE_subsurface_add_pass( + EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, unsigned int sss_id, struct GPUUniformBuffer *sss_profile) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); EEVEE_TextureList *txl = vedata->txl; @@ -127,23 +136,21 @@ void EEVEE_subsurface_add_pass(EEVEE_Data *vedata, unsigned int sss_id, struct G struct Gwn_Batch *quad = DRW_cache_fullscreen_quad_get(); DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_data); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); - DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call_add(grp, quad, NULL); struct GPUShader *sh = (effects->sss_separate_albedo) ? e_data.sss_sh[2] : e_data.sss_sh[1]; grp = DRW_shgroup_create(sh, psl->sss_resolve_ps); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2); DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex()); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &dtxl->depth); DRW_shgroup_uniform_buffer(grp, "sssData", &txl->sss_blur); DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile); - DRW_shgroup_uniform_float(grp, "jitterThreshold", &effects->sss_jitter_threshold, 1); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_stencil_mask(grp, sss_id); DRW_shgroup_call_add(grp, quad, NULL); diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c index 5faac4c42cc..24b8117b6f5 100644 --- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c +++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c @@ -44,6 +44,23 @@ static void eevee_create_shader_temporal_sampling(void) e_data.taa_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_temporal_aa_glsl, NULL); } +void EEVEE_temporal_sampling_matrices_calc( + EEVEE_EffectsInfo *effects, float viewmat[4][4], float persmat[4][4], double ht_point[2]) +{ + const float *viewport_size = DRW_viewport_size_get(); + + /* TODO Blackman-Harris filter */ + + window_translate_m4( + effects->overide_winmat, persmat, + ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0], + ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]); + + mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat); + invert_m4_m4(effects->overide_persinv, effects->overide_persmat); + invert_m4_m4(effects->overide_wininv, effects->overide_winmat); +} + int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata) { EEVEE_StorageList *stl = vedata->stl; @@ -51,14 +68,21 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects = stl->effects; + /* Reset for each "redraw". When rendering using ogl render, + * we accumulate the redraw inside the drawing loop in eevee_draw_background(). + * But we do NOT accumulate between "redraw" (as in full draw manager drawloop) + * because the opengl render already does that. */ + effects->taa_render_sample = 1; + const DRWContextState *draw_ctx = DRW_context_state_get(); ViewLayer *view_layer = draw_ctx->view_layer; IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); - if (BKE_collection_engine_property_value_get_int(props, "taa_samples") != 1 && + if ((BKE_collection_engine_property_value_get_int(props, "taa_samples") != 1 && /* FIXME the motion blur camera evaluation is tagging view_updated * thus making the TAA always reset and never stopping rendering. */ - (effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) + (effects->enabled_effects & EFFECT_MOTION_BLUR) == 0) || + DRW_state_is_image_render()) { const float *viewport_size = DRW_viewport_size_get(); float persmat[4][4], viewmat[4][4]; @@ -79,40 +103,41 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data DRW_viewport_matrix_get(persmat, DRW_MAT_PERS); DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW); DRW_viewport_matrix_get(effects->overide_winmat, DRW_MAT_WIN); - view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN); - copy_m4_m4(effects->prev_drw_persmat, persmat); + /* The view is jittered by the oglrenderer. So avoid testing in this case. */ + if (!DRW_state_is_image_render()) { + view_is_valid = view_is_valid && compare_m4m4(persmat, effects->prev_drw_persmat, FLT_MIN); + copy_m4_m4(effects->prev_drw_persmat, persmat); + } /* Prevent ghosting from probe data. */ view_is_valid = view_is_valid && (effects->prev_drw_support == DRW_state_draw_support()); effects->prev_drw_support = DRW_state_draw_support(); - if (view_is_valid && - ((effects->taa_total_sample == 0) || - (effects->taa_current_sample < effects->taa_total_sample))) + if (((effects->taa_total_sample == 0) || (effects->taa_current_sample < effects->taa_total_sample)) || + DRW_state_is_image_render()) { - effects->taa_current_sample += 1; - - effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample); - - double ht_point[2]; - double ht_offset[2] = {0.0, 0.0}; - unsigned int ht_primes[2] = {2, 3}; - - BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point); - - window_translate_m4( - effects->overide_winmat, persmat, - ((float)(ht_point[0]) * 2.0f - 1.0f) / viewport_size[0], - ((float)(ht_point[1]) * 2.0f - 1.0f) / viewport_size[1]); - - mul_m4_m4m4(effects->overide_persmat, effects->overide_winmat, viewmat); - invert_m4_m4(effects->overide_persinv, effects->overide_persmat); - invert_m4_m4(effects->overide_wininv, effects->overide_winmat); - - DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS); - DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV); - DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN); - DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV); + if (view_is_valid) { + /* OGL render already jitter the camera. */ + if (!DRW_state_is_image_render()) { + effects->taa_current_sample += 1; + + double ht_point[2]; + double ht_offset[2] = {0.0, 0.0}; + unsigned int ht_primes[2] = {2, 3}; + + BLI_halton_2D(ht_primes, ht_offset, effects->taa_current_sample - 1, ht_point); + + EEVEE_temporal_sampling_matrices_calc(effects, viewmat, persmat, ht_point); + + DRW_viewport_matrix_override_set(effects->overide_persmat, DRW_MAT_PERS); + DRW_viewport_matrix_override_set(effects->overide_persinv, DRW_MAT_PERSINV); + DRW_viewport_matrix_override_set(effects->overide_winmat, DRW_MAT_WIN); + DRW_viewport_matrix_override_set(effects->overide_wininv, DRW_MAT_WININV); + } + } + else { + effects->taa_current_sample = 1; + } } else { effects->taa_current_sample = 1; @@ -127,6 +152,8 @@ int EEVEE_temporal_sampling_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data return EFFECT_TAA | EFFECT_DOUBLE_BUFFER | EFFECT_POST_BUFFER; } + effects->taa_current_sample = 1; + /* Cleanup to release memory */ DRW_TEXTURE_FREE_SAFE(txl->depth_double_buffer); DRW_FRAMEBUFFER_FREE_SAFE(fbl->depth_double_buffer_fb); @@ -162,11 +189,21 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata) if ((effects->enabled_effects & EFFECT_TAA) != 0) { if (effects->taa_current_sample != 1) { + if (DRW_state_is_image_render()) { + /* See EEVEE_temporal_sampling_init() for more details. */ + effects->taa_alpha = 1.0f / (float)(effects->taa_render_sample); + } + else { + effects->taa_alpha = 1.0f / (float)(effects->taa_current_sample); + } + DRW_framebuffer_bind(fbl->effect_fb); DRW_draw_pass(psl->taa_resolve); /* Restore the depth from sample 1. */ - DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false); + if (!DRW_state_is_image_render()) { + DRW_framebuffer_blit(fbl->depth_double_buffer_fb, fbl->main, true, false); + } /* Special Swap */ SWAP(struct GPUFrameBuffer *, fbl->effect_fb, fbl->double_buffer); @@ -179,15 +216,25 @@ void EEVEE_temporal_sampling_draw(EEVEE_Data *vedata) /* Save the depth buffer for the next frame. * This saves us from doing anything special * in the other mode engines. */ - DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false); + if (!DRW_state_is_image_render()) { + DRW_framebuffer_blit(fbl->main, fbl->depth_double_buffer_fb, true, false); + } } - if ((effects->taa_total_sample == 0) || - (effects->taa_current_sample < effects->taa_total_sample)) - { - DRW_viewport_request_redraw(); + /* Make each loop count when doing a render. */ + if (DRW_state_is_image_render()) { + effects->taa_render_sample += 1; + effects->taa_current_sample += 1; + } + else { + if ((effects->taa_total_sample == 0) || + (effects->taa_current_sample < effects->taa_total_sample)) + { + DRW_viewport_request_redraw(); + } } } + } void EEVEE_temporal_sampling_free(void) diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c index dae4503dc32..a960682e8c9 100644 --- a/source/blender/draw/engines/eevee/eevee_volumes.c +++ b/source/blender/draw/engines/eevee/eevee_volumes.c @@ -27,8 +27,8 @@ #include "DRW_render.h" -#include "BLI_dynstr.h" #include "BLI_rand.h" +#include "BLI_string_utils.h" #include "DNA_object_force.h" #include "DNA_smoke_types.h" @@ -51,6 +51,7 @@ static struct { struct GPUShader *volumetric_clear_sh; struct GPUShader *volumetric_scatter_sh; + struct GPUShader *volumetric_scatter_with_lamps_sh; struct GPUShader *volumetric_integration_sh; struct GPUShader *volumetric_resolve_sh; @@ -63,6 +64,7 @@ static struct { extern char datatoc_bsdf_common_lib_glsl[]; extern char datatoc_bsdf_direct_lib_glsl[]; +extern char datatoc_common_uniforms_lib_glsl[]; extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_irradiance_lib_glsl[]; extern char datatoc_lamps_lib_glsl[]; @@ -77,21 +79,19 @@ extern char datatoc_gpu_shader_fullscreen_vert_glsl[]; static void eevee_create_shader_volumes(void) { - DynStr *ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl); - e_data.volumetric_common_lib = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); - - ds_frag = BLI_dynstr_new(); - BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_bsdf_direct_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_irradiance_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_lamps_lib_glsl); - BLI_dynstr_append(ds_frag, datatoc_volumetric_lib_glsl); - e_data.volumetric_common_lamps_lib = BLI_dynstr_get_cstring(ds_frag); - BLI_dynstr_free(ds_frag); + e_data.volumetric_common_lib = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_volumetric_lib_glsl); + + e_data.volumetric_common_lamps_lib = BLI_string_joinN( + datatoc_common_uniforms_lib_glsl, + datatoc_bsdf_common_lib_glsl, + datatoc_bsdf_direct_lib_glsl, + datatoc_octahedron_lib_glsl, + datatoc_irradiance_lib_glsl, + datatoc_lamps_lib_glsl, + datatoc_volumetric_lib_glsl); e_data.volumetric_clear_sh = DRW_shader_create_with_lib( datatoc_volumetric_vert_glsl, @@ -108,6 +108,15 @@ static void eevee_create_shader_volumes(void) SHADER_DEFINES "#define VOLUMETRICS\n" "#define VOLUME_SHADOW\n"); + e_data.volumetric_scatter_with_lamps_sh = DRW_shader_create_with_lib( + datatoc_volumetric_vert_glsl, + datatoc_volumetric_geom_glsl, + datatoc_volumetric_scatter_frag_glsl, + e_data.volumetric_common_lamps_lib, + SHADER_DEFINES + "#define VOLUMETRICS\n" + "#define VOLUME_LIGHTING\n" + "#define VOLUME_SHADOW\n"); e_data.volumetric_integration_sh = DRW_shader_create_with_lib( datatoc_volumetric_vert_glsl, datatoc_volumetric_geom_glsl, @@ -125,6 +134,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_FramebufferList *fbl = vedata->fbl; EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; const DRWContextState *draw_ctx = DRW_context_state_get(); ViewLayer *view_layer = draw_ctx->view_layer; @@ -141,29 +151,23 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) eevee_create_shader_volumes(); } - if (sldata->volumetrics == NULL) { - sldata->volumetrics = MEM_callocN(sizeof(EEVEE_VolumetricsInfo), "EEVEE_VolumetricsInfo"); - } - - EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics; - int tile_size = BKE_collection_engine_property_value_get_int(props, "volumetric_tile_size"); /* Find Froxel Texture resolution. */ - int froxel_tex_size[3]; + int tex_size[3]; - froxel_tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size)); - froxel_tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size)); - froxel_tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1); + tex_size[0] = (int)ceilf(fmaxf(1.0f, viewport_size[0] / (float)tile_size)); + tex_size[1] = (int)ceilf(fmaxf(1.0f, viewport_size[1] / (float)tile_size)); + tex_size[2] = max_ii(BKE_collection_engine_property_value_get_int(props, "volumetric_samples"), 1); - volumetrics->volume_coord_scale[0] = viewport_size[0] / (float)(tile_size * froxel_tex_size[0]); - volumetrics->volume_coord_scale[1] = viewport_size[1] / (float)(tile_size * froxel_tex_size[1]); + common_data->vol_coord_scale[0] = viewport_size[0] / (float)(tile_size * tex_size[0]); + common_data->vol_coord_scale[1] = viewport_size[1] / (float)(tile_size * tex_size[1]); /* TODO compute snap to maxZBuffer for clustered rendering */ - if ((volumetrics->froxel_tex_size[0] != froxel_tex_size[0]) || - (volumetrics->froxel_tex_size[1] != froxel_tex_size[1]) || - (volumetrics->froxel_tex_size[2] != froxel_tex_size[2])) + if ((common_data->vol_tex_size[0] != tex_size[0]) || + (common_data->vol_tex_size[1] != tex_size[1]) || + (common_data->vol_tex_size[2] != tex_size[2])) { DRW_TEXTURE_FREE_SAFE(txl->volume_prop_scattering); DRW_TEXTURE_FREE_SAFE(txl->volume_prop_extinction); @@ -176,38 +180,46 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_fb); DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_scat_fb); DRW_FRAMEBUFFER_FREE_SAFE(fbl->volumetric_integ_fb); - volumetrics->froxel_tex_size[0] = froxel_tex_size[0]; - volumetrics->froxel_tex_size[1] = froxel_tex_size[1]; - volumetrics->froxel_tex_size[2] = froxel_tex_size[2]; + common_data->vol_tex_size[0] = tex_size[0]; + common_data->vol_tex_size[1] = tex_size[1]; + common_data->vol_tex_size[2] = tex_size[2]; - volumetrics->inv_tex_size[0] = 1.0f / (float)(volumetrics->froxel_tex_size[0]); - volumetrics->inv_tex_size[1] = 1.0f / (float)(volumetrics->froxel_tex_size[1]); - volumetrics->inv_tex_size[2] = 1.0f / (float)(volumetrics->froxel_tex_size[2]); + common_data->vol_inv_tex_size[0] = 1.0f / (float)(tex_size[0]); + common_data->vol_inv_tex_size[1] = 1.0f / (float)(tex_size[1]); + common_data->vol_inv_tex_size[2] = 1.0f / (float)(tex_size[2]); } /* Like frostbite's paper, 5% blend of the new frame. */ - volumetrics->history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f; + common_data->vol_history_alpha = (txl->volume_prop_scattering == NULL) ? 0.0f : 0.95f; if (txl->volume_prop_scattering == NULL) { /* Volume properties: We evaluate all volumetric objects * and store their final properties into each froxel */ - txl->volume_prop_scattering = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); - txl->volume_prop_extinction = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); - txl->volume_prop_emission = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); - txl->volume_prop_phase = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RG_16, DRW_TEX_FILTER, NULL); + txl->volume_prop_scattering = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_prop_extinction = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_prop_emission = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_prop_phase = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RG_16, DRW_TEX_FILTER, NULL); /* Volume scattering: We compute for each froxel the * Scattered light towards the view. We also resolve temporal * super sampling during this stage. */ - txl->volume_scatter = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); - txl->volume_transmittance = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_scatter = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_transmittance = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); /* Final integration: We compute for each froxel the * amount of scattered light and extinction coef at this * given depth. We use theses textures as double buffer * for the volumetric history. */ - txl->volume_scatter_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); - txl->volume_transmittance_history = DRW_texture_create_3D(froxel_tex_size[0], froxel_tex_size[1], froxel_tex_size[2], DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_scatter_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); + txl->volume_transmittance_history = DRW_texture_create_3D(tex_size[0], tex_size[1], tex_size[2], + DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER, NULL); } /* Temporal Super sampling jitter */ @@ -225,7 +237,7 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } if (do_taa) { - volumetrics->history_alpha = 0.0f; + common_data->vol_history_alpha = 0.0f; current_sample = effects->taa_current_sample - 1; effects->volume_current_sample = -1; } @@ -238,9 +250,9 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) } BLI_halton_3D(ht_primes, ht_offset, current_sample, ht_point); - volumetrics->jitter[0] = (float)ht_point[0]; - volumetrics->jitter[1] = (float)ht_point[1]; - volumetrics->jitter[2] = (float)ht_point[2]; + common_data->vol_jitter[0] = (float)ht_point[0]; + common_data->vol_jitter[1] = (float)ht_point[1]; + common_data->vol_jitter[2] = (float)ht_point[2]; /* Framebuffer setup */ DRWFboTexture tex_vol[4] = {{&txl->volume_prop_scattering, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}, @@ -249,63 +261,64 @@ int EEVEE_volumes_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) {&txl->volume_prop_phase, DRW_TEX_RG_16, DRW_TEX_FILTER}}; DRW_framebuffer_init(&fbl->volumetric_fb, &draw_engine_eevee_type, - (int)froxel_tex_size[0], (int)froxel_tex_size[1], + (int)tex_size[0], (int)tex_size[1], tex_vol, 4); DRWFboTexture tex_vol_scat[2] = {{&txl->volume_scatter, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}, {&txl->volume_transmittance, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}}; DRW_framebuffer_init(&fbl->volumetric_scat_fb, &draw_engine_eevee_type, - (int)froxel_tex_size[0], (int)froxel_tex_size[1], + (int)tex_size[0], (int)tex_size[1], tex_vol_scat, 2); DRWFboTexture tex_vol_integ[2] = {{&txl->volume_scatter_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}, {&txl->volume_transmittance_history, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER}}; DRW_framebuffer_init(&fbl->volumetric_integ_fb, &draw_engine_eevee_type, - (int)froxel_tex_size[0], (int)froxel_tex_size[1], + (int)tex_size[0], (int)tex_size[1], tex_vol_integ, 2); - volumetrics->integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start"); - volumetrics->integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end"); - volumetrics->sample_distribution = 4.0f * (1.00001f - BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution")); - volumetrics->use_volume_shadows = BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows"); - volumetrics->light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp"); + float integration_start = BKE_collection_engine_property_value_get_float(props, "volumetric_start"); + float integration_end = BKE_collection_engine_property_value_get_float(props, "volumetric_end"); + common_data->vol_light_clamp = BKE_collection_engine_property_value_get_float(props, "volumetric_light_clamp"); - if (volumetrics->use_volume_shadows) { - volumetrics->shadow_step_count = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples"); + common_data->vol_shadow_steps = (float)BKE_collection_engine_property_value_get_int(props, "volumetric_shadow_samples"); + if (BKE_collection_engine_property_value_get_bool(props, "volumetric_shadows")) { } else { - volumetrics->shadow_step_count = 0; + common_data->vol_shadow_steps = 0; } if (DRW_viewport_is_persp_get()) { - const float clip_start = stl->g_data->viewvecs[0][2]; + float sample_distribution = BKE_collection_engine_property_value_get_float(props, "volumetric_sample_distribution"); + sample_distribution = 4.0f * (1.00001f - sample_distribution); + + const float clip_start = common_data->view_vecs[0][2]; /* Negate */ - float near = volumetrics->integration_start = min_ff(-volumetrics->integration_start, clip_start - 1e-4f); - float far = volumetrics->integration_end = min_ff(-volumetrics->integration_end, near - 1e-4f); + float near = integration_start = min_ff(-integration_start, clip_start - 1e-4f); + float far = integration_end = min_ff(-integration_end, near - 1e-4f); - volumetrics->depth_param[0] = (far - near * exp2(1.0f / volumetrics->sample_distribution)) / (far - near); - volumetrics->depth_param[1] = (1.0f - volumetrics->depth_param[0]) / near; - volumetrics->depth_param[2] = volumetrics->sample_distribution; + common_data->vol_depth_param[0] = (far - near * exp2(1.0f / sample_distribution)) / (far - near); + common_data->vol_depth_param[1] = (1.0f - common_data->vol_depth_param[0]) / near; + common_data->vol_depth_param[2] = sample_distribution; } else { - const float clip_start = stl->g_data->viewvecs[0][2]; - const float clip_end = stl->g_data->viewvecs[1][2]; - volumetrics->integration_start = min_ff(volumetrics->integration_end, clip_start); - volumetrics->integration_end = max_ff(-volumetrics->integration_end, clip_end); - - volumetrics->depth_param[0] = volumetrics->integration_start; - volumetrics->depth_param[1] = volumetrics->integration_end; - volumetrics->depth_param[2] = 1.0f / (volumetrics->integration_end - volumetrics->integration_start); + const float clip_start = common_data->view_vecs[0][2]; + const float clip_end = common_data->view_vecs[1][2]; + integration_start = min_ff(integration_end, clip_start); + integration_end = max_ff(-integration_end, clip_end); + + common_data->vol_depth_param[0] = integration_start; + common_data->vol_depth_param[1] = integration_end; + common_data->vol_depth_param[2] = 1.0f / (integration_end - integration_start); } /* Disable clamp if equal to 0. */ - if (volumetrics->light_clamp == 0.0) { - volumetrics->light_clamp = FLT_MAX; + if (common_data->vol_light_clamp == 0.0) { + common_data->vol_light_clamp = FLT_MAX; } - volumetrics->use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights"); + common_data->vol_use_lights = BKE_collection_engine_property_value_get_bool(props, "volumetric_lights"); return EFFECT_VOLUMETRIC | EFFECT_POST_BUFFER; } @@ -332,12 +345,11 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) EEVEE_StorageList *stl = vedata->stl; EEVEE_TextureList *txl = vedata->txl; EEVEE_EffectsInfo *effects = stl->effects; + EEVEE_CommonUniformBuffer *common_data = &sldata->common_data; if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { const DRWContextState *draw_ctx = DRW_context_state_get(); Scene *scene = draw_ctx->scene; - EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics; - static int zero = 0; DRWShadingGroup *grp; /* Quick breakdown of the Volumetric rendering: @@ -374,65 +386,59 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata) if (wo != NULL && wo->use_nodes && wo->nodetree) { struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo); - grp = DRW_shgroup_material_empty_tri_batch_create(mat, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]); + grp = DRW_shgroup_material_empty_tri_batch_create(mat, + psl->volumetric_world_ps, + common_data->vol_tex_size[2]); if (grp) { - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1); - DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1); - DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1); - DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); } } else { /* If no world or volume material is present just clear the buffer with this drawcall */ - grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps, volumetrics->froxel_tex_size[2]); + grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_clear_sh, + psl->volumetric_world_ps, + common_data->vol_tex_size[2]); - DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); } /* Volumetric Objects */ - psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); + psl->volumetric_objects_ps = DRW_pass_create("Volumetric Properties", DRW_STATE_WRITE_COLOR | + DRW_STATE_ADDITIVE); + struct GPUShader *scatter_sh = (common_data->vol_use_lights) ? e_data.volumetric_scatter_with_lamps_sh + : e_data.volumetric_scatter_sh; psl->volumetric_scatter_ps = DRW_pass_create("Volumetric Scattering", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_scatter_sh, psl->volumetric_scatter_ps, volumetrics->froxel_tex_size[2]); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1); - DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1); - DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1); - DRW_shgroup_uniform_mat4(grp, "PastViewProjectionMatrix", (float *)stl->g_data->prev_persmat); - DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); - DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); - DRW_shgroup_uniform_int(grp, "light_count", (volumetrics->use_lights) ? &sldata->lamps->num_light : &zero, 1); + grp = DRW_shgroup_empty_tri_batch_create(scatter_sh, psl->volumetric_scatter_ps, + common_data->vol_tex_size[2]); DRW_shgroup_uniform_buffer(grp, "irradianceGrid", &sldata->irradiance_pool); DRW_shgroup_uniform_buffer(grp, "shadowTexture", &sldata->shadow_pool); - DRW_shgroup_uniform_float(grp, "volume_light_clamp", &volumetrics->light_clamp, 1); - DRW_shgroup_uniform_float(grp, "volume_shadows_steps", &volumetrics->shadow_step_count, 1); - DRW_shgroup_uniform_float(grp, "volume_history_alpha", &volumetrics->history_alpha, 1); DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_prop_scattering); DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_prop_extinction); DRW_shgroup_uniform_buffer(grp, "volumeEmission", &txl->volume_prop_emission); DRW_shgroup_uniform_buffer(grp, "volumePhase", &txl->volume_prop_phase); DRW_shgroup_uniform_buffer(grp, "historyScattering", &txl->volume_scatter_history); DRW_shgroup_uniform_buffer(grp, "historyTransmittance", &txl->volume_transmittance_history); + DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo); + DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); psl->volumetric_integration_ps = DRW_pass_create("Volumetric Integration", DRW_STATE_WRITE_COLOR); - grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, psl->volumetric_integration_ps, volumetrics->froxel_tex_size[2]); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1); - DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1); + grp = DRW_shgroup_empty_tri_batch_create(e_data.volumetric_integration_sh, + psl->volumetric_integration_ps, + common_data->vol_tex_size[2]); DRW_shgroup_uniform_buffer(grp, "volumeScattering", &txl->volume_scatter); DRW_shgroup_uniform_buffer(grp, "volumeExtinction", &txl->volume_transmittance); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); psl->volumetric_resolve_ps = DRW_pass_create("Volumetric Resolve", DRW_STATE_WRITE_COLOR); grp = DRW_shgroup_create(e_data.volumetric_resolve_sh, psl->volumetric_resolve_ps); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1); - DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1); DRW_shgroup_uniform_buffer(grp, "inScattering", &txl->volume_scatter); DRW_shgroup_uniform_buffer(grp, "inTransmittance", &txl->volume_transmittance); DRW_shgroup_uniform_buffer(grp, "inSceneColor", &e_data.color_src); DRW_shgroup_uniform_buffer(grp, "inSceneDepth", &e_data.depth_src); + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_call_add(grp, DRW_cache_fullscreen_quad_get(), NULL); } } @@ -442,7 +448,6 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved float *texcoloc = NULL; float *texcosize = NULL; struct ModifierData *md = NULL; - EEVEE_VolumetricsInfo *volumetrics = sldata->volumetrics; Material *ma = give_current_material(ob, 1); if (ma == NULL) { @@ -451,7 +456,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma); - DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, volumetrics->froxel_tex_size[2]); + DRWShadingGroup *grp = DRW_shgroup_material_empty_tri_batch_create(mat, vedata->psl->volumetric_objects_ps, sldata->common_data.vol_tex_size[2]); /* Making sure it's updated. */ invert_m4_m4(ob->imat, ob->obmat); @@ -459,14 +464,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata, EEVEE_Data *ved BKE_mesh_texspace_get_reference((struct Mesh *)ob->data, NULL, &texcoloc, NULL, &texcosize); if (grp) { + DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo); DRW_shgroup_uniform_mat4(grp, "volumeObjectMatrix", (float *)ob->imat); DRW_shgroup_uniform_vec3(grp, "volumeOrcoLoc", texcoloc, 1); DRW_shgroup_uniform_vec3(grp, "volumeOrcoSize", texcosize, 1); - DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2); - DRW_shgroup_uniform_ivec3(grp, "volumeTextureSize", (int *)volumetrics->froxel_tex_size, 1); - DRW_shgroup_uniform_vec2(grp, "volume_uv_ratio", (float *)volumetrics->volume_coord_scale, 1); - DRW_shgroup_uniform_vec3(grp, "volume_param", (float *)volumetrics->depth_param, 1); - DRW_shgroup_uniform_vec3(grp, "volume_jitter", (float *)volumetrics->jitter, 1); } /* Smoke Simulation */ @@ -576,6 +577,7 @@ void EEVEE_volumes_free(void) DRW_SHADER_FREE_SAFE(e_data.volumetric_clear_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_sh); + DRW_SHADER_FREE_SAFE(e_data.volumetric_scatter_with_lamps_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_integration_sh); DRW_SHADER_FREE_SAFE(e_data.volumetric_resolve_sh); } diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl index 5ec72833379..55f66f5500a 100644 --- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl @@ -30,87 +30,18 @@ #ifndef UTIL_TEX #define UTIL_TEX uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ -uniform vec4 aoParameters[2]; -uniform sampler2DArray horizonBuffer; - -/* Cannot use textureSize(horizonBuffer) when rendering to it */ -uniform ivec2 aoHorizonTexSize; - -#define aoDistance aoParameters[0].x -#define aoSamples aoParameters[0].y -#define aoFactor aoParameters[0].z -#define aoInvSamples aoParameters[0].w - -#define aoOffset aoParameters[1].x /* UNUSED */ -#define aoBounceFac aoParameters[1].y -#define aoQuality aoParameters[1].z -#define aoSettings aoParameters[1].w +uniform sampler2D horizonBuffer; +/* aoSettings flags */ #define USE_AO 1 #define USE_BENT_NORMAL 2 #define USE_DENOISE 4 -vec2 pack_horizons(vec2 v) { return v * 0.5 + 0.5; } -vec2 unpack_horizons(vec2 v) { return v * 2.0 - 1.0; } - -/* Returns the texel coordinate in horizonBuffer - * for a given fullscreen coord */ -ivec2 get_hr_co(ivec2 fs_co) -{ - bvec2 quarter = notEqual(fs_co & ivec2(1), ivec2(0)); - - ivec2 hr_co = fs_co / 2; - hr_co += ivec2(quarter) * (aoHorizonTexSize / 2); - - return hr_co; -} - -/* Returns the texel coordinate in fullscreen (depthBuffer) - * for a given horizonBuffer coord */ -ivec2 get_fs_co(ivec2 hr_co) -{ - hr_co *= 2; - bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize); - - hr_co -= ivec2(quarter) * (aoHorizonTexSize - 1); - - return hr_co; -} - -/* Returns the phi angle in horizonBuffer - * for a given horizonBuffer coord */ -float get_phi(ivec2 hr_co, ivec2 fs_co, float sample) -{ - bvec2 quarter = greaterThanEqual(hr_co, aoHorizonTexSize / 2); - ivec2 tex_co = ((int(aoSettings) & USE_DENOISE) != 0) ? hr_co - ivec2(quarter) * (aoHorizonTexSize / 2) : fs_co; - float blue_noise = texture(utilTex, vec3((vec2(tex_co) + 0.5) / LUT_SIZE, 2.0)).r; - - float phi = sample * aoInvSamples; - - if ((int(aoSettings) & USE_DENOISE) != 0) { - /* Interleaved jitter for spatial 2x2 denoising */ - phi += 0.25 * aoInvSamples * (float(quarter.x) + 2.0 * float(quarter.y)); - blue_noise *= 0.25; - } - /* Blue noise is scaled to cover the rest of the range. */ - phi += aoInvSamples * blue_noise; - phi *= M_PI; - - return phi; -} - -/* Returns direction jittered offset for a given fullscreen coord */ -float get_offset(ivec2 fs_co, float sample) -{ - float offset = sample * aoInvSamples; - - /* Interleaved jitter for spatial 2x2 denoising */ - offset += 0.25 * dot(vec2(1.0), vec2(fs_co & 1)); - offset += texture(utilTex, vec3((vec2(fs_co / 2) + 0.5 + 16.0) / LUT_SIZE, 2.0)).r; - return offset; -} +vec4 pack_horizons(vec4 v) { return v * 0.5 + 0.5; } +vec4 unpack_horizons(vec4 v) { return v * 2.0 - 1.0; } /* Returns maximum screen distance an AO ray can travel for a given view depth */ vec2 get_max_dir(float view_depth) @@ -120,6 +51,13 @@ vec2 get_max_dir(float view_depth) return vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) * max_dist; } +vec2 get_ao_dir(float jitter) +{ + /* Only half a turn because we integrate in slices. */ + jitter *= M_PI; + return vec2(cos(jitter), sin(jitter)); +} + void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h) { co1 *= mipRatio[int(lod + 1.0)].xyxy; /* +1 because we are using half res top level */ @@ -161,10 +99,8 @@ void get_max_horizon_grouped(vec4 co1, vec4 co2, vec3 x, float lod, inout float h = mix(h, max(h, s_h.w), blend.w); } -vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir) +vec2 search_horizon_sweep(vec2 t_phi, vec3 pos, vec2 uvs, float jitter, vec2 max_dir) { - vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */ - max_dir *= max_v2(abs(t_phi)); /* Convert to pixel space. */ @@ -214,11 +150,8 @@ vec2 search_horizon_sweep(float phi, vec3 pos, vec2 uvs, float jitter, vec2 max_ return h; } -void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibility, inout vec3 bent_normal) +void integrate_slice(vec3 normal, vec2 t_phi, vec2 horizons, inout float visibility, inout vec3 bent_normal) { - /* TODO OPTI Could be precomputed. */ - vec2 t_phi = vec2(cos(phi), sin(phi)); /* Screen space direction */ - /* Projecting Normal to Plane P defined by t_phi and omega_o */ vec3 np = vec3(t_phi.y, -t_phi.x, 0.0); /* Normal vector to Integration plane */ vec3 t = vec3(-t_phi, 0.0); @@ -251,71 +184,43 @@ void integrate_slice(vec3 normal, float phi, vec2 horizons, inout float visibili bent_normal += vec3(sin(b_angle) * -t_phi, cos(b_angle) * 0.5); } -void denoise_ao(vec3 normal, float frag_depth, inout float visibility, inout vec3 bent_normal) +void gtao_deferred(vec3 normal, vec3 position, vec4 noise, float frag_depth, out float visibility, out vec3 bent_normal) { - vec2 d_sign = vec2(ivec2(gl_FragCoord.xy) & 1) - 0.5; - - if ((int(aoSettings) & USE_DENOISE) == 0) { - d_sign *= 0.0; - } - - /* 2x2 Bilateral Filter using derivatives. */ - vec2 n_step = step(-0.2, -abs(vec2(length(dFdx(normal)), length(dFdy(normal))))); - vec2 z_step = step(-0.1, -abs(vec2(dFdx(frag_depth), dFdy(frag_depth)))); - - visibility -= dFdx(visibility) * d_sign.x * z_step.x * n_step.x; - visibility -= dFdy(visibility) * d_sign.y * z_step.y * n_step.y; + /* Fetch early, hide latency! */ + vec4 horizons = texelFetch(horizonBuffer, ivec2(gl_FragCoord.xy), 0); - bent_normal -= dFdx(bent_normal) * d_sign.x * z_step.x * n_step.x; - bent_normal -= dFdy(bent_normal) * d_sign.y * z_step.y * n_step.y; -} - -void gtao_deferred(vec3 normal, vec3 position, float frag_depth, out float visibility, out vec3 bent_normal) -{ + vec4 dirs; + dirs.xy = get_ao_dir(noise.x * 0.5); + dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5); vec2 uvs = get_uvs_from_view(position); - vec4 texel_size = vec4(-1.0, -1.0, 1.0, 1.0) / vec2(textureSize(depthBuffer, 0)).xyxy; - - ivec2 fs_co = ivec2(gl_FragCoord.xy); - ivec2 hr_co = get_hr_co(fs_co); - bent_normal = vec3(0.0); visibility = 0.0; - for (float i = 0.0; i < MAX_PHI_STEP; i++) { - if (i >= aoSamples) break; + horizons = unpack_horizons(horizons); - vec2 horiz = unpack_horizons(texelFetch(horizonBuffer, ivec3(hr_co, int(i)), 0).rg); - float phi = get_phi(hr_co, fs_co, i); + integrate_slice(normal, dirs.xy, horizons.xy, visibility, bent_normal); + integrate_slice(normal, dirs.zw, horizons.zw, visibility, bent_normal); - integrate_slice(normal, phi, horiz.xy, visibility, bent_normal); - } + visibility *= 0.5; /* We integrated 2 slices. */ - visibility *= aoInvSamples; bent_normal = normalize(bent_normal); } -void gtao(vec3 normal, vec3 position, vec2 noise, out float visibility, out vec3 bent_normal) +void gtao(vec3 normal, vec3 position, vec4 noise, out float visibility, out vec3 bent_normal) { vec2 uvs = get_uvs_from_view(position); - - float homcco = ProjectionMatrix[2][3] * position.z + ProjectionMatrix[3][3]; - float max_dist = aoDistance / homcco; /* Search distance */ - vec2 max_dir = max_dist * vec2(ProjectionMatrix[0][0], ProjectionMatrix[1][1]); + vec2 max_dir = get_max_dir(position.z); + vec2 dir = get_ao_dir(noise.x); bent_normal = vec3(0.0); visibility = 0.0; - for (float i = 0.0; i < MAX_PHI_STEP; i++) { - if (i >= aoSamples) break; - - float phi = M_PI * (i + noise.x) * aoInvSamples; - vec2 horizons = search_horizon_sweep(phi, position, uvs, noise.g, max_dir); - - integrate_slice(normal, phi, horizons, visibility, bent_normal); - } + /* Only trace in 2 directions. May lead to a darker result but since it's mostly for + * alpha blended objects that will have overdraw, we limit the performance impact. */ + vec2 horizons = search_horizon_sweep(dir, position, uvs, noise.y, max_dir); + integrate_slice(normal, dir, horizons, visibility, bent_normal); - visibility *= aoInvSamples; bent_normal = normalize(bent_normal); } @@ -337,7 +242,7 @@ float gtao_multibounce(float visibility, vec3 albedo) } /* Use the right occlusion */ -float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, out vec3 bent_normal) +float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec4 rand, out vec3 bent_normal) { #ifndef USE_REFRACTION if ((int(aoSettings) & USE_AO) > 0) { @@ -345,11 +250,10 @@ float occlusion_compute(vec3 N, vec3 vpos, float user_occlusion, vec2 randuv, ou vec3 vnor = mat3(ViewMatrix) * N; #ifdef ENABLE_DEFERED_AO - gtao_deferred(vnor, vpos, gl_FragCoord.z, visibility, bent_normal); + gtao_deferred(vnor, vpos, rand, gl_FragCoord.z, visibility, bent_normal); #else - gtao(vnor, vpos, randuv, visibility, bent_normal); + gtao(vnor, vpos, rand, visibility, bent_normal); #endif - denoise_ao(vnor, gl_FragCoord.z, visibility, bent_normal); /* Prevent some problems down the road. */ visibility = max(1e-3, visibility); diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index 37ed2235c6f..68299fe7546 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -11,7 +11,6 @@ uniform mat4 ProjectionMatrix; uniform mat4 ViewProjectionMatrix; uniform mat4 ViewMatrixInverse; -uniform vec4 viewvecs[2]; #ifndef SHADOW_SHADER uniform mat4 ViewMatrix; #else @@ -31,8 +30,6 @@ flat in int shFace; /* Shadow layer we are rendering to. */ #define ViewMatrix FaceViewMatrix[shFace] #endif -uniform vec2 mipRatio[10]; - /* Buffers */ uniform sampler2D colorBuffer; uniform sampler2D depthBuffer; @@ -125,6 +122,10 @@ float min_v3(vec3 v) { return min(v.x, min(v.y, v.z)); } float max_v2(vec2 v) { return max(v.x, v.y); } float max_v3(vec3 v) { return max(v.x, max(v.y, v.z)); } +float sum(vec2 v) { return dot(vec2(1.0), v); } +float sum(vec3 v) { return dot(vec3(1.0), v); } +float sum(vec4 v) { return dot(vec4(1.0), v); } + float saturate(float a) { return clamp(a, 0.0, 1.0); } vec2 saturate(vec2 a) { return clamp(a, 0.0, 1.0); } vec3 saturate(vec3 a) { return clamp(a, 0.0, 1.0); } @@ -300,7 +301,7 @@ float get_view_z_from_depth(float depth) return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); } else { - return viewvecs[0].z + depth * viewvecs[1].z; + return viewVecs[0].z + depth * viewVecs[1].z; } } @@ -311,7 +312,7 @@ float get_depth_from_view_z(float z) return d * 0.5 + 0.5; } else { - return (z - viewvecs[0].z) / viewvecs[1].z; + return (z - viewVecs[0].z) / viewVecs[1].z; } } @@ -324,10 +325,10 @@ vec2 get_uvs_from_view(vec3 view) vec3 get_view_space_from_depth(vec2 uvcoords, float depth) { if (ProjectionMatrix[3][3] == 0.0) { - return (viewvecs[0].xyz + vec3(uvcoords, 0.0) * viewvecs[1].xyz) * get_view_z_from_depth(depth); + return (viewVecs[0].xyz + vec3(uvcoords, 0.0) * viewVecs[1].xyz) * get_view_z_from_depth(depth); } else { - return viewvecs[0].xyz + vec3(uvcoords, depth) * viewvecs[1].xyz; + return viewVecs[0].xyz + vec3(uvcoords, depth) * viewVecs[1].xyz; } } @@ -545,7 +546,7 @@ vec3 F_schlick(vec3 f0, float cos_theta) /* Fresnel approximation for LTC area lights (not MRP) */ vec3 F_area(vec3 f0, vec2 lut) { - vec2 fac = normalize(lut.xy); + vec2 fac = normalize(lut.xy); /* XXX FIXME this does not work!!! */ /* Unreal specular matching : if specular color is below 2% intensity, * treat as shadowning */ @@ -691,7 +692,6 @@ Closure closure_mix(Closure cl1, Closure cl2, float fac) } else { cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ - cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ cl.ssr_normal = cl2.ssr_normal; cl.ssr_id = cl2.ssr_id; } @@ -739,12 +739,10 @@ Closure closure_add(Closure cl1, Closure cl2) #endif #endif cl.radiance = cl1.radiance + cl2.radiance; - cl.opacity = cl1.opacity + cl2.opacity; + cl.opacity = saturate(cl1.opacity + cl2.opacity); return cl; } -uniform bool sssToggle; - #if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER) && !defined(USE_MULTIPLY) layout(location = 0) out vec4 fragColor; #ifdef USE_SSS @@ -774,6 +772,10 @@ vec4 volumetric_resolve(vec4 scene_color, vec2 frag_uvs, float frag_depth); void main() { Closure cl = nodetree_exec(); +#ifndef USE_ALPHA_BLEND + /* Prevent alpha hash material writing into alpha channel. */ + cl.opacity = 1.0; +#endif #if defined(USE_ALPHA_BLEND_VOLUMETRICS) /* XXX fragile, better use real viewport resolution */ diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl index ae03f22ac14..ddc7327334c 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl @@ -28,56 +28,30 @@ float direct_diffuse_sun(LightData ld, vec3 N) return bsdf; } -/* From Frostbite PBR Course - * Analytical irradiance from a sphere with correct horizon handling - * http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf */ +#ifdef USE_LTC float direct_diffuse_sphere(LightData ld, vec3 N, vec4 l_vector) { - float dist = l_vector.w; - vec3 L = l_vector.xyz / dist; - float radius = max(ld.l_sizex, 0.0001); - float costheta = clamp(dot(N, L), -0.999, 0.999); - float h = min(ld.l_radius / dist , 0.9999); - float h2 = h*h; - float costheta2 = costheta * costheta; - float bsdf; - - if (costheta2 > h2) { - bsdf = M_PI * h2 * clamp(costheta, 0.0, 1.0); - } - else { - float sintheta = sqrt(1.0 - costheta2); - float x = sqrt(1.0 / h2 - 1.0); - float y = -x * (costheta / sintheta); - float sinthetasqrty = sintheta * sqrt(1.0 - y * y); - bsdf = (costheta * acos(y) - x * sinthetasqrty) * h2 + atan(sinthetasqrty / x); - } - - bsdf = max(bsdf, 0.0); - bsdf *= M_1_PI2; + float NL = dot(N, l_vector.xyz / l_vector.w); - return bsdf; + return ltc_evaluate_disk_simple(ld.l_radius / l_vector.w, NL); } -#ifdef USE_LTC float direct_diffuse_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector) { vec3 corners[4]; - corners[0] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey; - corners[1] = l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey; - corners[2] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey; - corners[3] = l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey; + corners[0] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * ld.l_sizey); + corners[1] = normalize(l_vector.xyz + ld.l_right * -ld.l_sizex + ld.l_up * -ld.l_sizey); + corners[2] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * -ld.l_sizey); + corners[3] = normalize(l_vector.xyz + ld.l_right * ld.l_sizex + ld.l_up * ld.l_sizey); - float bsdf = ltc_evaluate(N, V, mat3(1.0), corners); - bsdf *= M_1_2PI; - return bsdf; + return ltc_evaluate_quad(corners, N); } -#endif -#if 0 -float direct_diffuse_unit_disc(vec3 N, vec3 L) +float direct_diffuse_unit_disc(LightData ld, vec3 N, vec3 V) { + float NL = dot(N, -ld.l_forward); + return ltc_evaluate_disk_simple(ld.l_radius, NL); } #endif @@ -106,47 +80,27 @@ vec3 direct_ggx_sun(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0) #ifdef USE_LTC vec3 direct_ggx_sphere(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness, vec3 f0) { - vec3 L = l_vector.xyz / l_vector.w; - vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughness); - vec3 P = line_aligned_plane_intersect(vec3(0.0), spec_dir, l_vector.xyz); - - vec3 Px = normalize(P - l_vector.xyz) * ld.l_radius; - vec3 Py = cross(Px, L); + roughness = clamp(roughness, 0.0008, 0.999); /* Fix low roughness artifacts. */ vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; mat3 ltc_mat = ltc_matrix(ltc_lut); -// #define HIGHEST_QUALITY -#ifdef HIGHEST_QUALITY - vec3 Pxy1 = normalize( Px + Py) * ld.l_radius; - vec3 Pxy2 = normalize(-Px + Py) * ld.l_radius; - - /* counter clockwise */ - vec3 points[8]; - points[0] = l_vector.xyz + Px; - points[1] = l_vector.xyz - Pxy2; - points[2] = l_vector.xyz - Py; - points[3] = l_vector.xyz - Pxy1; - points[4] = l_vector.xyz - Px; - points[5] = l_vector.xyz + Pxy2; - points[6] = l_vector.xyz + Py; - points[7] = l_vector.xyz + Pxy1; - float bsdf = ltc_evaluate_circle(N, V, ltc_mat, points); -#else - vec3 points[4]; - points[0] = l_vector.xyz + Px; - points[1] = l_vector.xyz - Py; - points[2] = l_vector.xyz - Px; - points[3] = l_vector.xyz + Py; - float bsdf = ltc_evaluate(N, V, ltc_mat, points); - /* sqrt(pi/2) difference between square and disk area */ - bsdf *= 1.25331413731; -#endif + /* Make orthonormal basis. */ + vec3 L = l_vector.xyz / l_vector.w; + vec3 Px, Py; + make_orthonormal_basis(L, Px, Py); + Px *= ld.l_radius; + Py *= ld.l_radius; + vec3 points[3]; + points[0] = l_vector.xyz - Px - Py; + points[1] = l_vector.xyz + Px - Py; + points[2] = l_vector.xyz + Px + Py; + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); bsdf *= brdf_lut.b; /* Bsdf intensity */ - bsdf *= M_1_2PI * M_1_PI; vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; @@ -165,19 +119,38 @@ vec3 direct_ggx_rectangle(LightData ld, vec3 N, vec3 V, vec4 l_vector, float rou vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; mat3 ltc_mat = ltc_matrix(ltc_lut); - float bsdf = ltc_evaluate(N, V, ltc_mat, corners); + + ltc_transform_quad(N, V, ltc_mat, corners); + float bsdf = ltc_evaluate_quad(corners, vec3(0.0, 0.0, 1.0)); bsdf *= brdf_lut.b; /* Bsdf intensity */ - bsdf *= M_1_2PI; vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; return spec; } -#endif -#if 0 -float direct_ggx_disc(vec3 N, vec3 L) +vec3 direct_ggx_unit_disc(LightData ld, vec3 N, vec3 V, float roughness, vec3 f0) { + roughness = clamp(roughness, 0.0004, 0.999); /* Fix low roughness artifacts. */ + + vec2 uv = lut_coords(dot(N, V), sqrt(roughness)); + vec3 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rgb; + vec4 ltc_lut = texture(utilTex, vec3(uv, 0.0)).rgba; + mat3 ltc_mat = ltc_matrix(ltc_lut); + vec3 Px = ld.l_right * ld.l_radius; + vec3 Py = ld.l_up * ld.l_radius; + + vec3 points[3]; + points[0] = -ld.l_forward - Px - Py; + points[1] = -ld.l_forward + Px - Py; + points[2] = -ld.l_forward + Px + Py; + + float bsdf = ltc_evaluate_disk(N, V, ltc_mat, points); + bsdf *= brdf_lut.b; /* Bsdf intensity */ + + vec3 spec = F_area(f0, brdf_lut.xy) * bsdf; + + return spec; } #endif
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl index 13586619fe9..e5c0cb9c9c9 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl @@ -9,12 +9,12 @@ vec2 jitternoise = vec2(0.0); #ifndef UTIL_TEX #define UTIL_TEX uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ void setup_noise(void) { - jitternoise = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).rg; /* Global variable */ - jitternoise.g = (jitternoise.g - 0.5) * 2.0; + jitternoise = texelfetch_noise_tex(gl_FragCoord.xy).rg; /* Global variable */ } #ifdef HAMMERSLEY_SIZE diff --git a/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl new file mode 100644 index 00000000000..37106fc32bd --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl @@ -0,0 +1,55 @@ + +layout(std140) uniform common_block { + mat4 pastViewProjectionMatrix; + vec4 viewVecs[2]; + vec2 mipRatio[10]; /* To correct mip level texel mis-alignement */ + /* Ambient Occlusion */ + vec4 aoParameters[2]; + /* Volumetric */ + ivec4 volTexSize; + vec4 volDepthParameters; /* Parameters to the volume Z equation */ + vec4 volInvTexSize; + vec4 volJitter; + vec4 volCoordScale; /* To convert volume uvs to screen uvs */ + float volHistoryAlpha; + float volLightClamp; + float volShadowSteps; + bool volUseLights; + /* Screen Space Reflections */ + vec4 ssrParameters; + float ssrBorderFac; + float ssrMaxRoughness; + float ssrFireflyFac; + float ssrBrdfBias; + bool ssrToggle; + /* SubSurface Scattering */ + float sssJitterThreshold; + bool sssToggle; + /* Specular */ + bool specToggle; + /* Lamps */ + int laNumLight; + /* Probes */ + int prbNumPlanar; + int prbNumRenderCube; + int prbNumRenderGrid; + int prbIrradianceVisSize; + float prbLodCubeMax; + float prbLodPlanarMax; +}; + +/* aoParameters */ +#define aoDistance aoParameters[0].x +#define aoSamples aoParameters[0].y /* UNUSED */ +#define aoFactor aoParameters[0].z +#define aoInvSamples aoParameters[0].w /* UNUSED */ + +#define aoOffset aoParameters[1].x /* UNUSED */ +#define aoBounceFac aoParameters[1].y +#define aoQuality aoParameters[1].z +#define aoSettings aoParameters[1].w + +/* ssrParameters */ +#define ssrQuality ssrParameters.x +#define ssrThickness ssrParameters.y +#define ssrPixelSize ssrParameters.zw
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index 45c5c88e763..6d941ae6ec3 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -11,7 +11,7 @@ Closure nodetree_exec(void) vec3 f0 = mix(dielectric, basecol, metallic); vec3 N = (gl_FrontFacing) ? worldNormal : -worldNormal; vec3 out_diff, out_spec, ssr_spec; - eevee_closure_default(N, albedo, f0, 0, roughness, 1.0, out_diff, out_spec, ssr_spec); + eevee_closure_default(N, albedo, f0, 1, roughness, 1.0, out_diff, out_spec, ssr_spec); Closure result = Closure(out_spec + out_diff * albedo, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0); diff --git a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl index 1c63051c65b..32edf709d88 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl @@ -12,8 +12,8 @@ uniform sampler2D normalBuffer; void main() { - vec4 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xyxy; - vec2 uvs = saturate(gl_FragCoord.xy * texel_size.xy); + vec2 texel_size = 1.0 / vec2(textureSize(depthBuffer, 0)).xy; + vec2 uvs = saturate(gl_FragCoord.xy * texel_size); float depth = textureLod(depthBuffer, uvs, 0.0).r; @@ -23,28 +23,32 @@ void main() vec3 bent_normal; float visibility; -#if 1 - gtao_deferred(normal, viewPosition, depth, visibility, bent_normal); -#else - vec2 rand = vec2((1.0 / 4.0) * float((int(gl_FragCoord.y) & 0x1) * 2 + (int(gl_FragCoord.x) & 0x1)), 0.5); - rand = fract(rand.x + texture(utilTex, vec3(floor(gl_FragCoord.xy * 0.5) / LUT_SIZE, 2.0)).rg); - gtao(normal, viewPosition, rand, visibility, bent_normal); -#endif - denoise_ao(normal, depth, visibility, bent_normal); + + vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy); + + gtao_deferred(normal, viewPosition, noise, depth, visibility, bent_normal); FragColor = vec4(visibility); } #else -uniform float sampleNbr; + +#ifdef LAYERED_DEPTH +uniform sampler2DArray depthBufferLayered; +uniform int layer; +# define gtao_depthBuffer depthBufferLayered +# define gtao_textureLod(a, b, c) textureLod(a, vec3(b, layer), c) + +#else +# define gtao_depthBuffer depthBuffer +# define gtao_textureLod(a, b, c) textureLod(a, b, c) + +#endif void main() { - ivec2 hr_co = ivec2(gl_FragCoord.xy); - ivec2 fs_co = get_fs_co(hr_co); - - vec2 uvs = saturate((vec2(fs_co) + 0.5) / vec2(textureSize(depthBuffer, 0))); - float depth = textureLod(depthBuffer, uvs, 0.0).r; + vec2 uvs = saturate(gl_FragCoord.xy / vec2(textureSize(gtao_depthBuffer, 0).xy)); + float depth = gtao_textureLod(gtao_depthBuffer, uvs, 0.0).r; if (depth == 1.0) { /* Do not trace for background */ @@ -56,14 +60,17 @@ void main() depth = saturate(depth - 3e-6); /* Tweaked for 24bit depth buffer. */ vec3 viewPosition = get_view_space_from_depth(uvs, depth); - - float phi = get_phi(hr_co, fs_co, sampleNbr); - float offset = get_offset(fs_co, sampleNbr); + vec4 noise = texelfetch_noise_tex(gl_FragCoord.xy); vec2 max_dir = get_max_dir(viewPosition.z); + vec4 dirs; + dirs.xy = get_ao_dir(noise.x * 0.5); + dirs.zw = get_ao_dir(noise.x * 0.5 + 0.5); - FragColor.xy = search_horizon_sweep(phi, viewPosition, uvs, offset, max_dir); + /* Search in 4 directions. */ + FragColor.xy = search_horizon_sweep(dirs.xy, viewPosition, uvs, noise.y, max_dir); + FragColor.zw = search_horizon_sweep(dirs.zw, viewPosition, uvs, noise.y, max_dir); /* Resize output for integer texture. */ - FragColor = pack_horizons(FragColor.xy).xyxy; + FragColor = pack_horizons(FragColor); } #endif diff --git a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl index ce6f3568cdf..65d3970a82a 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl @@ -23,6 +23,10 @@ uniform sampler2D depthBuffer; #define minmax(a, b) max(a, b) #endif +#ifdef GPU_INTEL +out vec4 fragColor; +#endif + void main() { ivec2 texelPos = ivec2(gl_FragCoord.xy); @@ -61,5 +65,10 @@ void main() } #endif +#ifdef GPU_INTEL + /* Use color format instead of 24bit depth texture */ + fragColor = vec4(val); +#else gl_FragDepth = val; +#endif }
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl index 1a01db3a1a3..73e284570cd 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl @@ -57,7 +57,7 @@ void main() float inc = 2.0 * inv_samples; float i = -1.0 + noise; - FragColor = vec4(0.0, 0.0, 0.0, 1.0); + FragColor = vec4(0.0); for (int j = 0; j < samples && j < MAX_SAMPLE; j++) { FragColor += textureLod(colorBuffer, uvcoordsvar.xy + motion * i, 0.0) * inv_samples; i += inc; diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl index 2dc8dfa0d1c..aa88e365d93 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -5,80 +5,78 @@ #ifndef UTIL_TEX #define UTIL_TEX uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ -#define BRDF_BIAS 0.7 #define MAX_MIP 9.0 -uniform float fireflyFactor; -uniform float maxRoughness; +uniform ivec2 halfresOffset; + +ivec2 encode_hit_data(vec2 hit_pos, bool has_hit, bool is_planar) +{ + ivec2 hit_data = ivec2(saturate(hit_pos) * 32767.0); /* 16bit signed int limit */ + hit_data.x *= (is_planar) ? -1 : 1; + hit_data.y *= (has_hit) ? 1 : -1; + return hit_data; +} + +vec2 decode_hit_data(vec2 hit_data, out bool has_hit, out bool is_planar) +{ + is_planar = (hit_data.x < 0); + has_hit = (hit_data.y > 0); + return vec2(abs(hit_data)) / 32767.0; /* 16bit signed int limit */ +} #ifdef STEP_RAYTRACE uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; -uniform int planar_count; -uniform float noiseOffset; - -layout(location = 0) out vec4 hitData0; -layout(location = 1) out vec4 hitData1; -layout(location = 2) out vec4 hitData2; -layout(location = 3) out vec4 hitData3; +layout(location = 0) out ivec2 hitData; +layout(location = 1) out float pdfData; -vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand, float ofs) +void do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec4 rand) { - float pdf, NH; - float jitter = fract(rand.x + ofs); - - /* Importance sampling bias */ - rand.x = mix(rand.x, 0.0, BRDF_BIAS); - - vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */ - pdf = pdf_ggx_reflect(NH, a2); + float NH; + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ + float pdf = pdf_ggx_reflect(NH, a2); vec3 R = reflect(-V, H); R = reflect(R, planeNormal); /* If ray is bad (i.e. going below the plane) regenerate. */ if (dot(R, planeNormal) > 0.0) { - vec3 H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ + vec3 H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ pdf = pdf_ggx_reflect(NH, a2); R = reflect(-V, H); R = reflect(R, planeNormal); } - pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */ - pdf *= -1.0; /* Tag as planar ray. */ + pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */ /* Since viewspace hit position can land behind the camera in this case, * we save the reflected view position (visualize it as the hit position * below the reflection plane). This way it's garanted that the hit will * be in front of the camera. That let us tag the bad rays with a negative * sign in the Z component. */ - vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, jitter, ssrQuality, a2, false); + vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, rand.y, ssrQuality, a2, false); - return vec4(hit_pos, pdf); + hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), true); } -vec4 do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec3 rand, float ofs) +void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec4 rand) { - float pdf, NH; - float jitter = fract(rand.x + ofs); - - /* Importance sampling bias */ - rand.x = mix(rand.x, 0.0, BRDF_BIAS); - - vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */ - pdf = pdf_ggx_reflect(NH, a2); + float NH; + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ + float pdf = pdf_ggx_reflect(NH, a2); vec3 R = reflect(-V, H); - pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */ + pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */ - vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, a2, true); + vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, a2, true); - return vec4(hit_pos, pdf); + hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), false); } void main() @@ -87,20 +85,22 @@ void main() ivec2 fullres_texel = ivec2(gl_FragCoord.xy); ivec2 halfres_texel = fullres_texel; #else - ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2; + ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2 + halfresOffset; ivec2 halfres_texel = ivec2(gl_FragCoord.xy); #endif float depth = texelFetch(depthBuffer, fullres_texel, 0).r; + /* Default: not hits. */ + hitData = encode_hit_data(vec2(0.5), false, false); + pdfData = 0.0; + /* Early out */ + /* We can't do discard because we don't clear the render target. */ if (depth == 1.0) - discard; + return; - vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0)); -#ifndef FULLRES - uvs *= 2.0; -#endif + vec2 uvs = vec2(fullres_texel) / vec2(textureSize(depthBuffer, 0)); /* Using view space */ vec3 viewPosition = get_view_space_from_depth(uvs, depth); @@ -112,18 +112,24 @@ void main() /* Early out */ if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) - discard; + return; float roughness = speccol_roughness.a; float roughnessSquared = max(1e-3, roughness * roughness); float a2 = roughnessSquared * roughnessSquared; - if (roughness > maxRoughness + 0.2) { - hitData0 = hitData1 = hitData2 = hitData3 = vec4(0.0); + /* Early out */ + if (roughness > ssrMaxRoughness + 0.2) return; - } - vec3 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0).rba; + vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0); + + /* Gives *perfect* reflection for very small roughness */ + if (roughness < 0.04) { + rand.xzw *= 0.0; + } + /* Importance sampling bias */ + rand.x = mix(rand.x, 0.0, ssrBrdfBias); vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); vec3 wN = transform_direction(ViewMatrixInverse, N); @@ -132,7 +138,7 @@ void main() make_orthonormal_basis(N, T, B); /* Generate tangent space */ /* Planar Reflections */ - for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) { + for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) { PlanarData pd = planars_data[i]; float fade = probe_attenuation_planar(pd, worldPosition, wN, 0.0); @@ -144,31 +150,12 @@ void main() tracePosition = transform_point(ViewMatrix, tracePosition); vec3 planeNormal = transform_direction(ViewMatrix, pd.pl_normal); - hitData0 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand, 0.0); -#if (RAY_COUNT > 1) - hitData1 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 2) - hitData2 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 3) - hitData3 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT)); -#endif + do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand); return; } } - /* TODO : Raytrace together if textureGather is supported. */ - hitData0 = do_ssr(V, N, T, B, viewPosition, a2, rand, 0.0); -#if (RAY_COUNT > 1) - hitData1 = do_ssr(V, N, T, B, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 2) - hitData2 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 3) - hitData3 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT)); -#endif + do_ssr(V, N, T, B, viewPosition, a2, rand); } #else /* STEP_RESOLVE */ @@ -177,30 +164,42 @@ uniform sampler2D prevColorBuffer; /* previous frame */ uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; -uniform sampler2D hitBuffer0; -uniform sampler2D hitBuffer1; -uniform sampler2D hitBuffer2; -uniform sampler2D hitBuffer3; +uniform isampler2D hitBuffer; +uniform sampler2D pdfBuffer; + +uniform int neighborOffset; -uniform int probe_count; -uniform int planar_count; +const ivec2 neighbors[32] = ivec2[32]( + ivec2( 0, 0), ivec2( 1, 1), ivec2(-2, 0), ivec2( 0, -2), + ivec2( 0, 0), ivec2( 1, -1), ivec2(-2, 0), ivec2( 0, 2), + ivec2( 0, 0), ivec2(-1, -1), ivec2( 2, 0), ivec2( 0, 2), + ivec2( 0, 0), ivec2(-1, 1), ivec2( 2, 0), ivec2( 0, -2), -uniform mat4 PastViewProjectionMatrix; + ivec2( 0, 0), ivec2( 2, 2), ivec2(-2, 2), ivec2( 0, -1), + ivec2( 0, 0), ivec2( 2, -2), ivec2(-2, -2), ivec2( 0, 1), + ivec2( 0, 0), ivec2(-2, -2), ivec2(-2, 2), ivec2( 1, 0), + ivec2( 0, 0), ivec2( 2, 2), ivec2( 2, -2), ivec2(-1, 0) +); out vec4 fragColor; -void fallback_cubemap(vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum) +void fallback_cubemap( + vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum) { /* Specular probes */ vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); - vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)); + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); vec3 bent_normal; - float final_ao = occlusion_compute(N, viewPosition, 1.0, rand.rg, bent_normal); +#ifdef SSR_AO + float final_ao = occlusion_compute(N, viewPosition, 1.0, rand, bent_normal); final_ao = specular_occlusion(dot(N, V), final_ao, roughness); +#else + const float final_ao = 1.0; +#endif /* Starts at 1 because 0 is world probe */ - for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) { + for (int i = 1; i < MAX_PROBE && i < prbNumRenderCube && spec_accum.a < 0.999; ++i) { CubeData cd = probes_data[i]; float fade = probe_attenuation_cube(cd, W); @@ -251,90 +250,177 @@ float brightness(vec3 c) vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N) { /* TODO real reprojection with motion vectors, etc... */ - return project_point(PastViewProjectionMatrix, hit).xy * 0.5 + 0.5; + return project_point(pastViewProjectionMatrix, hit).xy * 0.5 + 0.5; } -vec4 get_ssr_sample( - sampler2D hitBuffer, PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, float roughnessSquared, - float cone_tan, vec2 source_uvs, vec2 texture_size, ivec2 target_texel, - inout float weight_acc) +float get_sample_depth(vec2 hit_co, bool is_planar, float planar_index) { - vec4 hit_co_pdf = texelFetch(hitBuffer, target_texel, 0).rgba; - bool has_hit = (hit_co_pdf.z > 0.0); - bool is_planar = (hit_co_pdf.w < 0.0); - hit_co_pdf.z = abs(hit_co_pdf.z); - hit_co_pdf.w = abs(hit_co_pdf.w); - - /* Hit position in world space. */ - hit_co_pdf.xyz = get_view_space_from_depth(hit_co_pdf.xy, hit_co_pdf.z); - vec3 hit_pos = transform_point(ViewMatrixInverse, hit_co_pdf.xyz); + if (is_planar) { + return textureLod(planarDepth, vec3(hit_co, planar_index), 0.0).r; + } + else { + return textureLod(depthBuffer, hit_co, 0.0).r; + } +} - vec2 ref_uvs; +vec3 get_hit_vector( + vec3 hit_pos, PlanarData pd, vec3 worldPosition, vec3 N, vec3 V, bool is_planar, + inout vec2 hit_co, inout float mask) +{ vec3 hit_vec; - float mask = 1.0; + if (is_planar) { /* Reflect back the hit position to have it in non-reflected world space */ vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq); hit_vec = hit_pos - trace_pos; hit_vec = reflect(hit_vec, pd.pl_normal); - ref_uvs = project_point(ProjectionMatrix, hit_co_pdf.xyz).xy * 0.5 + 0.5; } else { /* Find hit position in previous frame. */ - ref_uvs = get_reprojected_reflection(hit_pos, worldPosition, N); + mask = screen_border_mask(gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0))); + hit_co = get_reprojected_reflection(hit_pos, worldPosition, N); hit_vec = hit_pos - worldPosition; - mask = screen_border_mask(gl_FragCoord.xy / texture_size); } - mask = min(mask, screen_border_mask(ref_uvs)); - mask *= float(has_hit); - float hit_dist = max(1e-8, length(hit_vec)); - vec3 L = hit_vec / hit_dist; + mask = min(mask, screen_border_mask(hit_co)); + return hit_vec; +} - float cone_footprint = hit_dist * cone_tan; +vec3 get_scene_color(vec2 ref_uvs, float mip, float planar_index, bool is_planar) +{ + if (is_planar) { + return textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, prbLodPlanarMax)).rgb; + } + else { + return textureLod(prevColorBuffer, ref_uvs, mip).rgb; + } +} + +vec4 get_ssr_samples( + vec4 hit_pdf, ivec4 hit_data[2], + PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, + float roughnessSquared, float cone_tan, vec2 source_uvs, + inout float weight_acc) +{ + bvec4 is_planar, has_hit; + vec4 hit_co[2]; + hit_co[0].xy = decode_hit_data(hit_data[0].xy, has_hit.x, is_planar.x); + hit_co[0].zw = decode_hit_data(hit_data[0].zw, has_hit.y, is_planar.y); + hit_co[1].xy = decode_hit_data(hit_data[1].xy, has_hit.z, is_planar.z); + hit_co[1].zw = decode_hit_data(hit_data[1].zw, has_hit.w, is_planar.w); + + vec4 hit_depth; + hit_depth.x = get_sample_depth(hit_co[0].xy, is_planar.x, planar_index); + hit_depth.y = get_sample_depth(hit_co[0].zw, is_planar.y, planar_index); + hit_depth.z = get_sample_depth(hit_co[1].xy, is_planar.z, planar_index); + hit_depth.w = get_sample_depth(hit_co[1].zw, is_planar.w, planar_index); + + /* Hit position in view space. */ + vec3 hit_view[4]; + hit_view[0] = get_view_space_from_depth(hit_co[0].xy, hit_depth.x); + hit_view[1] = get_view_space_from_depth(hit_co[0].zw, hit_depth.y); + hit_view[2] = get_view_space_from_depth(hit_co[1].xy, hit_depth.z); + hit_view[3] = get_view_space_from_depth(hit_co[1].zw, hit_depth.w); + + vec4 homcoord = vec4(hit_view[0].z, hit_view[1].z, hit_view[2].z, hit_view[3].z); + homcoord = ProjectionMatrix[2][3] * homcoord + ProjectionMatrix[3][3]; + + /* Hit position in world space. */ + vec3 hit_pos[4]; + hit_pos[0] = transform_point(ViewMatrixInverse, hit_view[0]); + hit_pos[1] = transform_point(ViewMatrixInverse, hit_view[1]); + hit_pos[2] = transform_point(ViewMatrixInverse, hit_view[2]); + hit_pos[3] = transform_point(ViewMatrixInverse, hit_view[3]); + + /* Get actual hit vector and hit coordinate (from last frame). */ + vec4 mask = vec4(1.0); + hit_pos[0] = get_hit_vector(hit_pos[0], pd, worldPosition, N, V, is_planar.x, hit_co[0].xy, mask.x); + hit_pos[1] = get_hit_vector(hit_pos[1], pd, worldPosition, N, V, is_planar.y, hit_co[0].zw, mask.y); + hit_pos[2] = get_hit_vector(hit_pos[2], pd, worldPosition, N, V, is_planar.z, hit_co[1].xy, mask.z); + hit_pos[3] = get_hit_vector(hit_pos[3], pd, worldPosition, N, V, is_planar.w, hit_co[1].zw, mask.w); + + vec4 hit_dist; + hit_dist.x = length(hit_pos[0]); + hit_dist.y = length(hit_pos[1]); + hit_dist.z = length(hit_pos[2]); + hit_dist.w = length(hit_pos[3]); + hit_dist = max(vec4(1e-8), hit_dist); + + /* Normalize */ + hit_pos[0] /= hit_dist.x; + hit_pos[1] /= hit_dist.y; + hit_pos[2] /= hit_dist.z; + hit_pos[3] /= hit_dist.w; /* Compute cone footprint in screen space. */ - float homcoord = ProjectionMatrix[2][3] * hit_co_pdf.z + ProjectionMatrix[3][3]; - cone_footprint = BRDF_BIAS * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord; + vec4 cone_footprint = hit_dist * cone_tan; + cone_footprint = ssrBrdfBias * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord; /* Estimate a cone footprint to sample a corresponding mipmap level. */ - float mip = clamp(log2(cone_footprint * max(texture_size.x, texture_size.y)), 0.0, MAX_MIP); + vec4 mip = log2(cone_footprint * max_v2(vec2(textureSize(depthBuffer, 0)))); + mip = clamp(mip, 0.0, MAX_MIP); /* Correct UVs for mipmaping mis-alignment */ - ref_uvs *= mip_ratio_interp(mip); + hit_co[0].xy *= mip_ratio_interp(mip.x); + hit_co[0].zw *= mip_ratio_interp(mip.y); + hit_co[1].xy *= mip_ratio_interp(mip.z); + hit_co[1].zw *= mip_ratio_interp(mip.w); /* Slide 54 */ - float bsdf = bsdf_ggx(N, L, V, roughnessSquared); - float weight = step(1e-8, hit_co_pdf.w) * bsdf / max(1e-8, hit_co_pdf.w); - weight_acc += weight; + vec4 bsdf; + bsdf.x = bsdf_ggx(N, hit_pos[0], V, roughnessSquared); + bsdf.y = bsdf_ggx(N, hit_pos[1], V, roughnessSquared); + bsdf.z = bsdf_ggx(N, hit_pos[2], V, roughnessSquared); + bsdf.w = bsdf_ggx(N, hit_pos[3], V, roughnessSquared); - vec3 sample; - if (is_planar) { - sample = textureLod(probePlanars, vec3(ref_uvs, planar_index), min(mip, lodPlanarMax)).rgb; - } - else { - sample = textureLod(prevColorBuffer, ref_uvs, mip).rgb; - } + vec4 weight = step(1e-8, hit_pdf) * bsdf / max(vec4(1e-8), hit_pdf); - /* Clamped brightness. */ - float luma = max(1e-8, brightness(sample)); - sample *= 1.0 - max(0.0, luma - fireflyFactor) / luma; + vec3 sample[4]; + sample[0] = get_scene_color(hit_co[0].xy, mip.x, planar_index, is_planar.x); + sample[1] = get_scene_color(hit_co[0].zw, mip.y, planar_index, is_planar.y); + sample[2] = get_scene_color(hit_co[1].xy, mip.z, planar_index, is_planar.z); + sample[3] = get_scene_color(hit_co[1].zw, mip.w, planar_index, is_planar.w); - /* Do not add light if ray has failed. */ - sample *= float(has_hit); + /* Clamped brightness. */ + vec4 luma; + luma.x = brightness(sample[0]); + luma.y = brightness(sample[1]); + luma.z = brightness(sample[2]); + luma.w = brightness(sample[3]); + luma = max(vec4(1e-8), luma); + luma = 1.0 - max(vec4(0.0), luma - ssrFireflyFac) / luma; + + sample[0] *= luma.x; + sample[1] *= luma.y; + sample[2] *= luma.z; + sample[3] *= luma.w; /* Protection against NaNs in the history buffer. * This could be removed if some previous pass has already * sanitized the input. */ - if (any(isnan(sample))) { - sample = vec3(0.0); - weight = 0.0; + if (any(isnan(sample[0]))) { + sample[0] = vec3(0.0); weight.x = 0.0; + } + if (any(isnan(sample[1]))) { + sample[1] = vec3(0.0); weight.y = 0.0; + } + if (any(isnan(sample[2]))) { + sample[2] = vec3(0.0); weight.z = 0.0; + } + if (any(isnan(sample[3]))) { + sample[3] = vec3(0.0); weight.w = 0.0; } - return vec4(sample, mask) * weight; -} + weight_acc += sum(weight); -#define NUM_NEIGHBORS 4 + /* Do not add light if ray has failed. */ + vec4 accum; + accum = vec4(sample[0], mask.x) * weight.x * float(has_hit.x); + accum += vec4(sample[1], mask.y) * weight.y * float(has_hit.y); + accum += vec4(sample[2], mask.z) * weight.z * float(has_hit.z); + accum += vec4(sample[3], mask.w) * weight.w * float(has_hit.w); + return accum; +} void main() { @@ -344,9 +430,7 @@ void main() #else ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0); #endif - vec2 texture_size = vec2(textureSize(depthBuffer, 0)); - vec2 uvs = gl_FragCoord.xy / texture_size; - vec3 rand = texelFetch(utilTex, ivec3(fullres_texel % LUT_SIZE, 2), 0).rba; + vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0)); float depth = textureLod(depthBuffer, uvs, 0.0).r; @@ -366,10 +450,24 @@ void main() if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) discard; + /* TODO optimize with textureGather */ + /* Doing these fetches early to hide latency. */ + vec4 hit_pdf; + hit_pdf.x = texelFetch(pdfBuffer, halfres_texel + neighbors[0 + neighborOffset], 0).r; + hit_pdf.y = texelFetch(pdfBuffer, halfres_texel + neighbors[1 + neighborOffset], 0).r; + hit_pdf.z = texelFetch(pdfBuffer, halfres_texel + neighbors[2 + neighborOffset], 0).r; + hit_pdf.w = texelFetch(pdfBuffer, halfres_texel + neighbors[3 + neighborOffset], 0).r; + + ivec4 hit_data[2]; + hit_data[0].xy = texelFetch(hitBuffer, halfres_texel + neighbors[0 + neighborOffset], 0).rg; + hit_data[0].zw = texelFetch(hitBuffer, halfres_texel + neighbors[1 + neighborOffset], 0).rg; + hit_data[1].xy = texelFetch(hitBuffer, halfres_texel + neighbors[2 + neighborOffset], 0).rg; + hit_data[1].zw = texelFetch(hitBuffer, halfres_texel + neighbors[3 + neighborOffset], 0).rg; + /* Find Planar Reflections affecting this pixel */ PlanarData pd; float planar_index; - for (int i = 0; i < MAX_PLANAR && i < planar_count; ++i) { + for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; ++i) { pd = planars_data[i]; float fade = probe_attenuation_planar(pd, worldPosition, N, 0.0); @@ -390,55 +488,21 @@ void main() float cone_tan = sqrt(1 - cone_cos * cone_cos) / cone_cos; cone_tan *= mix(saturate(dot(N, -V) * 2.0), 1.0, roughness); /* Elongation fit */ - vec2 source_uvs = project_point(PastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5; + vec2 source_uvs = project_point(pastViewProjectionMatrix, worldPosition).xy * 0.5 + 0.5; vec4 ssr_accum = vec4(0.0); float weight_acc = 0.0; - const ivec2 neighbors[9] = ivec2[9]( - ivec2(0, 0), - - ivec2(0, 1), - ivec2(-1, -1), ivec2(1, -1), - - ivec2(-1, 1), ivec2(1, 1), - ivec2(0, -1), - - ivec2(-1, 0), ivec2(1, 0) - ); - ivec2 invert_neighbor; - invert_neighbor.x = ((fullres_texel.x & 0x1) == 0) ? 1 : -1; - invert_neighbor.y = ((fullres_texel.y & 0x1) == 0) ? 1 : -1; - - if (roughness < maxRoughness + 0.2) { - for (int i = 0; i < NUM_NEIGHBORS; i++) { - ivec2 target_texel = halfres_texel + neighbors[i] * invert_neighbor; - - ssr_accum += get_ssr_sample(hitBuffer0, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#if (RAY_COUNT > 1) - ssr_accum += get_ssr_sample(hitBuffer1, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#endif -#if (RAY_COUNT > 2) - ssr_accum += get_ssr_sample(hitBuffer2, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#endif -#if (RAY_COUNT > 3) - ssr_accum += get_ssr_sample(hitBuffer3, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#endif - } + + if (roughness < ssrMaxRoughness + 0.2) { + ssr_accum += get_ssr_samples(hit_pdf, hit_data, pd, planar_index, worldPosition, N, V, + roughnessSquared, cone_tan, source_uvs, weight_acc); } /* Compute SSR contribution */ if (weight_acc > 0.0) { ssr_accum /= weight_acc; /* fade between 0.5 and 1.0 roughness */ - ssr_accum.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness); + ssr_accum.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness); accumulate_light(ssr_accum.rgb, ssr_accum.a, spec_accum); } diff --git a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl index 88e71a060c5..184eac54c26 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl @@ -8,16 +8,19 @@ layout(std140) uniform sssProfile { int sss_samples; }; -uniform float jitterThreshold; uniform sampler2D depthBuffer; uniform sampler2D sssData; uniform sampler2D sssAlbedo; + +#ifndef UTIL_TEX +#define UTIL_TEX uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) +#endif /* UTIL_TEX */ out vec4 FragColor; uniform mat4 ProjectionMatrix; -uniform vec4 viewvecs[2]; float get_view_z_from_depth(float depth) { @@ -26,7 +29,7 @@ float get_view_z_from_depth(float depth) return -ProjectionMatrix[3][2] / (d + ProjectionMatrix[2][2]); } else { - return viewvecs[0].z + depth * viewvecs[1].z; + return viewVecs[0].z + depth * viewVecs[1].z; } } @@ -41,7 +44,7 @@ void main(void) vec4 sss_data = texture(sssData, uvs).rgba; float depth_view = get_view_z_from_depth(texture(depthBuffer, uvs).r); - float rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2), 0).r; + float rand = texelfetch_noise_tex(gl_FragCoord.xy).r; #ifdef FIRST_PASS float angle = M_2PI * rand + M_PI_2; vec2 dir = vec2(1.0, 0.0); @@ -61,7 +64,7 @@ void main(void) vec3 accum = sss_data.rgb * kernel[0].rgb; for (int i = 1; i < sss_samples && i < MAX_SSS_SAMPLES; i++) { - vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > jitterThreshold) ? dir : dir_rand); + vec2 sample_uv = uvs + kernel[i].a * finalStep * ((abs(kernel[i].a) > sssJitterThreshold) ? dir : dir_rand); vec3 color = texture(sssData, sample_uv).rgb; float sample_depth = texture(depthBuffer, sample_uv).r; sample_depth = get_view_z_from_depth(sample_depth); diff --git a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl index 76d20486d3d..132cc16fcbd 100644 --- a/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl @@ -1,6 +1,5 @@ uniform sampler2DArray irradianceGrid; -uniform int irradianceVisibilitySize; #define IRRADIANCE_LIB @@ -81,8 +80,8 @@ IrradianceData load_irradiance_cell(int cell, vec3 N) float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed_bias, float range) { /* Keep in sync with diffuse_filter_probe() */ - ivec2 cell_co = ivec2(irradianceVisibilitySize); - ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / irradianceVisibilitySize; + ivec2 cell_co = ivec2(prbIrradianceVisSize); + ivec2 cell_per_row_col = textureSize(irradianceGrid, 0).xy / prbIrradianceVisSize; cell_co.x *= (cell % cell_per_row_col.x); cell_co.y *= (cell / cell_per_row_col.x) % cell_per_row_col.y; float layer = 1.0 + float((cell / cell_per_row_col.x) / cell_per_row_col.y); @@ -90,8 +89,8 @@ float load_visibility_cell(int cell, vec3 L, float dist, float bias, float bleed vec2 texel_size = 1.0 / vec2(textureSize(irradianceGrid, 0).xy); vec2 co = vec2(cell_co) * texel_size; - vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(irradianceVisibilitySize))); - uv *= vec2(irradianceVisibilitySize) * texel_size; + vec2 uv = mapping_octahedron(-L, vec2(1.0 / float(prbIrradianceVisSize))); + uv *= vec2(prbIrradianceVisSize) * texel_size; vec4 data = texture(irradianceGrid, vec3(co + uv, layer)); diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl index 933f056c401..1c7956bb807 100644 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -161,7 +161,7 @@ float light_visibility(LightData ld, vec3 W, float x = dot(ld.l_right, lL) / ld.l_sizex; float y = dot(ld.l_up, lL) / ld.l_sizey; - float ellipse = 1.0 / sqrt(1.0 + x * x + y * y); + float ellipse = inversesqrt(1.0 + x * x + y * y); float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend); @@ -203,14 +203,13 @@ float light_visibility(LightData ld, vec3 W, vec3 T, B; make_orthonormal_basis(L.xyz / L.w, T, B); - vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw; - /* XXX This is a hack to not have noise correlation artifacts. - * A better solution to have better noise is welcome. */ - rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_contact_spread; + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + /* WATCH THIS : This still seems to have correlation artifacts for low samples. */ + rand.zw *= fast_sqrt(rand.y) * data.sh_contact_spread; /* We use the full l_vector.xyz so that the spread is minimize * if the shading point is further away from the light source */ - vec3 ray_dir = L.xyz + T * rand.y + B * rand.z; + vec3 ray_dir = L.xyz + T * rand.z + B * rand.w; ray_dir = transform_direction(ViewMatrix, ray_dir); ray_dir = normalize(ray_dir); vec3 ray_origin = viewPosition + viewNormal * data.sh_contact_offset; @@ -235,8 +234,7 @@ float light_diffuse(LightData ld, vec3 N, vec3 V, vec4 l_vector) { #ifdef USE_LTC if (ld.l_type == SUN) { - /* TODO disk area light */ - return direct_diffuse_sun(ld, N); + return direct_diffuse_unit_disc(ld, N, V); } else if (ld.l_type == AREA) { return direct_diffuse_rectangle(ld, N, V, l_vector); @@ -258,8 +256,7 @@ vec3 light_specular(LightData ld, vec3 N, vec3 V, vec4 l_vector, float roughness { #ifdef USE_LTC if (ld.l_type == SUN) { - /* TODO disk area light */ - return direct_ggx_sun(ld, N, V, roughness, f0); + return direct_ggx_unit_disc(ld, N, V, roughness, f0); } else if (ld.l_type == AREA) { return direct_ggx_rectangle(ld, N, V, l_vector, roughness, f0); @@ -298,9 +295,7 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) { #if !defined(USE_TRANSLUCENCY) || defined(VOLUMETRICS) return vec3(0.0); -#endif - -#ifndef VOLUMETRICS +#else vec3 vis = vec3(1.0); /* Only shadowed light can produce translucency */ @@ -313,14 +308,13 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) vec3 T, B; make_orthonormal_basis(L.xyz / L.w, T, B); - vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw; - /* XXX This is a hack to not have noise correlation artifacts. - * A better solution to have better noise is welcome. */ - rand.yz *= fast_sqrt(fract(rand.x * 7919.0)) * data.sh_blur; + vec4 rand = texelfetch_noise_tex(gl_FragCoord.xy); + /* WATCH THIS : This still seems to have correlation artifacts for low samples. */ + rand.zw *= fast_sqrt(rand.y) * data.sh_blur; /* We use the full l_vector.xyz so that the spread is minimize * if the shading point is further away from the light source */ - W = W + T * rand.y + B * rand.z; + W = W + T * rand.z + B * rand.w; if (ld.l_type == SUN) { ShadowCascadeData scd = shadows_cascade_data[int(data.sh_data_start)]; @@ -374,19 +368,24 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) /* TODO : put this out of the shader. */ float falloff; if (ld.l_type == AREA) { - vis *= 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI); + vis *= (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + vis *= 0.3 * 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ vis /= (l_vector.w * l_vector.w); falloff = dot(N, l_vector.xyz / l_vector.w); } else if (ld.l_type == SUN) { + vis *= (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/ + vis *= M_2PI * 0.78; /* Matching cycles with point light. */ + vis *= 0.082; /* XXX ad hoc, empirical */ falloff = dot(N, -ld.l_forward); } else { - vis *= 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI); + vis *= (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); + vis *= 1.5; /* XXX ad hoc, empirical */ vis /= (l_vector.w * l_vector.w); falloff = dot(N, l_vector.xyz / l_vector.w); } - vis *= M_1_PI; /* Normalize */ + // vis *= M_1_PI; /* Normalize */ /* Applying profile */ vis *= sss_profile(abs(delta) / scale); @@ -400,7 +399,7 @@ vec3 light_translucent(LightData ld, vec3 W, vec3 N, vec4 l_vector, float scale) float x = dot(ld.l_right, lL) / ld.l_sizex; float y = dot(ld.l_up, lL) / ld.l_sizey; - float ellipse = 1.0 / sqrt(1.0 + x * x + y * y); + float ellipse = inversesqrt(1.0 + x * x + y * y); float spotmask = smoothstep(0.0, 1.0, (ellipse - ld.l_spot_size) / ld.l_spot_blend); diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl index fc0b5b9548b..d10f4bc0d42 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl @@ -11,5 +11,5 @@ void main() ? normalize(cameraPos - worldPosition) : cameraForward; vec3 N = normalize(worldNormal); - FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, lodCubeMax).rgb, 1.0); + FragColor = vec4(textureLod_octahedron(probeCubes, vec4(reflect(-V, N), pid), 0.0, prbLodCubeMax).rgb, 1.0); } diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl index eb4315c93a3..b19ee7a9ea3 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl @@ -3,6 +3,7 @@ uniform samplerCube probeHdr; uniform int probeSize; uniform float lodFactor; uniform float lodMax; +uniform float intensityFac; in vec3 worldPosition; @@ -192,6 +193,6 @@ void main() } } - FragColor = irradiance_encode(out_radiance / weight); + FragColor = irradiance_encode(intensityFac * out_radiance / weight); #endif }
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl index 33714c5293c..3aec3ce4642 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl @@ -5,6 +5,7 @@ uniform float texelSize; uniform float lodFactor; uniform float lodMax; uniform float paddingSize; +uniform float intensityFac; in vec3 worldPosition; @@ -82,5 +83,5 @@ void main() { } } - FragColor = vec4(out_radiance / weight, 1.0); + FragColor = vec4(intensityFac * out_radiance / weight, 1.0); }
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index e914228aded..429f6ea92e4 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -1,10 +1,7 @@ /* ----------- Uniforms --------- */ uniform sampler2DArray probePlanars; -uniform float lodPlanarMax; - uniform sampler2DArray probeCubes; -uniform float lodCubeMax; /* ----------- Structures --------- */ @@ -162,12 +159,12 @@ vec3 probe_evaluate_cube(float id, CubeData cd, vec3 W, vec3 R, float roughness) float fac = saturate(original_roughness * 2.0 - 1.0); R = mix(intersection, R, fac * fac); - return textureLod_octahedron(probeCubes, vec4(R, id), roughness * lodCubeMax, lodCubeMax).rgb; + return textureLod_octahedron(probeCubes, vec4(R, id), roughness * prbLodCubeMax, prbLodCubeMax).rgb; } vec3 probe_evaluate_world_spec(vec3 R, float roughness) { - return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * lodCubeMax, lodCubeMax).rgb; + return textureLod_octahedron(probeCubes, vec4(R, 0.0), roughness * prbLodCubeMax, prbLodCubeMax).rgb; } vec3 probe_evaluate_planar( diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index 6ecaf0a627b..cc66b477da0 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -2,19 +2,12 @@ #ifndef LIT_SURFACE_UNIFORM #define LIT_SURFACE_UNIFORM -uniform int light_count; -uniform int probe_count; -uniform int grid_count; -uniform int planar_count; - -uniform bool specToggle; -uniform bool ssrToggle; - uniform float refractionDepth; #ifndef UTIL_TEX #define UTIL_TEX uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ in vec3 worldPosition; @@ -28,9 +21,6 @@ in vec3 worldNormal; in vec3 viewNormal; #endif -uniform float maxRoughness; -uniform int rayCount; - #endif /* LIT_SURFACE_UNIFORM */ /** AUTO CONFIG @@ -176,7 +166,7 @@ void CLOSURE_NAME( vec3 V = cameraVec; - vec4 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)); + vec4 rand = texelFetch(utilTex, ivec3(ivec2(gl_FragCoord.xy) % LUT_SIZE, 2.0), 0); /* ---------------------------------------------------------------- */ /* -------------------- SCENE LAMPS LIGHTING ---------------------- */ @@ -187,7 +177,7 @@ void CLOSURE_NAME( norm_view = normalize(cross(norm_view, N)); /* Normal facing view */ #endif - for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) { + for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) { LightData ld = lights_data[i]; vec4 l_vector; /* Non-Normalized Light Vector with length in last component. */ @@ -266,7 +256,7 @@ void CLOSURE_NAME( /* Planar Reflections */ /* ---------------------------- */ - for (int i = 0; i < MAX_PLANAR && i < planar_count && spec_accum.a < 0.999; ++i) { + for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar && spec_accum.a < 0.999; ++i) { PlanarData pd = planars_data[i]; /* Fade on geometric normal. */ @@ -312,17 +302,11 @@ void CLOSURE_NAME( /* Screen Space Refraction */ /* ---------------------------- */ #ifdef USE_REFRACTION - if (ssrToggle && roughness < maxRoughness + 0.2) { + if (ssrToggle && roughness < ssrMaxRoughness + 0.2) { /* Find approximated position of the 2nd refraction event. */ vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition; - - float ray_ofs = 1.0 / float(rayCount); - vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw, 0.0); - if (rayCount > 1) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs); - if (rayCount > 2) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs); - if (rayCount > 3) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs); - trans /= float(rayCount); - trans.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness); + vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand); + trans.a *= smoothstep(ssrMaxRoughness + 0.2, ssrMaxRoughness, roughness); accumulate_light(trans.rgb, trans.a, refr_accum); } #endif @@ -342,7 +326,7 @@ void CLOSURE_NAME( #endif /* Starts at 1 because 0 is world probe */ - for (int i = 1; ACCUM.a < 0.999 && i < probe_count && i < MAX_PROBE; ++i) { + for (int i = 1; ACCUM.a < 0.999 && i < prbNumRenderCube && i < MAX_PROBE; ++i) { CubeData cd = probes_data[i]; float fade = probe_attenuation_cube(cd, worldPosition); @@ -402,7 +386,7 @@ void CLOSURE_NAME( /* ---------------------------- */ #if defined(CLOSURE_GLOSSY) || defined(CLOSURE_DIFFUSE) vec3 bent_normal; - float final_ao = occlusion_compute(N, viewPosition, ao, rand.rg, bent_normal); + float final_ao = occlusion_compute(N, viewPosition, ao, rand, bent_normal); #endif @@ -417,12 +401,14 @@ void CLOSURE_NAME( /* This factor is outputed to be used by SSR in order * to match the intensity of the regular reflections. */ ssr_spec = F_ibl(f0, brdf_lut); - if (!(ssrToggle && ssr_id == outputSsrId)) { - /* The SSR pass recompute the occlusion to not apply it to the SSR */ - ssr_spec *= specular_occlusion(NV, final_ao, roughness); + float spec_occlu = specular_occlusion(NV, final_ao, roughness); + + /* The SSR pass recompute the occlusion to not apply it to the SSR */ + if (ssrToggle && ssr_id == outputSsrId) { + spec_occlu = 1.0; } - out_spec += spec_accum.rgb * ssr_spec * float(specToggle); + out_spec += spec_accum.rgb * ssr_spec * spec_occlu * float(specToggle); #endif #ifdef CLOSURE_REFRACTION @@ -452,7 +438,7 @@ void CLOSURE_NAME( /* Irradiance Grids */ /* ---------------------------- */ /* Start at 1 because 0 is world irradiance */ - for (int i = 1; i < MAX_GRID && i < grid_count && diff_accum.a < 0.999; ++i) { + for (int i = 1; i < MAX_GRID && i < prbNumRenderGrid && diff_accum.a < 0.999; ++i) { GridData gd = grids_data[i]; vec3 localpos; @@ -467,7 +453,7 @@ void CLOSURE_NAME( /* ---------------------------- */ /* World Diffuse */ /* ---------------------------- */ - if (diff_accum.a < 0.999 && grid_count > 0) { + if (diff_accum.a < 0.999 && prbNumRenderGrid > 0) { vec3 diff = probe_evaluate_world_diff(bent_normal); accumulate_light(diff, 1.0, diff_accum); } diff --git a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl index ffaa81c3638..5c62cb19152 100644 --- a/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ltc_lib.glsl @@ -1,150 +1,140 @@ -/* Mainly From https://eheitzresearch.wordpress.com/415-2/ */ +/** + * Adapted from : + * Real-Time Polygonal-Light Shading with Linearly Transformed Cosines. + * Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt. + * ACM Transactions on Graphics (Proceedings of ACM SIGGRAPH 2016) 35(4), 2016. + * Project page: https://eheitzresearch.wordpress.com/415-2/ + **/ #define USE_LTC #ifndef UTIL_TEX #define UTIL_TEX uniform sampler2DArray utilTex; +#define texelfetch_noise_tex(coord) texelFetch(utilTex, ivec3(ivec2(coord) % LUT_SIZE, 2.0), 0) #endif /* UTIL_TEX */ -/* from Real-Time Area Lighting: a Journey from Research to Production - * Stephen Hill and Eric Heitz */ -float edge_integral(vec3 p1, vec3 p2) +/* Diffuse *clipped* sphere integral. */ +float diffuse_sphere_integral_lut(float avg_dir_z, float form_factor) { -#if 0 - /* more accurate replacement of acos */ - float x = dot(p1, p2); - float y = abs(x); + vec2 uv = vec2(avg_dir_z * 0.5 + 0.5, form_factor); + uv = uv * (LUT_SIZE - 1.0) / LUT_SIZE + 0.5 / LUT_SIZE; - float a = 5.42031 + (3.12829 + 0.0902326 * y) * y; - float b = 3.45068 + (4.18814 + y) * y; - float theta_sintheta = a / b; - - if (x < 0.0) { - theta_sintheta = (M_PI / sqrt(1.0 - x * x)) - theta_sintheta; - } - vec3 u = cross(p1, p2); - return theta_sintheta * dot(u, N); -#endif - float cos_theta = dot(p1, p2); - cos_theta = clamp(cos_theta, -0.9999, 0.9999); + return texture(utilTex, vec3(uv, 1.0)).w; +} - float theta = acos(cos_theta); - vec3 u = normalize(cross(p1, p2)); - return theta * cross(p1, p2).z / sin(theta); +float diffuse_sphere_integral_cheap(float avg_dir_z, float form_factor) +{ + return max((form_factor * form_factor + avg_dir_z) / (form_factor + 1.0), 0.0); } -int clip_quad_to_horizon(inout vec3 L[5]) +/** + * An extended version of the implementation from + * "How to solve a cubic equation, revisited" + * http://momentsingraphics.de/?p=105 + **/ +vec3 solve_cubic(vec4 coefs) { - /* detect clipping config */ - int config = 0; - if (L[0].z > 0.0) config += 1; - if (L[1].z > 0.0) config += 2; - if (L[2].z > 0.0) config += 4; - if (L[3].z > 0.0) config += 8; + /* Normalize the polynomial */ + coefs.xyz /= coefs.w; + /* Divide middle coefficients by three */ + coefs.yz /= 3.0; - /* clip */ - int n = 0; + float A = coefs.w; + float B = coefs.z; + float C = coefs.y; + float D = coefs.x; - if (config == 0) - { - /* clip all */ - } - else if (config == 1) /* V1 clip V2 V3 V4 */ - { - n = 3; - L[1] = -L[1].z * L[0] + L[0].z * L[1]; - L[2] = -L[3].z * L[0] + L[0].z * L[3]; - } - else if (config == 2) /* V2 clip V1 V3 V4 */ - { - n = 3; - L[0] = -L[0].z * L[1] + L[1].z * L[0]; - L[2] = -L[2].z * L[1] + L[1].z * L[2]; - } - else if (config == 3) /* V1 V2 clip V3 V4 */ - { - n = 4; - L[2] = -L[2].z * L[1] + L[1].z * L[2]; - L[3] = -L[3].z * L[0] + L[0].z * L[3]; - } - else if (config == 4) /* V3 clip V1 V2 V4 */ - { - n = 3; - L[0] = -L[3].z * L[2] + L[2].z * L[3]; - L[1] = -L[1].z * L[2] + L[2].z * L[1]; - } - else if (config == 5) /* V1 V3 clip V2 V4) impossible */ - { - n = 0; - } - else if (config == 6) /* V2 V3 clip V1 V4 */ - { - n = 4; - L[0] = -L[0].z * L[1] + L[1].z * L[0]; - L[3] = -L[3].z * L[2] + L[2].z * L[3]; - } - else if (config == 7) /* V1 V2 V3 clip V4 */ - { - n = 5; - L[4] = -L[3].z * L[0] + L[0].z * L[3]; - L[3] = -L[3].z * L[2] + L[2].z * L[3]; - } - else if (config == 8) /* V4 clip V1 V2 V3 */ - { - n = 3; - L[0] = -L[0].z * L[3] + L[3].z * L[0]; - L[1] = -L[2].z * L[3] + L[3].z * L[2]; - L[2] = L[3]; - } - else if (config == 9) /* V1 V4 clip V2 V3 */ - { - n = 4; - L[1] = -L[1].z * L[0] + L[0].z * L[1]; - L[2] = -L[2].z * L[3] + L[3].z * L[2]; - } - else if (config == 10) /* V2 V4 clip V1 V3) impossible */ - { - n = 0; - } - else if (config == 11) /* V1 V2 V4 clip V3 */ - { - n = 5; - L[4] = L[3]; - L[3] = -L[2].z * L[3] + L[3].z * L[2]; - L[2] = -L[2].z * L[1] + L[1].z * L[2]; - } - else if (config == 12) /* V3 V4 clip V1 V2 */ + /* Compute the Hessian and the discriminant */ + vec3 delta = vec3( + -coefs.z*coefs.z + coefs.y, + -coefs.y*coefs.z + coefs.x, + dot(vec2(coefs.z, -coefs.y), coefs.xy) + ); + + /* Discriminant */ + float discr = dot(vec2(4.0 * delta.x, -delta.y), delta.zy); + + vec2 xlc, xsc; + + /* Algorithm A */ { - n = 4; - L[1] = -L[1].z * L[2] + L[2].z * L[1]; - L[0] = -L[0].z * L[3] + L[3].z * L[0]; + float A_a = 1.0; + float C_a = delta.x; + float D_a = -2.0 * B * delta.x + delta.y; + + /* Take the cubic root of a normalized complex number */ + float theta = atan(sqrt(discr), -D_a) / 3.0; + + float x_1a = 2.0 * sqrt(-C_a) * cos(theta); + float x_3a = 2.0 * sqrt(-C_a) * cos(theta + (2.0 / 3.0) * M_PI); + + float xl; + if ((x_1a + x_3a) > 2.0 * B) { + xl = x_1a; + } + else { + xl = x_3a; + } + + xlc = vec2(xl - B, A); } - else if (config == 13) /* V1 V3 V4 clip V2 */ + + /* Algorithm D */ { - n = 5; - L[4] = L[3]; - L[3] = L[2]; - L[2] = -L[1].z * L[2] + L[2].z * L[1]; - L[1] = -L[1].z * L[0] + L[0].z * L[1]; + float A_d = D; + float C_d = delta.z; + float D_d = -D * delta.y + 2.0 * C * delta.z; + + /* Take the cubic root of a normalized complex number */ + float theta = atan(D * sqrt(discr), -D_d) / 3.0; + + float x_1d = 2.0 * sqrt(-C_d) * cos(theta); + float x_3d = 2.0 * sqrt(-C_d) * cos(theta + (2.0 / 3.0) * M_PI); + + float xs; + if (x_1d + x_3d < 2.0 * C) + xs = x_1d; + else + xs = x_3d; + + xsc = vec2(-D, xs + C); } - else if (config == 14) /* V2 V3 V4 clip V1 */ - { - n = 5; - L[4] = -L[0].z * L[3] + L[3].z * L[0]; - L[0] = -L[0].z * L[1] + L[1].z * L[0]; + + float E = xlc.y * xsc.y; + float F = -xlc.x * xsc.y - xlc.y * xsc.x; + float G = xlc.x * xsc.x; + + vec2 xmc = vec2(C * F - B * G, -B * F + C * E); + + vec3 root = vec3(xsc.x / xsc.y, + xmc.x / xmc.y, + xlc.x / xlc.y); + + if (root.x < root.y && root.x < root.z) { + root.xyz = root.yxz; } - else if (config == 15) /* V1 V2 V3 V4 */ - { - n = 4; + else if (root.z < root.x && root.z < root.y) { + root.xyz = root.xzy; } - if (n == 3) - L[3] = L[0]; - if (n == 4) - L[4] = L[0]; + return root; +} + +/* from Real-Time Area Lighting: a Journey from Research to Production + * Stephen Hill and Eric Heitz */ +vec3 edge_integral_vec(vec3 v1, vec3 v2) +{ + float x = dot(v1, v2); + float y = abs(x); + + float a = 0.8543985 + (0.4965155 + 0.0145206 * y) * y; + float b = 3.4175940 + (4.1616724 + y) * y; + float v = a / b; - return n; + float theta_sintheta = (x > 0.0) ? v : 0.5 * inversesqrt(max(1.0 - x * x, 1e-7)) - v; + + return cross(v1, v2) * theta_sintheta; } mat3 ltc_matrix(vec4 lut) @@ -159,7 +149,7 @@ mat3 ltc_matrix(vec4 lut) return Minv; } -float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4]) +void ltc_transform_quad(vec3 N, vec3 V, mat3 Minv, inout vec3 corners[4]) { /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */ V = normalize(V + 1e-8); @@ -172,42 +162,51 @@ float ltc_evaluate(vec3 N, vec3 V, mat3 Minv, vec3 corners[4]) /* rotate area light in (T1, T2, R) basis */ Minv = Minv * transpose(mat3(T1, T2, N)); - /* polygon (allocate 5 vertices for clipping) */ - vec3 L[5]; - L[0] = Minv * corners[0]; - L[1] = Minv * corners[1]; - L[2] = Minv * corners[2]; - L[3] = Minv * corners[3]; - - int n = clip_quad_to_horizon(L); - - if (n == 0) - return 0.0; - - /* project onto sphere */ - L[0] = normalize(L[0]); - L[1] = normalize(L[1]); - L[2] = normalize(L[2]); - L[3] = normalize(L[3]); - L[4] = normalize(L[4]); - - /* integrate */ - float sum = 0.0; - - sum += edge_integral(L[0], L[1]); - sum += edge_integral(L[1], L[2]); - sum += edge_integral(L[2], L[3]); - if (n >= 4) - sum += edge_integral(L[3], L[4]); - if (n == 5) - sum += edge_integral(L[4], L[0]); - - return abs(sum); + /* Apply LTC inverse matrix. */ + corners[0] = normalize(Minv * corners[0]); + corners[1] = normalize(Minv * corners[1]); + corners[2] = normalize(Minv * corners[2]); + corners[3] = normalize(Minv * corners[3]); } -/* Aproximate circle with an octogone */ -#define LTC_CIRCLE_RES 8 -float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES]) +/* If corners have already pass through ltc_transform_quad(), then N **MUST** be vec3(0.0, 0.0, 1.0), + * corresponding to the Up axis of the shading basis. */ +float ltc_evaluate_quad(vec3 corners[4], vec3 N) +{ + /* Approximation using a sphere of the same solid angle than the quad. + * Finding the clipped sphere diffuse integral is easier than clipping the quad. */ + vec3 avg_dir; + avg_dir = edge_integral_vec(corners[0], corners[1]); + avg_dir += edge_integral_vec(corners[1], corners[2]); + avg_dir += edge_integral_vec(corners[2], corners[3]); + avg_dir += edge_integral_vec(corners[3], corners[0]); + + float form_factor = length(avg_dir); + float avg_dir_z = dot(N, avg_dir / form_factor); + +#if 1 /* use tabulated horizon-clipped sphere */ + return form_factor * diffuse_sphere_integral_lut(avg_dir_z, form_factor); +#else /* Less accurate version, a bit cheaper. */ + return form_factor * diffuse_sphere_integral_cheap(avg_dir_z, form_factor); +#endif +} + +/* If disk does not need to be transformed and is already front facing. */ +float ltc_evaluate_disk_simple(float disk_radius, float NL) +{ + float r_sqr = disk_radius * disk_radius; + float one_r_sqr = 1.0 + r_sqr; + float form_factor = r_sqr * inversesqrt(one_r_sqr * one_r_sqr); + +#if 1 /* use tabulated horizon-clipped sphere */ + return form_factor * diffuse_sphere_integral_lut(NL, form_factor); +#else /* Less accurate version, a bit cheaper. */ + return form_factor * diffuse_sphere_integral_cheap(NL, form_factor); +#endif +} + +/* disk_points are WS vectors from the shading point to the disk "bounding domain" */ +float ltc_evaluate_disk(vec3 N, vec3 V, mat3 Minv, vec3 disk_points[3]) { /* Avoid dot(N, V) == 1 in ortho mode, leading T1 normalize to fail. */ V = normalize(V + 1e-8); @@ -218,23 +217,106 @@ float ltc_evaluate_circle(vec3 N, vec3 V, mat3 Minv, vec3 p[LTC_CIRCLE_RES]) T2 = cross(N, T1); /* rotate area light in (T1, T2, R) basis */ - Minv = Minv * transpose(mat3(T1, T2, N)); + mat3 R = transpose(mat3(T1, T2, N)); - for (int i = 0; i < LTC_CIRCLE_RES; ++i) { - p[i] = Minv * p[i]; - /* clip to horizon */ - p[i].z = max(0.0, p[i].z); - /* project onto sphere */ - p[i] = normalize(p[i]); - } + /* Intermediate step: init ellipse. */ + vec3 L_[3]; + L_[0] = mul(R, disk_points[0]); + L_[1] = mul(R, disk_points[1]); + L_[2] = mul(R, disk_points[2]); + + vec3 C = 0.5 * (L_[0] + L_[2]); + vec3 V1 = 0.5 * (L_[1] - L_[2]); + vec3 V2 = 0.5 * (L_[1] - L_[0]); + + /* Transform ellipse by Minv. */ + C = Minv * C; + V1 = Minv * V1; + V2 = Minv * V2; + + /* Compute eigenvectors of new ellipse. */ - /* integrate */ - float sum = 0.0; - for (int i = 0; i < LTC_CIRCLE_RES - 1; ++i) { - sum += edge_integral(p[i], p[i + 1]); + float d11 = dot(V1, V1); + float d22 = dot(V2, V2); + float d12 = dot(V1, V2); + float a, b; /* Eigenvalues */ + const float threshold = 0.0007; /* Can be adjusted. Fix artifacts. */ + if (abs(d12) / sqrt(d11 * d22) > threshold) { + float tr = d11 + d22; + float det = -d12 * d12 + d11 * d22; + + /* use sqrt matrix to solve for eigenvalues */ + det = sqrt(det); + float u = 0.5 * sqrt(tr - 2.0 * det); + float v = 0.5 * sqrt(tr + 2.0 * det); + float e_max = (u + v); + float e_min = (u - v); + e_max *= e_max; + e_min *= e_min; + + vec3 V1_, V2_; + if (d11 > d22) { + V1_ = d12 * V1 + (e_max - d11) * V2; + V2_ = d12 * V1 + (e_min - d11) * V2; + } + else { + V1_ = d12 * V2 + (e_max - d22) * V1; + V2_ = d12 * V2 + (e_min - d22) * V1; + } + + a = 1.0 / e_max; + b = 1.0 / e_min; + V1 = normalize(V1_); + V2 = normalize(V2_); } - sum += edge_integral(p[LTC_CIRCLE_RES - 1], p[0]); + else { + a = 1.0 / d11; + b = 1.0 / d22; + V1 *= sqrt(a); + V2 *= sqrt(b); + } + + /* Now find front facing ellipse with same solid angle. */ - return max(0.0, sum); + vec3 V3 = normalize(cross(V1, V2)); + if (dot(C, V3) < 0.0) + V3 *= -1.0; + + float L = dot(V3, C); + float x0 = dot(V1, C) / L; + float y0 = dot(V2, C) / L; + + a *= L*L; + b *= L*L; + + float c0 = a * b; + float c1 = a * b * (1.0 + x0 * x0 + y0 * y0) - a - b; + float c2 = 1.0 - a * (1.0 + x0 * x0) - b * (1.0 + y0 * y0); + float c3 = 1.0; + + vec3 roots = solve_cubic(vec4(c0, c1, c2, c3)); + float e1 = roots.x; + float e2 = roots.y; + float e3 = roots.z; + + vec3 avg_dir = vec3(a * x0 / (a - e2), b * y0 / (b - e2), 1.0); + + mat3 rotate = mat3(V1, V2, V3); + + avg_dir = rotate * avg_dir; + avg_dir = normalize(avg_dir); + + /* L1, L2 are the extends of the front facing ellipse. */ + float L1 = sqrt(-e2/e3); + float L2 = sqrt(-e2/e1); + + /* Find the sphere and compute lighting. */ + float form_factor = max(0.0, L1 * L2 * inversesqrt((1.0 + L1 * L1) * (1.0 + L2 * L2))); + +#if 1 /* use tabulated horizon-clipped sphere */ + return form_factor * diffuse_sphere_integral_lut(avg_dir.z, form_factor); +#else /* Less accurate version, a bit cheaper. */ + return form_factor * diffuse_sphere_integral_cheap(avg_dir.z, form_factor); +#endif } diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl index f921d56e3bc..1c0e65f0613 100644 --- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl @@ -10,14 +10,15 @@ float hash3d(vec3 a) { return hash(vec2(hash(a.xy), a.z)); } -//uniform float hashScale; -float hashScale = 0.001; +uniform float hashAlphaOffset; float hashed_alpha_threshold(vec3 co) { + const float hash_scale = 1.0; /* Roughly in pixel */ + /* Find the discretized derivatives of our coordinates. */ float max_deriv = max(length(dFdx(co)), length(dFdy(co))); - float pix_scale = 1.0 / (hashScale * max_deriv); + float pix_scale = 1.0 / (hash_scale * max_deriv); /* Find two nearest log-discretized noise scales. */ float pix_scale_log = log2(pix_scale); @@ -53,7 +54,8 @@ float hashed_alpha_threshold(vec3 co) /* Avoids threshold == 0. */ threshold = clamp(threshold, 1.0e-6, 1.0); - return threshold; + /* Jitter the threshold for TAA accumulation. */ + return fract(threshold + hashAlphaOffset); } #endif diff --git a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl index c593081ce91..cb75731b7da 100644 --- a/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl @@ -1,13 +1,5 @@ #define MAX_STEP 256 -uniform vec4 ssrParameters; - -#define ssrQuality ssrParameters.x -#define ssrThickness ssrParameters.y -#define ssrPixelSize ssrParameters.zw - -uniform float borderFadeFactor; - float sample_depth(vec2 uv, int index, float lod) { #ifdef PLANAR_PROBE_RAYTRACE @@ -233,7 +225,7 @@ vec3 raycast( float screen_border_mask(vec2 hit_co) { const float margin = 0.003; - float atten = borderFadeFactor + margin; /* Screen percentage */ + float atten = ssrBorderFac + margin; /* Screen percentage */ hit_co = smoothstep(margin, atten, hit_co) * (1 - smoothstep(1.0 - atten, 1.0 - margin, hit_co)); float screenfade = hit_co.x * hit_co.y; diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl index 92287d2ecbc..6c7bfeb6b82 100644 --- a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl @@ -2,10 +2,9 @@ #define BTDF_BIAS 0.85 -vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec3 rand, float ofs) +vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec4 rand) { float a2 = max(5e-6, roughnessSquared * roughnessSquared); - float jitter = fract(rand.x + ofs); /* Importance sampling bias */ rand.x = mix(rand.x, 0.0, BTDF_BIAS); @@ -13,12 +12,12 @@ vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float vec3 T, B; float NH; make_orthonormal_basis(N, T, B); - vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */ + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ float pdf = pdf_ggx_reflect(NH, a2); /* If ray is bad (i.e. going below the plane) regenerate. */ if (F_eta(ior, dot(H, V)) < 1.0) { - H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ + H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ pdf = pdf_ggx_reflect(NH, a2); } @@ -33,7 +32,7 @@ vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float R = transform_direction(ViewMatrix, R); - vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, roughnessSquared, false); + vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, roughnessSquared, false); if ((hit_pos.z > 0.0) && (F_eta(ior, dot(H, V)) < 1.0)) { hit_pos = get_view_space_from_depth(hit_pos.xy, hit_pos.z); diff --git a/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl new file mode 100644 index 00000000000..13ffe02eb0d --- /dev/null +++ b/source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl @@ -0,0 +1,18 @@ + +uniform sampler2D blueNoise; +uniform vec3 offsets; + +out vec4 FragColor; + +#define M_2PI 6.28318530717958647692 + +void main(void) +{ + vec2 blue_noise = texelFetch(blueNoise, ivec2(gl_FragCoord.xy), 0).xy; + + float noise = fract(blue_noise.y + offsets.z); + FragColor.x = fract(blue_noise.x + offsets.x); + FragColor.y = fract(blue_noise.y + offsets.y); + FragColor.z = cos(noise * M_2PI); + FragColor.w = sin(noise * M_2PI); +} diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl index 00e01e753f9..3a293647f84 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl @@ -4,9 +4,6 @@ #define NODETREE_EXEC -uniform ivec3 volumeTextureSize; -uniform vec3 volume_jitter; - #ifdef MESH_SHADER uniform mat4 volumeObjectMatrix; uniform vec3 volumeOrcoLoc; @@ -33,7 +30,7 @@ layout(location = 3) out vec4 volumePhase; void main() { ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice); - vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volumeTextureSize); + vec3 ndc_cell = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz); viewPosition = get_view_space_from_depth(ndc_cell.xy, ndc_cell.z); worldPosition = transform_point(ViewMatrixInverse, viewPosition); diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl index 1376c53d633..1a8167c2830 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl @@ -2,22 +2,16 @@ /* Based on Frosbite Unified Volumetric. * https://www.ea.com/frostbite/news/physically-based-unified-volumetric-rendering-in-frostbite */ -uniform float volume_light_clamp; - -uniform vec3 volume_param; /* Parameters to the volume Z equation */ - -uniform vec2 volume_uv_ratio; /* To convert volume uvs to screen uvs */ - /* Volume slice to view space depth. */ float volume_z_to_view_z(float z) { if (ProjectionMatrix[3][3] == 0.0) { /* Exponential distribution */ - return (exp2(z / volume_param.z) - volume_param.x) / volume_param.y; + return (exp2(z / volDepthParameters.z) - volDepthParameters.x) / volDepthParameters.y; } else { /* Linear distribution */ - return mix(volume_param.x, volume_param.y, z); + return mix(volDepthParameters.x, volDepthParameters.y, z); } } @@ -25,11 +19,11 @@ float view_z_to_volume_z(float depth) { if (ProjectionMatrix[3][3] == 0.0) { /* Exponential distribution */ - return volume_param.z * log2(depth * volume_param.y + volume_param.x); + return volDepthParameters.z * log2(depth * volDepthParameters.y + volDepthParameters.x); } else { /* Linear distribution */ - return (depth - volume_param.x) * volume_param.z; + return (depth - volDepthParameters.x) * volDepthParameters.z; } } @@ -38,7 +32,7 @@ vec3 volume_to_ndc(vec3 cos) { cos.z = volume_z_to_view_z(cos.z); cos.z = get_depth_from_view_z(cos.z); - cos.xy /= volume_uv_ratio; + cos.xy /= volCoordScale.xy; return cos; } @@ -46,7 +40,7 @@ vec3 ndc_to_volume(vec3 cos) { cos.z = get_view_z_from_depth(cos.z); cos.z = view_z_to_volume_z(cos.z); - cos.xy *= volume_uv_ratio; + cos.xy *= volCoordScale.xy; return cos; } @@ -71,14 +65,17 @@ vec3 light_volume(LightData ld, vec4 l_vector) /* TODO : Area lighting ? */ /* XXX : Removing Area Power. */ /* TODO : put this out of the shader. */ + /* See eevee_light_setup(). */ if (ld.l_type == AREA) { - power = 0.0962 * (ld.l_sizex * ld.l_sizey * 4.0 * M_PI); + power = (ld.l_sizex * ld.l_sizey * 4.0 * M_PI) * (1.0 / 80.0); + power *= 20.0 * max(0.0, dot(-ld.l_forward, l_vector.xyz / l_vector.w)); /* XXX ad hoc, empirical */ } else if (ld.l_type == SUN) { - power = 1.0; + power = (4.0f * ld.l_radius * ld.l_radius * M_2PI) * (1.0 / 12.5); /* Removing area light power*/ + power *= M_2PI * 0.78; /* Matching cycles with point light. */ } else { - power = 0.0248 * (4.0 * ld.l_radius * ld.l_radius * M_PI * M_PI); + power = (4.0 * ld.l_radius * ld.l_radius) * (1.0 /10.0); } /* OPTI: find a better way than calculating this on the fly */ @@ -87,15 +84,13 @@ vec3 light_volume(LightData ld, vec4 l_vector) power /= (l_vector.w * l_vector.w); - lum = min(lum * power, volume_light_clamp); + lum = min(lum * power, volLightClamp); return tint * lum; } #define VOLUMETRIC_SHADOW_MAX_STEP 32.0 -uniform float volume_shadows_steps; - vec3 participating_media_extinction(vec3 wpos, sampler3D volume_extinction) { /* Waiting for proper volume shadowmaps and out of frustum shadow map. */ @@ -110,11 +105,11 @@ vec3 light_volume_shadow(LightData ld, vec3 ray_wpos, vec4 l_vector, sampler3D v { #if defined(VOLUME_SHADOW) /* Heterogeneous volume shadows */ - float dd = l_vector.w / volume_shadows_steps; + float dd = l_vector.w / volShadowSteps; vec3 L = l_vector.xyz * l_vector.w; vec3 shadow = vec3(1.0); - for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volume_shadows_steps - 0.1); s += 1.0) { - vec3 pos = ray_wpos + L * (s / volume_shadows_steps); + for (float s = 0.5; s < VOLUMETRIC_SHADOW_MAX_STEP && s < (volShadowSteps - 0.1); s += 1.0) { + vec3 pos = ray_wpos + L * (s / volShadowSteps); vec3 s_extinction = participating_media_extinction(pos, volume_extinction); shadow *= exp(-s_extinction * dd); } diff --git a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl index ea402ff3d99..fcbb6661b14 100644 --- a/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl @@ -13,28 +13,20 @@ uniform sampler3D volumePhase; uniform sampler3D historyScattering; uniform sampler3D historyTransmittance; -uniform vec3 volume_jitter; -uniform float volume_history_alpha; -uniform int light_count; -uniform mat4 PastViewProjectionMatrix; - flat in int slice; layout(location = 0) out vec4 outScattering; layout(location = 1) out vec4 outTransmittance; -#define VOLUME_LIGHTING - void main() { - vec3 volume_tex_size = vec3(textureSize(volumeScattering, 0)); ivec3 volume_cell = ivec3(gl_FragCoord.xy, slice); /* Emission */ outScattering = texelFetch(volumeEmission, volume_cell, 0); outTransmittance = texelFetch(volumeExtinction, volume_cell, 0); vec3 s_scattering = texelFetch(volumeScattering, volume_cell, 0).rgb; - vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volume_jitter) / volume_tex_size); + vec3 volume_ndc = volume_to_ndc((vec3(volume_cell) + volJitter.xyz) * volInvTexSize.xyz); vec3 worldPosition = get_world_space_from_depth(volume_ndc.xy, volume_ndc.z); vec3 wdir = cameraVec; @@ -45,7 +37,7 @@ void main() outScattering.rgb += irradiance_volumetric(worldPosition) * s_scattering * phase_function_isotropic(); #ifdef VOLUME_LIGHTING /* Lights */ - for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) { + for (int i = 0; i < MAX_LIGHT && i < laNumLight; ++i) { LightData ld = lights_data[i]; @@ -63,16 +55,16 @@ void main() /* Temporal supersampling */ /* Note : this uses the cell non-jittered position (texel center). */ - vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) / volume_tex_size); + vec3 curr_ndc = volume_to_ndc(vec3(gl_FragCoord.xy, float(slice) + 0.5) * volInvTexSize.xyz); vec3 wpos = get_world_space_from_depth(curr_ndc.xy, curr_ndc.z); - vec3 prev_ndc = project_point(PastViewProjectionMatrix, wpos); + vec3 prev_ndc = project_point(pastViewProjectionMatrix, wpos); vec3 prev_volume = ndc_to_volume(prev_ndc * 0.5 + 0.5); - if ((volume_history_alpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) { + if ((volHistoryAlpha > 0.0) && all(greaterThan(prev_volume, vec3(0.0))) && all(lessThan(prev_volume, vec3(1.0)))) { vec4 h_Scattering = texture(historyScattering, prev_volume); vec4 h_Transmittance = texture(historyTransmittance, prev_volume); - outScattering = mix(outScattering, h_Scattering, volume_history_alpha); - outTransmittance = mix(outTransmittance, h_Transmittance, volume_history_alpha); + outScattering = mix(outScattering, h_Scattering, volHistoryAlpha); + outTransmittance = mix(outTransmittance, h_Transmittance, volHistoryAlpha); } /* Catch NaNs */ diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c index 851d0ef9eb7..ec0141953fe 100644 --- a/source/blender/draw/engines/external/external_engine.c +++ b/source/blender/draw/engines/external/external_engine.c @@ -218,6 +218,7 @@ DrawEngineType draw_engine_external_type = { &external_draw_scene, NULL, NULL, + NULL, }; /* Note: currently unused, we should not register unless we want to see this when debugging the view. */ |