diff options
Diffstat (limited to 'source/blender/draw/engines')
7 files changed, 248 insertions, 135 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 6c190d8b917..419b70092a4 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -46,6 +46,12 @@ #include "eevee_private.h" #include "GPU_texture.h" +#define SHADER_DEFINES \ + "#define EEVEE_ENGINE\n" \ + "#define MAX_PROBE " STRINGIFY(MAX_PROBE) "\n" \ + "#define MAX_GRID " STRINGIFY(MAX_GRID) "\n" \ + "#define MAX_PLANAR " STRINGIFY(MAX_PLANAR) "\n" + typedef struct EEVEE_LightProbeData { short probe_id, shadow_id; } EEVEE_LightProbeData; @@ -80,6 +86,8 @@ static struct { struct GPUTexture *depth_src; } e_data = {NULL}; /* Engine data */ +extern char datatoc_bsdf_common_lib_glsl[]; +extern char datatoc_octahedron_lib_glsl[]; extern char datatoc_effect_ssr_frag_glsl[]; extern char datatoc_effect_minmaxz_frag_glsl[]; extern char datatoc_effect_motion_blur_frag_glsl[]; @@ -87,6 +95,7 @@ extern char datatoc_effect_bloom_frag_glsl[]; extern char datatoc_effect_dof_vert_glsl[]; extern char datatoc_effect_dof_geom_glsl[]; extern char datatoc_effect_dof_frag_glsl[]; +extern char datatoc_lightprobe_lib_glsl[]; extern char datatoc_tonemap_frag_glsl[]; extern char datatoc_volumetric_frag_glsl[]; @@ -163,8 +172,18 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) /* Shaders */ if (!e_data.motion_blur_sh) { - e_data.ssr_raytrace_sh = DRW_shader_create_fullscreen(datatoc_effect_ssr_frag_glsl, "#define STEP_RAYTRACE\n"); - e_data.ssr_resolve_sh = DRW_shader_create_fullscreen(datatoc_effect_ssr_frag_glsl, "#define STEP_RESOLVE\n"); + DynStr *ds_frag = BLI_dynstr_new(); + BLI_dynstr_append(ds_frag, datatoc_bsdf_common_lib_glsl); + BLI_dynstr_append(ds_frag, datatoc_octahedron_lib_glsl); + BLI_dynstr_append(ds_frag, datatoc_lightprobe_lib_glsl); + BLI_dynstr_append(ds_frag, datatoc_effect_ssr_frag_glsl); + char *ssr_shader_str = BLI_dynstr_get_cstring(ds_frag); + BLI_dynstr_free(ds_frag); + + e_data.ssr_raytrace_sh = DRW_shader_create_fullscreen(ssr_shader_str, SHADER_DEFINES "#define STEP_RAYTRACE\n"); + e_data.ssr_resolve_sh = DRW_shader_create_fullscreen(ssr_shader_str, SHADER_DEFINES "#define STEP_RESOLVE\n"); + + MEM_freeN(ssr_shader_str); e_data.volumetric_upsample_sh = DRW_shader_create_fullscreen(datatoc_volumetric_frag_glsl, "#define STEP_UPSAMPLE\n"); @@ -612,20 +631,26 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) } if ((effects->enabled_effects & EFFECT_SSR) != 0) { - psl->ssr_raytrace = DRW_pass_create("Raytrace", DRW_STATE_WRITE_COLOR); + psl->ssr_raytrace = DRW_pass_create("SSR Raytrace", DRW_STATE_WRITE_COLOR); DRWShadingGroup *grp = DRW_shgroup_create(e_data.ssr_raytrace_sh, psl->ssr_raytrace); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); - DRW_shgroup_uniform_buffer(grp, "normalBuffer", &stl->g_data->minmaxz); - DRW_shgroup_uniform_buffer(grp, "specRoughBuffer", &stl->g_data->minmaxz); + DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); + DRW_shgroup_uniform_buffer(grp, "specRoughBuffer", &txl->ssr_specrough_input); DRW_shgroup_call_add(grp, quad, NULL); - psl->ssr_resolve = DRW_pass_create("Raytrace", DRW_STATE_WRITE_COLOR); + psl->ssr_resolve = DRW_pass_create("SSR Resolve", DRW_STATE_WRITE_COLOR | DRW_STATE_ADDITIVE); grp = DRW_shgroup_create(e_data.ssr_resolve_sh, psl->ssr_resolve); DRW_shgroup_uniform_buffer(grp, "depthBuffer", &e_data.depth_src); DRW_shgroup_uniform_buffer(grp, "normalBuffer", &txl->ssr_normal_input); DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input); DRW_shgroup_uniform_buffer(grp, "hitBuffer", &txl->ssr_hit_output); DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &txl->ssr_pdf_output); + DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2); + DRW_shgroup_uniform_int(grp, "probe_count", &sldata->probes->num_render_cube, 1); + DRW_shgroup_uniform_float(grp, "lodCubeMax", &sldata->probes->lod_cube_max, 1); + DRW_shgroup_uniform_float(grp, "lodPlanarMax", &sldata->probes->lod_planar_max, 1); + DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool); + DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool); DRW_shgroup_call_add(grp, quad, NULL); } @@ -789,7 +814,6 @@ void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *veda EEVEE_EffectsInfo *effects = stl->effects; if ((effects->enabled_effects & EFFECT_VOLUMETRIC) != 0) { - return; DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); e_data.depth_src = dtxl->depth; @@ -822,7 +846,7 @@ void EEVEE_effects_do_volumetrics(EEVEE_SceneLayerData *sldata, EEVEE_Data *veda } } -void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) +void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *UNUSED(sldata), EEVEE_Data *vedata) { EEVEE_PassList *psl = vedata->psl; EEVEE_FramebufferList *fbl = vedata->fbl; @@ -833,6 +857,8 @@ void EEVEE_effects_do_ssr(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata) if ((effects->enabled_effects & EFFECT_SSR) != 0) { DefaultTextureList *dtxl = DRW_viewport_texture_list_get(); + e_data.depth_src = dtxl->depth; + /* Raytrace at halfres. */ DRW_framebuffer_bind(fbl->screen_tracing_fb); DRW_draw_pass(psl->ssr_raytrace); 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 50b3309e93b..4c0e521a7f0 100644 --- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl @@ -28,114 +28,10 @@ flat in int shFace; /* Shadow layer we are rendering to. */ #define cameraForward normalize(ViewMatrixInverse[2].xyz) #define cameraPos ViewMatrixInverse[3].xyz - +#define cameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward) +#define viewCameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(viewPosition) : vec3(0.0, 0.0, -1.0)) /* ------- Structures -------- */ -#ifdef VOLUMETRICS - -struct Closure { - vec3 absorption; - vec3 scatter; - vec3 emission; - float anisotropy; -}; - -#define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0) - -Closure closure_mix(Closure cl1, Closure cl2, float fac) -{ - Closure cl; - cl.absorption = mix(cl1.absorption, cl2.absorption, fac); - cl.scatter = mix(cl1.scatter, cl2.scatter, fac); - cl.emission = mix(cl1.emission, cl2.emission, fac); - cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac); - return cl; -} - -Closure closure_add(Closure cl1, Closure cl2) -{ - Closure cl; - cl.absorption = cl1.absorption + cl2.absorption; - cl.scatter = cl1.scatter + cl2.scatter; - cl.emission = cl1.emission + cl2.emission; - cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */ - return cl; -} -#else - -struct Closure { - vec3 radiance; - float opacity; - vec4 ssr_data; - vec2 ssr_normal; - int ssr_id; -}; - -#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1) - -uniform int outputSsrId; - -Closure closure_mix(Closure cl1, Closure cl2, float fac) -{ - Closure cl; - if (cl1.ssr_id == outputSsrId) { - cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */ - cl.ssr_normal = cl1.ssr_normal; - cl.ssr_id = cl1.ssr_id; - } - else { - cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ - cl.ssr_normal = cl2.ssr_normal; - cl.ssr_id = cl2.ssr_id; - } - cl.radiance = mix(cl1.radiance, cl2.radiance, fac); - cl.opacity = mix(cl1.opacity, cl2.opacity, fac); - return cl; -} - -Closure closure_add(Closure cl1, Closure cl2) -{ - Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2; - cl.radiance = cl1.radiance + cl2.radiance; - cl.opacity = cl1.opacity + cl2.opacity; - return cl; -} - -#if defined(MESH_SHADER) && !defined(SHADOW_SHADER) -layout(location = 0) out vec4 fragColor; -layout(location = 1) out vec4 ssrNormals; -layout(location = 2) out vec4 ssrData; - -Closure nodetree_exec(void); /* Prototype */ - -#define NODETREE_EXEC -void main() -{ - Closure cl = nodetree_exec(); - fragColor = vec4(cl.radiance, cl.opacity); - ssrNormals = cl.ssr_normal.xyyy; - ssrData = cl.ssr_data; -} - -#endif /* MESH_SHADER && !SHADOW_SHADER */ - -#endif /* VOLUMETRICS */ - -Closure nodetree_exec(void); /* Prototype */ - -/* TODO find a better place */ -#ifdef USE_MULTIPLY - -out vec4 fragColor; - -#define NODETREE_EXEC -void main() -{ - Closure cl = nodetree_exec(); - fragColor = vec4(mix(vec3(1.0), cl.radiance, cl.opacity), 1.0); -} -#endif - struct LightData { vec4 position_influence; /* w : InfluenceRadius */ vec4 color_spec; /* w : Spec Intensity */ @@ -194,8 +90,6 @@ struct ShadowCascadeData { vec4 bias; }; -#define cameraVec ((ProjectionMatrix[3][3] == 0.0) ? normalize(cameraPos - worldPosition) : cameraForward) - /* ------- Convenience functions --------- */ vec3 mul(mat3 m, vec3 v) { return m * v; } @@ -364,6 +258,11 @@ vec3 get_view_space_from_depth(vec2 uvcoords, float depth) } } +vec3 get_world_space_from_depth(vec2 uvcoords, float depth) +{ + return (ViewMatrixInverse * vec4(get_view_space_from_depth(uvcoords, depth), 1.0)).xyz; +} + vec3 get_specular_dominant_dir(vec3 N, vec3 V, float roughness) { vec3 R = -reflect(V, N); @@ -377,6 +276,26 @@ float specular_occlusion(float NV, float AO, float roughness) return saturate(pow(NV + AO, roughness) - 1.0 + AO); } +/* ---- Encode / Decode Normal buffer data ---- */ +/* From http://aras-p.info/texts/CompactNormalStorage.html + * Using Method #4: Spheremap Transform */ +vec2 normal_encode(vec3 n, vec3 view) +{ + float p = sqrt(n.z * 8.0 + 8.0); + return n.xy / p + 0.5; +} + +vec3 normal_decode(vec2 enc, vec3 view) +{ + vec2 fenc = enc * 4.0 - 2.0; + float f = dot(fenc, fenc); + float g = sqrt(1.0 - f / 4.0); + vec3 n; + n.xy = fenc*g; + n.z = 1 - f / 2; + return n; +} + /* Fresnel */ vec3 F_schlick(vec3 f0, float cos_theta) { @@ -443,4 +362,110 @@ float bsdf_ggx(vec3 N, vec3 L, vec3 V, float roughness) void accumulate_light(vec3 light, float fac, inout vec4 accum) { accum += vec4(light, 1.0) * min(fac, (1.0 - accum.a)); -}
\ No newline at end of file +} + +/* --------- Closure ---------- */ +#ifdef VOLUMETRICS + +struct Closure { + vec3 absorption; + vec3 scatter; + vec3 emission; + float anisotropy; +}; + +#define CLOSURE_DEFAULT Closure(vec3(0.0), vec3(0.0), vec3(0.0), 0.0) + +Closure closure_mix(Closure cl1, Closure cl2, float fac) +{ + Closure cl; + cl.absorption = mix(cl1.absorption, cl2.absorption, fac); + cl.scatter = mix(cl1.scatter, cl2.scatter, fac); + cl.emission = mix(cl1.emission, cl2.emission, fac); + cl.anisotropy = mix(cl1.anisotropy, cl2.anisotropy, fac); + return cl; +} + +Closure closure_add(Closure cl1, Closure cl2) +{ + Closure cl; + cl.absorption = cl1.absorption + cl2.absorption; + cl.scatter = cl1.scatter + cl2.scatter; + cl.emission = cl1.emission + cl2.emission; + cl.anisotropy = (cl1.anisotropy + cl2.anisotropy) / 2.0; /* Average phase (no multi lobe) */ + return cl; +} +#else + +struct Closure { + vec3 radiance; + float opacity; + vec4 ssr_data; + vec2 ssr_normal; + int ssr_id; +}; + +#define CLOSURE_DEFAULT Closure(vec3(0.0), 1.0, vec4(0.0), vec2(0.0), -1) + +uniform int outputSsrId; + +Closure closure_mix(Closure cl1, Closure cl2, float fac) +{ + Closure cl; + if (cl1.ssr_id == outputSsrId) { + cl.ssr_data = mix(cl1.ssr_data.xyzw, vec4(vec3(0.0), cl1.ssr_data.w), fac); /* do not blend roughness */ + cl.ssr_normal = cl1.ssr_normal; + cl.ssr_id = cl1.ssr_id; + } + else { + cl.ssr_data = mix(vec4(vec3(0.0), cl2.ssr_data.w), cl2.ssr_data.xyzw, fac); /* do not blend roughness */ + cl.ssr_normal = cl2.ssr_normal; + cl.ssr_id = cl2.ssr_id; + } + cl.radiance = mix(cl1.radiance, cl2.radiance, fac); + cl.opacity = mix(cl1.opacity, cl2.opacity, fac); + return cl; +} + +Closure closure_add(Closure cl1, Closure cl2) +{ + Closure cl = (cl1.ssr_id == outputSsrId) ? cl1 : cl2; + cl.radiance = cl1.radiance + cl2.radiance; + cl.opacity = cl1.opacity + cl2.opacity; + return cl; +} + +#if defined(MESH_SHADER) && !defined(SHADOW_SHADER) +layout(location = 0) out vec4 fragColor; +layout(location = 1) out vec4 ssrNormals; +layout(location = 2) out vec4 ssrData; + +Closure nodetree_exec(void); /* Prototype */ + +#define NODETREE_EXEC +void main() +{ + Closure cl = nodetree_exec(); + fragColor = vec4(cl.radiance, cl.opacity); + ssrNormals = cl.ssr_normal.xyyy; + ssrData = cl.ssr_data; +} + +#endif /* MESH_SHADER && !SHADOW_SHADER */ + +#endif /* VOLUMETRICS */ + +Closure nodetree_exec(void); /* Prototype */ + +/* TODO find a better place */ +#ifdef USE_MULTIPLY + +out vec4 fragColor; + +#define NODETREE_EXEC +void main() +{ + Closure cl = nodetree_exec(); + fragColor = vec4(mix(vec3(1.0), cl.radiance, cl.opacity), 1.0); +} +#endif
\ No newline at end of file diff --git a/source/blender/draw/engines/eevee/shaders/default_frag.glsl b/source/blender/draw/engines/eevee/shaders/default_frag.glsl index db8ed2d04fe..e1d5bbd8511 100644 --- a/source/blender/draw/engines/eevee/shaders/default_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/default_frag.glsl @@ -12,7 +12,7 @@ Closure nodetree_exec(void) vec3 ssr_spec; vec3 radiance = eevee_surface_lit((gl_FrontFacing) ? worldNormal : -worldNormal, diffuse, f0, roughness, 1.0, 0, ssr_spec); - Closure result = Closure(radiance, 1.0, vec4(ssr_spec, roughness), viewNormal.xy, 0); + Closure result = Closure(radiance, 1.0, vec4(ssr_spec, roughness), normal_encode(normalize(viewNormal), viewCameraVec), 0); #if !defined(USE_ALPHA_BLEND) result.opacity = length(viewPosition); diff --git a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl index bbf33661ef5..63f87da1468 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -10,6 +10,13 @@ layout(location = 1) out vec4 pdfData; void main() { + ivec2 fullres_texel = ivec2(gl_FragCoord.xy) * 2; + float depth = texelFetch(depthBuffer, fullres_texel, 0).r; + + /* Early discard */ + if (depth == 1.0) + discard; + hitData = vec4(0.2); pdfData = vec4(0.5); } @@ -23,14 +30,63 @@ uniform sampler2D specroughBuffer; uniform sampler2D hitBuffer; uniform sampler2D pdfBuffer; +uniform int probe_count; + out vec4 fragColor; +void fallback_cubemap(vec3 N, vec3 V, vec3 W, float roughness, float roughnessSquared, inout vec4 spec_accum) +{ + /* Specular probes */ + vec3 spec_dir = get_specular_dominant_dir(N, V, roughnessSquared); + + /* Starts at 1 because 0 is world probe */ + for (int i = 1; i < MAX_PROBE && i < probe_count && spec_accum.a < 0.999; ++i) { + CubeData cd = probes_data[i]; + + float fade = probe_attenuation_cube(cd, W); + + if (fade > 0.0) { + vec3 spec = probe_evaluate_cube(float(i), cd, W, spec_dir, roughness); + accumulate_light(spec, fade, spec_accum); + } + } + + /* World Specular */ + if (spec_accum.a < 0.999) { + vec3 spec = probe_evaluate_world_spec(spec_dir, roughness); + accumulate_light(spec, 1.0, spec_accum); + } +} + void main() { ivec2 halfres_texel = ivec2(gl_FragCoord.xy / 2.0); ivec2 fullres_texel = ivec2(gl_FragCoord.xy); + vec2 uvs = gl_FragCoord.xy / vec2(textureSize(depthBuffer, 0)); + + float depth = textureLod(depthBuffer, uvs, 0.0).r; + + /* Early discard */ + if (depth == 1.0) + discard; + + vec3 worldPosition = get_world_space_from_depth(uvs, depth); + vec3 V = cameraVec; + vec3 N = mat3(ViewMatrixInverse) * normal_decode(texelFetch(normalBuffer, fullres_texel, 0).rg, V); + vec4 speccol_roughness = texelFetch(specroughBuffer, fullres_texel, 0).rgba; + float roughness = speccol_roughness.a; + float roughnessSquared = roughness * roughness; + + vec4 spec_accum = vec4(0.0); + + /* Resolve SSR and compute contribution */ + + /* If SSR contribution is not 1.0, blend with cubemaps */ + if (spec_accum.a < 1.0) { + fallback_cubemap(N, V, worldPosition, roughness, roughnessSquared, spec_accum); + } - fragColor = vec4(texelFetch(specroughBuffer, fullres_texel, 0).aaa, 1.0); + fragColor = vec4(spec_accum.rgb * speccol_roughness.rgb, 1.0); } #endif diff --git a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl index 061719b5685..75ec5ade58d 100644 --- a/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lamps_lib.glsl @@ -8,18 +8,6 @@ layout(std140) uniform shadow_block { ShadowCascadeData shadows_cascade_data[MAX_SHADOW_CASCADE]; }; -layout(std140) uniform probe_block { - CubeData probes_data[MAX_PROBE]; -}; - -layout(std140) uniform grid_block { - GridData grids_data[MAX_GRID]; -}; - -layout(std140) uniform planar_block { - PlanarData planars_data[MAX_PLANAR]; -}; - layout(std140) uniform light_block { LightData lights_data[MAX_LIGHT]; }; diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl index 32da31339d1..2f117668687 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_lib.glsl @@ -60,6 +60,28 @@ struct GridData { #define g_resolution resolution_offset.xyz #define g_offset resolution_offset.w +#ifndef MAX_PROBE +#define MAX_PROBE 1 +#endif +#ifndef MAX_GRID +#define MAX_GRID 1 +#endif +#ifndef MAX_PLANAR +#define MAX_PLANAR 1 +#endif + +layout(std140) uniform probe_block { + CubeData probes_data[MAX_PROBE]; +}; + +layout(std140) uniform grid_block { + GridData grids_data[MAX_GRID]; +}; + +layout(std140) uniform planar_block { + PlanarData planars_data[MAX_PLANAR]; +}; + /* ----------- Functions --------- */ float probe_attenuation_cube(CubeData pd, vec3 W) diff --git a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl index 2cb43336ace..c5e57cee718 100644 --- a/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lightprobe_planar_display_frag.glsl @@ -1,10 +1,6 @@ uniform int probeIdx; -layout(std140) uniform planar_block { - PlanarData planars_data[MAX_PLANAR]; -}; - in vec3 worldPosition; out vec4 FragColor; |