Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Eisel <eiseljulian@gmail.com>2018-01-30 00:53:32 +0300
committerJulian Eisel <eiseljulian@gmail.com>2018-01-30 01:24:11 +0300
commit3f0871dfcfbb1dda15c176dba92d36639305385a (patch)
treede7ffeeef7a99fc6103d413ebfa564596811087d /source/blender/draw/engines
parent53d94dafc474380651fc529f9c03f84ce7142b13 (diff)
parent1fe2b4bf608b22ae4513051e01cf45e5012c2409 (diff)
Merge branch 'blender2.8' into topbar
Diffstat (limited to 'source/blender/draw/engines')
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c1
-rw-r--r--source/blender/draw/engines/clay/clay_engine.c103
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c106
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c25
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c107
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c217
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c334
-rw-r--r--source/blender/draw/engines/eevee/eevee_lights.c393
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut.h515
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c371
-rw-r--r--source/blender/draw/engines/eevee/eevee_motion_blur.c82
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c115
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h231
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c278
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c181
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c31
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c119
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c232
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl164
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl26
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_direct_lib.glsl123
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_sampling_lib.glsl4
-rw-r--r--source/blender/draw/engines/eevee/shaders/common_uniforms_lib.glsl55
-rw-r--r--source/blender/draw/engines/eevee/shaders/default_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_gtao_frag.glsl49
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_minmaxz_frag.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_motion_blur_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl410
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_subsurface_frag.glsl13
-rw-r--r--source/blender/draw/engines/eevee/shaders/irradiance_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/lamps_lib.glsl43
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_cube_display_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_diffuse_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_filter_glossy_frag.glsl3
-rw-r--r--source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl7
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl48
-rw-r--r--source/blender/draw/engines/eevee/shaders/ltc_lib.glsl426
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/raytrace_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/ssr_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/update_noise_frag.glsl18
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_frag.glsl5
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_lib.glsl37
-rw-r--r--source/blender/draw/engines/eevee/shaders/volumetric_scatter_frag.glsl22
-rw-r--r--source/blender/draw/engines/external/external_engine.c1
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(&params);
- /* 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(&params, draw_ctx->depsgraph, v3d, rv3d);
+ BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
+ }
+ else {
BKE_camera_params_from_object(&params, &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(&params, scene->r.xsch, scene->r.ysch, scene->r.xasp, scene->r.yasp);
}
- BKE_camera_params_compute_viewplane(&params, ar->winx, ar->winy, 1.0f, 1.0f);
BKE_camera_params_compute_matrix(&params);
/* 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. */