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:
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c19
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c4
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h15
-rw-r--r--source/blender/draw/engines/eevee/eevee_probes.c264
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl9
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl28
7 files changed, 271 insertions, 71 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 66cb82ae277..514953f3d51 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -70,6 +70,13 @@ static void eevee_lamp_data_free(void *storage)
BLI_freelistN(&led->shadow_caster_list);
}
+static void eevee_probe_data_free(void *storage)
+{
+ EEVEE_ProbeEngineData *ped = (EEVEE_ProbeEngineData *)storage;
+
+ BLI_freelistN(&ped->captured_object_list);
+}
+
EEVEE_SceneLayerData *EEVEE_scene_layer_data_get(void)
{
EEVEE_SceneLayerData **sldata = (EEVEE_SceneLayerData **)DRW_scene_layer_engine_data_get(&draw_engine_eevee_type, &eevee_scene_layer_data_free);
@@ -92,6 +99,18 @@ EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob)
return *oedata;
}
+EEVEE_ProbeEngineData *EEVEE_probe_data_get(Object *ob)
+{
+ EEVEE_ProbeEngineData **pedata = (EEVEE_ProbeEngineData **)DRW_object_engine_data_get(ob, &draw_engine_eevee_type, &eevee_probe_data_free);
+
+ if (*pedata == NULL) {
+ *pedata = MEM_callocN(sizeof(**pedata), "EEVEE_ProbeEngineData");
+ (*pedata)->need_update = true;
+ }
+
+ return *pedata;
+}
+
EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob)
{
EEVEE_LampEngineData **ledata = (EEVEE_LampEngineData **)DRW_object_engine_data_get(ob, &draw_engine_eevee_type, &eevee_lamp_data_free);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index 2a75777c15e..46d1a6e1ac0 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -104,6 +104,9 @@ static void EEVEE_cache_populate(void *vedata, Object *ob)
oedata->need_update = ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0);
}
}
+ else if (ob->type == OB_PROBE) {
+ EEVEE_probes_cache_add(sldata, ob);
+ }
else if (ob->type == OB_LAMP) {
EEVEE_lights_cache_add(sldata, ob);
}
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index a5f29872e58..6baa5351e3b 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -244,7 +244,7 @@ struct GPUMaterial *EEVEE_material_mesh_probe_get(struct Scene *scene, Material
return GPU_material_from_nodetree(
scene, ma->nodetree, &ma->gpumaterial, &DRW_engine_viewport_eevee_type,
VAR_MAT_MESH | VAR_MAT_PROBE,
- datatoc_probe_vert_glsl, datatoc_probe_geom_glsl, e_data.frag_shader_lib,
+ datatoc_probe_vert_glsl, NULL, e_data.frag_shader_lib,
SHADER_DEFINES "#define MESH_SHADER\n" "#define PROBE_CAPTURE\n");
}
@@ -263,7 +263,7 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *
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_cube, 1);
+ DRW_shgroup_uniform_int(shgrp, "probe_count", &sldata->probes->num_render_probe, 1);
DRW_shgroup_uniform_float(shgrp, "lodMax", &sldata->probes->lodmax, 1);
DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool);
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 84c6de8593c..eb89ee999f4 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -48,6 +48,7 @@ typedef struct EEVEE_PassList {
/* Probes */
struct DRWPass *probe_background;
+ struct DRWPass *probe_meshes;
struct DRWPass *probe_prefilter;
struct DRWPass *probe_sh_compute;
@@ -166,14 +167,17 @@ enum {
/* ************ PROBE UBO ************* */
typedef struct EEVEE_Probe {
- float position[3], dist;
- float shcoefs[9][3], pad;
+ float position[3], pad1;
+ float shcoefs[9][3], pad2;
+ float attenuation_bias, attenuation_scale, pad3[2];
} EEVEE_Probe;
/* ************ PROBE DATA ************* */
typedef struct EEVEE_ProbesInfo {
int num_cube, cache_num_cube;
int update_flag;
+ /* Actual number of probes that have datas. */
+ int num_render_probe;
/* For rendering probes */
float probemat[6][4][4];
int layer;
@@ -285,6 +289,12 @@ typedef struct EEVEE_LampEngineData {
void *storage; /* either EEVEE_LightData, EEVEE_ShadowCubeData, EEVEE_ShadowCascadeData */
} EEVEE_LampEngineData;
+typedef struct EEVEE_ProbeEngineData {
+ bool need_update;
+ bool ready_to_shade;
+ struct ListBase captured_object_list;
+} EEVEE_ProbeEngineData;
+
typedef struct EEVEE_ObjectEngineData {
bool need_update;
} EEVEE_ObjectEngineData;
@@ -309,6 +319,7 @@ typedef struct EEVEE_PrivateData {
/* eevee_data.c */
EEVEE_SceneLayerData *EEVEE_scene_layer_data_get(void);
EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob);
+EEVEE_ProbeEngineData *EEVEE_probe_data_get(Object *ob);
EEVEE_LampEngineData *EEVEE_lamp_data_get(Object *ob);
diff --git a/source/blender/draw/engines/eevee/eevee_probes.c b/source/blender/draw/engines/eevee/eevee_probes.c
index 10ba7bafde7..48947e004b6 100644
--- a/source/blender/draw/engines/eevee/eevee_probes.c
+++ b/source/blender/draw/engines/eevee/eevee_probes.c
@@ -26,22 +26,24 @@
#include "DNA_world_types.h"
#include "DNA_texture_types.h"
#include "DNA_image_types.h"
+#include "DNA_probe_types.h"
+#include "DNA_view3d_types.h"
#include "BLI_dynstr.h"
+#include "ED_screen.h"
+
#include "DRW_render.h"
#include "GPU_material.h"
#include "GPU_texture.h"
#include "GPU_glew.h"
+#include "DRW_render.h"
+
#include "eevee_engine.h"
#include "eevee_private.h"
-typedef struct EEVEE_ProbeCubeData {
- short probe_id;
-} EEVEE_ProbeCubeData;
-
/* TODO Option */
#define PROBE_CUBE_SIZE 512
#define PROBE_SIZE 1024
@@ -54,6 +56,7 @@ static struct {
struct GPUTexture *hammersley;
bool update_world;
+ bool world_ready_to_shade;
} e_data = {NULL}; /* Engine data */
extern char datatoc_default_world_frag_glsl[];
@@ -156,7 +159,7 @@ void EEVEE_probes_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
memset(pinfo->probes_ref, 0, sizeof(pinfo->probes_ref));
{
- psl->probe_background = DRW_pass_create("World Probe Pass", DRW_STATE_WRITE_DEPTH | DRW_STATE_WRITE_COLOR);
+ psl->probe_background = DRW_pass_create("World Probe Pass", DRW_STATE_WRITE_COLOR);
struct Batch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -203,6 +206,10 @@ void EEVEE_probes_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
}
{
+ psl->probe_meshes = DRW_pass_create("Probe Meshes", DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS);
+ }
+
+ {
psl->probe_prefilter = DRW_pass_create("Probe Filtering", DRW_STATE_WRITE_COLOR);
struct Batch *geom = DRW_cache_fullscreen_quad_get();
@@ -236,84 +243,90 @@ void EEVEE_probes_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
}
}
-void EEVEE_probes_cache_add(EEVEE_SceneLayerData *UNUSED(sldata), Object *UNUSED(ob))
+void EEVEE_probes_cache_add(EEVEE_SceneLayerData *sldata, Object *ob)
{
- return;
+ EEVEE_ProbesInfo *pinfo = sldata->probes;
+
+ /* Step 1 find all lamps in the scene and setup them */
+ if (pinfo->num_cube > MAX_PROBE) {
+ printf("Too much probes in the scene !!!\n");
+ pinfo->num_cube = MAX_PROBE;
+ }
+ else {
+ EEVEE_ProbeEngineData *ped = EEVEE_probe_data_get(ob);
+
+ if ((ob->deg_update_flag & DEG_RUNTIME_DATA_UPDATE) != 0) {
+ ped->need_update = true;
+ }
+
+ if (e_data.update_world) {
+ ped->need_update = true;
+ }
+
+ pinfo->probes_ref[pinfo->num_cube] = ob;
+ pinfo->num_cube++;
+ }
+}
+
+static void EEVEE_probes_updates(EEVEE_SceneLayerData *sldata)
+{
+ EEVEE_ProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+
+ for (int i = 1; (ob = pinfo->probes_ref[i]) && (i < MAX_PROBE); i++) {
+ Probe *probe = (Probe *)ob->data;
+ EEVEE_Probe *eprobe = &pinfo->probe_data[i];
+
+ float dist_minus_falloff = probe->dist - (1.0f - probe->falloff) * probe->dist;
+ eprobe->attenuation_bias = probe->dist / max_ff(1e-8f, dist_minus_falloff);
+ eprobe->attenuation_scale = 1.0f / max_ff(1e-8f, dist_minus_falloff);
+ }
}
void EEVEE_probes_cache_finish(EEVEE_SceneLayerData *sldata)
{
EEVEE_ProbesInfo *pinfo = sldata->probes;
+ Object *ob;
/* Setup enough layers. */
/* Free textures if number mismatch. */
if (pinfo->num_cube != pinfo->cache_num_cube) {
DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
- pinfo->cache_num_cube = pinfo->num_cube;
- pinfo->update_flag |= PROBE_UPDATE_CUBE;
}
if (!sldata->probe_pool) {
sldata->probe_pool = DRW_texture_create_2D_array(PROBE_SIZE, PROBE_SIZE, max_ff(1, pinfo->num_cube),
DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
+ if (sldata->probe_filter_fb) {
+ DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
+ }
+
+ /* Tag probes to refresh */
+ e_data.update_world = true;
+ e_data.world_ready_to_shade = false;
+ pinfo->num_render_probe = 0;
+ pinfo->update_flag |= PROBE_UPDATE_CUBE;
+ pinfo->cache_num_cube = pinfo->num_cube;
+
+ for (int i = 1; (ob = pinfo->probes_ref[i]) && (i < MAX_PROBE); i++) {
+ EEVEE_ProbeEngineData *ped = EEVEE_probe_data_get(ob);
+ ped->need_update = true;
+ ped->ready_to_shade = false;
+ }
}
DRWFboTexture tex_filter = {&sldata->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP};
DRW_framebuffer_init(&sldata->probe_filter_fb, &draw_engine_eevee_type, PROBE_SIZE, PROBE_SIZE, &tex_filter, 1);
+ EEVEE_probes_updates(sldata);
+
DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
}
-/* Renders the probe with index probe_idx.
- * Renders the world probe if probe_idx = -1. */
-static void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int probe_idx)
+static void filter_probe(EEVEE_Probe *eprobe, EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int probe_idx)
{
EEVEE_ProbesInfo *pinfo = sldata->probes;
- EEVEE_Probe *eprobe = &pinfo->probe_data[probe_idx];
- Object *ob = NULL;
- struct DRWPass *probe_pass;
- bool is_object_probe = (probe_idx > 0);
-
- float projmat[4][4], posmat[4][4];
- float near, far;
- float clear_color[4] = {0.5, 0.5, 0.5, 0.0f};
-
- unit_m4(posmat);
-
- if (is_object_probe) {
- ob = pinfo->probes_ref[probe_idx];
- near = 0.1f;
- far = 100.0f;
-
- /* Move to capture position */
- negate_v3_v3(posmat[3], ob->obmat[3]);
- probe_pass = psl->probe_background; /* TODO use objects in the scene */
- }
- else {
- /* World cubemap */
- near = 0.1f;
- far = 100.0f;
- probe_pass = psl->probe_background;
- }
-
- /* 1 - Render to cubemap target using geometry shader. */
- /* For world probe, we don't need to clear since we render the background directly. */
- pinfo->layer = 0;
- perspective_m4(projmat, -near, near, -near, near, near, far);
-
- for (int i = 0; i < 6; ++i) {
- float tmp[4][4];
- mul_m4_m4m4(tmp, cubefacemat[i], posmat);
- mul_m4_m4m4(pinfo->probemat[i], projmat, tmp);
- }
-
- DRW_framebuffer_bind(sldata->probe_fb);
- DRW_draw_pass(probe_pass);
-
- if (is_object_probe) {
- DRW_framebuffer_clear(true, true, false, clear_color, 1.0);
- }
/* 2 - Let gpu create Mipmaps for Filtered Importance Sampling. */
/* Bind next framebuffer to be able to gen. mips for probe_rt. */
@@ -389,13 +402,150 @@ static void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl,
DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0);
}
+/* Renders the probe with index probe_idx.
+ * Renders the world probe if probe_idx = -1. */
+static void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int probe_idx)
+{
+ EEVEE_ProbesInfo *pinfo = sldata->probes;
+ EEVEE_Probe *eprobe = &pinfo->probe_data[probe_idx];
+ Object *ob = NULL;
+
+ float winmat[4][4], posmat[4][4];
+ float near = 0.1f; /* TODO parameters */
+ float far = 100.0f;
+
+ unit_m4(posmat);
+
+ ob = pinfo->probes_ref[probe_idx];
+
+ /* Update transforms */
+ copy_v3_v3(eprobe->position, ob->obmat[3]);
+
+ /* Move to capture position */
+ negate_v3_v3(posmat[3], ob->obmat[3]);
+
+ /* 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). */
+ pinfo->layer = 0;
+ perspective_m4(winmat, -near, near, -near, near, near, far);
+
+ /* Detach to rebind the right cubeface. */
+ DRW_framebuffer_bind(sldata->probe_fb);
+ DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
+ for (int i = 0; i < 6; ++i) {
+ float viewmat[4][4], persmat[4][4];
+ float viewinv[4][4], persinv[4][4];
+
+ DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_rt, 0, i, 0);
+ DRW_framebuffer_cubeface_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, i, 0);
+ DRW_framebuffer_viewport_size(sldata->probe_fb, PROBE_CUBE_SIZE, PROBE_CUBE_SIZE);
+
+ DRW_framebuffer_clear(false, true, false, NULL, 1.0);
+
+ /* Setup custom matrices */
+ mul_m4_m4m4(viewmat, cubefacemat[i], posmat);
+ mul_m4_m4m4(persmat, winmat, viewmat);
+ invert_m4_m4(persinv, persmat);
+ invert_m4_m4(viewinv, viewmat);
+
+ DRW_viewport_matrix_override_set(persmat, DRW_MAT_PERS);
+ DRW_viewport_matrix_override_set(persinv, DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_set(viewmat, DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_set(viewinv, DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_override_set(winmat, DRW_MAT_WIN);
+
+ DRW_draw_pass(psl->background_pass);
+
+ /* Depth prepass */
+ DRW_draw_pass(psl->depth_pass);
+ DRW_draw_pass(psl->depth_pass_cull);
+
+ /* Shading pass */
+ DRW_draw_pass(psl->default_pass);
+ DRW_draw_pass(psl->default_flat_pass);
+ DRW_draw_pass(psl->material_pass);
+
+ DRW_framebuffer_texture_detach(sldata->probe_rt);
+ DRW_framebuffer_texture_detach(sldata->probe_depth_rt);
+ }
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_rt, 0, 0);
+ DRW_framebuffer_texture_attach(sldata->probe_fb, sldata->probe_depth_rt, 0, 0);
+
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERS);
+ DRW_viewport_matrix_override_unset(DRW_MAT_PERSINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEW);
+ DRW_viewport_matrix_override_unset(DRW_MAT_VIEWINV);
+ DRW_viewport_matrix_override_unset(DRW_MAT_WIN);
+
+ filter_probe(eprobe, sldata, psl, probe_idx);
+}
+
+static void render_world_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
+{
+ EEVEE_ProbesInfo *pinfo = sldata->probes;
+ EEVEE_Probe *eprobe = &pinfo->probe_data[0];
+
+ /* 1 - Render to cubemap target using geometry shader. */
+ /* For world probe, we don't need to clear since we render the background directly. */
+ pinfo->layer = 0;
+
+ DRW_framebuffer_bind(sldata->probe_fb);
+ DRW_draw_pass(psl->probe_background);
+
+ filter_probe(eprobe, sldata, psl, 0);
+}
+
void EEVEE_probes_refresh(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl)
{
+ EEVEE_ProbesInfo *pinfo = sldata->probes;
+ Object *ob;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ RegionView3D *rv3d = draw_ctx->rv3d;
+ struct wmWindowManager *wm = CTX_wm_manager(draw_ctx->evil_C);
+
+ /* Render world in priority */
if (e_data.update_world) {
- render_one_probe(sldata, psl, 0);
+ render_world_probe(sldata, psl);
e_data.update_world = false;
+ if (!e_data.world_ready_to_shade) {
+ e_data.world_ready_to_shade = true;
+ pinfo->num_render_probe = 1;
+ }
+
DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
+
+ DRW_viewport_request_redraw();
+ }
+ else if (true) { /* TODO if at least one probe needs refresh */
+
+ /* Only compute probes if not navigating or in playback */
+ if (((rv3d->rflag & RV3D_NAVIGATING) != 0) || ED_screen_animation_no_scrub(wm) != NULL) {
+ return;
+ }
+
+ for (int i = 1; (ob = pinfo->probes_ref[i]) && (i < MAX_PROBE); i++) {
+ EEVEE_ProbeEngineData *ped = EEVEE_probe_data_get(ob);
+
+ if (ped->need_update) {
+ render_one_probe(sldata, psl, i);
+ ped->need_update = false;
+
+ if (!ped->ready_to_shade) {
+ pinfo->num_render_probe++;
+ ped->ready_to_shade = true;
+ }
+
+ DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data);
+
+ DRW_viewport_request_redraw();
+
+ /* Only do one probe per frame */
+ break;
+ }
+ }
}
}
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 b0b11c489b6..124f1e2bdb5 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -10,12 +10,15 @@
/* ------- Structures -------- */
struct ProbeData {
- vec4 position_influence; /* w : InfluenceRadius */
+ vec4 position;
vec4 shcoefs[7];
+ vec4 attenuation;
};
-#define p_position position_influence.xyz
-#define p_spec position_influence.w
+
+#define p_position position.xyz
+#define p_atten_bias attenuation.x
+#define p_atten_scale attenuation.y
#define shcoef0 shcoefs[0].rgb
#define shcoef1 vec3(shcoefs[0].a, shcoefs[1].rg)
#define shcoef2 vec3(shcoefs[1].ba, shcoefs[2].r)
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 1b68db8364c..83bcd919697 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -196,11 +196,10 @@ void light_visibility(LightData ld, ShadingData sd, out float vis)
}
}
-void probe_lighting(ShadingData sd, int index, vec3 spec_dir, float roughness, out vec3 diff, out vec3 spec)
+vec3 probe_parallax_correction(vec3 W, vec3 spec_dir, ProbeData pd, inout float roughness)
{
- ProbeData pd = probes_data[index];
- spec = textureLod_octahedron(probeCubes, vec4(spec_dir, index), roughness * lodMax).rgb;
- diff = spherical_harmonics(sd.N, pd.shcoefs);
+ /* TODO */
+ return spec_dir;
}
vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, float ao)
@@ -237,14 +236,29 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness,
vec4 spec_accum = vec4(0.0);
vec4 diff_accum = vec4(0.0);
+
+ /* Specular probes */
/* Start at 1 because 0 is world probe */
for (int i = 1; i < MAX_PROBE && i < probe_count; ++i) {
- /* TODO */
+ ProbeData pd = probes_data[i];
+
+ vec3 sample_vec = probe_parallax_correction(sd.W, spec_dir, pd, roughness);
+ vec4 sample = textureLod_octahedron(probeCubes, vec4(sample_vec, i), roughness * lodMax).rgba;
+
+ float dist_attenuation = saturate(pd.p_atten_bias - pd.p_atten_scale * distance(sd.W, pd.p_position));
+ float influ_spec = min(dist_attenuation, (1.0 - spec_accum.a));
+
+ spec_accum.rgb += sample.rgb * influ_spec;
+ spec_accum.a += influ_spec;
}
+ /* World probe */
if (spec_accum.a < 1.0 || diff_accum.a < 1.0) {
- vec3 diff, spec;
- probe_lighting(sd, 0, spec_dir, roughness, diff, spec);
+ ProbeData pd = probes_data[0];
+
+ vec3 spec = textureLod_octahedron(probeCubes, vec4(spec_dir, 0), roughness * lodMax).rgb;
+ vec3 diff = spherical_harmonics(sd.N, pd.shcoefs);
+
diff_accum.rgb += diff * (1.0 - diff_accum.a);
spec_accum.rgb += spec * (1.0 - spec_accum.a);
}