diff options
author | Clément Foucault <foucault.clem@gmail.com> | 2017-06-04 17:50:22 +0300 |
---|---|---|
committer | Clément Foucault <foucault.clem@gmail.com> | 2017-06-04 17:50:22 +0300 |
commit | 819b8adb94f5ab617a0b2bcac37678eb4874dfbd (patch) | |
tree | c332ee04fd4431fe4c7ac7f5baf53bf8b363eb07 | |
parent | 28b597b6df46b6d2581d7948578922bb3566d242 (diff) |
Eevee: Move Spherical Harmonics to a new Probe UBO.
Keep data packing tight to prevent use of padding floats
5 files changed, 91 insertions, 37 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 23f87a41b24..7297f3a1e90 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -37,6 +37,7 @@ #define SHADER_DEFINES \ "#define EEVEE_ENGINE\n" \ + "#define MAX_PROBE " STRINGIFY(MAX_PROBE) "\n" \ "#define MAX_LIGHT " STRINGIFY(MAX_LIGHT) "\n" \ "#define MAX_SHADOW_CUBE " STRINGIFY(MAX_SHADOW_CUBE) "\n" \ "#define MAX_SHADOW_MAP " STRINGIFY(MAX_SHADOW_MAP) "\n" \ @@ -257,12 +258,14 @@ struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene, Material *ma) static void add_standard_uniforms(DRWShadingGroup *shgrp, EEVEE_SceneLayerData *sldata) { + DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo); DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo); DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo); DRW_shgroup_uniform_int(shgrp, "light_count", &sldata->lamps->num_light, 1); + DRW_shgroup_uniform_int(shgrp, "probe_count", &sldata->probes->num_cube, 1); + DRW_shgroup_uniform_float(shgrp, "lodMax", &sldata->probes->lodmax, 1); DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex); DRW_shgroup_uniform_buffer(shgrp, "probeCubes", &sldata->probe_pool); - DRW_shgroup_uniform_float(shgrp, "lodMax", &sldata->probes->lodmax, 1); DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool); DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool); } @@ -339,8 +342,7 @@ void EEVEE_materials_cache_init(EEVEE_Data *vedata) } } -/* Macro to call the right */ -#define ADD_MATERIAL_CALL(shgrp, ob, geom) do { \ +#define ADD_SHGROUP_CALL(shgrp, ob, geom) do { \ if (is_sculpt_mode) { \ DRW_shgroup_call_sculpt_add(shgrp, ob, ob->obmat); \ } \ @@ -363,7 +365,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl /* Depth Prepass */ DRWShadingGroup *depth_shgrp = do_cull ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp; - ADD_MATERIAL_CALL(depth_shgrp, ob, geom); + ADD_SHGROUP_CALL(depth_shgrp, ob, geom); /* Get per-material split surface */ struct Batch **mat_geom = DRW_cache_object_surface_material_get(ob); @@ -398,7 +400,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl if (shgrp) { add_standard_uniforms(shgrp, sldata); - ADD_MATERIAL_CALL(shgrp, ob, mat_geom[i]); + ADD_SHGROUP_CALL(shgrp, ob, mat_geom[i]); } else { /* Shader failed : pink color */ @@ -418,7 +420,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1); DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1); - ADD_MATERIAL_CALL(shgrp, ob, mat_geom[i]); + ADD_SHGROUP_CALL(shgrp, ob, mat_geom[i]); } } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 3e4547e76ac..0d5ab592563 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -167,6 +167,7 @@ enum { /* ************ PROBE UBO ************* */ typedef struct EEVEE_Probe { float position[3], dist; + float shcoefs[9][3], pad; } EEVEE_Probe; /* ************ PROBE DATA ************* */ @@ -185,7 +186,6 @@ typedef struct EEVEE_ProbesInfo { float lodmax; int shres; int shnbr; - float shcoefs[9][3]; /* Temp */ struct GPUTexture *backgroundtex; /* List of probes in the scene. */ /* XXX This is fragile, can get out of sync quickly. */ diff --git a/source/blender/draw/engines/eevee/eevee_probes.c b/source/blender/draw/engines/eevee/eevee_probes.c index a5097080646..70e1ac02ef9 100644 --- a/source/blender/draw/engines/eevee/eevee_probes.c +++ b/source/blender/draw/engines/eevee/eevee_probes.c @@ -128,6 +128,7 @@ void EEVEE_probes_init(EEVEE_SceneLayerData *sldata) if (!sldata->probes) { sldata->probes = MEM_callocN(sizeof(EEVEE_ProbesInfo), "EEVEE_ProbesInfo"); + sldata->probe_ubo = DRW_uniformbuffer_create(sizeof(EEVEE_Probe) * MAX_PROBE, NULL); } /* Setup Render Target Cubemap */ @@ -151,7 +152,7 @@ void EEVEE_probes_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) { EEVEE_ProbesInfo *pinfo = sldata->probes; - pinfo->num_cube = 0; + pinfo->num_cube = 1; /* at least one for the world */ memset(pinfo->probes_ref, 0, sizeof(pinfo->probes_ref)); { @@ -260,15 +261,19 @@ void EEVEE_probes_cache_finish(EEVEE_SceneLayerData *sldata) DRWFboTexture tex_filter = {&sldata->probe_pool, DRW_TEX_RGBA_16, DRW_TEX_FILTER | DRW_TEX_MIPMAP}; DRW_framebuffer_init(&sldata->probe_filter_fb, &draw_engine_eevee_type, PROBE_SIZE, PROBE_SIZE, &tex_filter, 1); + + DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data); } /* Renders the probe with index probe_idx. * Renders the world probe if probe_idx = -1. */ -void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int probe_idx) +static void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int probe_idx) { EEVEE_ProbesInfo *pinfo = sldata->probes; + EEVEE_Probe *eprobe = &pinfo->probe_data[probe_idx]; Object *ob = NULL; - bool is_object_probe = (probe_idx != -1); + struct DRWPass *probe_pass; + bool is_object_probe = (probe_idx > 0); float projmat[4][4], posmat[4][4]; float near, far; @@ -283,11 +288,13 @@ void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int pro /* Move to capture position */ negate_v3_v3(posmat[3], ob->obmat[3]); + probe_pass = psl->probe_background; /* TODO use objects in the scene */ } else { /* World cubemap */ near = 0.1f; far = 100.0f; + probe_pass = psl->probe_background; } /* 1 - Render to cubemap target using geometry shader. */ @@ -302,7 +309,7 @@ void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int pro } DRW_framebuffer_bind(sldata->probe_fb); - DRW_draw_pass(psl->probe_background); + DRW_draw_pass(probe_pass); if (is_object_probe) { DRW_framebuffer_clear(true, true, false, clear_color, 1.0); @@ -337,7 +344,7 @@ void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int pro else if (pinfo->padding_size > 4) { pinfo->padding_size += 1; } - pinfo->layer = probe_idx + 1; /* 0 is world */ + pinfo->layer = probe_idx; pinfo->roughness = (float)i / ((float)maxlevel - 4.0f); pinfo->roughness *= pinfo->roughness; /* Disney Roughness */ pinfo->roughness *= pinfo->roughness; /* Distribute Roughness accros lod more evenly */ @@ -369,8 +376,6 @@ void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int pro } /* For shading, save max level of the octahedron map */ pinfo->lodmax = (float)(maxlevel - min_lod_level) - 1.0f; - /* reattach to have a valid framebuffer. */ - DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); /* 4 - Compute spherical harmonics */ /* Tweaking parameters to balance perf. vs precision */ @@ -378,14 +383,19 @@ void render_one_probe(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl, int pro pinfo->lodfactor = 4.0f; /* Improve cache reuse */ DRW_framebuffer_bind(sldata->probe_sh_fb); DRW_draw_pass(psl->probe_sh_compute); - DRW_framebuffer_read_data(0, 0, 9, 1, 3, 0, (float *)pinfo->shcoefs); + DRW_framebuffer_read_data(0, 0, 9, 1, 3, 0, (float *)eprobe->shcoefs); + + /* reattach to have a valid framebuffer. */ + DRW_framebuffer_texture_attach(sldata->probe_filter_fb, sldata->probe_pool, 0, 0); } void EEVEE_probes_refresh(EEVEE_SceneLayerData *sldata, EEVEE_PassList *psl) { if (e_data.update_world) { - render_one_probe(sldata, psl, -1); + render_one_probe(sldata, psl, 0); e_data.update_world = false; + + DRW_uniformbuffer_update(sldata->probe_ubo, &sldata->probes->probe_data); } } diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl index 8963ad2b93e..b0b11c489b6 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -9,6 +9,23 @@ /* ------- Structures -------- */ +struct ProbeData { + vec4 position_influence; /* w : InfluenceRadius */ + vec4 shcoefs[7]; +}; + +#define p_position position_influence.xyz +#define p_spec position_influence.w +#define shcoef0 shcoefs[0].rgb +#define shcoef1 vec3(shcoefs[0].a, shcoefs[1].rg) +#define shcoef2 vec3(shcoefs[1].ba, shcoefs[2].r) +#define shcoef3 shcoefs[2].gba +#define shcoef4 shcoefs[3].rgb +#define shcoef5 vec3(shcoefs[3].a, shcoefs[4].rg) +#define shcoef6 vec3(shcoefs[4].ba, shcoefs[5].r) +#define shcoef7 shcoefs[5].gba +#define shcoef8 shcoefs[6].rgb + struct LightData { vec4 position_influence; /* w : InfluenceRadius */ vec4 color_spec; /* w : Spec Intensity */ @@ -172,34 +189,34 @@ float buffer_depth(bool is_persp, float z, float zf, float zn) #define spherical_harmonics spherical_harmonics_L2 /* http://seblagarde.wordpress.com/2012/01/08/pi-or-not-to-pi-in-game-lighting-equation/ */ -vec3 spherical_harmonics_L1(vec3 N, vec3 shcoefs[9]) +vec3 spherical_harmonics_L1(vec3 N, vec4 shcoefs[3]) { vec3 sh = vec3(0.0); - sh += 0.282095 * shcoefs[0]; + sh += 0.282095 * shcoef0; - sh += -0.488603 * N.z * shcoefs[1]; - sh += 0.488603 * N.y * shcoefs[2]; - sh += -0.488603 * N.x * shcoefs[3]; + sh += -0.488603 * N.z * shcoef1; + sh += 0.488603 * N.y * shcoef2; + sh += -0.488603 * N.x * shcoef3; return sh; } -vec3 spherical_harmonics_L2(vec3 N, vec3 shcoefs[9]) +vec3 spherical_harmonics_L2(vec3 N, vec4 shcoefs[7]) { vec3 sh = vec3(0.0); - sh += 0.282095 * shcoefs[0]; + sh += 0.282095 * shcoef0; - sh += -0.488603 * N.z * shcoefs[1]; - sh += 0.488603 * N.y * shcoefs[2]; - sh += -0.488603 * N.x * shcoefs[3]; + sh += -0.488603 * N.z * shcoef1; + sh += 0.488603 * N.y * shcoef2; + sh += -0.488603 * N.x * shcoef3; - sh += 1.092548 * N.x * N.z * shcoefs[4]; - sh += -1.092548 * N.z * N.y * shcoefs[5]; - sh += 0.315392 * (3.0 * N.y * N.y - 1.0) * shcoefs[6]; - sh += -1.092548 * N.x * N.y * shcoefs[7]; - sh += 0.546274 * (N.x * N.x - N.z * N.z) * shcoefs[8]; + sh += 1.092548 * N.x * N.z * shcoef4; + sh += -1.092548 * N.z * N.y * shcoef5; + sh += 0.315392 * (3.0 * N.y * N.y - 1.0) * shcoef6; + sh += -1.092548 * N.x * N.y * shcoef7; + sh += 0.546274 * (N.x * N.x - N.z * N.z) * shcoef8; return sh; } diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl index b8eb84f24de..5ee0cb74894 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -1,5 +1,6 @@ uniform int light_count; +uniform int probe_count; uniform mat4 ProjectionMatrix; uniform mat4 ViewMatrixInverse; @@ -15,6 +16,10 @@ uniform sampler2DArray utilTex; uniform sampler2DArray shadowCubes; uniform sampler2DArrayShadow shadowCascades; +layout(std140) uniform probe_block { + ProbeData probes_data[MAX_PROBE]; +}; + layout(std140) uniform light_block { LightData lights_data[MAX_LIGHT]; }; @@ -191,6 +196,13 @@ void light_visibility(LightData ld, ShadingData sd, out float vis) } } +void probe_lighting(ShadingData sd, int index, vec3 spec_dir, float roughness, out vec3 diff, out vec3 spec) +{ + ProbeData pd = probes_data[index]; + spec = textureLod_octahedron(probeCubes, vec4(spec_dir, index), roughness * lodMax).rgb; + diff = spherical_harmonics(sd.N, pd.shcoefs); +} + vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, float ao) { float roughnessSquared = roughness * roughness; @@ -203,8 +215,6 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, sd.W = worldPosition; vec3 radiance = vec3(0.0); - vec3 indirect_radiance = vec3(0.0); - /* Analitic Lights */ for (int i = 0; i < MAX_LIGHT && i < light_count; ++i) { LightData ld = lights_data[i]; @@ -219,14 +229,29 @@ vec3 eevee_surface_lit(vec3 world_normal, vec3 albedo, vec3 f0, float roughness, radiance += vis * (diff + spec) * ld.l_color; } - vec3 spec_dir = get_specular_dominant_dir(sd.N, reflect(-sd.V, sd.N), roughnessSquared); /* Envmaps */ + vec3 spec_dir = get_specular_dominant_dir(sd.N, reflect(-sd.V, sd.N), roughnessSquared); vec2 uv = lut_coords(dot(sd.N, sd.V), roughness); vec2 brdf_lut = texture(utilTex, vec3(uv, 1.0)).rg; - vec3 Li = textureLod_octahedron(probeCubes, vec4(spec_dir, 0.0), roughness * lodMax).rgb; - indirect_radiance += Li * F_ibl(f0, brdf_lut); - indirect_radiance += spherical_harmonics(sd.N, shCoefs) * albedo; + + vec4 spec_accum = vec4(0.0); + vec4 diff_accum = vec4(0.0); + /* Start at 1 because 0 is world probe */ + for (int i = 1; i < MAX_PROBE && i < probe_count; ++i) { + /* TODO */ + } + + if (spec_accum.a < 1.0 || diff_accum.a < 1.0) { + vec3 diff, spec; + probe_lighting(sd, 0, spec_dir, roughness, diff, spec); + diff_accum.rgb += diff * (1.0 - diff_accum.a); + spec_accum.rgb += spec * (1.0 - spec_accum.a); + } + + vec3 indirect_radiance = + spec_accum.rgb * F_ibl(f0, brdf_lut) + + diff_accum.rgb * albedo; return radiance + indirect_radiance * ao; }
\ No newline at end of file |