[Bf-blender-cvs] [8e36089e411] blender2.8: Eevee: LUT generation.

Clément Foucault noreply at git.blender.org
Thu Aug 10 15:48:01 CEST 2017


Commit: 8e36089e411391243617808413d4d2b550aeb3b3
Author: Clément Foucault
Date:   Fri Aug 4 18:43:02 2017 +0200
Branches: blender2.8
https://developer.blender.org/rB8e36089e411391243617808413d4d2b550aeb3b3

Eevee: LUT generation.

We generate a 3D lut to precompute the btdf intensity.
I decided to use a 64*64*16 (N dot V, ior, roughness) because the btdf varies less with roughness than with IOR.
We also remap the ior to better use the space in the LUT.

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

M	source/blender/draw/CMakeLists.txt
M	source/blender/draw/engines/clay/clay_engine.c
M	source/blender/draw/engines/eevee/eevee_materials.c
A	source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl

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

diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index e3a3ac499a1..3293b4d7241 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -155,6 +155,7 @@ data_to_c_simple(engines/eevee/shaders/shadow_store_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/shadow_store_geom.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/shadow_store_vert.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/bsdf_lut_frag.glsl SRC)
+data_to_c_simple(engines/eevee/shaders/btdf_lut_frag.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/bsdf_direct_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/bsdf_common_lib.glsl SRC)
 data_to_c_simple(engines/eevee/shaders/irradiance_lib.glsl SRC)
diff --git a/source/blender/draw/engines/clay/clay_engine.c b/source/blender/draw/engines/clay/clay_engine.c
index a9192a30412..44178f66563 100644
--- a/source/blender/draw/engines/clay/clay_engine.c
+++ b/source/blender/draw/engines/clay/clay_engine.c
@@ -326,7 +326,7 @@ static struct GPUTexture *create_jitter_texture(int num_samples)
 		jitter[i][2] = bn * num_samples_inv;
 	}
 
-	UNUSED_VARS(bsdf_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);
 
 	return DRW_texture_create_2D(64, 64, DRW_TEX_RGB_16, DRW_TEX_FILTER | DRW_TEX_WRAP, &jitter[0][0]);
 }
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 046a7ea1367..65e91a38053 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -90,6 +90,7 @@ extern char datatoc_default_frag_glsl[];
 extern char datatoc_default_world_frag_glsl[];
 extern char datatoc_ltc_lib_glsl[];
 extern char datatoc_bsdf_lut_frag_glsl[];
+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[];
@@ -169,8 +170,97 @@ static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
 
 	return tex;
 }
-#endif
 
