Visibility and dilate pass for soft shadows

This commit is contained in:
Lubos Lenco 2017-12-03 11:19:13 +01:00
parent d657f03cf8
commit fbeeeac2d7
13 changed files with 418 additions and 3 deletions

View file

@ -0,0 +1,50 @@
#version 450
#include "../compiled.glsl"
#include "../std/gbuffer.glsl"
uniform sampler2D tex;
uniform sampler2D gbuffer0;
uniform sampler2D dist;
uniform vec2 dirInv; // texStep
in vec2 texCoord;
out float fragColor;
const float blurWeights[10] = float[] (0.132572, 0.125472, 0.106373, 0.08078, 0.05495, 0.033482, 0.018275, 0.008934, 0.003912, 0.001535);
const float discardThreshold = 0.95;
const int penumbraScale = 1;
float doBlur(const float blurWeight, const int pos, const vec3 nor, const vec2 texCoord) {
const float posadd = pos + 0.5;
vec3 nor2 = getNor(texture(gbuffer0, texCoord + pos * dirInv).rg);
float influenceFactor = step(discardThreshold, dot(nor2, nor));
float col = texture(tex, texCoord + posadd * dirInv).r;
fragColor += col * blurWeight * influenceFactor;
float weight = blurWeight * influenceFactor;
nor2 = getNor(texture(gbuffer0, texCoord - pos * dirInv).rg);
influenceFactor = step(discardThreshold, dot(nor2, nor));
col = texture(tex, texCoord - posadd * dirInv).r;
fragColor += col * blurWeight * influenceFactor;
weight += blurWeight * influenceFactor;
return weight;
}
void main() {
vec3 nor = getNor(texture(gbuffer0, texCoord).rg);
float sm = texture(tex, texCoord).r;
fragColor = sm * blurWeights[0];
float weight = blurWeights[0];
float d = texture(dist, texCoord).r;
int numTaps = min(int(d * 10 * penumbraScale), 10 * penumbraScale);
for (int i = 1; i < numTaps; ++i) weight += doBlur(blurWeights[i - 1], i, nor, texCoord);
// scale=2
// for (int i = 1; i < numTaps; ++i) weight += doBlur(blurWeights[int(i / 2)], i, nor, texCoord);
fragColor /= weight;
}

View file

@ -0,0 +1,82 @@
{
"contexts": [
{
"name": "blur_shadow_pass_x",
"color_write_alpha": false,
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "dirInv",
"link": "_vec2xInv"
}
],
"texture_params": [],
"vertex_shader": "blur_shadow_pass.vert.glsl",
"vertex_shader_path": "../include/pass.vert.glsl",
"fragment_shader": "blur_shadow_pass.frag.glsl"
},
{
"name": "blur_shadow_pass_y",
"color_write_alpha": false,
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "dirInv",
"link": "_vec2yInv"
}
],
"texture_params": [],
"vertex_shader": "blur_shadow_pass.vert.glsl",
"vertex_shader_path": "../include/pass.vert.glsl",
"fragment_shader": "blur_shadow_pass.frag.glsl"
},
{
"name": "blur_shadow_pass_y_blend",
"color_write_alpha": false,
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"blend_source": "destination_color",
"blend_destination": "blend_zero",
"blend_operation": "add",
"links": [
{
"name": "dirInv",
"link": "_vec2yInv"
}
],
"texture_params": [],
"vertex_shader": "blur_shadow_pass.vert.glsl",
"vertex_shader_path": "../include/pass.vert.glsl",
"fragment_shader": "blur_shadow_pass.frag.glsl"
},
{
"name": "blur_shadow_pass_y_blend_add",
"color_write_alpha": false,
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"blend_source": "blend_one",
"blend_destination": "blend_one",
"blend_operation": "add",
"alpha_blend_source": "blend_one",
"alpha_blend_destination": "blend_one",
"alpha_blend_operation": "add",
"links": [
{
"name": "dirInv",
"link": "_vec2yInv"
}
],
"texture_params": [],
"vertex_shader": "blur_shadow_pass.vert.glsl",
"vertex_shader_path": "../include/pass.vert.glsl",
"fragment_shader": "blur_shadow_pass.frag.glsl"
}
]
}

View file

