Cascaded shadows
This commit is contained in:
parent
402a710eb7
commit
900f2b77c7
|
@ -91,23 +91,6 @@ uniform vec3 eye;
|
|||
in vec4 wvpposition;
|
||||
out vec4 fragColor;
|
||||
|
||||
#ifndef _NoShadows
|
||||
float shadowTest(const vec3 lPos) {
|
||||
|
||||
// Out of bounds
|
||||
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return 1.0;
|
||||
|
||||
#ifdef _PCSS
|
||||
return PCSS(lPos.xy, lPos.z - shadowsBias);
|
||||
#else
|
||||
return PCF(lPos.xy, lPos.z - shadowsBias);
|
||||
#endif
|
||||
}
|
||||
float shadowTestCube(const vec3 lp, const vec3 l) {
|
||||
return PCFCube(lp, -l, shadowsBias, lightPlane);
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec2 texCoord = wvpposition.xy / wvpposition.w;
|
||||
texCoord = texCoord * 0.5 + 0.5;
|
||||
|
@ -151,13 +134,18 @@ void main() {
|
|||
// float cosAngle = max(1.0 - dotNL, 0.0);
|
||||
// vec3 noff = n * shadowsBias * cosAngle;
|
||||
if (lightShadow == 1) {
|
||||
// vec4 lampPos = LWVP * vec4(p + noff, 1.0);
|
||||
vec4 lampPos = LWVP * vec4(p, 1.0);
|
||||
if (lampPos.w > 0.0) visibility = shadowTest(lampPos.xyz / lampPos.w);
|
||||
// vec4 lPos = LWVP * vec4(p + noff, 1.0);
|
||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||
if (lPos.w > 0.0) {
|
||||
#ifdef _PCSS
|
||||
visibility = PCSS(lPos.xy, lPos.z - shadowsBias);
|
||||
#else
|
||||
visibility = shadowTest(lPos.xyz / lPos.w, shadowsBias);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if (lightShadow == 2) { // Cube
|
||||
// visibility = shadowTestCube(lp + noff, l);
|
||||
visibility = shadowTestCube(lp, l);
|
||||
visibility = PCFCube(lp, -l, shadowsBias, lightPlane);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -11,11 +11,11 @@ precision mediump float;
|
|||
#include "../std/conetrace.glsl"
|
||||
#endif
|
||||
#ifndef _NoShadows
|
||||
#ifdef _PCSS
|
||||
#include "../std/shadows_pcss.glsl"
|
||||
#else
|
||||
#include "../std/shadows.glsl"
|
||||
#endif
|
||||
// #ifdef _PCSS
|
||||
// #include "../std/shadows_pcss.glsl"
|
||||
// #else
|
||||
#include "../std/shadows_csm.glsl"
|
||||
// #endif
|
||||
#endif
|
||||
#ifdef _SSS
|
||||
#include "../std/sss.glsl"
|
||||
|
@ -38,9 +38,14 @@ uniform sampler2D gbuffer1;
|
|||
|
||||
#ifndef _NoShadows
|
||||
//!uniform sampler2D shadowMap;
|
||||
#ifdef _PCSS
|
||||
//!uniform sampler2D snoise;
|
||||
//!uniform float lampSizeUV;
|
||||
// #ifdef _PCSS
|
||||
//-!uniform sampler2D snoise;
|
||||
//-!uniform float lampSizeUV;
|
||||
// #endif
|
||||
#ifdef _CSM
|
||||
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
|
||||
#else
|
||||
uniform mat4 LWVP;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef _LampClouds
|
||||
|
@ -48,7 +53,6 @@ uniform sampler2D gbuffer1;
|
|||
uniform float time;
|
||||
#endif
|
||||
|
||||
uniform mat4 LWVP;
|
||||
uniform vec3 lightColor;
|
||||
uniform vec3 l; // lightDir
|
||||
uniform int lightShadow;
|
||||
|
@ -69,17 +73,6 @@ in vec2 texCoord;
|
|||
in vec3 viewRay;
|
||||
out vec4 fragColor;
|
||||
|
||||
#ifndef _NoShadows
|
||||
float shadowTest(const vec3 lPos) {
|
||||
|
||||
#ifdef _PCSS
|
||||
return PCSS(lPos.xy, lPos.z - shadowsBias);
|
||||
#else
|
||||
return PCF(lPos.xy, lPos.z - shadowsBias);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
vec4 g0 = texture(gbuffer0, texCoord); // Normal.xy, metallic/roughness, occlusion
|
||||
vec4 g1 = texture(gbuffer1, texCoord); // Basecolor.rgb,
|
||||
|
@ -105,11 +98,12 @@ void main() {
|
|||
float visibility = 1.0;
|
||||
#ifndef _NoShadows
|
||||
if (lightShadow == 1) {
|
||||
// float cosAngle = max(1.0 - dotNL, 0.0);
|
||||
// vec3 noff = n * shadowsBias * cosAngle;
|
||||
// vec4 lampPos = LWVP * vec4(p + noff, 1.0);
|
||||
vec4 lampPos = LWVP * vec4(p, 1.0);
|
||||
if (lampPos.w > 0.0) visibility = shadowTest(lampPos.xyz / lampPos.w);
|
||||
#ifdef _CSM
|
||||
visibility = shadowTestCascade(eye, p, shadowsBias);
|
||||
#else
|
||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||
if (lPos.w > 0.0) visibility = shadowTest(lPos.xyz / lPos.w, shadowsBias);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -63,7 +63,13 @@
|
|||
},
|
||||
{
|
||||
"name": "LWVP",
|
||||
"link": "_biasLampWorldViewProjectionMatrix"
|
||||
"link": "_biasLampWorldViewProjectionMatrix",
|
||||
"ifndef": ["_CSM"]
|
||||
},
|
||||
{
|
||||
"name": "casData",
|
||||
"link": "_cascadeData",
|
||||
"ifdef": ["_CSM"]
|
||||
},
|
||||
{
|
||||
"name": "snoise",
|
||||
|
|
|
@ -3,15 +3,25 @@
|
|||
uniform sampler2D shadowMap;
|
||||
uniform samplerCube shadowMapCube;
|
||||
|
||||
#ifdef _CSM
|
||||
uniform vec4 casData[shadowmapCascades * 4 + 4];
|
||||
#endif
|
||||
|
||||
// #ifdef _CSM
|
||||
// const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);
|
||||
// #else
|
||||
const vec2 smSize = shadowmapSize;
|
||||
// #endif
|
||||
|
||||
float shadowCompare(const vec2 uv, const float compare){
|
||||
float depth = texture(shadowMap, uv).r;
|
||||
return step(compare, depth);
|
||||
}
|
||||
|
||||
float shadowLerp(const vec2 uv, const float compare){
|
||||
const vec2 texelSize = vec2(1.0) / shadowmapSize;
|
||||
vec2 f = fract(uv * shadowmapSize + 0.5);
|
||||
vec2 centroidUV = floor(uv * shadowmapSize + 0.5) / shadowmapSize;
|
||||
const vec2 texelSize = vec2(1.0) / smSize;
|
||||
vec2 f = fract(uv * smSize + 0.5);
|
||||
vec2 centroidUV = floor(uv * smSize + 0.5) / smSize;
|
||||
float lb = shadowCompare(centroidUV, compare);
|
||||
float lt = shadowCompare(centroidUV + texelSize * vec2(0.0, 1.0), compare);
|
||||
float rb = shadowCompare(centroidUV + texelSize * vec2(1.0, 0.0), compare);
|
||||
|
@ -26,17 +36,17 @@ float PCF(const vec2 uv, const float compare) {
|
|||
// float result = 0.0;
|
||||
// for (int x = -1; x <= 1; x++){
|
||||
// for(int y = -1; y <= 1; y++){
|
||||
// vec2 off = vec2(x, y) / shadowmapSize;
|
||||
// result += shadowLerp(shadowmapSize, uv + off, compare);
|
||||
float result = shadowLerp(uv + (vec2(-1.0, -1.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(-1.0, 0.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(-1.0, 1.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(0.0, -1.0) / shadowmapSize), compare);
|
||||
// vec2 off = vec2(x, y) / smSize;
|
||||
// result += shadowLerp(smSize, uv + off, compare);
|
||||
float result = shadowLerp(uv + (vec2(-1.0, -1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(-1.0, 0.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(-1.0, 1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(0.0, -1.0) / smSize), compare);
|
||||
result += shadowLerp(uv, compare);
|
||||
result += shadowLerp(uv + (vec2(0.0, 1.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, -1.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, 0.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, 1.0) / shadowmapSize), compare);
|
||||
result += shadowLerp(uv + (vec2(0.0, 1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, -1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, 0.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, 1.0) / smSize), compare);
|
||||
// }
|
||||
// }
|
||||
return result / 9.0;
|
||||
|
@ -69,3 +79,89 @@ float PCFCube(const vec3 lp, const vec3 ml, const float bias, const vec2 lightPl
|
|||
result /= 9.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float shadowTest(const vec3 lPos, const float shadowsBias) {
|
||||
|
||||
// float cosAngle = max(1.0 - dotNL, 0.0);
|
||||
// vec3 noff = n * shadowsBias * cosAngle;
|
||||
// vec4 lPos = LWVP * vec4(p + noff, 1.0);
|
||||
|
||||
// Out of bounds
|
||||
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return 1.0;
|
||||
|
||||
return PCF(lPos.xy, lPos.z - shadowsBias);
|
||||
}
|
||||
|
||||
#ifdef _CSM
|
||||
mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
||||
const int c = shadowmapCascades;
|
||||
|
||||
// Get cascade index
|
||||
// TODO: use bounding box slice selection instead of sphere
|
||||
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
|
||||
// int ci;
|
||||
// if (d < casData[c * 4].x) ci = 0;
|
||||
// else if (d < casData[c * 4].y) ci = 1 * 4;
|
||||
// else if (d < casData[c * 4].z) ci = 2 * 4;
|
||||
// else ci = 3 * 4;
|
||||
// Splits
|
||||
vec4 comp = vec4(
|
||||
float(d > casData[c * 4].x),
|
||||
float(d > casData[c * 4].y),
|
||||
float(d > casData[c * 4].z),
|
||||
float(d > casData[c * 4].w));
|
||||
casi = int(min(dot(ci, comp), c));
|
||||
|
||||
// Get cascade mat
|
||||
casIndex = casi * 4;
|
||||
return mat4(
|
||||
casData[casIndex + 0],
|
||||
casData[casIndex + 1],
|
||||
casData[casIndex + 2],
|
||||
casData[casIndex + 3]);
|
||||
}
|
||||
|
||||
float shadowTestCascade(const vec3 eye, const vec3 p, const float shadowsBias) {
|
||||
const int c = shadowmapCascades;
|
||||
float d = distance(eye, p);
|
||||
|
||||
int casi;
|
||||
int casIndex;
|
||||
mat4 LWVP = getCascadeMat(d, casi, casIndex);
|
||||
|
||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||
float visibility = 1.0;
|
||||
if (lPos.w > 0.0) visibility = shadowTest(lPos.xyz / lPos.w, shadowsBias);
|
||||
|
||||
// Blend cascade
|
||||
// https://github.com/TheRealMJP/Shadows
|
||||
const float blendThres = 0.15;
|
||||
float nextSplit = casData[c * 4][casi];
|
||||
float splitSize = casi == 0 ? nextSplit : nextSplit - casData[c * 4][casi - 1];
|
||||
float splitDist = (nextSplit - d) / splitSize;
|
||||
if (splitDist <= blendThres && casi != c - 1) {
|
||||
int casIndex2 = casIndex + 4;
|
||||
mat4 LWVP2 = mat4(
|
||||
casData[casIndex2 + 0],
|
||||
casData[casIndex2 + 1],
|
||||
casData[casIndex2 + 2],
|
||||
casData[casIndex2 + 3]);
|
||||
|
||||
vec4 lPos2 = LWVP2 * vec4(p, 1.0);
|
||||
float visibility2 = 1.0;
|
||||
if (lPos2.w > 0.0) visibility2 = shadowTest(lPos2.xyz / lPos2.w, shadowsBias);
|
||||
|
||||
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
||||
return mix(visibility2, visibility, lerpAmt);
|
||||
}
|
||||
return visibility;
|
||||
|
||||
// Visualize cascades
|
||||
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
|
||||
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
|
||||
// if (ci == 8) albedo.rgb = vec3(0.0, 0.0, 1.0);
|
||||
// if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0);
|
||||
}
|
||||
#endif
|
||||
|
|
167
Shaders/std/shadows_csm.glsl
Executable file
167
Shaders/std/shadows_csm.glsl
Executable file
|
@ -0,0 +1,167 @@
|
|||
#include "../compiled.glsl"
|
||||
|
||||
uniform sampler2D shadowMap;
|
||||
uniform samplerCube shadowMapCube;
|
||||
|
||||
#ifdef _CSM
|
||||
uniform vec4 casData[shadowmapCascades * 4 + 4];
|
||||
#endif
|
||||
|
||||
#ifdef _CSM
|
||||
const vec2 smSize = shadowmapSize * vec2(shadowmapCascades, 1.0);
|
||||
#else
|
||||
const vec2 smSize = shadowmapSize;
|
||||
#endif
|
||||
|
||||
float shadowCompare(const vec2 uv, const float compare){
|
||||
float depth = texture(shadowMap, uv).r;
|
||||
return step(compare, depth);
|
||||
}
|
||||
|
||||
float shadowLerp(const vec2 uv, const float compare){
|
||||
const vec2 texelSize = vec2(1.0) / smSize;
|
||||
vec2 f = fract(uv * smSize + 0.5);
|
||||
vec2 centroidUV = floor(uv * smSize + 0.5) / smSize;
|
||||
float lb = shadowCompare(centroidUV, compare);
|
||||
float lt = shadowCompare(centroidUV + texelSize * vec2(0.0, 1.0), compare);
|
||||
float rb = shadowCompare(centroidUV + texelSize * vec2(1.0, 0.0), compare);
|
||||
float rt = shadowCompare(centroidUV + texelSize, compare);
|
||||
float a = mix(lb, lt, f.y);
|
||||
float b = mix(rb, rt, f.y);
|
||||
float c = mix(a, b, f.x);
|
||||
return c;
|
||||
}
|
||||
|
||||
float PCF(const vec2 uv, const float compare) {
|
||||
// float result = 0.0;
|
||||
// for (int x = -1; x <= 1; x++){
|
||||
// for(int y = -1; y <= 1; y++){
|
||||
// vec2 off = vec2(x, y) / smSize;
|
||||
// result += shadowLerp(smSize, uv + off, compare);
|
||||
float result = shadowLerp(uv + (vec2(-1.0, -1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(-1.0, 0.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(-1.0, 1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(0.0, -1.0) / smSize), compare);
|
||||
result += shadowLerp(uv, compare);
|
||||
result += shadowLerp(uv + (vec2(0.0, 1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, -1.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, 0.0) / smSize), compare);
|
||||
result += shadowLerp(uv + (vec2(1.0, 1.0) / smSize), compare);
|
||||
// }
|
||||
// }
|
||||
return result / 9.0;
|
||||
}
|
||||
|
||||
float lpToDepth(vec3 lp, const vec2 lightPlane) {
|
||||
// TODO: pass uniforms
|
||||
float a = lightPlane.y + lightPlane.x;
|
||||
float b = lightPlane.y - lightPlane.x;
|
||||
float c = 2.0 * lightPlane.y * lightPlane.x;
|
||||
lp = abs(lp);
|
||||
float zcomp = max(lp.x, max(lp.y, lp.z));
|
||||
zcomp = a / b - c / b / zcomp;
|
||||
return zcomp * 0.5 + 0.5;
|
||||
}
|
||||
|
||||
float PCFCube(const vec3 lp, const vec3 ml, const float bias, const vec2 lightPlane) {
|
||||
// return float(texture(shadowMapCube, ml).r + bias > lpToDepth(lp, lightPlane));
|
||||
float compare = lpToDepth(lp, lightPlane) - bias;
|
||||
float result = step(compare, texture(shadowMapCube, ml).r);
|
||||
const float s = shadowmapCubePcfSize; // 0.001 TODO: incorrect...
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(s, s, s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(-s, s, s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(s, -s, s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(s, s, -s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(-s, -s, s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(s, -s, -s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(-s, s, -s)).r);
|
||||
result += step(compare, texture(shadowMapCube, ml + vec3(-s, -s, -s)).r);
|
||||
result /= 9.0;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
float shadowTest(const vec3 lPos, const float shadowsBias) {
|
||||
|
||||
// float cosAngle = max(1.0 - dotNL, 0.0);
|
||||
// vec3 noff = n * shadowsBias * cosAngle;
|
||||
// vec4 lPos = LWVP * vec4(p + noff, 1.0);
|
||||
|
||||
// Out of bounds
|
||||
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return 1.0;
|
||||
|
||||
return PCF(lPos.xy, lPos.z - shadowsBias);
|
||||
}
|
||||
|
||||
#ifdef _CSM
|
||||
mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
|
||||
const int c = shadowmapCascades;
|
||||
|
||||
// Get cascade index
|
||||
// TODO: use bounding box slice selection instead of sphere
|
||||
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
|
||||
// int ci;
|
||||
// if (d < casData[c * 4].x) ci = 0;
|
||||
// else if (d < casData[c * 4].y) ci = 1 * 4;
|
||||
// else if (d < casData[c * 4].z) ci = 2 * 4;
|
||||
// else ci = 3 * 4;
|
||||
// Splits
|
||||
vec4 comp = vec4(
|
||||
float(d > casData[c * 4].x),
|
||||
float(d > casData[c * 4].y),
|
||||
float(d > casData[c * 4].z),
|
||||
float(d > casData[c * 4].w));
|
||||
casi = int(min(dot(ci, comp), c));
|
||||
|
||||
// Get cascade mat
|
||||
casIndex = casi * 4;
|
||||
return mat4(
|
||||
casData[casIndex + 0],
|
||||
casData[casIndex + 1],
|
||||
casData[casIndex + 2],
|
||||
casData[casIndex + 3]);
|
||||
}
|
||||
|
||||
float shadowTestCascade(const vec3 eye, const vec3 p, const float shadowsBias) {
|
||||
const int c = shadowmapCascades;
|
||||
float d = distance(eye, p);
|
||||
|
||||
int casi;
|
||||
int casIndex;
|
||||
mat4 LWVP = getCascadeMat(d, casi, casIndex);
|
||||
|
||||
vec4 lPos = LWVP * vec4(p, 1.0);
|
||||
float visibility = 1.0;
|
||||
if (lPos.w > 0.0) visibility = shadowTest(lPos.xyz / lPos.w, shadowsBias);
|
||||
|
||||
// Blend cascade
|
||||
// https://github.com/TheRealMJP/Shadows
|
||||
const float blendThres = 0.15;
|
||||
float nextSplit = casData[c * 4][casi];
|
||||
float splitSize = casi == 0 ? nextSplit : nextSplit - casData[c * 4][casi - 1];
|
||||
float splitDist = (nextSplit - d) / splitSize;
|
||||
if (splitDist <= blendThres && casi != c - 1) {
|
||||
int casIndex2 = casIndex + 4;
|
||||
mat4 LWVP2 = mat4(
|
||||
casData[casIndex2 + 0],
|
||||
casData[casIndex2 + 1],
|
||||
casData[casIndex2 + 2],
|
||||
casData[casIndex2 + 3]);
|
||||
|
||||
vec4 lPos2 = LWVP2 * vec4(p, 1.0);
|
||||
float visibility2 = 1.0;
|
||||
if (lPos2.w > 0.0) visibility2 = shadowTest(lPos2.xyz / lPos2.w, shadowsBias);
|
||||
|
||||
float lerpAmt = smoothstep(0.0, blendThres, splitDist);
|
||||
return mix(visibility2, visibility, lerpAmt);
|
||||
}
|
||||
return visibility;
|
||||
|
||||
// Visualize cascades
|
||||
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
|
||||
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);
|
||||
// if (ci == 8) albedo.rgb = vec3(0.0, 0.0, 1.0);
|
||||
// if (ci == 12) albedo.rgb = vec3(1.0, 1.0, 0.0);
|
||||
}
|
||||
#endif
|
|
@ -4,39 +4,17 @@ uniform vec4 skinBones[skinMaxBones * 2];
|
|||
|
||||
void getSkinningDualQuat(const ivec4 bone, vec4 weight, out vec4 A, inout vec4 B) {
|
||||
// Retrieve the real and dual part of the dual-quaternions
|
||||
mat4 matA, matB;
|
||||
matA[0][0] = skinBones[bone.x * 2].x;
|
||||
matA[0][1] = skinBones[bone.x * 2].y;
|
||||
matA[0][2] = skinBones[bone.x * 2].z;
|
||||
matA[0][3] = skinBones[bone.x * 2].w;
|
||||
matB[0][0] = skinBones[bone.x * 2 + 1].x;
|
||||
matB[0][1] = skinBones[bone.x * 2 + 1].y;
|
||||
matB[0][2] = skinBones[bone.x * 2 + 1].z;
|
||||
matB[0][3] = skinBones[bone.x * 2 + 1].w;
|
||||
matA[1][0] = skinBones[bone.y * 2].x;
|
||||
matA[1][1] = skinBones[bone.y * 2].y;
|
||||
matA[1][2] = skinBones[bone.y * 2].z;
|
||||
matA[1][3] = skinBones[bone.y * 2].w;
|
||||
matB[1][0] = skinBones[bone.y * 2 + 1].x;
|
||||
matB[1][1] = skinBones[bone.y * 2 + 1].y;
|
||||
matB[1][2] = skinBones[bone.y * 2 + 1].z;
|
||||
matB[1][3] = skinBones[bone.y * 2 + 1].w;
|
||||
matA[2][0] = skinBones[bone.z * 2].x;
|
||||
matA[2][1] = skinBones[bone.z * 2].y;
|
||||
matA[2][2] = skinBones[bone.z * 2].z;
|
||||
matA[2][3] = skinBones[bone.z * 2].w;
|
||||
matB[2][0] = skinBones[bone.z * 2 + 1].x;
|
||||
matB[2][1] = skinBones[bone.z * 2 + 1].y;
|
||||
matB[2][2] = skinBones[bone.z * 2 + 1].z;
|
||||
matB[2][3] = skinBones[bone.z * 2 + 1].w;
|
||||
matA[3][0] = skinBones[bone.w * 2].x;
|
||||
matA[3][1] = skinBones[bone.w * 2].y;
|
||||
matA[3][2] = skinBones[bone.w * 2].z;
|
||||
matA[3][3] = skinBones[bone.w * 2].w;
|
||||
matB[3][0] = skinBones[bone.w * 2 + 1].x;
|
||||
matB[3][1] = skinBones[bone.w * 2 + 1].y;
|
||||
matB[3][2] = skinBones[bone.w * 2 + 1].z;
|
||||
matB[3][3] = skinBones[bone.w * 2 + 1].w;
|
||||
ivec4 bonei = bone * 2;
|
||||
mat4 matA = mat4(
|
||||
skinBones[bonei.x],
|
||||
skinBones[bonei.y],
|
||||
skinBones[bonei.z],
|
||||
skinBones[bonei.w]);
|
||||
mat4 matB = mat4(
|
||||
skinBones[bonei.x + 1],
|
||||
skinBones[bonei.y + 1],
|
||||
skinBones[bonei.z + 1],
|
||||
skinBones[bonei.w + 1]);
|
||||
// Handles antipodality by sticking joints in the same neighbourhood
|
||||
// weight.xyz *= sign(matA[3] * mat3x4(matA)).xyz;
|
||||
weight.xyz *= sign(matA[3] * matA).xyz;
|
||||
|
|
|
@ -1,21 +1,10 @@
|
|||
uniform vec4 skinBones[skinMaxBones * 3];
|
||||
|
||||
mat4 getBoneMat(const int boneIndex) {
|
||||
vec4 v0 = vec4(skinBones[boneIndex * 3].x,
|
||||
skinBones[boneIndex * 3].y,
|
||||
skinBones[boneIndex * 3].z,
|
||||
skinBones[boneIndex * 3].w);
|
||||
vec4 v1 = vec4(skinBones[boneIndex * 3 + 1].x,
|
||||
skinBones[boneIndex * 3 + 1].y,
|
||||
skinBones[boneIndex * 3 + 1].z,
|
||||
skinBones[boneIndex * 3 + 1].w);
|
||||
vec4 v2 = vec4(skinBones[boneIndex * 3 + 2].x,
|
||||
skinBones[boneIndex * 3 + 2].y,
|
||||
skinBones[boneIndex * 3 + 2].z,
|
||||
skinBones[boneIndex * 3 + 2].w);
|
||||
return mat4(v0.x, v0.y, v0.z, v0.w,
|
||||
v1.x, v1.y, v1.z, v1.w,
|
||||
v2.x, v2.y, v2.z, v2.w,
|
||||
int bonei = boneIndex * 3;
|
||||
return mat4(skinBones[bonei],
|
||||
skinBones[bonei + 1],
|
||||
skinBones[bonei + 2],
|
||||
0.0, 0.0, 0.0, 1.0);
|
||||
}
|
||||
|
||||
|
|
|
@ -165,6 +165,9 @@ class DebugConsole extends Trait {
|
|||
}
|
||||
frameTime = Scheduler.realTime() - lastTime;
|
||||
lastTime = Scheduler.realTime();
|
||||
|
||||
// var rp = pathdata.renderTargets.get("shadowMap");
|
||||
// g.drawScaledImage(rp.image, 0, 0, 256, 256);
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
|
|
@ -2202,7 +2202,7 @@ class ArmoryExporter:
|
|||
else:
|
||||
o['shadowmap_size'] = int(rpdat.rp_shadowmap)
|
||||
if o['type'] == 'sun': # Scale bias for ortho light matrix
|
||||
o['shadows_bias'] *= 10.0
|
||||
o['shadows_bias'] *= 25.0
|
||||
if (objtype == 'POINT' or objtype == 'SPOT') and objref.shadow_soft_size > 0.1:
|
||||
o['lamp_size'] = objref.shadow_soft_size * 10 # Match to Cycles
|
||||
gapi = arm.utils.get_gapi()
|
||||
|
|
|
@ -63,8 +63,8 @@ def set_preset(self, context, preset):
|
|||
rpdat.rp_renderer = 'Forward'
|
||||
rpdat.rp_depthprepass = True
|
||||
rpdat.arm_material_model = 'Full'
|
||||
rpdat.rp_shadowmap = '2048'
|
||||
rpdat.rp_shadowmap_cascades = '3'
|
||||
rpdat.rp_shadowmap = '1024'
|
||||
rpdat.rp_shadowmap_cascades = '4'
|
||||
rpdat.rp_translucency_state = 'Auto'
|
||||
rpdat.rp_overlays_state = 'Auto'
|
||||
rpdat.rp_decals_state = 'Auto'
|
||||
|
@ -95,8 +95,8 @@ def set_preset(self, context, preset):
|
|||
elif preset == 'Deferred':
|
||||
rpdat.rp_renderer = 'Deferred'
|
||||
rpdat.arm_material_model = 'Full'
|
||||
rpdat.rp_shadowmap = '2048'
|
||||
rpdat.rp_shadowmap_cascades = '3'
|
||||
rpdat.rp_shadowmap = '1024'
|
||||
rpdat.rp_shadowmap_cascades = '4'
|
||||
rpdat.rp_translucency_state = 'Auto'
|
||||
rpdat.rp_overlays_state = 'Auto'
|
||||
rpdat.rp_decals_state = 'Auto'
|
||||
|
@ -126,8 +126,8 @@ def set_preset(self, context, preset):
|
|||
rpdat.arm_diffuse_model = 'Lambert'
|
||||
elif preset == 'Render Capture':
|
||||
rpdat.rp_renderer = 'Deferred'
|
||||
rpdat.rp_shadowmap = '8192'
|
||||
rpdat.rp_shadowmap_cascades = '3'
|
||||
rpdat.rp_shadowmap = '4096'
|
||||
rpdat.rp_shadowmap_cascades = '4'
|
||||
rpdat.rp_translucency_state = 'Auto'
|
||||
rpdat.rp_overlays_state = 'Auto'
|
||||
rpdat.rp_decals_state = 'Auto'
|
||||
|
@ -162,7 +162,7 @@ def set_preset(self, context, preset):
|
|||
elif preset == 'Deferred Plus':
|
||||
rpdat.rp_renderer = 'Deferred Plus'
|
||||
rpdat.arm_material_model = 'Full'
|
||||
rpdat.rp_shadowmap = '4096'
|
||||
rpdat.rp_shadowmap = '1024'
|
||||
rpdat.rp_shadowmap_cascades = '1'
|
||||
rpdat.rp_translucency_state = 'Auto'
|
||||
rpdat.rp_overlays_state = 'Auto'
|
||||
|
@ -290,8 +290,8 @@ def set_preset(self, context, preset):
|
|||
rpdat.arm_diffuse_model = 'Lambert'
|
||||
elif preset == 'Max':
|
||||
rpdat.rp_renderer = 'Deferred'
|
||||
rpdat.rp_shadowmap = '8192'
|
||||
rpdat.rp_shadowmap_cascades = '3'
|
||||
rpdat.rp_shadowmap = '4096'
|
||||
rpdat.rp_shadowmap_cascades = '4'
|
||||
rpdat.rp_translucency_state = 'Auto'
|
||||
rpdat.rp_overlays_state = 'Auto'
|
||||
rpdat.rp_decals_state = 'Auto'
|
||||
|
|
|
@ -78,11 +78,11 @@ def build_node_tree(world):
|
|||
wrd.world_defs += '_EnvClouds'
|
||||
|
||||
# Percentage closer soft shadows
|
||||
if rpdat.arm_pcss_state == 'On':
|
||||
wrd.world_defs += '_PCSS'
|
||||
sdk_path = arm.utils.get_sdk_path()
|
||||
assets.add(sdk_path + 'armory/Assets/noise64.png')
|
||||
assets.add_embedded_data('noise64.png')
|
||||
# if rpdat.arm_pcss_state == 'On':
|
||||
# wrd.world_defs += '_PCSS'
|
||||
# sdk_path = arm.utils.get_sdk_path()
|
||||
# assets.add(sdk_path + 'armory/Assets/noise64.png')
|
||||
# assets.add_embedded_data('noise64.png')
|
||||
|
||||
# Screen-space ray-traced shadows
|
||||
if rpdat.arm_ssrs:
|
||||
|
@ -115,16 +115,19 @@ def build_node_tree(world):
|
|||
voxelao = False
|
||||
if rpdat.rp_renderer == 'Deferred':
|
||||
assets.add_khafile_def('arm_deferred')
|
||||
# Shadows
|
||||
if rpdat.rp_shadowmap_cascades != '1' and rpdat.rp_gi == 'Off':
|
||||
wrd.world_defs += '_CSM'
|
||||
assets.add_khafile_def('arm_csm')
|
||||
if rpdat.rp_shadowmap == 'None':
|
||||
wrd.world_defs += '_NoShadows'
|
||||
assets.add_khafile_def('arm_no_shadows')
|
||||
if rpdat.rp_shadowmap_cascades != '1':
|
||||
wrd.world_defs += '_CSM'
|
||||
assets.add_khafile_def('arm_csm')
|
||||
# GI
|
||||
if rpdat.rp_gi == 'Voxel GI':
|
||||
voxelgi = True
|
||||
elif rpdat.rp_gi == 'Voxel AO':
|
||||
voxelao = True
|
||||
# SS
|
||||
if rpdat.rp_dfrs:
|
||||
wrd.world_defs += '_DFRS'
|
||||
assets.add_khafile_def('arm_sdf')
|
||||
|
|
|
@ -428,6 +428,7 @@ def make_forward_mobile(con_mesh):
|
|||
# frag.write(' visibility *= PCF(lpos.xy, lpos.z - shadowsBias);')
|
||||
frag.write(' const float texelSize = 1.0 / shadowmapSize.x;')
|
||||
frag.write(' visibility = 0.0;')
|
||||
# TODO: CSM
|
||||
frag.write(' visibility += float(texture(shadowMap, lpos.xy).r + shadowsBias > lpos.z);')
|
||||
frag.write(' visibility += float(texture(shadowMap, lpos.xy + vec2(texelSize, 0.0)).r + shadowsBias > lpos.z) * 0.5;')
|
||||
frag.write(' visibility += float(texture(shadowMap, lpos.xy + vec2(-texelSize, 0.0)).r + shadowsBias > lpos.z) * 0.25;')
|
||||
|
@ -585,10 +586,11 @@ def make_forward_base(con_mesh, parse_opacity=False):
|
|||
tese.add_uniform('int lightShadow', '_lampCastShadow')
|
||||
tese.write('if (lightShadow == 1) lampPos = LVP * vec4(wposition, 1.0);')
|
||||
else:
|
||||
vert.add_out('vec4 lampPos')
|
||||
vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix')
|
||||
vert.add_uniform('int lightShadow', '_lampCastShadow')
|
||||
vert.write('if (lightShadow == 1) lampPos = LWVP * spos;')
|
||||
if not '_CSM' in wrd.world_defs:
|
||||
vert.add_out('vec4 lampPos')
|
||||
vert.add_uniform('int lightShadow', '_lampCastShadow')
|
||||
vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix')
|
||||
vert.write('if (lightShadow == 1) lampPos = LWVP * spos;')
|
||||
|
||||
if is_pcss:
|
||||
frag.add_include('../../Shaders/std/shadows_pcss.glsl')
|
||||
|
@ -604,7 +606,15 @@ def make_forward_base(con_mesh, parse_opacity=False):
|
|||
frag.add_uniform('vec2 lightPlane', '_lampPlane')
|
||||
|
||||
frag.write('if (receiveShadow) {')
|
||||
frag.write(' if (lightShadow == 1 && lampPos.w > 0.0) {')
|
||||
frag.write(' if (lightShadow == 1) {')
|
||||
if '_CSM' in wrd.world_defs:
|
||||
frag.add_include('../../Shaders/compiled.glsl')
|
||||
frag.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True)
|
||||
frag.add_uniform('vec3 eye', '_cameraPosition')
|
||||
frag.write(' int casi;')
|
||||
frag.write(' int casindex;')
|
||||
frag.write(' mat4 LWVP = getCascadeMat(distance(eye, wposition), casi, casindex);')
|
||||
frag.write(' vec4 lampPos = LWVP * vec4(wposition, 1.0);')
|
||||
frag.write(' vec3 lpos = lampPos.xyz / lampPos.w;')
|
||||
# frag.write('float bias = clamp(shadowsBias * 1.0 * tan(acos(clamp(dotNL, 0.0, 1.0))), 0.0, 0.01);')
|
||||
if is_pcss:
|
||||
|
@ -696,4 +706,3 @@ def make_forward_base(con_mesh, parse_opacity=False):
|
|||
frag.write('vec3 indirectSpecular = traceSpecular(voxpos, n, vVec, roughness);')
|
||||
frag.write('indirectSpecular *= f0 * envBRDF.x + envBRDF.y;')
|
||||
frag.write('indirect = indirect * voxelgiEnv + vec3(indirectDiffuse.rgb * voxelgiDiff * basecol + indirectSpecular * voxelgiSpec);')
|
||||
|
||||
|
|
|
@ -166,7 +166,14 @@ def make_gi(context_id):
|
|||
|
||||
if is_shadows:
|
||||
vert.add_out('vec4 lampPosGeom')
|
||||
vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix')
|
||||
if '_CSM' in wrd.world_defs:
|
||||
vert.add_include('../../Shaders/compiled.glsl')
|
||||
vert.add_include('../../Shaders/std/shadows.glsl')
|
||||
vert.add_uniform('vec4 casData[shadowmapCascades * 4 + 4]', '_cascadeData', included=True)
|
||||
# TODO: Using second cascade
|
||||
vert.write('mat4 LWVP = mat4(casData[4 + 0], casData[4 + 1], casData[4 + 2], casData[4 + 3]);')
|
||||
else:
|
||||
vert.add_uniform('mat4 LWVP', '_biasLampWorldViewProjectionMatrix')
|
||||
vert.write('lampPosGeom = LWVP * vec4(pos, 1.0);')
|
||||
|
||||
geom.add_out('vec3 voxposition')
|
||||
|
|
|
@ -86,13 +86,13 @@ class ArmRPListItem(bpy.types.PropertyGroup):
|
|||
('4096', '4096', '4096'),
|
||||
('8192', '8192', '8192'),
|
||||
('16384', '16384', '16384'),],
|
||||
name="Shadow Map", description="Shadow map resolution", default='2048', update=update_renderpath)
|
||||
name="Shadow Map", description="Shadow map resolution", default='1024', update=update_renderpath)
|
||||
rp_shadowmap_cascades = EnumProperty(
|
||||
items=[('1', '1', '1'),
|
||||
('2', '2', '2'),
|
||||
('3', '3', '3'),
|
||||
# ('3', '3', '3'),
|
||||
('4', '4', '4')],
|
||||
name="Cascades", description="Shadow map cascades", default='3', update=udpate_shadowmap_cascades)
|
||||
name="Cascades", description="Shadow map cascades", default='4', update=udpate_shadowmap_cascades)
|
||||
rp_supersampling = EnumProperty(
|
||||
items=[('1', '1X', '1X'),
|
||||
('2', '2X', '2X'),
|
||||
|
|
|
@ -1018,7 +1018,7 @@ class ArmRenderPathPanel(bpy.types.Panel):
|
|||
layout.prop(rpdat, 'arm_rp_resolution')
|
||||
|
||||
layout.separator()
|
||||
layout.prop(rpdat, 'arm_pcss_state')
|
||||
# layout.prop(rpdat, 'arm_pcss_state')
|
||||
layout.prop(rpdat, 'arm_samples_per_pixel')
|
||||
layout.prop(rpdat, 'arm_texture_filter')
|
||||
layout.prop(rpdat, "arm_diffuse_model")
|
||||
|
|
|
@ -272,6 +272,12 @@ class Main {
|
|||
f.write("""
|
||||
public static function main() {
|
||||
iron.object.BoneAnimation.skinMaxBones = """ + str(wrd.arm_skin_max_bones) + """;
|
||||
""")
|
||||
if rpdat.rp_shadowmap_cascades != '1':
|
||||
f.write("""
|
||||
iron.object.LampObject.shadowmapCascades = """ + str(rpdat.rp_shadowmap_cascades) + """;
|
||||
""")
|
||||
f.write("""
|
||||
state = 1;
|
||||
#if (js && arm_bullet) state++; loadLibAmmo("ammo.js"); #end
|
||||
#if (js && arm_navigation) state++; loadLib("recast.js"); #end
|
||||
|
|
Loading…
Reference in a new issue