From 3cb2b2956b140b840ba8a481ad15df1b567d9c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Foucault?= Date: Mon, 15 Jan 2018 17:23:17 +0100 Subject: Eevee: SSR: Remove ray count and use integer texture for hit coord. Using GL_RG16I texture for the hit coordinates increase tremendously the precision of the hit. The sign of the integer is used to 2 flags (has_hit and is_planar). We do not store the depth and retrieve it from the depth buffer (increasing bandwith by +8bit/px). The PDF is stored into another GL_R16F texture. We remove the raycount for simplicity and to reduce compilation time (less branching in refraction shader). --- source/blender/draw/engines/eevee/eevee_effects.c | 2 +- source/blender/draw/engines/eevee/eevee_engine.c | 1 - .../blender/draw/engines/eevee/eevee_materials.c | 1 - source/blender/draw/engines/eevee/eevee_private.h | 4 +- .../draw/engines/eevee/eevee_screen_raytrace.c | 72 +++++----- .../engines/eevee/shaders/effect_ssr_frag.glsl | 148 ++++++++++----------- .../engines/eevee/shaders/lit_surface_frag.glsl | 9 +- .../draw/engines/eevee/shaders/ssr_lib.glsl | 4 +- source/blender/makesrna/intern/rna_layer.c | 9 -- 9 files changed, 104 insertions(+), 146 deletions(-) (limited to 'source') diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c index 223012e3906..5322f84679b 100644 --- a/source/blender/draw/engines/eevee/eevee_effects.c +++ b/source/blender/draw/engines/eevee/eevee_effects.c @@ -441,7 +441,7 @@ void EEVEE_draw_effects(EEVEE_Data *vedata) if (txl->maxzbuffer) DRW_transform_to_display(txl->maxzbuffer); break; case 2: - if (stl->g_data->ssr_hit_output[0]) DRW_transform_to_display(stl->g_data->ssr_hit_output[0]); + if (stl->g_data->ssr_pdf_output) DRW_transform_to_display(stl->g_data->ssr_pdf_output); break; case 3: if (txl->ssr_normal_input) DRW_transform_to_display(txl->ssr_normal_input); diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c index e9c4a1a7727..678501528c8 100644 --- a/source/blender/draw/engines/eevee/eevee_engine.c +++ b/source/blender/draw/engines/eevee/eevee_engine.c @@ -361,7 +361,6 @@ static void eevee_view_layer_settings_create(RenderEngine *UNUSED(engine), IDPro BKE_collection_engine_property_add_bool(props, "ssr_enable", false); BKE_collection_engine_property_add_bool(props, "ssr_refraction", false); BKE_collection_engine_property_add_bool(props, "ssr_halfres", true); - BKE_collection_engine_property_add_int(props, "ssr_ray_count", 1); BKE_collection_engine_property_add_float(props, "ssr_quality", 0.25f); BKE_collection_engine_property_add_float(props, "ssr_max_roughness", 0.5f); BKE_collection_engine_property_add_float(props, "ssr_thickness", 0.2f); diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c index 5bd7fe979b8..31cda5936ad 100644 --- a/source/blender/draw/engines/eevee/eevee_materials.c +++ b/source/blender/draw/engines/eevee/eevee_materials.c @@ -391,7 +391,6 @@ static void add_standard_uniforms( DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color); DRW_shgroup_uniform_float(shgrp, "borderFadeFactor", &vedata->stl->effects->ssr_border_fac, 1); DRW_shgroup_uniform_float(shgrp, "maxRoughness", &vedata->stl->effects->ssr_max_roughness, 1); - DRW_shgroup_uniform_int(shgrp, "rayCount", &vedata->stl->effects->ssr_ray_count, 1); } if (vedata->stl->effects->use_ao) { diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index c1108dd7dc7..6f276a891ba 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -248,6 +248,7 @@ typedef struct EEVEE_TextureList { struct GPUTexture *bloom_upsample[MAX_BLOOM_STEP - 1]; /* R16_G16_B16 */ struct GPUTexture *ssr_normal_input; struct GPUTexture *ssr_specrough_input; + struct GPUTexture *ssr_hit_output; struct GPUTexture *refract_color; struct GPUTexture *volume_prop_scattering; @@ -496,7 +497,6 @@ typedef struct EEVEE_EffectsInfo { bool use_ssr; bool reflection_trace_full; bool ssr_use_normalization; - int ssr_ray_count; float ssr_firefly_fac; float ssr_border_fac; float ssr_max_roughness; @@ -702,7 +702,7 @@ typedef struct EEVEE_PrivateData { struct GHash *material_hash; struct GHash *hair_material_hash; struct GPUTexture *minzbuffer; - struct GPUTexture *ssr_hit_output[4]; + struct GPUTexture *ssr_pdf_output; struct GPUTexture *gtao_horizons_debug; float background_alpha; /* TODO find a better place for this. */ float viewvecs[2][4]; diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c index 35669968337..27e72b9e8d6 100644 --- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c +++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c @@ -34,10 +34,9 @@ /* SSR shader variations */ enum { - SSR_SAMPLES = (1 << 0) | (1 << 1), - SSR_RESOLVE = (1 << 2), - SSR_FULL_TRACE = (1 << 3), - SSR_MAX_SHADER = (1 << 4), + SSR_RESOLVE = (1 << 0), + SSR_FULL_TRACE = (1 << 1), + SSR_MAX_SHADER = (1 << 2), }; static struct { @@ -71,11 +70,8 @@ static struct GPUShader *eevee_effects_screen_raytrace_shader_get(int options) char *ssr_shader_str = BLI_dynstr_get_cstring(ds_frag); BLI_dynstr_free(ds_frag); - int samples = (SSR_SAMPLES & options) + 1; - DynStr *ds_defines = BLI_dynstr_new(); BLI_dynstr_appendf(ds_defines, SHADER_DEFINES); - BLI_dynstr_appendf(ds_defines, "#define RAY_COUNT %d\n", samples); if (options & SSR_RESOLVE) { BLI_dynstr_appendf(ds_defines, "#define STEP_RESOLVE\n"); } @@ -108,7 +104,9 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * const DRWContextState *draw_ctx = DRW_context_state_get(); ViewLayer *view_layer = draw_ctx->view_layer; - IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, COLLECTION_MODE_NONE, RE_engine_id_BLENDER_EEVEE); + IDProperty *props = BKE_view_layer_engine_evaluated_get(view_layer, + COLLECTION_MODE_NONE, + RE_engine_id_BLENDER_EEVEE); /* Compute pixel size, (shared with contact shadows) */ copy_v2_v2(effects->ssr_pixelsize, viewport_size); @@ -120,10 +118,12 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * if (use_refraction) { DRWFboTexture tex = {&txl->refract_color, DRW_TEX_RGB_11_11_10, DRW_TEX_FILTER | DRW_TEX_MIPMAP}; - DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type, (int)viewport_size[0], (int)viewport_size[1], &tex, 1); + DRW_framebuffer_init(&fbl->refract_fb, &draw_engine_eevee_type, + (int)viewport_size[0], (int)viewport_size[1], + &tex, 1); } - effects->ssr_ray_count = BKE_collection_engine_property_value_get_int(props, "ssr_ray_count"); + bool prev_trace_full = effects->reflection_trace_full; effects->reflection_trace_full = !BKE_collection_engine_property_value_get_bool(props, "ssr_halfres"); effects->ssr_use_normalization = BKE_collection_engine_property_value_get_bool(props, "ssr_normalize_weight"); effects->ssr_quality = 1.0f - BKE_collection_engine_property_value_get_float(props, "ssr_quality"); @@ -136,8 +136,9 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * effects->ssr_firefly_fac = FLT_MAX; } - /* Important, can lead to breakage otherwise. */ - CLAMP(effects->ssr_ray_count, 1, 4); + if (prev_trace_full != effects->reflection_trace_full) { + DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output); + } const int divisor = (effects->reflection_trace_full) ? 1 : 2; int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor}; @@ -147,7 +148,8 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * /* TODO create one texture layer per lobe */ if (txl->ssr_specrough_input == NULL) { DRWTextureFormat specrough_format = (high_qual_input) ? DRW_TEX_RGBA_16 : DRW_TEX_RGBA_8; - txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], specrough_format, 0, NULL); + txl->ssr_specrough_input = DRW_texture_create_2D((int)viewport_size[0], (int)viewport_size[1], + specrough_format, 0, NULL); } /* Reattach textures to the right buffer (because we are alternating between buffers) */ @@ -156,15 +158,15 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * DRW_framebuffer_texture_attach(fbl->main, txl->ssr_specrough_input, 2, 0); /* Raytracing output */ - /* TODO try integer format for hit coord to increase precision */ - DRWFboTexture tex_output[4] = { - {&stl->g_data->ssr_hit_output[0], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - {&stl->g_data->ssr_hit_output[1], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - {&stl->g_data->ssr_hit_output[2], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - {&stl->g_data->ssr_hit_output[3], DRW_TEX_RGBA_16, DRW_TEX_TEMP}, - }; + /* (AMD or Intel) For some reason DRW_TEX_TEMP with DRW_TEX_RG_16I + * creates problems when toggling ssr_halfres. Texture is not read correctly (black output). + * So using a persistent buffer instead. */ + DRWFboTexture tex_output[2] = {{&txl->ssr_hit_output, DRW_TEX_RG_16I, 0}, + {&stl->g_data->ssr_pdf_output, DRW_TEX_R_16, DRW_TEX_TEMP}}; - DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, tracing_res[0], tracing_res[1], tex_output, effects->ssr_ray_count); + DRW_framebuffer_init(&fbl->screen_tracing_fb, &draw_engine_eevee_type, + tracing_res[0], tracing_res[1], + tex_output, 2); /* Enable double buffering to be able to read previous frame color */ return EFFECT_SSR | EFFECT_NORMAL_BUFFER | EFFECT_DOUBLE_BUFFER | ((use_refraction) ? EFFECT_REFRACT : 0); @@ -172,10 +174,9 @@ int EEVEE_screen_raytrace_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data * /* Cleanup to release memory */ DRW_TEXTURE_FREE_SAFE(txl->ssr_specrough_input); + DRW_TEXTURE_FREE_SAFE(txl->ssr_hit_output); DRW_FRAMEBUFFER_FREE_SAFE(fbl->screen_tracing_fb); - for (int i = 0; i < 4; ++i) { - stl->g_data->ssr_hit_output[i] = NULL; - } + stl->g_data->ssr_pdf_output = NULL; return 0; } @@ -191,7 +192,6 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v if ((effects->enabled_effects & EFFECT_SSR) != 0) { int options = (effects->reflection_trace_full) ? SSR_FULL_TRACE : 0; - options |= (effects->ssr_ray_count - 1); struct GPUShader *trace_shader = eevee_effects_screen_raytrace_shader_get(options); struct GPUShader *resolve_shader = eevee_effects_screen_raytrace_shader_get(SSR_RESOLVE | options); @@ -246,16 +246,9 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo); DRW_shgroup_uniform_buffer(grp, "probeCubes", &sldata->probe_pool); DRW_shgroup_uniform_buffer(grp, "probePlanars", &vedata->txl->planar_pool); - DRW_shgroup_uniform_buffer(grp, "hitBuffer0", &stl->g_data->ssr_hit_output[0]); - if (effects->ssr_ray_count > 1) { - DRW_shgroup_uniform_buffer(grp, "hitBuffer1", &stl->g_data->ssr_hit_output[1]); - } - if (effects->ssr_ray_count > 2) { - DRW_shgroup_uniform_buffer(grp, "hitBuffer2", &stl->g_data->ssr_hit_output[2]); - } - if (effects->ssr_ray_count > 3) { - DRW_shgroup_uniform_buffer(grp, "hitBuffer3", &stl->g_data->ssr_hit_output[3]); - } + DRW_shgroup_uniform_buffer(grp, "planarDepth", &vedata->txl->planar_depth); + DRW_shgroup_uniform_buffer(grp, "hitBuffer", &vedata->txl->ssr_hit_output); + DRW_shgroup_uniform_buffer(grp, "pdfBuffer", &stl->g_data->ssr_pdf_output); DRW_shgroup_uniform_vec4(grp, "aoParameters[0]", &effects->ao_dist, 2); if (effects->use_ao) { @@ -301,18 +294,13 @@ void EEVEE_reflection_compute(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *v e_data.depth_src = dtxl->depth; DRW_stats_group_start("SSR"); - - for (int i = 0; i < effects->ssr_ray_count; ++i) { - DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_hit_output[i], i, 0); - } + DRW_framebuffer_texture_attach(fbl->screen_tracing_fb, stl->g_data->ssr_pdf_output, 1, 0); DRW_framebuffer_bind(fbl->screen_tracing_fb); /* Raytrace. */ DRW_draw_pass(psl->ssr_raytrace); - for (int i = 0; i < effects->ssr_ray_count; ++i) { - DRW_framebuffer_texture_detach(stl->g_data->ssr_hit_output[i]); - } + DRW_framebuffer_texture_detach(stl->g_data->ssr_pdf_output); EEVEE_downsample_buffer(vedata, fbl->downsample_fb, txl->color_double_buffer, 9); 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 2dc8dfa0d1c..ac73f9ea26b 100644 --- a/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/effect_ssr_frag.glsl @@ -13,6 +13,21 @@ uniform sampler2DArray utilTex; uniform float fireflyFactor; uniform float maxRoughness; +ivec2 encode_hit_data(vec2 hit_pos, bool has_hit, bool is_planar) +{ + ivec2 hit_data = ivec2(saturate(hit_pos) * 32767.0); /* 16bit signed int limit */ + hit_data.x *= (is_planar) ? -1 : 1; + hit_data.y *= (has_hit) ? 1 : -1; + return hit_data; +} + +vec2 decode_hit_data(vec2 hit_data, out bool has_hit, out bool is_planar) +{ + is_planar = (hit_data.x < 0); + has_hit = (hit_data.y > 0); + return vec2(abs(hit_data)) / 32767.0; /* 16bit signed int limit */ +} + #ifdef STEP_RAYTRACE uniform sampler2D normalBuffer; @@ -21,20 +36,17 @@ uniform sampler2D specroughBuffer; uniform int planar_count; uniform float noiseOffset; -layout(location = 0) out vec4 hitData0; -layout(location = 1) out vec4 hitData1; -layout(location = 2) out vec4 hitData2; -layout(location = 3) out vec4 hitData3; +layout(location = 0) out ivec2 hitData; +layout(location = 1) out float pdfData; -vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec3 rand, float ofs) +void do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, vec3 viewPosition, float a2, vec4 rand) { float pdf, NH; - float jitter = fract(rand.x + ofs); /* Importance sampling bias */ rand.x = mix(rand.x, 0.0, BRDF_BIAS); - vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */ + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ pdf = pdf_ggx_reflect(NH, a2); vec3 R = reflect(-V, H); @@ -42,43 +54,41 @@ vec4 do_planar_ssr(int index, vec3 V, vec3 N, vec3 T, vec3 B, vec3 planeNormal, /* If ray is bad (i.e. going below the plane) regenerate. */ if (dot(R, planeNormal) > 0.0) { - vec3 H = sample_ggx(rand * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ + vec3 H = sample_ggx(rand.xzw * vec3(1.0, -1.0, -1.0), a2, N, T, B, NH); /* Microfacet normal */ pdf = pdf_ggx_reflect(NH, a2); R = reflect(-V, H); R = reflect(R, planeNormal); } - pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */ - pdf *= -1.0; /* Tag as planar ray. */ + pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */ /* Since viewspace hit position can land behind the camera in this case, * we save the reflected view position (visualize it as the hit position * below the reflection plane). This way it's garanted that the hit will * be in front of the camera. That let us tag the bad rays with a negative * sign in the Z component. */ - vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, jitter, ssrQuality, a2, false); + vec3 hit_pos = raycast(index, viewPosition, R * 1e16, 1e16, rand.y, ssrQuality, a2, false); - return vec4(hit_pos, pdf); + hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), true); } -vec4 do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec3 rand, float ofs) +void do_ssr(vec3 V, vec3 N, vec3 T, vec3 B, vec3 viewPosition, float a2, vec4 rand) { float pdf, NH; - float jitter = fract(rand.x + ofs); /* Importance sampling bias */ rand.x = mix(rand.x, 0.0, BRDF_BIAS); - vec3 H = sample_ggx(rand, a2, N, T, B, NH); /* Microfacet normal */ + vec3 H = sample_ggx(rand.xzw, a2, N, T, B, NH); /* Microfacet normal */ pdf = pdf_ggx_reflect(NH, a2); vec3 R = reflect(-V, H); - pdf = min(1024e32, pdf); /* Theoretical limit of 16bit float */ + pdfData = min(1024e32, pdf); /* Theoretical limit of 16bit float */ - vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, jitter, ssrQuality, a2, true); + vec3 hit_pos = raycast(-1, viewPosition, R * 1e16, ssrThickness, rand.y, ssrQuality, a2, true); - return vec4(hit_pos, pdf); + hitData = encode_hit_data(hit_pos.xy, (hit_pos.z > 0.0), false); } void main() @@ -119,11 +129,17 @@ void main() float a2 = roughnessSquared * roughnessSquared; if (roughness > maxRoughness + 0.2) { - hitData0 = hitData1 = hitData2 = hitData3 = vec4(0.0); + hitData = ivec2(0); + pdfData = 0.0; return; } - vec3 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0).rba; + vec4 rand = texelFetch(utilTex, ivec3(halfres_texel % LUT_SIZE, 2), 0); + + /* Gives *perfect* reflection for very small roughness */ + if (roughness < 0.04) { + rand *= vec4(0.0, 1.0, 0.0, 0.0); + } vec3 worldPosition = transform_point(ViewMatrixInverse, viewPosition); vec3 wN = transform_direction(ViewMatrixInverse, N); @@ -144,31 +160,12 @@ void main() tracePosition = transform_point(ViewMatrix, tracePosition); vec3 planeNormal = transform_direction(ViewMatrix, pd.pl_normal); - hitData0 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand, 0.0); -#if (RAY_COUNT > 1) - hitData1 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 2) - hitData2 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 3) - hitData3 = do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT)); -#endif + do_planar_ssr(i, V, N, T, B, planeNormal, tracePosition, a2, rand); return; } } - /* TODO : Raytrace together if textureGather is supported. */ - hitData0 = do_ssr(V, N, T, B, viewPosition, a2, rand, 0.0); -#if (RAY_COUNT > 1) - hitData1 = do_ssr(V, N, T, B, viewPosition, a2, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 2) - hitData2 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 / float(RAY_COUNT)); -#endif -#if (RAY_COUNT > 3) - hitData3 = do_ssr(V, N, T, B, viewPosition, a2, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 / float(RAY_COUNT)); -#endif + do_ssr(V, N, T, B, viewPosition, a2, rand); } #else /* STEP_RESOLVE */ @@ -177,10 +174,8 @@ uniform sampler2D prevColorBuffer; /* previous frame */ uniform sampler2D normalBuffer; uniform sampler2D specroughBuffer; -uniform sampler2D hitBuffer0; -uniform sampler2D hitBuffer1; -uniform sampler2D hitBuffer2; -uniform sampler2D hitBuffer3; +uniform isampler2D hitBuffer; +uniform sampler2D pdfBuffer; uniform int probe_count; uniform int planar_count; @@ -189,7 +184,8 @@ uniform mat4 PastViewProjectionMatrix; out vec4 fragColor; -void fallback_cubemap(vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum) +void fallback_cubemap( + vec3 N, vec3 V, vec3 W, vec3 viewPosition, float roughness, float roughnessSquared, inout vec4 spec_accum) { /* Specular probes */ vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared); @@ -255,19 +251,31 @@ vec2 get_reprojected_reflection(vec3 hit, vec3 pos, vec3 N) } vec4 get_ssr_sample( - sampler2D hitBuffer, PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, float roughnessSquared, - float cone_tan, vec2 source_uvs, vec2 texture_size, ivec2 target_texel, + PlanarData pd, float planar_index, vec3 worldPosition, vec3 N, vec3 V, + float roughnessSquared, float cone_tan, vec2 source_uvs, vec2 texture_size, ivec2 target_texel, inout float weight_acc) { - vec4 hit_co_pdf = texelFetch(hitBuffer, target_texel, 0).rgba; - bool has_hit = (hit_co_pdf.z > 0.0); - bool is_planar = (hit_co_pdf.w < 0.0); - hit_co_pdf.z = abs(hit_co_pdf.z); - hit_co_pdf.w = abs(hit_co_pdf.w); + float hit_pdf = texelFetch(pdfBuffer, target_texel, 0).r; + ivec2 hit_data = texelFetch(hitBuffer, target_texel, 0).rg; + + bool is_planar, has_hit; + vec2 hit_co = decode_hit_data(hit_data, has_hit, is_planar); + + /* Get precise depth of the hit. */ + float hit_depth; + if (is_planar) { + hit_depth = textureLod(planarDepth, vec3(hit_co, planar_index), 0.0).r; + } + else { + hit_depth = textureLod(depthBuffer, hit_co, 0.0).r; + } + + /* Hit position in view space. */ + vec3 hit_view = get_view_space_from_depth(hit_co, hit_depth); + float homcoord = ProjectionMatrix[2][3] * hit_view.z + ProjectionMatrix[3][3]; /* Hit position in world space. */ - hit_co_pdf.xyz = get_view_space_from_depth(hit_co_pdf.xy, hit_co_pdf.z); - vec3 hit_pos = transform_point(ViewMatrixInverse, hit_co_pdf.xyz); + vec3 hit_pos = transform_point(ViewMatrixInverse, hit_view.xyz); vec2 ref_uvs; vec3 hit_vec; @@ -277,7 +285,7 @@ vec4 get_ssr_sample( vec3 trace_pos = line_plane_intersect(worldPosition, V, pd.pl_plane_eq); hit_vec = hit_pos - trace_pos; hit_vec = reflect(hit_vec, pd.pl_normal); - ref_uvs = project_point(ProjectionMatrix, hit_co_pdf.xyz).xy * 0.5 + 0.5; + ref_uvs = hit_co; } else { /* Find hit position in previous frame. */ @@ -286,7 +294,6 @@ vec4 get_ssr_sample( mask = screen_border_mask(gl_FragCoord.xy / texture_size); } mask = min(mask, screen_border_mask(ref_uvs)); - mask *= float(has_hit); float hit_dist = max(1e-8, length(hit_vec)); vec3 L = hit_vec / hit_dist; @@ -294,7 +301,6 @@ vec4 get_ssr_sample( float cone_footprint = hit_dist * cone_tan; /* Compute cone footprint in screen space. */ - float homcoord = ProjectionMatrix[2][3] * hit_co_pdf.z + ProjectionMatrix[3][3]; cone_footprint = BRDF_BIAS * 0.5 * cone_footprint * max(ProjectionMatrix[0][0], ProjectionMatrix[1][1]) / homcoord; /* Estimate a cone footprint to sample a corresponding mipmap level. */ @@ -305,7 +311,7 @@ vec4 get_ssr_sample( /* Slide 54 */ float bsdf = bsdf_ggx(N, L, V, roughnessSquared); - float weight = step(1e-8, hit_co_pdf.w) * bsdf / max(1e-8, hit_co_pdf.w); + float weight = step(1e-8, hit_pdf) * bsdf / max(1e-8, hit_pdf); weight_acc += weight; vec3 sample; @@ -320,9 +326,6 @@ vec4 get_ssr_sample( float luma = max(1e-8, brightness(sample)); sample *= 1.0 - max(0.0, luma - fireflyFactor) / luma; - /* Do not add light if ray has failed. */ - sample *= float(has_hit); - /* Protection against NaNs in the history buffer. * This could be removed if some previous pass has already * sanitized the input. */ @@ -331,7 +334,8 @@ vec4 get_ssr_sample( weight = 0.0; } - return vec4(sample, mask) * weight; + /* Do not add light if ray has failed. */ + return vec4(sample, mask) * weight * float(has_hit); } #define NUM_NEIGHBORS 4 @@ -346,7 +350,6 @@ void main() #endif vec2 texture_size = vec2(textureSize(depthBuffer, 0)); vec2 uvs = gl_FragCoord.xy / texture_size; - vec3 rand = texelFetch(utilTex, ivec3(fullres_texel % LUT_SIZE, 2), 0).rba; float depth = textureLod(depthBuffer, uvs, 0.0).r; @@ -413,24 +416,9 @@ void main() for (int i = 0; i < NUM_NEIGHBORS; i++) { ivec2 target_texel = halfres_texel + neighbors[i] * invert_neighbor; - ssr_accum += get_ssr_sample(hitBuffer0, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#if (RAY_COUNT > 1) - ssr_accum += get_ssr_sample(hitBuffer1, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#endif -#if (RAY_COUNT > 2) - ssr_accum += get_ssr_sample(hitBuffer2, pd, planar_index, worldPosition, N, V, + ssr_accum += get_ssr_sample(pd, planar_index, worldPosition, N, V, roughnessSquared, cone_tan, source_uvs, texture_size, target_texel, weight_acc); -#endif -#if (RAY_COUNT > 3) - ssr_accum += get_ssr_sample(hitBuffer3, pd, planar_index, worldPosition, N, V, - roughnessSquared, cone_tan, source_uvs, - texture_size, target_texel, weight_acc); -#endif } } 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 9ccfd127536..cac3edaee45 100644 --- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl +++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl @@ -29,7 +29,6 @@ in vec3 viewNormal; #endif uniform float maxRoughness; -uniform int rayCount; #endif /* LIT_SURFACE_UNIFORM */ @@ -315,13 +314,7 @@ void CLOSURE_NAME( if (ssrToggle && roughness < maxRoughness + 0.2) { /* Find approximated position of the 2nd refraction event. */ vec3 refr_vpos = (refractionDepth > 0.0) ? transform_point(ViewMatrix, refr_pos) : viewPosition; - - float ray_ofs = 1.0 / float(rayCount); - vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw, 0.0); - if (rayCount > 1) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs); - if (rayCount > 2) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs); - if (rayCount > 3) trans += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xwz * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs); - trans /= float(rayCount); + vec4 trans = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzw); trans.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness); accumulate_light(trans.rgb, trans.a, refr_accum); } diff --git a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl index 92287d2ecbc..2be7a6d2e73 100644 --- a/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl +++ b/source/blender/draw/engines/eevee/shaders/ssr_lib.glsl @@ -2,10 +2,10 @@ #define BTDF_BIAS 0.85 -vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec3 rand, float ofs) +vec4 screen_space_refraction(vec3 viewPosition, vec3 N, vec3 V, float ior, float roughnessSquared, vec3 rand) { float a2 = max(5e-6, roughnessSquared * roughnessSquared); - float jitter = fract(rand.x + ofs); + float jitter = rand.x; /* Importance sampling bias */ rand.x = mix(rand.x, 0.0, BTDF_BIAS); diff --git a/source/blender/makesrna/intern/rna_layer.c b/source/blender/makesrna/intern/rna_layer.c index bcf8f36d7ce..6cdd77dc7ce 100644 --- a/source/blender/makesrna/intern/rna_layer.c +++ b/source/blender/makesrna/intern/rna_layer.c @@ -387,7 +387,6 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(sss_separate_albedo) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_refraction) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_enable) RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_halfres) -RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(ssr_ray_count) RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_quality) RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_max_roughness) RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_thickness) @@ -1299,14 +1298,6 @@ static void rna_def_view_layer_engine_settings_eevee(BlenderRNA *brna) RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update"); - prop = RNA_def_property(srna, "ssr_ray_count", PROP_INT, PROP_NONE); - RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_ray_count_get", - "rna_LayerEngineSettings_Eevee_ssr_ray_count_set", NULL); - RNA_def_property_ui_text(prop, "Samples", "Number of rays to trace per pixels"); - RNA_def_property_range(prop, 1, 4); - RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE); - RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_ViewLayerEngineSettings_update"); - prop = RNA_def_property(srna, "ssr_thickness", PROP_FLOAT, PROP_DISTANCE); RNA_def_property_float_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_thickness_get", "rna_LayerEngineSettings_Eevee_ssr_thickness_set", NULL); -- cgit v1.2.3