soft shadows done

This commit is contained in:
2023-02-18 19:12:16 +03:00
parent eb5f50fc9d
commit 91bc31e7db
6 changed files with 157 additions and 25 deletions

View File

@@ -18,13 +18,15 @@ in vec3 view_dir, world_dir;
uniform vec2 dt, shadow_size;
uniform float z_near;
uniform sampler2D tex_coeffs[2];
uniform sampler2D tex_coeffs[2], tex_noise;
uniform sampler2D tex_0, tex_1, tex_2, tex_3, tex_4, tex_sh;
//uniform sampler2DShadow tex_shadow[16];
uniform sampler2DArrayShadow tex_shadows_cone;
uniform sampler2DArray tex_depths_cone;
uniform samplerCubeArrayShadow tex_shadows_omni;
uniform samplerCubeArray tex_depths_omni;
uniform samplerCube tex_env;
uniform int lights_start, lights_count, soft_shadows_samples = 16;
uniform int lights_start, lights_count, soft_shadows_samples = 16, noise_size = 64;
uniform bool soft_shadows_enabled = false;
uniform vec4 fog_color = vec4(0.5, 0.5, 0.5, 1);
@@ -36,6 +38,7 @@ const vec3 luma = vec3(0.299, 0.587, 0.114);
const float _min_rough = 1.e-8, max_lod = 8;
const float PI = 3.1416;
ivec2 tc;
vec4 pos, lpos, shp;
vec3 li, si, ldir, halfV, bn, bn2, lwdir;
vec3 normal, vds, vds2;
@@ -87,13 +90,55 @@ float getShadowOmni(in vec4 uvwz, in int layer) {
#endif
uint hash(uint x) {
x += (x << 10u);
x ^= (x >> 6u);
x += (x << 3u);
x ^= (x >> 11u);
x += (x << 15u);
return x;
}
uint hash( uvec2 v ) { return hash( v.x ^ hash(v.y) ); }
uint hash( uvec3 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ); }
uint hash( uvec4 v ) { return hash( v.x ^ hash(v.y) ^ hash(v.z) ^ hash(v.w) ); }
float floatConstruct( uint m ) {
const uint ieeeMantissa = 0x007FFFFFu; // binary32 mantissa bitmask
const uint ieeeOne = 0x3F800000u; // 1.0 in IEEE binary32
m &= ieeeMantissa; // Keep only mantissa bits (fractional part)
m |= ieeeOne; // Add fractional part to 1.0
float f = uintBitsToFloat( m ); // Range [1:2]
return f - 1.0; // Range [0:1]
}
float random( float x ) { return floatConstruct(hash(floatBitsToUint(x))); }
float random( vec2 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec3 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( vec4 v ) { return floatConstruct(hash(floatBitsToUint(v))); }
float random( int x ) { return floatConstruct(hash(x)); }
float random( ivec2 v ) { return floatConstruct(hash(v)); }
float random( ivec3 v ) { return floatConstruct(hash(v)); }
float random( ivec4 v ) { return floatConstruct(hash(v)); }
uvec2 noise_hash;
void noise2init(vec2 v) {
noise_hash = uvec2(hash(uint(v.x + 1)), hash(uint(v.y - 1)));
}
vec2 noise2() {
noise2init(vec2(noise_hash));
//return vec2(floatConstruct(noise_hash.x), floatConstruct(noise_hash.y)) * 2 - vec2(1.);
float r = floatConstruct(noise_hash.x);
float a = floatConstruct(noise_hash.y) * 2 * PI;
return r * vec2(cos(a), sin(a));
}
float rand(vec2 co) {
float a = 12.9898;
float b = 78.233;
float c = 43758.5453;
float dt= dot(co.xy ,vec2(a,b));
float sn= mod(dt,3.14);
return fract(sin(sn) * c) - 0.5;
float d = dot(co.xy, vec2(a, b));
float e = sin(mod(d, 3.14)) * c;
return fract(e) - 0.5;
}
vec4 qgl_lightTexture(int index, vec2 coord, vec4 tex_shift) {
@@ -121,7 +166,8 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
spot *= scos * step(qgl_light_parameter[index].angles.w, scos);
spot *= smoothstep(qgl_light_parameter[index].angles.w, qgl_light_parameter[index].angles.y, scos);
vec4 shp = mapScreenToShadow(index, vec3(0));
vec4 light_map_pix = qgl_lightTexture(index, shp.xy / shp.w, vec4(0));
shp.xy /= shp.w;
vec4 light_map_pix = qgl_lightTexture(index, shp.xy, vec4(0));
light_color *= light_map_pix.rgb;
spot *= light_map_pix.a;
#endif
@@ -131,37 +177,76 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
int layer = index - lights_start;
float shadow = 0.;
//float bias = abs(tan(PI/2.*(1 - abs(dot(normal, ldir)))) + 1) * z_near * 1;
float bias = (1. + 1. / abs(dot(normal, ldir))) * z_near * 5;
float bias = (1. + 1. / abs(dot(normal, ldir))) * z_near * 2;
//bias = bias * bias + z_near;
if (soft_shadows_enabled) {
float ds = (ldist / 2.) / qgl_light_parameter[index].size;
#ifdef SPOT
float depth = 1;
const int gm_size = 3;
for (int i = -gm_size; i <= gm_size; ++i) {
for (int j = -gm_size; j <= gm_size; ++j) {
depth = min(depth, textureOffset(tex_depths_cone, vec3(shp.xy, layer), ivec2(i, j)).r);
}
}
depth = 1 / (1 - depth) - 1 + z_near;
float dz = max(0, shp.z - depth);
float ds = qgl_light_parameter[index].size * dz / (ldist - dz);
//qgl_FragColor.rgb = vec3(0);
#else
float depth = 1;
const int gm_size = 3;
for (int i = -gm_size; i <= gm_size; ++i) {
for (int j = -gm_size; j <= gm_size; ++j) {
for (int k = -gm_size; k <= gm_size; ++k) {
depth = min(depth, texture(tex_depths_omni, vec4(odir + vec3(i, j, k) / vec3(shadow_size.x), layer)).r);
}
}
}
depth = 1 / (1 - depth) - 1 + z_near;
float dz = max(0, ldist - depth);
float ds = qgl_light_parameter[index].size * dz / (ldist - dz);
//qgl_FragColor.rgb = vec3(dz/5);
//float ds = (ldist / 2.) / qgl_light_parameter[index].size;
#endif
vds = ds * bn.xyz;
vds2 = ds * bn2.xyz;
vec2 so;
ivec2 sotc = tc;
noise2init(vec2(hash(ivec2(tc.x * 2 + 1, tc.y)), hash(ivec2(tc.x, (tc.y * 2 + 1)))));
for (int i = 1; i <= soft_shadows_samples; ++i) {
so = noise2();
#ifdef SPOT
so = vec2(rand(vec2(shp.x + i, shp.y)), rand(vec2(shp.x + i + 1, shp.y)));
//vec4 nc = texelFetch(tex_noise, sotc % noise_size, 0);
//sotc += ivec2(nc.ba * 256) % noise_size;
//so = (nc.rg - vec2(0.5));
//so = vec2(rand(vec2(shp.x + i, shp.y)), rand(vec2(shp.x + i + 1, shp.y)));
vec4 shp = mapScreenToShadow(index, vds * so.x + vds2 * so.y);
shp.xy /= shp.w;
shp.z -= bias;
shadow += getShadowCone(shp.xyz, layer);
#else
so = vec2(rand(vec2(odir.x + i, odir.y)), rand(vec2(odir.x + i + 1, odir.y)));
//so = vec2(rand(vec2(odir.x + i, odir.y)), rand(vec2(odir.x + i + 1, odir.y)))*1.25;
vec3 old = lpos.xyz - ((pos.xyz + vec3(vds * so.x + vds2 * so.y)) * lpos.w);
odir = -(view_mat * old);
shadow += getShadowOmni(vec4(odir, length(old) - bias), layer);
#endif
}
spot *= shadow / (soft_shadows_samples + 0);
spot *= min(1, 2. * shadow / soft_shadows_samples);
//spot *= shadow / soft_shadows_samples;
//spot *= shadow / soft_shadows_samples + 1;
} else {
#ifdef SPOT
shp.xy /= shp.w;
shp.xy;
shp.z -= bias;
spot *= getShadowCone(shp.xyz, layer);
#else
@@ -194,7 +279,7 @@ void calcLight(in int index, in vec3 n, in vec3 v) {
void main(void) {
ivec2 tc = ivec2(gl_FragCoord.xy);
tc = ivec2(gl_FragCoord.xy);
vec4 v1 = texelFetch(tex_1, tc, 0);
float z = v1.w;
if (z == 1.) {
@@ -218,8 +303,9 @@ void main(void) {
float reflectivity = v2.b;
float NdotV = dot(normal, v);
float roughness3 = roughness*roughness*roughness;
bn = normalize(cross(normal, view_dir));
bn = normalize(cross(normal, vec3(1,0,0)) + cross(normal, vec3(0,1,0)));
bn2 = normalize(cross(normal, bn));
bn = cross(normal, bn2);
rough_diff = max(roughness, _min_rough);
rough_spec = max(roughness3, _min_rough);
float shlick = clamp(metalness + (1 - metalness) * pow(1 - NdotV, 5), 0, 1);
@@ -254,18 +340,23 @@ void main(void) {
}
qgl_FragColor = vec4(res_col, alpha);
//qgl_FragColor.rgb = vec3(qgl_light_parameter[0].size);
//qgl_FragColor.rgb = vec3(bn.z);
#ifdef SPOT
vec4 shp = mapScreenToShadow(0, vec3(0));
//shp.xy /= shp.w;
shp.xy /= shp.w;
float depth = texture(tex_depths_cone, vec3(shp.xy, 0)).r;
depth = 1 / (1 - depth) - 1 + z_near;
float dz = max(0, shp.z - depth);
//shp.z -= bias;
//for (int xi = -2; xi <= 2; ++xi) {
// for (int yi = -2; yi <= 2; ++yi) {
//qgl_FragColor.rgb = vec3(step(shp.z, texture(tex_shadows_cone, vec3(shp.xy, 0)).r));
//qgl_FragColor.r = texture(tex_shadows_cone, vec3(0)).r;
//qgl_FragColor.gb = vec2(1);
//qgl_FragColor.rgb = vec3(shp.z / shp.w);//vec4(res_col, alpha);
//float _d = texture(tex_depths_cone, vec3(shp.xy, 0)).r;
//_d = 1 / (1 - _d) - 1 + z_near;
//qgl_FragColor.rgb = vec3(texelFetch(tex_noise, tc % noise_size, 0).b);//vec4(res_col, alpha);
//shp.z += 0.095;
//qgl_FragColor.rgb = vec3(texture(tex_sh, shp.xy).rgb);