+static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
+{
+	struct GPUTexture *tex;
+	struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
+	struct GPUFrameBuffer *fb = NULL;
+	static float samples_ct = 8192.0f;
+	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);
+
+	struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
+	        "#define HAMMERSLEY_SIZE 8192\n"
+	        "#define BRDF_LUT_SIZE 64\n"
+	        "#define NOISE_SIZE 64\n"
+	        "#define LUT_SIZE 64\n");
+
+	MEM_freeN(frag_str);
+
+	DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+	DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+	DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
+	DRW_shgroup_uniform_float(grp, "sampleCount", &samples_ct, 1);
+	DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_ct, 1);
+	DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
+	DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+
+	struct Gwn_Batch *geom = DRW_cache_fullscreen_quad_get();
+	DRW_shgroup_call_add(grp, geom, NULL);
+
+	float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+	tex = DRW_texture_create_2D(w, h, DRW_TEX_R_16, DRW_TEX_FILTER, (float *)texels);
+
+	DRWFboTexture tex_filter = {&tex, DRW_TEX_R_16, DRW_TEX_FILTER};
+	DRW_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+	DRW_framebuffer_bind(fb);
+
+	float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+
+	float inc = 1.0f / 31.0f;
+	float roughness = 1e-8f - inc;
+	FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
+	fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
+	do {
+		roughness += inc;
+		CLAMP(roughness, 1e-4f, 1.0f);
+		a2 = powf(roughness, 4.0f);
+		DRW_draw_pass(pass);
+
+		DRW_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+
+	#if 1
+		fprintf(f, "\t{\n\t\t");
+		for (int i = 0; i < w*h * 3; i+=3) {
+			fprintf(f, "%ff,", data[i]);
+			if (((i/3)+1) % 12 == 0) fprintf(f, "\n\t\t");
+			else fprintf(f, " ");
+		}
+		fprintf(f, "\n\t},\n");
+	#else
+		for (int i = 0; i < w*h * 3; i+=3) {
+			if (data[i] < 0.01) printf(" ");
+			else if (data[i] < 0.3) printf(".");
+			else if (data[i] < 0.6) printf("+");
+			else if (data[i] < 0.9) printf("%%");
+			else printf("#");
+			if ((i/3+1) % 64 == 0) printf("\n");
+		}
+	#endif
+
+	} while (roughness < 1.0f);
+	fprintf(f, "\n};\n");
+
+	fclose(f);
+
+	MEM_freeN(texels);
+	MEM_freeN(data);
+
+	return tex;
+}
+#endif
 /* XXX TODO define all shared resources in a shared place without duplication */
 struct GPUTexture *EEVEE_materials_get_util_tex(void)
 {
diff --git a/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
new file mode 100644
index 00000000000..2c604d69641
--- /dev/null
+++ b/source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl
@@ -0,0 +1,59 @@
+
+uniform float a2;
+
+out vec4 FragColor;
+
+void main() {
+	vec3 N, T, B, V;
+
+	float x = gl_FragCoord.x / BRDF_LUT_SIZE;
+	float y = gl_FragCoord.y / BRDF_LUT_SIZE;
+	/* There is little variation if ior > 1.0 so we
+	 * maximize LUT precision for ior < 1.0 */
+	x = x * 1.1;
+	float ior = (x > 1.0) ? ior_from_f0((x-1.0) * 10.0) : sqrt(x);
+	float NV = (1.0 - (clamp(y, 1e-4, 0.9999)));
+
+	N = vec3(0.0, 0.0, 1.0);
+	T = vec3(1.0, 0.0, 0.0);
+	B = vec3(0.0, 1.0, 0.0);
+	V = vec3(sqrt(1.0 - NV * NV), 0.0, NV);
+
+	setup_noise();
+
+	/* Integrating BTDF */
+	float btdf_accum = 0.0;
+	for (float i = 0.0; i < sampleCount; i++) {
+		vec3 H = sample_ggx(i, a2, N, T, B); /* Microfacet normal */
+
+		float VH = dot(V, H);
+
+		/* Check if there is total internal reflections. */
+		float c = abs(VH);
+		float g = ior * ior - 1.0 + c * c;
+
+		float eta = 1.0/ior;
+		if (dot(H, V) < 0.0) {
+			H = -H;
+			eta = ior;
+		}
+
+		vec3 L = refract(-V, H, eta);
+		float NL = -dot(N, L);
+
+		if ((NL > 0.0) && (g > 0.0)) {
+			float LH = dot(L, H);
+
+			float G1_l = NL * 2.0 / G1_Smith_GGX(NL, a2); /* Balancing the adjustments made in G1_Smith */
+
+			/* btdf = abs(VH*LH) * (ior*ior) * D * G(V) * G(L) / (Ht2 * NV)
+			 * pdf = (VH * abs(LH)) * (ior*ior) * D * G(V) / (Ht2 * NV) */
+			float btdf = G1_l * abs(VH*LH) / (VH * abs(LH));
+
+			btdf_accum += btdf;
+		}
+	}
+	btdf_accum /= sampleCount;
+
+	FragColor = vec4(btdf_accum, 0.0, 0.0, 1.0);
+}
\ No newline at end of file




More information about the Bf-blender-cvs mailing list