[Bf-blender-cvs] [7747d4cecf0] blender2.8: Workbench: increased Quality of the diffuse lighting model

Jeroen Bakker noreply at git.blender.org
Mon Jun 18 15:35:42 CEST 2018


Commit: 7747d4cecf078589f614813d0e5e0a753d4e10b5
Author: Jeroen Bakker
Date:   Mon Jun 18 15:17:46 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB7747d4cecf078589f614813d0e5e0a753d4e10b5

Workbench: increased Quality of the diffuse lighting model

- implemented Spherical Harmonics L2 for diffuse shading.

TODO: caching the precalculated harmonics so it won't take soo long to
open the popover

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

M	source/blender/blenkernel/BKE_studiolight.h
M	source/blender/blenkernel/intern/studiolight.c
M	source/blender/draw/engines/workbench/shaders/workbench_data_lib.glsl
M	source/blender/draw/engines/workbench/shaders/workbench_world_light_lib.glsl
M	source/blender/draw/engines/workbench/workbench_data.c
M	source/blender/draw/engines/workbench/workbench_private.h
M	source/blender/draw/engines/workbench/workbench_studiolight.c
M	source/blender/makesrna/intern/rna_space.c

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

diff --git a/source/blender/blenkernel/BKE_studiolight.h b/source/blender/blenkernel/BKE_studiolight.h
index 36de1e4d22f..0e94411030b 100644
--- a/source/blender/blenkernel/BKE_studiolight.h
+++ b/source/blender/blenkernel/BKE_studiolight.h
@@ -60,7 +60,7 @@
 struct GPUTexture;
 
 enum StudioLightFlag {
-	STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED                    = (1 << 0),
+	STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED = (1 << 0),
 	STUDIOLIGHT_LIGHT_DIRECTION_CALCULATED                  = (1 << 1),
 	STUDIOLIGHT_INTERNAL                                    = (1 << 2),
 	STUDIOLIGHT_EXTERNAL_FILE                               = (1 << 3),
@@ -91,7 +91,7 @@ typedef struct StudioLight {
 	int icon_id_matcap;
 	int icon_id_matcap_flipped;
 	int index;
-	float diffuse_light[6][3];
+	float spherical_harmonics_coefs[9][3];
 	float light_direction[3];
 	ImBuf *equirectangular_radiance_buffer;
 	ImBuf *equirectangular_irradiance_buffer;
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index c20fe34b46a..b4b82965fbf 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -56,8 +56,8 @@
 
 /* Statics */
 static ListBase studiolights;
-#define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 16
-#define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT 64
+#define STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE 128
+#define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT 32
 #define STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_WIDTH (STUDIOLIGHT_IRRADIANCE_EQUIRECTANGULAR_HEIGHT * 2)
 
 static const char *STUDIOLIGHT_CAMERA_FOLDER = "studiolights/camera/";
@@ -316,63 +316,162 @@ BLI_INLINE void studiolight_evaluate_radiance_buffer(
 
 }
 
-static void studiolight_calculate_irradiance(StudioLight *sl, float color[3], const float normal[3])
+BLI_INLINE float studiolight_area_element(float x, float y)
+{
+	return atan2(x * y, sqrtf(x * x + y * y + 1));
+}
+
+BLI_INLINE float studiolight_texel_solid_angle(float x, float y, float halfpix)
+{
+	float v1x = (x - halfpix) * 2.0f - 1.0f;
+	float v1y = (y - halfpix) * 2.0f - 1.0f;
+	float v2x = (x + halfpix) * 2.0f - 1.0f;
+	float v2y = (y + halfpix) * 2.0f - 1.0f;
+
+	return studiolight_area_element(v1x, v1y) - studiolight_area_element(v1x, v2y) - studiolight_area_element(v2x, v1y) + studiolight_area_element(v2x, v2y);
+}
+
+static void studiolight_calculate_cubemap_vector_weight(float normal[3], float *weight, int face, float x, float y)
+{
+	copy_v3_fl3(normal, x * 2.0f - 1.0f, y * 2.0f - 1.0f, 1.0f);
+	const float conversion_matrices[6][3][3] = {
+		{
+			{0.0f, 0.0f, -1.0f},
+			{0.0f, -1.0f, 0.0f},
+			{-1.0f, 0.0f, 0.0f},
+		},
+		{
+			{0.0f, 0.0f, -1.0f},
+			{0.0f, -1.0f, 0.0f},
+			{-1.0f, 0.0f, 0.0f},
+		},
+		{
+			{1.0f, 0.0f, 0.0f},
+			{0.0f, 0.0f, 1.0f},
+			{0.0f, -1.0f, 0.0f},
+		},
+		{
+			{1.0f, 0.0f, 0.0f},
+			{0.0f, 0.0f, -1.0f},
+			{0.0f, 1.0f, 0.0f},
+		},
+		{
+			{1.0f, 0.0f, 0.0f},
+			{0.0f, -1.0f, 0.0f},
+			{0.0f, 0.0f, -1.0f},
+		},
+		{
+			{-1.0f, 0.0f, 0.0f},
+			{0.0f, -1.0f, 0.0f},
+			{0.0f, 0.0f, 1.0f},
+		}
+	};
+	mul_m3_v3(conversion_matrices[face], normal);
+	normalize_v3(normal);
+	const float halfpix = 1.0f / (2.0f* STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE);
+	*weight = studiolight_texel_solid_angle(x + halfpix, y + halfpix, halfpix);
+}
+
+static void studiolight_calculate_spherical_harmonics_coefficient(StudioLight *sl, int sh_component)
 {
-	int hits = 0;
-	copy_v3_fl(color, 0.0f);
+	const float M_4PI = M_PI * 4.0f;
+	
+	float weight_accum = 0.0f;
+	float sh[3] = {0.0f, 0.0f, 0.0f};
+	for (int face = 0; face < 6; face++)
+	{
+		float *color;
+		color = sl->radiance_cubemap_buffers[face]->rect_float;
+		for (int y = 0; y < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; y++) {
+			float yf = y / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE;
+			for (int x = 0; x < STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE; x++) {
+				float xf = x / (float)STUDIOLIGHT_RADIANCE_CUBEMAP_SIZE;
+				float weight, coef;
+				float cubevec[3];
+				studiolight_calculate_cubemap_vector_weight(cubevec, &weight, face, xf, yf);
+				
+				switch (sh_component) {
+					case 0:
+					{
+						coef = 0.2822095f;
+						break;
+					}
 
-	/* back */
-	studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_POS], normal, color, &hits, 0, 2, 1, 0.5);
-	/* front */
-	studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Y_NEG], normal, color, &hits, 0, 2, 1, -0.5);
+					case 1:
+					{
+						coef = -0.488603f * cubevec[2] * 2.0f / 3.0f;
+						break;
+					}
+					case 2:
+					{
+						coef = 0.488603f * cubevec[1] * 2.0f / 3.0f;
+						break;
+					}
+					case 3:
+					{
+						coef = -0.488603f * cubevec[0] * 2.0f / 3.0f;
+						break;
+					}
 
-	/* left */
-	studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_POS], normal, color, &hits, 1, 2, 0, 0.5);
-	/* right */
-	studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_X_NEG], normal, color, &hits, 1, 2, 0, -0.5);
+					case 4:
+					{
+						coef = 1.092548f * cubevec[0] * cubevec[2] * 1.0f / 4.0f;
+						break;
+					}
+					case 5:
+					{
+						coef = -1.092548f * cubevec[2] * cubevec[1] * 1.0f / 4.0f;
+						break;
+					}
+					case 6:
+					{
+						coef = 0.315392f * (3.0f * cubevec[2] * cubevec[2] - 1.0f) * 1.0f / 4.0f;
+						break;
+					}
+					case 7:
+					{
+						coef = 1.092548f * cubevec[0] * cubevec[1] * 1.0f / 4.0f;
+						break;
+					}
+					case 8:
+					{
+						coef = 0.546274f * (cubevec[0] * cubevec[0] - cubevec[2] * cubevec[2]) * 1.0f / 4.0f;
+						break;
+					}
 
