Cleanup: EEVEE: Split effect_ssr.glsl

This split is to make code easier to manage and rename the files to
`effect_reflection_*` to avoid confusion.

Also this cleans up a bit of the branching mess in the trace shader.
This commit is contained in:
Clément Foucault 2021-03-12 18:54:41 +01:00
parent 6a7f6f2867
commit 40d579b69f
5 changed files with 196 additions and 196 deletions

View File

@ -234,6 +234,9 @@ data_to_c_simple(engines/eevee/shaders/effect_dof_resolve_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_dof_scatter_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_dof_scatter_vert.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_dof_setup_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_reflection_lib.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_reflection_resolve_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_reflection_trace_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_downsample_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_downsample_cube_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_gtao_frag.glsl SRC)
@ -242,7 +245,6 @@ data_to_c_simple(engines/eevee/shaders/effect_velocity_tile_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_minmaxz_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_mist_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_motion_blur_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_ssr_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_subsurface_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_translucency_frag.glsl SRC)
data_to_c_simple(engines/eevee/shaders/effect_temporal_aa.glsl SRC)

View File

@ -217,7 +217,9 @@ extern char datatoc_effect_gtao_frag_glsl[];
extern char datatoc_effect_minmaxz_frag_glsl[];
extern char datatoc_effect_mist_frag_glsl[];
extern char datatoc_effect_motion_blur_frag_glsl[];
extern char datatoc_effect_ssr_frag_glsl[];
extern char datatoc_effect_reflection_lib_glsl[];
extern char datatoc_effect_reflection_resolve_frag_glsl[];
extern char datatoc_effect_reflection_trace_frag_glsl[];
extern char datatoc_effect_subsurface_frag_glsl[];
extern char datatoc_effect_temporal_aa_glsl[];
extern char datatoc_effect_translucency_frag_glsl[];
@ -304,6 +306,7 @@ static void eevee_shader_library_ensure(void)
DRW_SHADER_LIB_ADD(e_data.lib, volumetric_lib);
DRW_SHADER_LIB_ADD(e_data.lib, ssr_lib);
DRW_SHADER_LIB_ADD(e_data.lib, effect_dof_lib);
DRW_SHADER_LIB_ADD(e_data.lib, effect_reflection_lib);
DRW_SHADER_LIB_ADD(e_data.lib, closure_type_lib);
DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_lib);
DRW_SHADER_LIB_ADD(e_data.lib, closure_eval_diffuse_lib);
@ -767,8 +770,14 @@ struct GPUShader *EEVEE_shaders_effect_screen_raytrace_sh_get(EEVEE_SSRShaderOpt
char *ssr_define_str = BLI_dynstr_get_cstring(ds_defines);
BLI_dynstr_free(ds_defines);
e_data.ssr_sh[options] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_ssr_frag_glsl, lib, ssr_define_str);
if (options & SSR_RESOLVE) {
e_data.ssr_sh[options] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_reflection_resolve_frag_glsl, lib, ssr_define_str);
}
else {
e_data.ssr_sh[options] = DRW_shader_create_fullscreen_with_shaderlib(
datatoc_effect_reflection_trace_frag_glsl, lib, ssr_define_str);
}
MEM_freeN(ssr_define_str);
}

View File

