diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-08-04 19:43:02 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-08-10 16:43:47 +0300 |
commit | 8e36089e411391243617808413d4d2b550aeb3b3 (patch) | |
tree | d6fe9c02d90271aab0fc98a27325d417d88af0f5 /source/blender/draw | |
parent | 4ec58659adaf693994e09dda00bcaa8f58674adb (diff) |
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.
Diffstat (limited to 'source/blender/draw')
-rw-r--r-- | source/blender/draw/CMakeLists.txt | 1 | ||||
-rw-r--r-- | source/blender/draw/engines/clay/clay_engine.c | 2 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_materials.c | 92 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/shaders/btdf_lut_frag.glsl | 59 |
4 files changed, 152 insertions, 2 deletions
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 |