[Bf-blender-cvs] [5d280a2397f] temp-eeveelightcache: Eevee: LightCache: Add back progressive rendering.

Clément Foucault noreply at git.blender.org
Fri Jun 22 17:46:29 CEST 2018


Commit: 5d280a2397fa349ef72d9410110a6cddbe8f7aaa
Author: Clément Foucault
Date:   Thu Jun 21 16:00:21 2018 +0200
Branches: temp-eeveelightcache
https://developer.blender.org/rB5d280a2397fa349ef72d9410110a6cddbe8f7aaa

Eevee: LightCache: Add back progressive rendering.

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

M	source/blender/draw/engines/eevee/eevee_lightcache.c
M	source/blender/draw/engines/eevee/eevee_lightprobes.c
M	source/blender/editors/render/render_shading.c

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

diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 5a7fe9aa22d..8c5c0f7e804 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -275,12 +275,16 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
 	lbake->vis_res      = eevee->gi_visibility_resolution;
 	lbake->rt_res       = eevee->gi_cubemap_resolution;
 
+	irradiance_pool_size_get(lbake->vis_res, lbake->total_irr_samples, lbake->irr_size);
+
 	lbake->ref_cube_res = OCTAHEDRAL_SIZE_FROM_CUBESIZE(lbake->rt_res);
 
 	lbake->cube_prb = MEM_callocN(sizeof(LightProbe *) * lbake->cube_count, "EEVEE Cube visgroup ptr");
 	lbake->grid_prb = MEM_callocN(sizeof(LightProbe *) * lbake->grid_count, "EEVEE Grid visgroup ptr");
 
-	/* Only one render target for now. */
+	lbake->grid_prev = DRW_texture_create_2D_array(lbake->irr_size[0], lbake->irr_size[1], lbake->irr_size[2],
+	                                               IRRADIANCE_FORMAT, DRW_TEX_FILTER, NULL);
+
 	lbake->rt_depth = DRW_texture_create_cube(lbake->rt_res, GPU_DEPTH_COMPONENT24, 0, NULL);
 	lbake->rt_color = DRW_texture_create_cube(lbake->rt_res, GPU_RGBA16F, DRW_TEX_FILTER | DRW_TEX_MIPMAP, NULL);
 
@@ -296,11 +300,6 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
 		GPU_ATTACHMENT_NONE
 	});
 
-	irradiance_pool_size_get(lbake->vis_res, lbake->total_irr_samples, lbake->irr_size);
-
-	lbake->grid_prev = DRW_texture_create_2D_array(lbake->irr_size[0], lbake->irr_size[1], lbake->irr_size[2],
-	                                               IRRADIANCE_FORMAT, DRW_TEX_FILTER, NULL);
-
 	/* Ensure Light Cache is ready to accept new data. If not recreate one.
 	 * WARNING: All the following must be threadsafe. It's currently protected
 	 * by the DRW mutex. */
@@ -321,6 +320,8 @@ static void eevee_lightbake_create_resources(EEVEE_LightBake *lbake)
 		DEG_id_tag_update(&scene_orig->id, DEG_TAG_COPY_ON_WRITE);
 	}
 
+	lcache->flag = LIGHTCACHE_UPDATE_WORLD | LIGHTCACHE_UPDATE_CUBE | LIGHTCACHE_UPDATE_GRID;
+
 	/* Share light cache with the evaluated (baking) layer and the original layer.
 	 * This avoid full scene re-evaluation by depsgraph. */
 	scene_eval->eevee.light_cache = lcache;
@@ -344,12 +345,11 @@ void *EEVEE_lightbake_job_data_alloc(struct Main *bmain, struct ViewLayer *view_
 	int frame = 0; /* TODO make it user param. */
 	DEG_evaluate_on_framechange(lbake->bmain, lbake->depsgraph, frame);
 
-	/* The following needs to run on the main thread. */
-
 	/* Count lightprobes */
 	eevee_lightbake_count_probes(lbake);
 
 	DRW_opengl_context_enable();
+	/* This function needs to run on the main thread. */
 	eevee_lightbake_create_resources(lbake);
 	DRW_opengl_context_disable();
 
@@ -448,6 +448,17 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
 	DRW_hair_update();
 }
 
