soft shadows done
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "qglview.h"
|
||||
|
||||
#include <QPainter>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
|
||||
QString readCharsUntilNull(QDataStream & s) {
|
||||
@@ -387,3 +388,21 @@ QVector3D vectorFromString(const QString & str) {
|
||||
ret.setZ(f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
QImage generateNoise(QSize sz) {
|
||||
QImage im(sz, QImage::Format_ARGB32);
|
||||
QRandomGenerator rg[2] = {1, 2};
|
||||
uint pcnt = im.sizeInBytes() / sizeof(QRgb);
|
||||
QRgb * data = (QRgb *)im.bits();
|
||||
for (uint i = 0; i < pcnt; ++i) {
|
||||
double r = rg[0].generateDouble();
|
||||
double a = rg[0].generateDouble() * M_2PI;
|
||||
double x = r * cos(a) / 2. + 0.5, y = r * sin(a) / 2. + 0.5;
|
||||
data[i] = qRgba(qRound(x * 256),
|
||||
qRound(y * 256),
|
||||
(rg[1].generate() % sz.width()) % 256,
|
||||
(rg[1].generate() % sz.height()) % 256); // argb GLSL
|
||||
}
|
||||
return im;
|
||||
}
|
||||
|
||||
@@ -494,6 +494,7 @@ inline QVector3D directionFromAngles(const QVector3D & a) {
|
||||
inline float frac(const float & x, const float & b) {
|
||||
return x - int(x / b) * b;
|
||||
}
|
||||
QImage generateNoise(QSize sz);
|
||||
|
||||
|
||||
#endif // GLTYPES_H
|
||||
|
||||
@@ -205,6 +205,7 @@ void Renderer::initShaders() {
|
||||
prog->setUniformValue(QString("tex_%1").arg(i).toLatin1().constData(), i);
|
||||
prog->setUniformValue("tex_coeffs[0]", (int)Renderer::dbrBuffersCount);
|
||||
prog->setUniformValue("tex_env", (int)Renderer::dbrBuffersCount + 1);
|
||||
prog->setUniformValue("tex_noise", (int)Renderer::dbrBuffersCount + 2);
|
||||
setUniformMaps(prog);
|
||||
prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone);
|
||||
}
|
||||
@@ -309,7 +310,7 @@ void Renderer::renderObjects(Scene & scene, RenderPass pass) {
|
||||
void Renderer::renderLight(int first_wr_buff, bool clear_only) {
|
||||
QOpenGLShaderProgram * prog = 0;
|
||||
Camera * cam = view->camera();
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
view->glActiveTexture(GL_TEXTURE0 + Renderer::dbrBuffersCount + i);
|
||||
view->glBindTexture(GL_TEXTURE_2D, tex_coeff[i]);
|
||||
}
|
||||
@@ -343,12 +344,20 @@ void Renderer::renderLight(int first_wr_buff, bool clear_only) {
|
||||
prog->setUniformValue("fog_density", view->fogDensity());
|
||||
prog->setUniformValue("view_mat", cam->viewMatrix().inverted().toGenericMatrix<3, 3>());
|
||||
prog->setUniformValue("shadow_size", view->shadow_map_size);
|
||||
prog->setUniformValue("noise_size", noise_size);
|
||||
prog->setUniformValue("tex_shadows_cone", (int)tarShadowsCone);
|
||||
prog->setUniformValue("tex_shadows_omni", (int)tarShadowsOmni);
|
||||
prog->setUniformValue("tex_depths_cone", (int)tarShadowsCone);
|
||||
prog->setUniformValue("tex_depths_omni", (int)tarShadowsOmni);
|
||||
prog->setUniformValue("soft_shadows_enabled", view->soft_shadows);
|
||||
prog->setUniformValue("soft_shadows_samples", view->soft_shadows_samples);
|
||||
GLenum filter = view->softShadows() ? GL_NEAREST : GL_LINEAR;
|
||||
shadow_maps_cone.bind(view, tarShadowsCone);
|
||||
view->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, filter);
|
||||
view->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, filter);
|
||||
shadow_maps_omni.bind(view, tarShadowsOmni);
|
||||
view->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, filter);
|
||||
view->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, filter);
|
||||
renderQuad(prog, quad, cam);
|
||||
}
|
||||
}
|
||||
@@ -364,8 +373,6 @@ void Renderer::renderConeShadows() {
|
||||
textures_maps.bind(f, tarMaps);
|
||||
auto cone_ll = cur_lights.value(Light::Cone);
|
||||
if (shadow_maps_cone.resize(f, view->shadow_map_size, cone_ll.size())) {
|
||||
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
f->glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
@@ -400,8 +407,6 @@ void Renderer::renderOmniShadows() {
|
||||
textures_maps.bind(f, tarMaps);
|
||||
auto omni_ll = cur_lights.value(Light::Omni);
|
||||
if (shadow_maps_omni.resize(f, view->shadow_map_size, omni_ll.size())) {
|
||||
f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
// f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
// f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
// f->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
|
||||
@@ -550,7 +555,6 @@ void Renderer::renderScene() {
|
||||
setUniformCamera(prog, cam);
|
||||
textures_empty.bind(f, tarEmpty);
|
||||
textures_maps.bind(f, tarMaps);
|
||||
shadow_maps_cone.bind(f, tarShadowsCone);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, view->renderMode());
|
||||
renderObjects(scene, rpSolid);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
@@ -42,7 +42,7 @@ RendererBase::RendererBase(QGLView * view_)
|
||||
textures_manager = new TextureManager(view);
|
||||
maps_size = QSize(1024, 1024);
|
||||
maps_hash = 0;
|
||||
tex_coeff[0] = tex_coeff[1] = 0;
|
||||
tex_coeff[0] = tex_coeff[1] = tex_coeff[2] = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -400,6 +400,7 @@ void RendererBase::initCoeffTextures() {
|
||||
}
|
||||
}
|
||||
createCoeffTexture(tex_coeff[0], data.constData(), size, 2);
|
||||
createNoiseTexture(tex_coeff[2]);
|
||||
}
|
||||
|
||||
|
||||
@@ -428,3 +429,17 @@ void RendererBase::createCoeffTexture(GLuint & id, const void * data, int size,
|
||||
}
|
||||
f->glTexImage2D(GL_TEXTURE_2D, 0, iformat, size, size, 0, format, GL_FLOAT, data);
|
||||
}
|
||||
|
||||
|
||||
void RendererBase::createNoiseTexture(GLuint & id) {
|
||||
QOpenGLExtraFunctions * f = view;
|
||||
deleteGLTexture(f, id);
|
||||
f->glGenTextures(1, &id);
|
||||
f->glBindTexture(GL_TEXTURE_2D, id);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
f->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
QImage im = generateNoise(QSize(noise_size, noise_size));
|
||||
f->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, im.width(), im.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, im.bits());
|
||||
}
|
||||
|
||||
@@ -50,6 +50,7 @@ protected:
|
||||
void renderQuad(QOpenGLShaderProgram * prog, Mesh * mesh, Camera * cam = 0, bool uniforms = true);
|
||||
void initCoeffTextures();
|
||||
void createCoeffTexture(GLuint & id, const void * data, int size, int channels = 1);
|
||||
void createNoiseTexture(GLuint & id);
|
||||
|
||||
QGLView * view;
|
||||
TextureManager * textures_manager;
|
||||
@@ -63,9 +64,10 @@ protected:
|
||||
CubeMapArray shadow_maps_omni;
|
||||
QSize maps_size;
|
||||
uint maps_hash;
|
||||
GLuint tex_coeff[2];
|
||||
GLuint tex_coeff[3];
|
||||
QMap<int, int> lights_start;
|
||||
QList<Light *> current_lights;
|
||||
int noise_size = 256;
|
||||
};
|
||||
|
||||
#endif // RENDERER_BASE_H
|
||||
|
||||
Reference in New Issue
Block a user