@ -46,6 +46,9 @@ uniform sampler2D gbuffer1;
//!uniform sampler2D shadowMap;
//!uniform samplerCube shadowMapCube;
#endif
#ifdef _SoftShadows
uniform sampler2D svisibility;
#endif
#ifdef _DFRS
//!uniform sampler3D sdftex;
#endif
@ -125,7 +128,15 @@ void main() {
float dotNL = dot(n, l);
float visibility = 1.0;
#ifndef _NoShadows
#ifdef _SoftShadows
visibility = texture(svisibility, texCoord).r;
#else
// TODO: merge..
// float cosAngle = max(1.0 - dotNL, 0.0);
// vec3 noff = n * shadowsBias * cosAngle;
@ -139,7 +150,10 @@ void main() {
else if (lightShadow == 2) { // Cube
visibility = PCFCube(lp, -l, shadowsBias, lightProj, n);
}
#endif
#endif
#ifdef _VoxelGIShadow // #else
#ifdef _VoxelGICam

View file

@ -44,6 +44,9 @@ vec2 lightPlane;
uniform mat4 LWVP;
#endif
#endif
#ifdef _SoftShadows
uniform sampler2D svisibility;
#endif
#ifdef _LampClouds
uniform sampler2D texClouds;
uniform float time;
@ -93,6 +96,13 @@ void main() {
float visibility = 1.0;
#ifndef _NoShadows
#ifdef _SoftShadows
visibility = texture(svisibility, texCoord).r;
#else
if (lightShadow == 1) {
#ifdef _CSM
visibility = shadowTestCascade(eye, p, shadowsBias, shadowmapSize * vec2(shadowmapCascades, 1.0));
@ -101,6 +111,7 @@ void main() {
if (lPos.w > 0.0) visibility = shadowTest(lPos.xyz / lPos.w, shadowsBias, shadowmapSize);
#endif
}
#endif
#endif
#ifdef _VoxelGIShadow // #else

View file

@ -0,0 +1,19 @@
#version 450
#include "../compiled.glsl"
#include "../std/gbuffer.glsl"
uniform sampler2D shadowMap;
in vec2 texCoord;
out float fragColor;
uniform vec2 step;
const int penumbraScale = 1;
void main() {
fragColor = 1.0;
const vec2 smStep = 1.0 / shadowmapSize;
for (int i = -20 * penumbraScale; i < 20 * penumbraScale; i++) fragColor = min(fragColor, texture(shadowMap, texCoord.xy + step * smStep * i).r);
}

View file

@ -0,0 +1,36 @@
{
"contexts": [
{
"name": "dilate_pass_x",
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "step",
"link": "_vec2x"
}
],
"texture_params": [],
"vertex_shader": "dilate_pass.vert.glsl",
"vertex_shader_path": "../include/pass.vert.glsl",
"fragment_shader": "dilate_pass.frag.glsl"
},
{
"name": "dilate_pass_y",
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "step",
"link": "_vec2y"
}
],
"texture_params": [],
"vertex_shader": "dilate_pass.vert.glsl",
"vertex_shader_path": "../include/pass.vert.glsl",
"fragment_shader": "dilate_pass.frag.glsl"
}
]
}

View file

