Commit: 3e4b9d2b5a6479ef71cdedf980bcd714f4f94d56
Author: Clément Foucault
Date:   Sat Jun 17 00:08:03 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB3e4b9d2b5a6479ef71cdedf980bcd714f4f94d56

Eevee: Initial implementation of planar reflections.

Still pretty barebone: No roughness support, No normal distortion support.

===================================================================

M       source/blender/draw/engines/eevee/eevee_data.c
M       source/blender/draw/engines/eevee/eevee_engine.c
M       source/blender/draw/engines/eevee/eevee_lightprobes.c
M       source/blender/draw/engines/eevee/eevee_materials.c
M       source/blender/draw/engines/eevee/eevee_private.h
M       source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
M       source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl

===================================================================

diff --git a/source/blender/draw/engines/eevee/eevee_data.c 
b/source/blender/draw/engines/eevee/eevee_data.c
index 9dfc3e5f07b..da1f5317dab 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -54,6 +54,7 @@ static void eevee_scene_layer_data_free(void *storage)
        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_FRAMEBUFFER_FREE_SAFE(sldata->probe_fb);
        DRW_FRAMEBUFFER_FREE_SAFE(sldata->probe_filter_fb);
        DRW_TEXTURE_FREE_SAFE(sldata->probe_rt);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c 
b/source/blender/draw/engines/eevee/eevee_engine.c
index c13351be43c..325758f4eb9 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -57,7 +57,7 @@ static void EEVEE_engine_init(void *ved)
 
        EEVEE_materials_init();
        EEVEE_lights_init(sldata);
-       EEVEE_lightprobes_init(sldata);
+       EEVEE_lightprobes_init(sldata, vedata);
        EEVEE_effects_init(vedata);
 }
 
@@ -134,7 +134,7 @@ static void EEVEE_draw_scene(void *vedata)
        EEVEE_draw_shadows(sldata, psl);
 
        /* Refresh Probes */
-       EEVEE_lightprobes_refresh(sldata, psl);
+       EEVEE_lightprobes_refresh(sldata, vedata);
 
        /* Attach depth to the hdr buffer and bind it */        
        DRW_framebuffer_texture_detach(dtxl->depth);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c 
b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index bfb1b43e28b..a58c338b14b 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -59,6 +59,7 @@ static struct {
        struct GPUShader *probe_cube_display_sh;
 
        struct GPUTexture *hammersley;
+       struct GPUTexture *planar_depth;
 
        bool update_world;
        bool world_ready_to_shade;
@@ -112,7 +113,46 @@ static struct GPUTexture 
*create_hammersley_sample_texture(int samples)
        return tex;
 }
 