@ -0,0 +1,48 @@
#pragma BLENDER_REQUIRE(common_view_lib.glsl)
/* Based on:
* "Stochastic Screen Space Reflections"
* by Tomasz Stachowiak.
* https://www.ea.com/frostbite/news/stochastic-screen-space-reflections
* and
* "Stochastic all the things: raytracing in hybrid real-time rendering"
* by Tomasz Stachowiak.
* https://media.contentapi.ea.com/content/dam/ea/seed/presentations/dd18-seed-raytracing-in-hybrid-real-time-rendering.pdf
*/
uniform ivec2 halfresOffset;
struct HitData {
/** Hit direction scaled by intersection time. */
vec3 hit_dir;
/** Screen space [0..1] depth of the reflection hit position, or -1.0 for planar reflections. */
float hit_depth;
/** Inverse probability of ray spawning in this direction. */
float ray_pdf_inv;
/** True if ray has hit valid geometry. */
bool is_hit;
/** True if ray was generated from a planar reflection probe. */
bool is_planar;
};
void encode_hit_data(HitData data, vec3 hit_sP, vec3 vP, out vec4 hit_data, out float hit_depth)
{
vec3 hit_vP = get_view_space_from_depth(hit_sP.xy, hit_sP.z);
hit_data.xyz = hit_vP - vP;
hit_depth = data.is_planar ? -1.0 : hit_sP.z;
/* Record 1.0 / pdf to reduce the computation in the resolve phase. */
/* Encode hit validity in sign. */
hit_data.w = data.ray_pdf_inv * ((data.is_hit) ? 1.0 : -1.0);
}
HitData decode_hit_data(vec4 hit_data, float hit_depth)
{
HitData data;
data.hit_dir.xyz = hit_data.xyz;
data.hit_depth = hit_depth;
data.is_planar = (hit_depth == -1.0);
data.ray_pdf_inv = abs(hit_data.w);
data.is_hit = (hit_data.w > 0.0);
return data;
}

View File