-	/* top */
-	studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_POS], normal, color, &hits, 0, 1, 2, 0.5);
-	/* bottom */
-	studiolight_evaluate_radiance_buffer(sl->radiance_cubemap_buffers[STUDIOLIGHT_Z_NEG], normal, color, &hits, 0, 1, 2, -0.5);
+					default:
+					{
+						coef = 0.0f;
+					}
+				}
 
-	if (hits) {
-		mul_v3_fl(color, 3.0 / hits);
-	}
-	else {
-		copy_v3_fl3(color, 1.0, 0.0, 1.0);
+				madd_v3_v3fl(sh, color, coef * weight);
+				weight_accum += weight;
+				color += 4;
+			}
+		}
 	}
+
+	mul_v3_fl(sh, M_4PI / weight_accum);
+	copy_v3_v3(sl->spherical_harmonics_coefs[sh_component], sh);
 }
 
 
 static void studiolight_calculate_diffuse_light(StudioLight *sl)
 {
 	/* init light to black */
-	copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_POS], 0.0f);
-	copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_X_NEG], 0.0f);
-	copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_POS], 0.0f);
-	copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Y_NEG], 0.0f);
-	copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_POS], 0.0f);
-	copy_v3_fl(sl->diffuse_light[STUDIOLIGHT_Z_NEG], 0.0f);
-
 	if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