-void EEVEE_lightprobes_init(EEVEE_SceneLayerData *sldata)
+static void planar_pool_ensure_alloc(EEVEE_Data *vedata, int num_planar_ref)
+{
+       /* XXX TODO OPTIMISATION : This is a complete waist of texture memory.
+        * Instead of allocating each planar probe for each viewport,
+        * only alloc them once using the biggest viewport resolution. */
+       EEVEE_FramebufferList *fbl = vedata->fbl;
+       EEVEE_TextureList *txl = vedata->txl;
+
+       const float *viewport_size = DRW_viewport_size_get();
+
+       /* TODO get screen percentage from layer setting */
+       // const DRWContextState *draw_ctx = DRW_context_state_get();
+       // SceneLayer *sl = draw_ctx->sl;
+       float screen_percentage = 1.0f;
+
+       int width = (int)(viewport_size[0] * screen_percentage);
+       int height = (int)(viewport_size[1] * screen_percentage);
+
+       /* We need an Array texture so allocate it ourself */
+       if (!txl->planar_pool && (num_planar_ref > 0)) {
+               txl->planar_pool = DRW_texture_create_2D_array(width, height, 
max_ff(1, num_planar_ref),
+                                                                
DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
+       }
+       else if (txl->planar_pool && (num_planar_ref == 0)) {
+               DRW_TEXTURE_FREE_SAFE(txl->planar_pool);
+       }
+
+       if (num_planar_ref > 0) {
+               /* NOTE : Depth buffer is 2D but the planar_pool tex is 2D 
array.
+                * DRW_framebuffer_init binds the whole texture making the 
framebuffer invalid.
+                * To overcome this, we bind the planar pool ourselves later */
+
+               DRWFboTexture tex = {&e_data.planar_depth, DRW_TEX_DEPTH_24, 
DRW_TEX_TEMP};
+
+               DRW_framebuffer_init(&fbl->planarref_fb, 
&draw_engine_eevee_type,
+                                    width, height, &tex, 1);
+       }
+}
+
+void EEVEE_lightprobes_init(EEVEE_SceneLayerData *sldata, EEVEE_Data 
*UNUSED(vedata))
 {
        /* Shaders */
        if (!e_data.probe_filter_glossy_sh) {
@@ -195,6 +235,7 @@ void EEVEE_lightprobes_init(EEVEE_SceneLayerData *sldata)
                sldata->probes->specular_toggle = true;
                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);
        }
 
        /* Setup Render Target Cubemap */
@@ -215,8 +256,10 @@ void EEVEE_lightprobes_cache_init(EEVEE_SceneLayerData 
*sldata, EEVEE_PassList *
 
        pinfo->num_cube = 1; /* at least one for the world */
        pinfo->num_grid = 1;
+       pinfo->num_planar = 0;
        memset(pinfo->probes_cube_ref, 0, sizeof(pinfo->probes_cube_ref));
        memset(pinfo->probes_grid_ref, 0, sizeof(pinfo->probes_grid_ref));
+       memset(pinfo->probes_planar_ref, 0, sizeof(pinfo->probes_planar_ref));
 
        {
                psl->probe_background = DRW_pass_create("World Probe Pass", 
DRW_STATE_WRITE_COLOR);
@@ -356,17 +399,122 @@ void EEVEE_lightprobes_cache_add(EEVEE_SceneLayerData 
*sldata, Object *ob)
                pinfo->probes_cube_ref[pinfo->num_cube] = ob;
                pinfo->num_cube++;
        }
+       else if (probe->type == LIGHTPROBE_TYPE_PLANAR) {
+               pinfo->probes_planar_ref[pinfo->num_planar] = ob;
+               pinfo->num_planar++;
+       }
        else { /* GRID */
                pinfo->probes_grid_ref[pinfo->num_grid] = ob;
                pinfo->num_grid++;
        }
 }
 
+/* TODO find a nice name to push it to math_matrix.c */
+static void scale_m4_v3(float R[4][4], float v[3])
+{
+       for (int i = 0; i < 4; ++i)
+               mul_v3_v3(R[i], v);
+}
+
+static void EEVEE_planar_reflections_updates(EEVEE_SceneLayerData *sldata)
+{
+       EEVEE_LightProbesInfo *pinfo = sldata->probes;
+       Object *ob;
+       float mtx[4][4], normat[4][4], imat[4][4], rangemat[4][4];
+
+       float viewmat[4][4], winmat[4][4];
+       DRW_viewport_matrix_get(viewmat, DRW_MAT_VIEW);
+       DRW_viewport_matrix_get(winmat, DRW_MAT_WIN);
+
+       zero_m4(rangemat);
+       rangemat[0][0] = rangemat[1][1] = rangemat[2][2] = 0.5f;
+       rangemat[3][0] = rangemat[3][1] = rangemat[3][2] = 0.5f;
+       rangemat[3][3] = 1.0f;
+
+       /* PLANAR REFLECTION */
+       for (int i = 0; (ob = pinfo->probes_planar_ref[i]) && (i < MAX_PLANAR); 
i++) {
+               LightProbe *probe = (LightProbe *)ob->data;
+               EEVEE_PlanarReflection *eplanar = &pinfo->planar_data[i];
+               EEVEE_LightProbeEngineData *ped = EEVEE_lightprobe_data_get(ob);
+
+               /* Computing mtx : matrix that mirror position around object's 
XY plane. */
+               normalize_m4_m4(normat, ob->obmat);  /* object > world */
+               invert_m4_m4(imat, normat); /* world > object */
+
+               float reflect[3] = {1.0f, 1.0f, -1.0f}; /* XY reflection plane 
*/
+               scale_m4_v3(imat, reflect); /* world > object > mirrored obj */
+               mul_m4_m4m4(mtx, normat, imat); /* world > object > mirrored 
obj > world */
+
+               /* Reflect Camera Matrix. */
+               mul_m4_m4m4(ped->viewmat, viewmat, mtx);
+
+               /* TODO FOV margin */
+               float winmat_fov[4][4];
+               copy_m4_m4(winmat_fov, winmat);
+
+               /* Apply Perspective Matrix. */
+               mul_m4_m4m4(ped->persmat, winmat_fov, ped->viewmat);
+
+               /* This is the matrix used to reconstruct texture coordinates.
+                * We use the original view matrix because it does not create
+                * visual artifacts if receiver is not perfectly aligned with
+                * the planar reflection probe. */
+               mul_m4_m4m4(eplanar->reflectionmat, winmat_fov, viewmat); /* 
TODO FOV margin */
+               /* Convert from [-1, 1] to [0, 1] (NDC to Texture coord). */
+               mul_m4_m4m4(eplanar->reflectionmat, rangemat, 
eplanar->reflectionmat);
+
+               /* TODO frustum check. */
+               ped->need_update = true;
+
+               /* Compute clip plane equation / normal. */
+               float refpoint[3];
+               copy_v3_v3(eplanar->plane_equation, ob->obmat[2]);
+               normalize_v3(eplanar->plane_equation); /* plane normal */
+               mul_v3_v3fl(refpoint, eplanar->plane_equation, -probe->clipsta);
+               add_v3_v3(refpoint, ob->obmat[3]);
+               eplanar->plane_equation[3] = -dot_v3v3(eplanar->plane_equation, 
refpoint);
+
+               /* Compute XY clip planes. */
+               normalize_v3_v3(eplanar->clip_vec_x, ob->obmat[0]);
+               normalize_v3_v3(eplanar->clip_vec_y, ob->obmat[1]);
+
+               float vec[3] = {0.0f, 0.0f, 0.0f};
+               vec[0] = 1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
+               mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+               eplanar->clip_edge_x_pos = dot_v3v3(eplanar->clip_vec_x, vec);
+
+               vec[0] = 0.0f; vec[1] = 1.0f; vec[2] = 0.0f;
+               mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+               eplanar->clip_edge_y_pos = dot_v3v3(eplanar->clip_vec_y, vec);
+
+               vec[0] = -1.0f; vec[1] = 0.0f; vec[2] = 0.0f;
+               mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+               eplanar->clip_edge_x_neg = dot_v3v3(eplanar->clip_vec_x, vec);
+
+               vec[0] = 0.0f; vec[1] = -1.0f; vec[2] = 0.0f;
+               mul_m4_v3(ob->obmat, vec); /* Point on the edge */
+               eplanar->clip_edge_y_neg = dot_v3v3(eplanar->clip_vec_y, vec);
+
+               /* Facing factors */
+               float max_angle = max_ff(1e-2f, probe->falloff) * M_PI * 0.5f;
+               float min_angle = 0.0f;
+               eplanar->facing_scale = 1.0f / max_ff(1e-8f, cosf(min_angle) - 
cosf(max_angle));
+               eplanar->facing_bias = -min_ff(1.0f - 1e-8f, cosf(max_angle)) * 
eplanar->facing_scale;
+
+               /* Distance factors */
+               float max_dist = probe->distinf;
+               float min_dist = min_ff(1.0f - 1e-8f, 1.0f - probe->falloff) * 
probe->distinf;
+               eplanar->attenuation_scale = -1.0f / max_ff(1e-8f, max_dist - 
min_dist);
+               eplanar->attenuation_bias = max_dist * 
-eplanar->attenuation_scale;
+       }
+}
+
 static void EEVEE_lightprobes_updates(EEVEE_SceneLayerData *sldata, 
EEVEE_PassList *psl, EEVEE_StorageList *stl)
 {
        EEVEE_LightProbesInfo *pinfo = sldata->probes;
        Object *ob;
 
+       /* CUBE REFLECTION */
        for (int i = 1; (ob = pinfo->probes_cube_ref[i]) && (i < MAX_PROBE); 
i++) {
                LightProbe *probe = (LightProbe *)ob->data;
                EEVEE_LightProbe *eprobe = &pinfo->probe_data[i];
@@ -406,6 +554,7 @@ static void EEVEE_lightprobes_updates(EEVEE_SceneLayerData 
*sldata, EEVEE_PassLi
                }
        }
 
+       /* IRRADIANCE GRID */
        int offset = 1; /* to account for the world probe */
        for (int i = 1; (ob = pinfo->probes_grid_ref[i]) && (i < MAX_GRID); 
i++) {
                LightProbe *probe = (LightProbe *)ob->data;
@@ -485,6 +634,14 @@ void EEVEE_lightprobes_cache_finish(EEVEE_SceneLayerData 
*sldata, EEVEE_Data *ve
                DRW_TEXTURE_FREE_SAFE(sldata->probe_pool);
        }
 
+       if (pinfo->num_planar != pinfo->cache_num_planar) {
+               DRW_TEXTURE_FREE_SAFE(vedata->txl->planar_pool);
+               pinfo->cache_num_planar = pinfo->num_planar;
+       }
+
+       /* XXX this should be run each frame as it

@@ Diff output truncated at 10240 characters. @@

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to