@ -99,11 +99,15 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
// Get cascade mat
casIndex = casi * 4;
return mat4(
casData[casIndex + 0],
casData[casIndex + 1],
casData[casIndex + 2],
casData[casIndex + 3]);
// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
// ..
}
float shadowTestCascade(const vec3 eye, const vec3 p, const float shadowsBias, const vec2 smSize) {

View file

@ -0,0 +1,52 @@
#version 450
#include "../compiled.glsl"
#include "../std/gbuffer.glsl"
#include "../std/math.glsl"
uniform sampler2D shadowMap;
uniform sampler2D dilate;
// uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
// uniform sampler2D gbuffer1;
uniform vec2 cameraProj;
uniform float shadowsBias;
uniform vec3 eye;
uniform vec3 eyeLook;
uniform mat4 LWVP;
// uniform int lightShadow;
in vec2 texCoord;
in vec3 viewRay;
out float fragColor[2];
void main() {
vec4 g0 = texture(gbuffer0, texCoord);
// #ifdef _InvY // D3D
// float depth = texture(gbufferD, texCoord).r * 2.0 - 1.0;
// #else
float depth = (1.0 - g0.a) * 2.0 - 1.0;
// #endif
vec3 p = getPos(eye, eyeLook, viewRay, depth, cameraProj);
vec4 lampPos = LWVP * vec4(p, 1.0);
vec3 lPos = lampPos.xyz / lampPos.w;
// Visibility
// if (lightShadow == 1) {
float sm = texture(shadowMap, lPos.xy).r;
fragColor[0] = float(sm + shadowsBias > lPos.z);
// }
// else if (lightShadow == 2) { // Cube
// visibility = PCFCube(lp, -l, shadowsBias, lightProj, n);
// }
// Distance
float d = texture(dilate, lPos.xy).r;
fragColor[1] = max((lPos.z - d), 0.0);
fragColor[1] *= 200;
// Mask non-occluded pixels
// fragColor.b = mask;
}

View file

@ -0,0 +1,43 @@
{
"contexts": [
{
"name": "visibility_pass",
"depth_write": false,
"compare_mode": "always",
"cull_mode": "none",
"links": [
{
"name": "eye",
"link": "_cameraPosition"
},
{
"name": "eyeLook",
"link": "_cameraLook"
},
{
"name": "invVP",
"link": "_inverseViewProjectionMatrix"
},
{
"name": "cameraProj",
"link": "_cameraPlaneProj"
},
{
"name": "shadowsBias",
"link": "_lampShadowsBias"
},
{
"name": "LWVP",
"link": "_biasLampWorldViewProjectionMatrix"
},
{
"name": "lightType",
"link": "_lampType",
"ifdef": ["_Disabled"]
}
],
"vertex_shader": "visibility_pass.vert.glsl",
"fragment_shader": "visibility_pass.frag.glsl"
}
]
}

View file

@ -0,0 +1,26 @@
#version 450
uniform mat4 invVP;
uniform vec3 eye;
in vec2 pos;
out vec2 texCoord;
out vec3 viewRay;
void main() {
// Scale vertex attribute to [0-1] range
const vec2 madd = vec2(0.5, 0.5);
texCoord = pos.xy * madd + madd;
#ifdef _InvY
texCoord.y = 1.0 - texCoord.y;
#endif
gl_Position = vec4(pos.xy, 0.0, 1.0);
// NDC (at the back of cube)
vec4 v = vec4(pos.x, pos.y, 1.0, 1.0);
v = vec4(invVP * v);
v.xyz /= v.w;
viewRay = v.xyz - eye;
}

View file

@ -482,6 +482,40 @@ class RenderPathCreator {
#end
}
#end
#if rp_soft_shadows
{
path.loadShader("dilate_pass/dilate_pass/dilate_pass_x");
path.loadShader("dilate_pass/dilate_pass/dilate_pass_y");
path.loadShader("visibility_pass/visibility_pass/visibility_pass");
path.loadShader("blur_shadow_pass/blur_shadow_pass/blur_shadow_pass_x");
path.loadShader("blur_shadow_pass/blur_shadow_pass/blur_shadow_pass_y");
{
var t = new RenderTargetRaw();
t.name = "visa";
t.width = 0;
t.height = 0;
t.format = 'R16';
path.createRenderTarget(t);
}
{
var t = new RenderTargetRaw();
t.name = "visb";
t.width = 0;
t.height = 0;
t.format = 'R16';
path.createRenderTarget(t);
}
{
var t = new RenderTargetRaw();
t.name = "dist";
t.width = 0;
t.height = 0;
t.format = 'R16';
path.createRenderTarget(t);
}
}
#end
}
static function commands() {
@ -626,13 +660,46 @@ class RenderPathCreator {
{
if (path.lampCastShadow()) {
var faces = l.data.raw.shadowmap_cube ? 6 : 1;
for (i in 0...faces) {
if (faces > 1) path.currentFace = i;
for (j in 0...faces) {
if (faces > 1) path.currentFace = j;
path.setTarget("shadowMap");
path.clearTarget(null, 1.0);
path.drawMeshes("shadowmap");
}
path.currentFace = -1;
// One lamp at a time for now, precompute all lamps for tiled
#if rp_soft_shadows
path.setTarget("visa"); // Merge using min blend
path.bindTarget("shadowMap", "shadowMap");
path.drawShader("dilate_pass/dilate_pass/dilate_pass_x");
path.setTarget("visb");
path.bindTarget("visa", "shadowMap");
path.drawShader("dilate_pass/dilate_pass/dilate_pass_y");
path.setTarget("visa", ["dist"]);
//if (i == 0) path.clearTarget(0x00000000);
path.bindTarget("visb", "dilate");
path.bindTarget("shadowMap", "shadowMap");
//path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("visibility_pass/visibility_pass/visibility_pass");
path.setTarget("visb");
path.bindTarget("visa", "tex");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("dist", "dist");
path.drawShader("blur_shadow_pass/blur_shadow_pass/blur_shadow_pass_x");
path.setTarget("visa");
path.bindTarget("visb", "tex");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("dist", "dist");
path.drawShader("blur_shadow_pass/blur_shadow_pass/blur_shadow_pass_y");
#end
}
}
#end
@ -645,7 +712,11 @@ class RenderPathCreator {
#if rp_shadowmap
{
if (path.lampCastShadow()) {
#if rp_soft_shadows
path.bindTarget("visa", "svisibility");
#else
path.bindTarget("shadowMap", "shadowMap");
#end
}
}
#end

View file

@ -189,3 +189,10 @@ def build():
if rpdat.rp_dynres:
assets.add_khafile_def('rp_dynres')
if rpdat.arm_soft_shadows == 'On':
assets.add_shader2('dilate_pass', 'dilate_pass')
assets.add_shader2('visibility_pass', 'visibility_pass')
assets.add_shader2('blur_shadow_pass', 'blur_shadow_pass')
assets.add_khafile_def('rp_soft_shadows')
wrd.world_defs += '_SoftShadows'

View file

@ -419,7 +419,7 @@ class ArmRPListItem(bpy.types.PropertyGroup):
items=[('On', 'On', 'On'),
('Off', 'Off', 'Off'),
('Auto', 'Auto', 'Auto')],
name="Soft Shadows", description="Percentage Closer Soft Shadows", default='Off', update=assets.invalidate_shader_cache)
name="Soft Shadows", description="Soft shadows with variable penumbra (spot and non-cascaded sun lamp supported)", default='Off', update=assets.invalidate_shader_cache)
arm_ssrs = bpy.props.BoolProperty(name="SSRS", description="Screen-space ray-traced shadows", default=False, update=assets.invalidate_shader_cache)
arm_texture_filter = EnumProperty(
items=[('Anisotropic', 'Anisotropic', 'Anisotropic'),