+static void eevee_lightbake_copy_irradiance(EEVEE_LightBake *lbake, EEVEE_LightCache *lcache)
+{
+	DRW_TEXTURE_FREE_SAFE(lbake->grid_prev);
+
+	/* Copy texture by reading back and reuploading it. */
+	float *tex = GPU_texture_read(lcache->grid_tx, 0);
+	lbake->grid_prev = DRW_texture_create_2D_array(lbake->irr_size[0], lbake->irr_size[1], lbake->irr_size[2],
+	                                               IRRADIANCE_FORMAT, DRW_TEX_FILTER, tex);
+	MEM_freeN(tex);
+}
+
 static void eevee_lightbake_render_world(void *ved, void *user_data)
 {
 	EEVEE_Data *vedata = (EEVEE_Data *)ved;
@@ -463,12 +474,20 @@ static void eevee_lightbake_render_world(void *ved, void *user_data)
 	EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, 0, 1.0f);
 	EEVEE_lightbake_filter_diffuse(sldata, vedata, lbake->rt_color, lbake->store_fb, 0, 1.0f);
 
-	if (lcache->cube_count == 0) {
-		lcache->cube_count = 1;
-	}
-	if (lcache->grid_count == 0) {
-		lcache->grid_count = 1;
-	}
+	/* Clear the cache to avoid white values in the grid. */
+	GPU_framebuffer_texture_attach(lbake->store_fb, lbake->grid_prev, 0, 0);
+	GPU_framebuffer_bind(lbake->store_fb);
+	/* Clear to 1.0f for visibility. */
+	GPU_framebuffer_clear_color(lbake->store_fb, (float[4]){1.0f});
+	DRW_draw_pass(vedata->psl->probe_grid_fill);
+
+	SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx);
+
+	/* Make a copy for later. */
+	eevee_lightbake_copy_irradiance(lbake, lcache);
+
+	lcache->cube_count = 1;
+	lcache->grid_count = lbake->grid_count;
 
 	lcache->flag |= LIGHTCACHE_CUBE_READY | LIGHTCACHE_GRID_READY;
 	lcache->flag &= ~LIGHTCACHE_UPDATE_WORLD;
@@ -482,6 +501,47 @@ static void cell_id_to_grid_loc(EEVEE_LightGrid *egrid, int cell_idx, int r_loca
 	r_local_cell[0] = cell_idx / (egrid->resolution[2] * egrid->resolution[1]);
 }
 
+static void compute_cell_id(
+        EEVEE_LightGrid *egrid, LightProbe *probe,
+        int cell_idx, int *r_final_idx, int r_local_cell[3], int *r_stride)
+{
+	const int cell_count = probe->grid_resolution_x * probe->grid_resolution_y * probe->grid_resolution_z;
+
+	/* Add one for level 0 */
+	int max_lvl = (int)floorf(log2f((float)MAX3(probe->grid_resolution_x,
+	                                            probe->grid_resolution_y,
+	                                            probe->grid_resolution_z)));
+
+	int visited_cells = 0;
+	for (int lvl = max_lvl; lvl >= 0; --lvl) {
+		*r_stride = 1 << lvl;
+		int prev_stride = *r_stride << 1;
+		for (int i = 0; i < cell_count; ++i) {
+			*r_final_idx = i;
+			cell_id_to_grid_loc(egrid, *r_final_idx, r_local_cell);
+			if (((r_local_cell[0] % *r_stride) == 0) &&
+			    ((r_local_cell[1] % *r_stride) == 0) &&
+			    ((r_local_cell[2] % *r_stride) == 0))
+			{
+				if (!(((r_local_cell[0] % prev_stride) == 0) &&
+				      ((r_local_cell[1] % prev_stride) == 0) &&
+				      ((r_local_cell[2] % prev_stride) == 0)) ||
+				      (i == 0))
+				{
+					if (visited_cells == cell_idx) {
+						return;
+					}
+					else {
+						visited_cells++;
+					}
+				}
+			}
+		}
+	}
+
+	BLI_assert(0);
+}
+
 static void grid_loc_to_world_loc(EEVEE_LightGrid *egrid, int local_cell[3], float r_pos[3])
 {
 	copy_v3_v3(r_pos, egrid->corner);
@@ -498,30 +558,63 @@ static void eevee_lightbake_render_grid_sample(void *ved, void *user_data)
 	EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
 	EEVEE_LightGrid *egrid = lbake->grid;
 	LightProbe *prb = *lbake->probe;
+	Scene *scene_eval = DEG_get_evaluated_scene(lbake->depsgraph);
+	EEVEE_LightCache *lcache = scene_eval->eevee.light_cache;
+	int grid_loc[3], sample_id, sample_offset, stride;
+	float pos[3];
+	const bool is_last_bounce_sample = ((egrid->offset + lbake->grid_sample) == (lbake->total_irr_samples - 1));
 
-	/* TODO do this once for the whole bake when we have independant DRWManagers. */
+	/* No bias for rendering the probe. */
+	egrid->level_bias = 1.0f;
+
+	/* Use the previous bounce for rendering this bounce. */
+	SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx);
+
+	/* TODO do this once for the whole bake when we have independant DRWManagers.
+	 * Warning: Some of the things above require this. */
 	eevee_lightbake_cache_create(vedata, lbake);
 
 	/* Compute sample position */
