Eevee: SSR: Add stride and thickness parameters.
Also polished the raytracing algorithm.
This commit is contained in:
@@ -726,6 +726,9 @@ class RENDER_PT_eevee_shading(RenderButtonsPanel, Panel):
|
||||
|
||||
col = layout.column()
|
||||
col.prop(props, "ssr_enable")
|
||||
col.prop(props, "ssr_stride")
|
||||
col.prop(props, "ssr_thickness")
|
||||
col.prop(props, "ssr_border_fade")
|
||||
|
||||
|
||||
classes = (
|
||||
|
||||
@@ -268,6 +268,8 @@ class RENDERLAYER_PT_eevee_shading(RenderLayerButtonsPanel, Panel):
|
||||
|
||||
col = layout.column()
|
||||
col.template_override_property(layer_props, scene_props, "ssr_enable")
|
||||
col.template_override_property(layer_props, scene_props, "ssr_stride")
|
||||
col.template_override_property(layer_props, scene_props, "ssr_thickness")
|
||||
|
||||
|
||||
classes = (
|
||||
|
||||
@@ -549,6 +549,8 @@ void EEVEE_effects_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
|
||||
effects->enabled_effects |= EFFECT_DOUBLE_BUFFER;
|
||||
|
||||
effects->reflection_trace_full = true;
|
||||
effects->ssr_stride = (float)BKE_collection_engine_property_value_get_int(props, "ssr_stride");
|
||||
effects->ssr_thickness = BKE_collection_engine_property_value_get_float(props, "ssr_thickness");
|
||||
|
||||
const int divisor = (effects->reflection_trace_full) ? 1 : 2;
|
||||
int tracing_res[2] = {(int)viewport_size[0] / divisor, (int)viewport_size[1] / divisor};
|
||||
@@ -723,6 +725,7 @@ void EEVEE_effects_cache_init(EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata)
|
||||
DRW_shgroup_uniform_buffer(grp, "specroughBuffer", &txl->ssr_specrough_input);
|
||||
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
|
||||
DRW_shgroup_uniform_vec4(grp, "viewvecs[0]", (float *)stl->g_data->viewvecs, 2);
|
||||
DRW_shgroup_uniform_vec2(grp, "ssrParameters", &effects->ssr_stride, 1);
|
||||
DRW_shgroup_uniform_mat4(grp, "PixelProjMatrix", (float *)&e_data.pixelprojmat);
|
||||
DRW_shgroup_call_add(grp, quad, NULL);
|
||||
|
||||
|
||||
@@ -212,6 +212,8 @@ static void EEVEE_scene_layer_settings_create(RenderEngine *UNUSED(engine), IDPr
|
||||
props->subtype == IDP_GROUP_SUB_ENGINE_RENDER);
|
||||
|
||||
BKE_collection_engine_property_add_bool(props, "ssr_enable", false);
|
||||
BKE_collection_engine_property_add_int(props, "ssr_stride", 16);
|
||||
BKE_collection_engine_property_add_float(props, "ssr_thickness", 0.5f);
|
||||
|
||||
BKE_collection_engine_property_add_bool(props, "volumetric_enable", false);
|
||||
BKE_collection_engine_property_add_float(props, "volumetric_start", 0.1f);
|
||||
|
||||
@@ -321,6 +321,8 @@ typedef struct EEVEE_EffectsInfo {
|
||||
/* SSR */
|
||||
bool use_ssr;
|
||||
bool reflection_trace_full;
|
||||
float ssr_stride;
|
||||
float ssr_thickness;
|
||||
|
||||
/* Ambient Occlusion */
|
||||
bool use_ao, use_bent_normals;
|
||||
|
||||
@@ -4,8 +4,13 @@
|
||||
* http://casual-effects.blogspot.fr/2014/08/screen-space-ray-tracing.html */
|
||||
|
||||
#define MAX_STEP 256
|
||||
#define MAX_REFINE_STEP 32 /* Should be max allowed stride */
|
||||
|
||||
uniform mat4 PixelProjMatrix; /* View > NDC > Texel : maps view coords to texel coord */
|
||||
uniform vec2 ssrParameters;
|
||||
|
||||
#define ssrStride ssrParameters.x
|
||||
#define ssrThickness ssrParameters.y
|
||||
|
||||
void swapIfBigger(inout float a, inout float b)
|
||||
{
|
||||
@@ -48,9 +53,6 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir)
|
||||
|
||||
/* [Optional clipping to frustum sides here] */
|
||||
|
||||
/* Initialize to off screen */
|
||||
vec2 hitpixel = vec2(-1.0, -1.0);
|
||||
|
||||
/* If the line is degenerate, make it cover at least one pixel
|
||||
* to not have to handle zero-pixel extent as a special case later */
|
||||
P1 += vec2((distance_squared(P0, P1) < 0.0001) ? 0.01 : 0.0);
|
||||
@@ -80,82 +82,83 @@ float raycast(sampler2D depth_texture, vec3 ray_origin, vec3 ray_dir)
|
||||
vec4 pqk = vec4(P0, Q0.z, k0);
|
||||
|
||||
/* Scale derivatives by the desired pixel stride */
|
||||
vec4 dPQK = vec4(dP, dQ.z, dk) * 8.0;
|
||||
vec4 dPQK = vec4(dP, dQ.z, dk) * ssrStride;
|
||||
|
||||
/* We track the ray depth at +/- 1/2 pixel to treat pixels as clip-space solid
|
||||
* voxels. Because the depth at -1/2 for a given pixel will be the same as at
|
||||
* +1/2 for the previous iteration, we actually only have to compute one value
|
||||
* per iteration. */
|
||||
float prev_zmax = ray_origin.z;
|
||||
float zmax, zmin;
|
||||
float zmax;
|
||||
|
||||
/* P1.x is never modified after this point, so pre-scale it by
|
||||
* the step direction for a signed comparison */
|
||||
float end = P1.x * step_sign;
|
||||
|
||||
bool hit = false;
|
||||
float hitstep, raw_depth, view_depth;
|
||||
for (hitstep = 0.0; hitstep < MAX_STEP && !hit; hitstep++) {
|
||||
float raw_depth;
|
||||
for (float hitstep = 0.0; hitstep < MAX_STEP && !hit; hitstep++) {
|
||||
/* Ray finished & no hit*/
|
||||
if ((pqk.x * step_sign) > end) break;
|
||||
|
||||
/* step through current cell */
|
||||
pqk += dPQK;
|
||||
|
||||
hitpixel = permute ? pqk.yx : pqk.xy;
|
||||
zmin = prev_zmax;
|
||||
ivec2 hitpixel = ivec2(permute ? pqk.yx : pqk.xy);
|
||||
raw_depth = texelFetch(depth_texture, ivec2(hitpixel), 0).r;
|
||||
|
||||
float zmin = prev_zmax;
|
||||
zmax = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w);
|
||||
prev_zmax = zmax;
|
||||
swapIfBigger(zmin, zmax);
|
||||
swapIfBigger(zmin, zmax); /* ??? why don't we need this ??? */
|
||||
|
||||
raw_depth = texelFetch(depth_texture, ivec2(hitpixel), 0).r;
|
||||
view_depth = get_view_z_from_depth(raw_depth);
|
||||
float vmax = get_view_z_from_depth(raw_depth);
|
||||
float vmin = vmax - ssrThickness;
|
||||
|
||||
/* TODO user threshold */
|
||||
const float threshold = 0.5; /* In view space */
|
||||
/* Check if we are somewhere near the surface. */
|
||||
if ((zmax < view_depth) && (zmax > view_depth - threshold)) {
|
||||
/* Note: we consider hitting the screen borders (raw_depth == 0.0)
|
||||
* as valid to check for occluder in the refine pass */
|
||||
if (!((zmin > vmax) || (zmax < vmin)) || (raw_depth == 0.0)) {
|
||||
/* Below surface, cannot trace further */
|
||||
hit = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hit) {
|
||||
/* Rewind back a step */
|
||||
/* Rewind back a step. */
|
||||
pqk -= dPQK;
|
||||
|
||||
/* And do a finer trace over this segment */
|
||||
dPQK /= 16.0;
|
||||
/* And do a finer trace over this segment. */
|
||||
dPQK /= ssrStride;
|
||||
|
||||
for (float refinestep = 0.0; refinestep < 16.0; refinestep++) {
|
||||
prev_zmax = (dPQK.z * -0.5 + pqk.z) / (dPQK.w * -0.5 + pqk.w);
|
||||
|
||||
for (float refinestep = 0.0; refinestep < ssrStride * 2.0 && refinestep < MAX_REFINE_STEP * 2.0; refinestep++) {
|
||||
/* step through current cell */
|
||||
pqk += dPQK;
|
||||
|
||||
hitpixel = permute ? pqk.yx : pqk.xy;
|
||||
zmin = prev_zmax;
|
||||
ivec2 hitpixel = ivec2(permute ? pqk.yx : pqk.xy);
|
||||
raw_depth = texelFetch(depth_texture, hitpixel, 0).r;
|
||||
|
||||
float zmin = prev_zmax;
|
||||
zmax = (dPQK.z * 0.5 + pqk.z) / (dPQK.w * 0.5 + pqk.w);
|
||||
prev_zmax = zmax;
|
||||
swapIfBigger(zmin, zmax);
|
||||
|
||||
raw_depth = texelFetch(depth_texture, ivec2(hitpixel), 0).r;
|
||||
view_depth = get_view_z_from_depth(raw_depth);
|
||||
float vmax = get_view_z_from_depth(raw_depth);
|
||||
float vmin = vmax - ssrThickness;
|
||||
|
||||
/* TODO user threshold */
|
||||
const float threshold = 0.5; /* In view space */
|
||||
/* Check if we are somewhere near the surface. */
|
||||
if ((zmax < view_depth) && (zmax > view_depth - threshold)) {
|
||||
if (!((zmin > vmax) || (zmax < vmin)) || (raw_depth == 0.0)) {
|
||||
/* Below surface, cannot trace further */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check failure cases (out of screen, hit background) */
|
||||
if (hit && (raw_depth != 1.0) && (raw_depth != 0.0)) {
|
||||
/* Return length */
|
||||
return (zmax - ray_origin.z) / ray_dir.z;
|
||||
}
|
||||
/* Background case. */
|
||||
hit = hit && (raw_depth != 1.0);
|
||||
|
||||
/* Failure, return no hit */
|
||||
return -1.0;
|
||||
/* Return length */
|
||||
return (hit) ? (zmax - ray_origin.z) / ray_dir.z : -1.0;
|
||||
}
|
||||
|
||||
@@ -2623,6 +2623,8 @@ RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_shadows)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(volumetric_shadow_samples)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(volumetric_colored_transmittance)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_BOOL(ssr_enable)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_INT(ssr_stride)
|
||||
RNA_LAYER_ENGINE_EEVEE_GET_SET_FLOAT(ssr_thickness)
|
||||
|
||||
/* object engine */
|
||||
RNA_LAYER_MODE_OBJECT_GET_SET_BOOL(show_wire)
|
||||
@@ -6185,6 +6187,23 @@ static void rna_def_scene_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_SceneLayerEngineSettings_update");
|
||||
|
||||
prop = RNA_def_property(srna, "ssr_stride", PROP_INT, PROP_PIXEL);
|
||||
RNA_def_property_int_funcs(prop, "rna_LayerEngineSettings_Eevee_ssr_stride_get",
|
||||
"rna_LayerEngineSettings_Eevee_ssr_stride_set", NULL);
|
||||
RNA_def_property_ui_text(prop, "Stride", "Step size between two raymarching samples");
|
||||
RNA_def_property_range(prop, 1, 32);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_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);
|
||||
RNA_def_property_ui_text(prop, "Thickness", "Pixel thickness used to detect intersection");
|
||||
RNA_def_property_range(prop, 1e-6f, FLT_MAX);
|
||||
RNA_def_property_ui_range(prop, 0.001f, FLT_MAX, 5, 3);
|
||||
RNA_def_property_flag(prop, PROP_CONTEXT_UPDATE);
|
||||
RNA_def_property_update(prop, NC_SCENE | ND_LAYER_CONTENT, "rna_SceneLayerEngineSettings_update");
|
||||
|
||||
/* Volumetrics */
|
||||
prop = RNA_def_property(srna, "volumetric_enable", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_funcs(prop, "rna_LayerEngineSettings_Eevee_volumetric_enable_get",
|
||||
|
||||
Reference in New Issue
Block a user