Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Foucault <foucault.clem@gmail.com>2017-08-10 16:43:15 +0300
committerClément Foucault <foucault.clem@gmail.com>2017-08-10 16:43:48 +0300
commit6e2f17ea02be5caa9eee8a68ccd558474030b29a (patch)
tree29584459e5306ede452923a4956b17ac85eacc3d /source/blender/draw
parent896154d15de716ef360d0187cb89f44102ac31ef (diff)
Eevee: Refraction: Add "thickness" parameter.
This enables to fake a second refraction event. This is great to simulate thin planar objects such as glass panels.
Diffstat (limited to 'source/blender/draw')
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c28
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl57
2 files changed, 52 insertions, 33 deletions
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index cf27cba0b1a..517d7780719 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -353,7 +353,7 @@ static char *eevee_get_volume_defines(int options)
**/
static void add_standard_uniforms(
DRWShadingGroup *shgrp, EEVEE_SceneLayerData *sldata, EEVEE_Data *vedata,
- int *ssr_id, float *refract_thickness)
+ int *ssr_id, float *refract_depth, bool use_ssrefraction)
{
if (ssr_id == NULL) {
static int no_ssr = -1.0f;
@@ -379,13 +379,15 @@ static void add_standard_uniforms(
DRW_shgroup_uniform_buffer(shgrp, "shadowCubes", &sldata->shadow_depth_cube_pool);
DRW_shgroup_uniform_buffer(shgrp, "shadowCascades", &sldata->shadow_depth_cascade_pool);
DRW_shgroup_uniform_int(shgrp, "outputSsrId", ssr_id, 1);
- if (vedata->stl->effects->use_ao || refract_thickness) {
+ if (refract_depth != NULL) {
+ DRW_shgroup_uniform_float(shgrp, "refractionDepth", refract_depth, 1);
+ }
+ if (vedata->stl->effects->use_ao || use_ssrefraction) {
DRW_shgroup_uniform_vec4(shgrp, "viewvecs[0]", (float *)vedata->stl->g_data->viewvecs, 2);
DRW_shgroup_uniform_buffer(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
}
- if (refract_thickness) {
+ if (use_ssrefraction) {
DRW_shgroup_uniform_buffer(shgrp, "colorBuffer", &vedata->txl->refract_color);
- DRW_shgroup_uniform_float(shgrp, "refractionThickness", refract_thickness, 1);
DRW_shgroup_uniform_vec4(shgrp, "ssrParameters", &vedata->stl->effects->ssr_quality, 1);
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);
@@ -733,7 +735,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_create(
}
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false);
return shgrp;
}
@@ -763,7 +765,7 @@ static struct DRWShadingGroup *EEVEE_default_shading_group_get(
vedata->psl->default_pass[options] = DRW_pass_create("Default Lit Pass", state);
DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL);
+ add_standard_uniforms(shgrp, sldata, vedata, &ssr_id, NULL, false);
}
return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
@@ -944,10 +946,10 @@ static void material_opaque(
*shgrp = DRW_shgroup_material_create(*gpumat, use_refract ? psl->refract_pass : psl->material_pass);
if (*shgrp) {
- static int ssr_id;
- static float refract_thickness = 0.0f; /* TODO Param */
- ssr_id = (stl->effects->use_ssr) ? 0 : -1;
- add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, (use_refract) ? &refract_thickness : NULL);
+ static int no_ssr = -1;
+ static int first_ssr = 0;
+ int *ssr_id = (stl->effects->use_ssr && !use_refract) ? &first_ssr : &no_ssr;
+ add_standard_uniforms(*shgrp, sldata, vedata, ssr_id, &ma->refract_depth, use_refract);
}
else {
/* Shader failed : pink color */
@@ -1036,9 +1038,7 @@ static void material_transparent(
*shgrp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
if (*shgrp) {
static int ssr_id = -1; /* TODO transparent SSR */
- static float refract_thickness = 0.0f; /* TODO Param */
- add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id,
- (use_refract) ? &refract_thickness : NULL);
+ add_standard_uniforms(*shgrp, sldata, vedata, &ssr_id, &ma->refract_depth, use_refract);
}
else {
/* Shader failed : pink color */
@@ -1272,7 +1272,7 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata, EEVEE_SceneLayerData *sl
shgrp = DRW_shgroup_material_create(gpumat, psl->material_pass);
if (shgrp) {
- add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL);
+ add_standard_uniforms(shgrp, sldata, vedata, NULL, NULL, false);
BLI_ghash_insert(material_hash, ma, shgrp);
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 b3559e3d366..4ee2e778c21 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -7,9 +7,7 @@ uniform int planar_count;
uniform bool specToggle;
uniform bool ssrToggle;
-#ifdef USE_REFRACTION
-uniform float refractionThickness;
-#endif
+uniform float refractionDepth;
#ifndef UTIL_TEX
#define UTIL_TEX
@@ -551,7 +549,7 @@ vec3 eevee_surface_glossy_lit(vec3 N, vec3 f0, float roughness, float ao, int ss
/* ----------- Transmission ----------- */
-vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int ssr_id, out vec3 ssr_spec)
+vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior)
{
/* Zero length vectors cause issues, see: T51979. */
#if 0
@@ -581,16 +579,26 @@ vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int s
/* Accumulate light from all sources until accumulator is full. Then apply Occlusion and BRDF. */
vec4 trans_accum = vec4(0.0);
+ /* Refract the view vector using the depth heuristic.
+ * Then later Refract a second time the already refracted
+ * ray using the inverse ior. */
+ float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior;
+ vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V;
+ vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition;
+
#ifdef USE_REFRACTION
/* Screen Space Refraction */
if (ssrToggle && roughness < maxRoughness + 0.2) {
vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
+ /* 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 spec = screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand, 0.0);
- if (rayCount > 1) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
- if (rayCount > 2) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
- if (rayCount > 3) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
+ vec4 spec = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand, 0.0);
+ if (rayCount > 1) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
+ if (rayCount > 2) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
+ if (rayCount > 3) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
spec /= float(rayCount);
spec.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
accumulate_light(spec.rgb, spec.a, trans_accum);
@@ -599,7 +607,7 @@ vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int s
/* Specular probes */
/* NOTE: This bias the IOR */
- vec3 spec_dir = get_specular_refraction_dominant_dir(N, V, roughness, ior);
+ vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
/* Starts at 1 because 0 is world probe */
for (int i = 1; i < MAX_PROBE && i < probe_count && trans_accum.a < 0.999; ++i) {
@@ -608,14 +616,14 @@ vec3 eevee_surface_refraction(vec3 N, vec3 f0, float roughness, float ior, int s
float fade = probe_attenuation_cube(cd, worldPosition);
if (fade > 0.0) {
- vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughnessSquared);
+ vec3 spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
accumulate_light(spec, fade, trans_accum);
}
}
/* World Specular */
if (trans_accum.a < 0.999) {
- vec3 spec = probe_evaluate_world_spec(spec_dir, roughnessSquared);
+ vec3 spec = probe_evaluate_world_spec(refr_dir, roughnessSquared);
accumulate_light(spec, 1.0, trans_accum);
}
@@ -701,9 +709,13 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i
}
}
- /* Specular probes */
- vec3 spec_dir = get_specular_reflection_dominant_dir(N, V, roughnessSquared);
- vec3 refr_dir = get_specular_refraction_dominant_dir(N, V, roughness, ior);
+ /* Refract the view vector using the depth heuristic.
+ * Then later Refract a second time the already refracted
+ * ray using the inverse ior. */
+ float final_ior = (refractionDepth > 0.0) ? 1.0 / ior : ior;
+ vec3 refr_V = (refractionDepth > 0.0) ? -refract(-V, N, final_ior) : V;
+ vec3 refr_pos = (refractionDepth > 0.0) ? line_plane_intersect(worldPosition, refr_V, worldPosition - N * refractionDepth, N) : worldPosition;
+
vec4 trans_accum = vec4(0.0);
#ifdef USE_REFRACTION
@@ -711,17 +723,24 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i
if (ssrToggle && roughness < maxRoughness + 0.2) {
vec3 rand = texture(utilTex, vec3(gl_FragCoord.xy / LUT_SIZE, 2.0)).xzw;
+ /* 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 spec = screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand, 0.0);
- if (rayCount > 1) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
- if (rayCount > 2) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
- if (rayCount > 3) spec += screen_space_refraction(viewPosition, N, V, ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
+ vec4 spec = screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand, 0.0);
+ if (rayCount > 1) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xyz * vec3(1.0, -1.0, -1.0), 1.0 * ray_ofs);
+ if (rayCount > 2) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, 1.0, -1.0), 2.0 * ray_ofs);
+ if (rayCount > 3) spec += screen_space_refraction(refr_vpos, N, refr_V, final_ior, roughnessSquared, rand.xzy * vec3(1.0, -1.0, 1.0), 3.0 * ray_ofs);
spec /= float(rayCount);
spec.a *= smoothstep(maxRoughness + 0.2, maxRoughness, roughness);
accumulate_light(spec.rgb, spec.a, trans_accum);
}
#endif
+ /* Specular probes */
+ vec3 refr_dir = get_specular_refraction_dominant_dir(N, refr_V, roughness, final_ior);
+ vec3 spec_dir = get_specular_reflection_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 && trans_accum.a < 0.999; ++i) {
CubeData cd = probes_data[i];
@@ -733,7 +752,7 @@ vec3 eevee_surface_glass(vec3 N, vec3 transmission_col, float roughness, float i
vec3 spec = probe_evaluate_cube(float(i), cd, worldPosition, spec_dir, roughness);
accumulate_light(spec, fade, spec_accum);
- spec = probe_evaluate_cube(float(i), cd, worldPosition, refr_dir, roughnessSquared);
+ spec = probe_evaluate_cube(float(i), cd, refr_pos, refr_dir, roughnessSquared);
accumulate_light(spec, fade, trans_accum);
}
}