-	int grid_loc[3];
-	float pos[3];
-	cell_id_to_grid_loc(egrid, lbake->grid_sample, grid_loc);
+	compute_cell_id(egrid, prb, lbake->grid_sample, &sample_id, grid_loc, &stride);
+	sample_offset = egrid->offset + sample_id;
+
 	grid_loc_to_world_loc(egrid, grid_loc, pos);
 
 	/* Disable specular lighting when rendering probes to avoid feedback loops (looks bad). */
 	common_data->spec_toggle = false;
 	common_data->prb_num_planar = 0;
 	common_data->prb_num_render_cube = 0;
-	common_data->prb_num_render_grid = 0;
-	egrid->level_bias = 1.0f; /* No bias */
+	if (lbake->bounce_curr == 0) {
+		common_data->prb_num_render_grid = 0;
+	}
 	DRW_uniformbuffer_update(sldata->common_ubo, &sldata->common_data);
 
-	int sample_offset = egrid->offset + lbake->grid_sample;
 	EEVEE_lightbake_render_scene(sldata, vedata, lbake->rt_fb, pos, prb->clipsta, prb->clipend);
+
+	/* Restore before filtering. */
+	SWAP(GPUTexture *, lbake->grid_prev, lcache->grid_tx);
+
 	EEVEE_lightbake_filter_diffuse(sldata, vedata, lbake->rt_color, lbake->store_fb, sample_offset, prb->intensity);
-	EEVEE_lightbake_filter_visibility(sldata, vedata, lbake->rt_depth, lbake->store_fb, sample_offset,
-	                                  prb->clipsta, prb->clipend, egrid->visibility_range,
-	                                  prb->vis_blur, lbake->vis_res);
+
+	if (lbake->bounce_curr == 0) {
+		/* We only need to filter the visibility for the first bounce. */
+		EEVEE_lightbake_filter_visibility(sldata, vedata, lbake->rt_depth, lbake->store_fb, sample_offset,
+		                                  prb->clipsta, prb->clipend, egrid->visibility_range,
+		                                  prb->vis_blur, lbake->vis_res);
+	}
+
+	/* Update level for progressive update. */
+	if (lbake->bounce_curr == 0) {
+		egrid->level_bias = (float)(stride << 1);
+	}
+	else if (is_last_bounce_sample) {
+		egrid->level_bias = 1.0f;
+	}
+
+	/* Only run this for the last sample of a bounce. */
+	if (is_last_bounce_sample) {
+		eevee_lightbake_copy_irradiance(lbake, lcache);
+	}
 }
 
 static void eevee_lightbake_render_probe(void *ved, void *user_data)
@@ -530,6 +623,7 @@ static void eevee_lightbake_render_probe(void *ved, void *user_data)
 	EEVEE_ViewLayerData *sldata = EEVEE_view_layer_data_ensure();
 	EEVEE_CommonUniformBuffer *common_data = &sldata->common_data;
 	EEVEE_LightBake *lbake = (EEVEE_LightBake *)user_data;
+	EEVEE_LightCache *lcache = lbake->scene->eevee.light_cache;
 	EEVEE_LightProbe *eprobe = lbake->cube;
 	LightProbe *prb = *lbake->probe;
 
@@ -544,6 +638,8 @@ static void eevee_lightbake_render_probe(void *ved, void *user_data)
 
 	EEVEE_lightbake_render_scene(sldata, vedata, lbake->rt_fb, eprobe->position, prb->clipsta, prb->clipend);
 	EEVEE_lightbake_filter_glossy(sldata, vedata, lbake->rt_color, lbake->store_fb, lbake->cube_offset, prb->intensity);
+
+	lcache->cube_count += 1;
 }
 
 static void eevee_lightbake_gather_probes(EEVEE_LightBake *lbake)
@@ -597,6 +693,7 @@ static bool lightbake_do_sample(EEVEE_LightBake *lbake, void (*r

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list