-		const float normal_x_neg[3] = {-1.0f,  0.0f,  0.0f};
-		const float normal_x_pos[3] = { 1.0f,  0.0f,  0.0f};
-		const float normal_y_neg[3] = { 0.0f,  1.0f,  0.0f};
-		const float normal_y_pos[3] = { 0.0f, -1.0f,  0.0f};
-		const float normal_z_neg[3] = { 0.0f,  0.0f, -1.0f};
-		const float normal_z_pos[3] = { 0.0f,  0.0f,  1.0f};
-
 		BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_RADIANCE_BUFFERS_CALCULATED);
 
-		studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_X_POS], normal_x_pos);
-		studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_X_NEG], normal_x_neg);
-		studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Y_POS], normal_y_pos);
-		studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Y_NEG], normal_y_neg);
-		studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Z_POS], normal_z_pos);
-		studiolight_calculate_irradiance(sl, sl->diffuse_light[STUDIOLIGHT_Z_NEG], normal_z_neg);
+		for (int comp = 0; comp < 9; comp ++) {
+			studiolight_calculate_spherical_harmonics_coefficient(sl, comp);
+#if 0
+			print_v3("SH2", sl->spherical_harmonics_coefs[comp]);
+#endif
+		}
 	}
-	sl->flag |= STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED;
+
+	sl->flag |= STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED;
 }
 
 static float area_element(float x, float y )
@@ -454,7 +553,6 @@ static void studiolight_calculate_specular_irradiance(StudioLight *sl, float col
 
 static bool studiolight_load_irradiance_equirectangular_image(StudioLight *sl)
 {
-#if 1
 	if (sl->flag & STUDIOLIGHT_EXTERNAL_FILE) {
 		ImBuf *ibuf = NULL;
 		ibuf = IMB_loadiffname(sl->path_irr, 0, NULL);
@@ -465,7 +563,6 @@ static bool studiolight_load_irradiance_equirectangular_image(StudioLight *sl)
 			return true;
 		}
 	}
-#endif
 	return false;
 }
 
@@ -561,7 +658,6 @@ static void studiolight_add_files_from_datafolder(const int folder_id, const cha
 		BLI_filelist_free(dir, totfile);
 		dir = NULL;
 	}
-
 }
 
 static int studiolight_flag_cmp_order(const StudioLight *sl)
@@ -633,7 +729,7 @@ static uint *studiolight_radiance_preview(StudioLight *sl, int icon_size)
 				normal[0] = dx * 2.0f - 1.0f;
 				normal[1] = dy * 2.0f - 1.0f;
 				float dist = len_v2(normal);
-				normal[2] = sqrtf(1.0f - SQUARE(dist));
+				normal[2] = -sqrtf(1.0f - SQUARE(dist));
 
 				float direction[3];
 				reflect_v3_v3v3(direction, incoming, normal);
@@ -691,105 +787,54 @@ static uint *studiolight_matcap_preview(StudioLight *sl, int icon_size, bool fli
 
 static uint *studiolight_irradiance_preview(StudioLight *sl, int icon_size)
 {
-#if 0
-	if (!(sl->flag & STUDIOLIGHT_EXTERNAL_FILE))
-#endif
-	{
+	BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_SPHERICAL_HARMONICS_COEFFICIENTS_CALCULATED);
 
-		BKE_studiolight_ensure_flag(sl, STUDIOLIGHT_DIFFUSE_LIGHT_CALCULATED);
-
-		uint *rect = MEM_mallocN(icon_size * icon_size * sizeof(uint), __func__);
-		float pixel_size = 1.0f / (float)icon_size;
-
-		int offset = 0;
-		for (int y = 0; y < icon_size; y++) {
-			float dy = (y + 0.5f) / (float)icon_size;
-			dy = dy / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
-			for (int x = 0; x < icon_size; x++) {
-				float dx = (x + 0.5f) / (float)icon_size;
-				dx = dx / STUDIOLIGHT_DIAMETER - (1.0f - STUDIOLIGHT_DIAMETER) / 2.0f;
-
-				uint pixelresult = 0x0;
-				uint alphamask = alpha_circle_mask(dx, dy, 0.5f - pixel_size, 0.5f);
-				if (alphamask != 0) {
-					/* 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list