@ -1,14 +1,12 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(closure_eval_glossy_lib.glsl)
#pragma BLENDER_REQUIRE(closure_eval_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_common_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(surface_lib.glsl)
#pragma BLENDER_REQUIRE(effect_reflection_lib.glsl)
/* Based on:
* "Stochastic Screen Space Reflections"
@ -20,193 +18,7 @@
* https://media.contentapi.ea.com/content/dam/ea/seed/presentations/dd18-seed-raytracing-in-hybrid-real-time-rendering.pdf
*/
uniform ivec2 halfresOffset;
struct HitData {
/** Hit direction scaled by intersection time. */
vec3 hit_dir;
/** Screen space [0..1] depth of the reflection hit position, or -1.0 for planar reflections. */
float hit_depth;
/** Inverse probability of ray spawning in this direction. */
float ray_pdf_inv;
/** True if ray has hit valid geometry. */
bool is_hit;
/** True if ray was generated from a planar reflection probe. */
bool is_planar;
};
void encode_hit_data(HitData data, vec3 hit_sP, vec3 vP, out vec4 hit_data, out float hit_depth)
{
vec3 hit_vP = get_view_space_from_depth(hit_sP.xy, hit_sP.z);
hit_data.xyz = hit_vP - vP;
hit_depth = data.is_planar ? -1.0 : hit_sP.z;
/* Record 1.0 / pdf to reduce the computation in the resolve phase. */
/* Encode hit validity in sign. */
hit_data.w = data.ray_pdf_inv * ((data.is_hit) ? 1.0 : -1.0);
}
HitData decode_hit_data(vec4 hit_data, float hit_depth)
{
HitData data;
data.hit_dir.xyz = hit_data.xyz;
data.hit_depth = hit_depth;
data.is_planar = (hit_depth == -1.0);
data.ray_pdf_inv = abs(hit_data.w);
data.is_hit = (hit_data.w > 0.0);
return data;
}
#ifdef STEP_RAYTRACE
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
layout(location = 0) out vec4 hitData;
layout(location = 1) out float hitDepth;
void do_planar_ssr(int index,
vec3 vV,
vec3 vN,
vec3 vT,
vec3 vB,
vec3 viewPlaneNormal,
vec3 vP,
float alpha,
vec4 rand)
{
float pdf;
/* Microfacet normal */
vec3 vH = sample_ggx(rand.xzw, alpha, vV, vN, vT, vB, pdf);
vec3 vR = reflect(-vV, vH);
vR = reflect(vR, viewPlaneNormal);
Ray ray;
ray.origin = vP;
ray.direction = vR * 1e16;
RayTraceParameters params;
params.jitter = rand.y;
params.trace_quality = ssrQuality;
params.roughness = alpha * alpha;
vec3 hit_sP;
HitData data;
data.is_planar = true;
data.ray_pdf_inv = safe_rcp(pdf);
data.is_hit = raytrace_planar(ray, params, index, hit_sP);
encode_hit_data(data, hit_sP, ray.origin, hitData, hitDepth);
}
void do_ssr(vec3 vV, vec3 vN, vec3 vT, vec3 vB, vec3 vP, float alpha, vec4 rand)
{
float pdf;
/* Microfacet normal */
vec3 vH = sample_ggx(rand.xzw, alpha, vV, vN, vT, vB, pdf);
vec3 vR = reflect(-vV, vH);
Ray ray;
ray.origin = vP + vN * 1e-4;
ray.direction = vR * 1e16;
RayTraceParameters params;
params.thickness = ssrThickness;
params.jitter = rand.y;
params.trace_quality = ssrQuality;
params.roughness = alpha * alpha;
vec3 hit_sP;
HitData data;
data.is_planar = false;
data.ray_pdf_inv = safe_rcp(pdf);
data.is_hit = raytrace(ray, params, true, hit_sP);
encode_hit_data(data, hit_sP, ray.origin, hitData, hitDepth);
}
in vec4 uvcoordsvar;
void main()
{
vec2 uvs = uvcoordsvar.xy;
float depth = textureLod(maxzBuffer, uvs * hizUvScale.xy, 0.0).r;
HitData data;
data.is_planar = false;
data.ray_pdf_inv = 0.0;
data.is_hit = false;
data.hit_dir = vec3(0.0, 0.0, 0.0);
/* Default: not hits. */
encode_hit_data(data, data.hit_dir, data.hit_dir, hitData, hitDepth);
/* Early out */
/* We can't do discard because we don't clear the render target. */
if (depth == 1.0) {
return;
}
/* Using view space */
vec3 vP = get_view_space_from_depth(uvs, depth);
vec3 P = transform_point(ViewMatrixInverse, vP);
vec3 vV = viewCameraVec(vP);
vec3 V = cameraVec(P);
vec3 vN = normal_decode(texture(normalBuffer, uvs, 0).rg, vV);
vec3 N = transform_direction(ViewMatrixInverse, vN);
/* Retrieve pixel data */
vec4 speccol_roughness = texture(specroughBuffer, uvs, 0).rgba;
/* Early out */
if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) {
return;
}
float roughness = speccol_roughness.a;
float alpha = max(1e-3, roughness * roughness);
/* Early out */
if (roughness > ssrMaxRoughness + 0.2) {
return;
}
vec4 rand = texelfetch_noise_tex(vec2(gl_FragCoord.xy));
/* Gives *perfect* reflection for very small roughness */
if (roughness < 0.04) {
rand.xzw *= 0.0;
}
/* Importance sampling bias */
rand.x = mix(rand.x, 0.0, ssrBrdfBias);
vec3 vT, vB;
make_orthonormal_basis(vN, vT, vB); /* Generate tangent space */
/* Planar Reflections */
for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; i++) {
PlanarData pd = planars_data[i];
float fade = probe_attenuation_planar(pd, P);
fade *= probe_attenuation_planar_normal_roughness(pd, N, 0.0);
if (fade > 0.5) {
/* Find view vector / reflection plane intersection. */
/* TODO optimize, use view space for all. */
vec3 tracePosition = line_plane_intersect(P, V, pd.pl_plane_eq);
tracePosition = transform_point(ViewMatrix, tracePosition);
vec3 viewPlaneNormal = transform_direction(ViewMatrix, pd.pl_normal);
do_planar_ssr(i, vV, vN, vT, vB, viewPlaneNormal, tracePosition, alpha, rand);
return;
}
}
do_ssr(vV, vN, vT, vB, vP, alpha, rand);
}
#else /* STEP_RESOLVE */
uniform sampler2D colorBuffer; /* previous frame */
uniform sampler2D colorBuffer;
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
uniform sampler2D hitBuffer;
@ -398,5 +210,3 @@ void main()
fragColor = vec4(out_Glossy_0.radiance * brdf, 1.0);
}
#endif

View File

@ -0,0 +1,131 @@
#pragma BLENDER_REQUIRE(common_math_lib.glsl)
#pragma BLENDER_REQUIRE(common_math_geom_lib.glsl)
#pragma BLENDER_REQUIRE(common_utiltex_lib.glsl)
#pragma BLENDER_REQUIRE(raytrace_lib.glsl)
#pragma BLENDER_REQUIRE(lightprobe_lib.glsl)
#pragma BLENDER_REQUIRE(bsdf_sampling_lib.glsl)
#pragma BLENDER_REQUIRE(effect_reflection_lib.glsl)
/* Based on:
* "Stochastic Screen Space Reflections"
* by Tomasz Stachowiak.
* https://www.ea.com/frostbite/news/stochastic-screen-space-reflections
* and
* "Stochastic all the things: raytracing in hybrid real-time rendering"
* by Tomasz Stachowiak.
* https://media.contentapi.ea.com/content/dam/ea/seed/presentations/dd18-seed-raytracing-in-hybrid-real-time-rendering.pdf
*/
uniform sampler2D normalBuffer;
uniform sampler2D specroughBuffer;
in vec4 uvcoordsvar;
layout(location = 0) out vec4 hitData;
layout(location = 1) out float hitDepth;
void main()
{
vec2 uvs = uvcoordsvar.xy;
float depth = textureLod(maxzBuffer, uvs * hizUvScale.xy, 0.0).r;
HitData data;
data.is_planar = false;
data.ray_pdf_inv = 0.0;
data.is_hit = false;
data.hit_dir = vec3(0.0, 0.0, 0.0);
/* Default: not hits. */
encode_hit_data(data, data.hit_dir, data.hit_dir, hitData, hitDepth);
/* Early out */
/* We can't do discard because we don't clear the render target. */
if (depth == 1.0) {
return;
}
/* Using view space */
vec3 vP = get_view_space_from_depth(uvs, depth);
vec3 P = transform_point(ViewMatrixInverse, vP);
vec3 vV = viewCameraVec(vP);
vec3 V = cameraVec(P);
vec3 vN = normal_decode(texture(normalBuffer, uvs, 0).rg, vV);
vec3 N = transform_direction(ViewMatrixInverse, vN);
/* Retrieve pixel data */
vec4 speccol_roughness = texture(specroughBuffer, uvs, 0).rgba;
/* Early out */
if (dot(speccol_roughness.rgb, vec3(1.0)) == 0.0) {
return;
}
float roughness = speccol_roughness.a;
float alpha = max(1e-3, roughness * roughness);
/* Early out */
if (roughness > ssrMaxRoughness + 0.2) {
return;
}
/* Planar Reflections */
int planar_id = -1;
for (int i = 0; i < MAX_PLANAR && i < prbNumPlanar; i++) {
PlanarData pd = planars_data[i];
float fade = probe_attenuation_planar(pd, P);
fade *= probe_attenuation_planar_normal_roughness(pd, N, 0.0);
if (fade > 0.5) {
/* Find view vector / reflection plane intersection. */
/* TODO optimize, use view space for all. */
vec3 P_plane = line_plane_intersect(P, V, pd.pl_plane_eq);
vP = transform_point(ViewMatrix, P_plane);
planar_id = i;
data.is_planar = true;
break;
}
}
vec4 rand = texelfetch_noise_tex(vec2(gl_FragCoord.xy));
/* Gives *perfect* reflection for very small roughness */
if (roughness < 0.04) {
rand.xzw *= 0.0;
}
/* Importance sampling bias */
rand.x = mix(rand.x, 0.0, ssrBrdfBias);
vec3 vT, vB;
make_orthonormal_basis(vN, vT, vB); /* Generate tangent space */
float pdf;
vec3 vH = sample_ggx(rand.xzw, alpha, vV, vN, vT, vB, pdf);
vec3 vR = reflect(-vV, vH);
if (data.is_planar) {
vec3 view_plane_normal = transform_direction(ViewMatrix, planars_data[planar_id].pl_normal);
/* For planar reflections, we trace inside the reflected view. */
vR = reflect(vR, view_plane_normal);
}
Ray ray;
ray.origin = vP;
ray.direction = vR * 1e16;
RayTraceParameters params;
params.jitter = rand.y;
params.trace_quality = ssrQuality;
params.roughness = alpha * alpha;
vec3 hit_sP;
if (data.is_planar) {
data.is_hit = raytrace_planar(ray, params, planar_id, hit_sP);
}
else {
data.is_hit = raytrace(ray, params, true, hit_sP);
}
data.ray_pdf_inv = safe_rcp(pdf);
encode_hit_data(data, hit_sP, ray.origin, hitData, hitDepth);
}