Compare commits

..

15 Commits

Author SHA1 Message Date
365c624d73 Tilesheets To Objects 2026-09-09 02:33:00 -07:00
384a8a7ee8 Voxel Shadow - No Temporal 2026-09-09 00:35:34 -07:00
4e2b59a1d6 Merge pull request 'main' (#138) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#138
2026-09-09 05:42:48 +00:00
6d07e70b11 Hashlink Compile - Curve/Console 2026-09-08 22:34:51 -07:00
42fdff4757 TriVoxel: Burley + (EON, Gotanda, Chan) Diffuse Models 2026-09-08 22:02:48 -07:00
d44fd9993a Get Transform Update 2026-09-07 11:33:15 -07:00
3fd1b395fb Merge branch 'main' of https://dev.leenkx.com/Onek8/LNXSDK 2026-09-07 11:13:11 -07:00
40bca62f96 Get Transform Node Replacement Update 2026-09-07 11:12:57 -07:00
e5082835c4 Merge pull request 'Reflections / Refractions' (#137) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#137
2026-09-06 08:39:04 +00:00
bc700a6374 Reflections / Refractions 2026-09-06 01:37:13 -07:00
1e500993d9 Merge pull request 'main' (#136) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#136
2026-09-04 21:02:18 +00:00
d842744aeb 9 Tap PCF 2026-09-04 13:59:07 -07:00
ada18b4648 Merge branch 'main' of https://dev.leenkx.com/Onek8/LNXSDK 2026-09-04 13:51:26 -07:00
5004efe046 Transparent Shadow Fix 2026-09-04 13:50:03 -07:00
1015e0df34 Merge pull request 'main' (#135) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#135
2026-09-04 17:49:34 +00:00
23 changed files with 391 additions and 127 deletions

View File

@ -420,7 +420,7 @@ void main() {
#endif
#endif
envl.rgb *= albedo;
envl.rgb *= diffuseIBL(albedo, roughness, f0, dotNV);
#ifdef _Brdf
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
@ -581,15 +581,15 @@ void main() {
vec3 sdirect;
if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) {
vec3 sbitangent = normalize(cross(n, wTangent));
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
sdirect = diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) +
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
wTangent, sbitangent, n, sunDir, v, sdotNL, dotNV) * occspec.y;
} else {
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
sdirect = diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
}
#else
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
vec3 sdirect = diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
#endif

View File

@ -227,7 +227,7 @@ void main() {
#endif
#endif
envl.rgb *= albedo;
envl.rgb *= diffuseIBL(albedo, roughness, f0, dotNV);
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y) * 1.5 * occspec.y;
@ -342,15 +342,15 @@ void main() {
vec3 sdirect;
if (abs(matp0.x) > 0.001 && dot(wTangent, wTangent) > 0.001) {
vec3 sbitangent = normalize(cross(n, wTangent));
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
sdirect = diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) +
anisotropicBRDF(f0, roughness, matp0.x, matp0.y,
wTangent, sbitangent, n, sunDir, v, sdotNL, dotNV) * occspec.y;
} else {
sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
sdirect = diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
}
#else
vec3 sdirect = lambertDiffuseBRDF(albedo, sdotNL) +
vec3 sdirect = diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) +
specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * occspec.y;
#endif

View File

@ -88,6 +88,199 @@ vec3 lambertDiffuseBRDF(const vec3 albedo, const float nl) {
return albedo * INV_PI * nl;
}
#ifdef _BurleyDiffuse
vec3 burleyDiffuseBRDF(const vec3 albedo, const float roughness,
const float dotNL, const float dotNV, const float dotVH) {
float nl = clamp(dotNL, 0.0, 1.0);
float nv = clamp(dotNV, 0.0, 1.0);
float energyBias = mix(0.0, 0.5, roughness);
float energyFactor = mix(1.0, 1.0 / 1.51, roughness);
float fd90 = energyBias + 2.0 * roughness * dotVH * dotVH;
float lightScatter = 1.0 + (fd90 - 1.0) * pow(1.0 - nl, 5.0);
float viewScatter = 1.0 + (fd90 - 1.0) * pow(1.0 - nv, 5.0);
return albedo * INV_PI * lightScatter * viewScatter * energyFactor * nl;
}
#endif
#ifdef _EONDiffuse
const float constant1_FON = 0.5 - 2.0 / (3.0 * PI);
const float constant2_FON = 2.0 / 3.0 - 28.0 / (15.0 * PI);
float E_FON_approx(float mu, float r) {
float mucomp = 1.0 - mu;
const float g1 = 0.0571085289;
const float g2 = 0.491881867;
const float g3 = -0.332181442;
const float g4 = 0.0714429953;
float GoverPi = mucomp * (g1 + mucomp * (g2 + mucomp * (g3 + mucomp * g4)));
return (1.0 + r * GoverPi) / (1.0 + constant1_FON * r);
}
vec3 eonDiffuseBRDF(const vec3 albedo, const float roughness,
const float dotNL, const float dotNV, const float dotVH) {
float r = roughness;
float mu_i = clamp(dotNL, 0.0, 1.0);
float mu_o = clamp(dotNV, 0.0, 1.0);
if (mu_i < 1.0e-7 || mu_o < 1.0e-7) return vec3(0.0);
float dotLV = 2.0 * dotVH * dotVH - 1.0;
float s = dotLV - mu_i * mu_o;
float sovertF = s > 0.0 ? s / max(mu_i, mu_o) : s;
float AF = 1.0 / (1.0 + constant1_FON * r);
vec3 f_ss = (albedo * INV_PI) * AF * (1.0 + r * sovertF);
float EFo = E_FON_approx(mu_o, r);
float EFi = E_FON_approx(mu_i, r);
float avgEF = AF * (1.0 + constant2_FON * r);
vec3 rho_ms = (albedo * albedo) * avgEF
/ max(vec3(1.0) - albedo * (1.0 - avgEF), vec3(1.0e-7));
const float eps = 1.0e-7;
vec3 f_ms = (rho_ms * INV_PI)
* max(eps, 1.0 - EFo)
* max(eps, 1.0 - EFi)
/ max(eps, 1.0 - avgEF);
return (f_ss + f_ms) * mu_i;
}
#endif
#ifdef _GotandaDiffuse
vec3 gotandaDiffuseBRDF(const vec3 albedo, const float roughness, const vec3 f0,
const float dotNL, const float dotNV, const float dotVH) {
float nl = clamp(dotNL, 0.0, 1.0);
float nv = clamp(dotNV, 0.0, 1.0);
float a = roughness * roughness;
float a2 = a * a;
float dotLV = 2.0 * dotVH * dotVH - 1.0;
float Cosri = dotLV - nv * nl;
float a2_13 = a2 + 1.36053;
float Fr = (1.0 - (0.542026 * a2 + 0.303573 * a) / a2_13)
* (1.0 - pow(1.0 - nv, 5.0 - 4.0 * a2) / a2_13)
* ((-0.733996 * a2 * a + 1.50912 * a2 - 1.16402 * a)
* pow(1.0 - nv, 1.0 + 1.0 / (39.0 * a2 * a2 + 1.0)) + 1.0);
float Lm = (max(1.0 - 2.0 * a, 0.0) * (1.0 - pow(1.0 - nl, 5.0))
+ min(2.0 * a, 1.0)) * (1.0 - 0.5 * a * (nl - 1.0)) * nl;
float Vd = (a2 / ((a2 + 0.09) * (1.31072 + 0.995584 * nv)))
* (1.0 - pow(1.0 - nl,
(1.0 - 0.3726732 * nv * nv)
/ (0.188566 + 0.38841 * nv)));
float Bp = Cosri < 0.0 ? 1.4 * nv * nl * Cosri : Cosri;
vec3 Lr = (21.0 / 20.0) * (1.0 - f0) * (Fr * Lm + Vd + Bp);
return max(albedo * INV_PI * Lr, vec3(0.0));
}
#endif
#ifdef _ChanDiffuse
vec3 chanDiffuseBRDF(const vec3 albedo, const float roughness,
const float dotNL, const float dotNV, const float dotVH) {
float nl = clamp(dotNL, 0.0, 1.0);
float nv = clamp(dotNV, 0.0, 1.0);
float vh = clamp(dotVH, 0.0, 1.0);
float a = roughness * roughness;
float a2 = a * a;
float g = clamp((1.0 / 18.0) * log2(2.0 / max(a2, 1e-7) - 1.0), 0.0, 1.0);
float dotNH = clamp((nl + nv) / max(2.0 * vh, 1e-5), 0.0, 1.0);
float F0 = vh + pow(1.0 - vh, 5.0);
float FdV = 1.0 - 0.75 * pow(1.0 - nv, 5.0);
float FdL = 1.0 - 0.75 * pow(1.0 - nl, 5.0);
float Fd = mix(F0, FdV * FdL, clamp(2.2 * g - 0.5, 0.0, 1.0));
float Fb = ((34.5 * g - 59.0) * g + 24.5) * vh
* exp2(-max(73.2 * g - 21.2, 8.9) * sqrt(dotNH));
float Lobe = clamp(Fd + Fb, 0.0, 1.0);
return albedo * INV_PI * Lobe * nl;
}
#endif
vec3 diffuseBRDF(const vec3 albedo, const float roughness, const vec3 f0,
const float dotNL, const float dotNV, const float dotVH) {
#ifdef _BurleyDiffuse
return burleyDiffuseBRDF(albedo, roughness, dotNL, dotNV, dotVH);
#elif defined(_EONDiffuse)
return eonDiffuseBRDF(albedo, roughness, dotNL, dotNV, dotVH);
#elif defined(_GotandaDiffuse)
return gotandaDiffuseBRDF(albedo, roughness, f0, dotNL, dotNV, dotVH);
#elif defined(_ChanDiffuse)
return chanDiffuseBRDF(albedo, roughness, dotNL, dotNV, dotVH);
#else
return lambertDiffuseBRDF(albedo, dotNL);
#endif
}
vec3 lambertDiffuseIBL(const vec3 albedo) {
return albedo;
}
#ifdef _BurleyDiffuse
vec3 burleyDiffuseIBL(const vec3 albedo, const float roughness, const float dotNV) {
float nv = clamp(dotNV, 0.0, 1.0);
float energyBias = mix(0.0, 0.5, roughness);
float energyFactor = mix(1.0, 1.0 / 1.51, roughness);
float fd90 = energyBias + 2.0 * roughness * nv * nv;
float viewScatter = 1.0 + (fd90 - 1.0) * pow(1.0 - nv, 5.0);
return albedo * viewScatter * energyFactor;
}
#endif
#ifdef _EONDiffuse
vec3 eonDiffuseIBL(const vec3 albedo, const float roughness, const float dotNV) {
float r = roughness;
float AF = 1.0 / (1.0 + constant1_FON * r);
float EF = E_FON_approx(clamp(dotNV, 0.0, 1.0), r);
float avgEF = AF * (1.0 + constant2_FON * r);
vec3 rho_ms = (albedo * albedo) * avgEF
/ max(vec3(1.0) - albedo * (1.0 - avgEF), vec3(1.0e-7));
return max(albedo * EF + rho_ms * (1.0 - EF), vec3(0.0));
}
#endif
#ifdef _GotandaDiffuse
vec3 gotandaDiffuseIBL(const vec3 albedo, const float roughness, const vec3 f0, const float dotNV) {
float nv = clamp(dotNV, 0.0, 1.0);
float a = roughness * roughness;
float a2 = a * a;
float a2_13 = a2 + 1.36053;
float Fr = (1.0 - (0.542026 * a2 + 0.303573 * a) / a2_13)
* (1.0 - pow(1.0 - nv, 5.0 - 4.0 * a2) / a2_13)
* ((-0.733996 * a2 * a + 1.50912 * a2 - 1.16402 * a)
* pow(1.0 - nv, 1.0 + 1.0 / (39.0 * a2 * a2 + 1.0)) + 1.0);
float Lm = (max(1.0 - 2.0 * a, 0.0) * (1.0 - pow(1.0 - nv, 5.0))
+ min(2.0 * a, 1.0)) * (1.0 - 0.5 * a * (nv - 1.0)) * nv;
float Vd = (a2 / ((a2 + 0.09) * (1.31072 + 0.995584 * nv)))
* (1.0 - pow(1.0 - nv,
(1.0 - 0.3726732 * nv * nv)
/ (0.188566 + 0.38841 * nv)));
float Cosri = 1.0 - nv * nv;
float Bp = Cosri;
vec3 Lr = (21.0 / 20.0) * (1.0 - f0) * (Fr * Lm + Vd + Bp);
return max(albedo * Lr, vec3(0.0));
}
#endif
#ifdef _ChanDiffuse
vec3 chanDiffuseIBL(const vec3 albedo, const float roughness, const float dotNV) {
float nv = clamp(dotNV, 0.0, 1.0);
float a = roughness * roughness;
float a2 = a * a;
float g = clamp((1.0 / 18.0) * log2(2.0 / max(a2, 1e-7) - 1.0), 0.0, 1.0);
float FdV = 1.0 - 0.75 * pow(1.0 - nv, 5.0);
float Fd = mix(1.0, FdV * FdV, clamp(2.2 * g - 0.5, 0.0, 1.0));
float Fb = ((34.5 * g - 59.0) * g + 24.5)
* exp2(-max(73.2 * g - 21.2, 8.9) * sqrt(nv));
return albedo * clamp(Fd + Fb, 0.0, 1.0);
}
#endif
vec3 diffuseIBL(const vec3 albedo, const float roughness, const vec3 f0, const float dotNV) {
#ifdef _BurleyDiffuse
return burleyDiffuseIBL(albedo, roughness, dotNV);
#elif defined(_EONDiffuse)
return eonDiffuseIBL(albedo, roughness, dotNV);
#elif defined(_GotandaDiffuse)
return gotandaDiffuseIBL(albedo, roughness, f0, dotNV);
#elif defined(_ChanDiffuse)
return chanDiffuseIBL(albedo, roughness, dotNV);
#else
return lambertDiffuseIBL(albedo);
#endif
}
vec3 surfaceAlbedo(const vec3 baseColor, const float metalness) {
return mix(baseColor, vec3(0.0), metalness);
}

View File

@ -131,15 +131,15 @@ vec3 sampleLightCore(const vec3 p, const vec3 n, const vec3 v, const float dotNV
#ifdef _Anisotropy
if (abs(anisotropy) > 0.001 && dot(tangent, tangent) > 0.001) {
vec3 bitangent = normalize(cross(n, tangent));
standard = lambertDiffuseBRDF(albedo, dotNL) +
standard = diffuseBRDF(albedo, rough, f0, dotNL, dotNV, dotVH) +
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
tangent, bitangent, n, l, v, dotNL, dotNV) * spec;
} else {
standard = lambertDiffuseBRDF(albedo, dotNL) +
standard = diffuseBRDF(albedo, rough, f0, dotNL, dotNV, dotVH) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
}
#else
standard = lambertDiffuseBRDF(albedo, dotNL) +
standard = diffuseBRDF(albedo, rough, f0, dotNL, dotNV, dotVH) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#endif

View File

@ -83,16 +83,16 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
vec3 direct;
if (abs(anisotropy) > 0.001 && dot(tangent, tangent) > 0.001) {
vec3 bitangent = normalize(cross(n, tangent));
direct = lambertDiffuseBRDF(albedo, dotNL) +
direct = diffuseBRDF(albedo, rough, f0, dotNL, dotNV, dotVH) +
anisotropicBRDF(f0, rough, anisotropy, anisoRot,
tangent, bitangent, n, l, v, dotNL, dotNV) * spec;
} else {
direct = lambertDiffuseBRDF(albedo, dotNL) +
direct = diffuseBRDF(albedo, rough, f0, dotNL, dotNV, dotVH) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
}
#else
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
vec3 direct = diffuseBRDF(albedo, rough, f0, dotNL, dotNV, dotVH) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#endif
#ifdef _ExtBRDF

View File

@ -75,9 +75,15 @@ vec3 PCFTileAware(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb;
vec3 transResult = vec3(0.0);
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
vec4 smt = texture(shadowMapTransparent,
clamp(uv + vec2(x, y) / smSize, tileMin, tileMax));
transResult += (smt.a < compare) ? smt.rgb : vec3(1.0);
}
}
result *= transResult / 9.0;
}
#endif
@ -142,9 +148,15 @@ vec3 PCF(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb;
vec3 transResult = vec3(0.0);
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
vec4 smt = texture(shadowMapTransparent,
uv + vec2(x, y) / smSize);
transResult += (smt.a < compare) ? smt.rgb : vec3(1.0);
}
}
result *= transResult / 9.0;
}
#endif
@ -187,9 +199,19 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube,
#ifdef _ShadowMapTransparent
if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb;
vec3 transResult = vec3(0.0);
vec4 smt = texture(shadowMapCubeTransparent, ml);
transResult += (smt.a < compare) ? smt.rgb : vec3(1.0);
for (int x = -1; x <= 1; x += 2) {
for (int y = -1; y <= 1; y += 2) {
for (int z = -1; z <= 1; z += 2) {
smt = texture(shadowMapCubeTransparent,
ml + vec3(x, y, z) * s);
transResult += (smt.a < compare) ? smt.rgb : vec3(1.0);
}
}
}
result *= transResult / 9.0;
}
#endif
@ -385,9 +407,15 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled);
if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb;
vec3 transResult = vec3(0.0);
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
vec4 smt = texture(shadowMapTransparent,
clamp(uvtiled + vec2(x, y) / smSize, 0.0, 1.0));
transResult += (smt.a < compare) ? smt.rgb : vec3(1.0);
}
}
result *= transResult / 9.0;
}
#endif

View File

@ -151,7 +151,7 @@ void main() {
#endif
#endif
envl.rgb *= albedo;
envl.rgb *= diffuseIBL(albedo, roughness, f0, dotNV);
#ifdef _Brdf
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account

View File

@ -137,7 +137,7 @@ void main() {
envl.rgb = pow(envl.rgb, vec3(2.2));
#endif
envl.rgb *= albedo;
envl.rgb *= diffuseIBL(albedo, roughness, f0, dotNV);
#ifdef _Brdf
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
@ -146,7 +146,7 @@ void main() {
envl.rgb *= envmapStrength * voxelgiEnv * occspec.x;
vec4 trace = traceDiffuse(P, n, voxels, clipmaps);
vec3 color = trace.rgb * albedo * (1.0 - F);
vec3 color = trace.rgb * diffuseIBL(albedo, roughness, f0, dotNV) * (1.0 - F);
color += envl * (1.0 - trace.a);
imageStore(voxels_diffuse, ivec2(pixel), vec4(color, 1.0));

View File

@ -69,7 +69,7 @@ void main() {
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n);
float occ = 1.0 - traceShadow(P, n, voxels, voxelsSDF, normalize(lPos - P), clipmaps, pixel);
float occ = 1.0 - traceShadow(P, n, voxels, voxelsSDF, normalize(lPos - P), clipmaps, pixel, vec2(0.0));
imageStore(voxels_shadows, ivec2(pixel), vec4(occ));
}

View File

@ -84,7 +84,7 @@ class CurveObject extends Object {
};
for (spline in data.splines) {
var newSpline = {
var newSpline: TSpline = {
points: [],
closed: spline.closed,
resolution: spline.resolution,
@ -441,7 +441,7 @@ class CurveObject extends Object {
for (splineIndex in 0...splinesLength) {
var spline = data.splines[splineIndex];
var matIdx = spline.material_index != null ? spline.material_index : 0;
var matIdx = spline.material_index;
if (!indicesByMaterial.exists(matIdx)) indicesByMaterial.set(matIdx, []);
var indices = indicesByMaterial.get(matIdx);
@ -704,7 +704,7 @@ class CurveObject extends Object {
for (splineIndex in 0...splinesLength) {
var spline = data.splines[splineIndex];
var matIdx = spline.material_index != null ? spline.material_index : 0;
var matIdx = spline.material_index;
if (!indicesByMaterial.exists(matIdx)) indicesByMaterial.set(matIdx, []);
var indices = indicesByMaterial.get(matIdx);
@ -1032,7 +1032,8 @@ class CurveObject extends Object {
if (basePos == null) return null;
var baseVertCount = Std.int(basePos.length / 4);
var baseScale = baseRaw.scale_pos;
var baseScale: kha.FastFloat = 1.0;
if (baseRaw.scale_pos != null) baseScale = baseRaw.scale_pos;
var minVal = 1e10;
var maxVal = -1e10;

View File

@ -333,7 +333,7 @@ class Inc {
var shadowmap = getShadowMapAtlas(atlas, true);
path.setTargetStream(shadowmap);
path.clearTarget(0xffffff, 0.0);
path.currentG.clear(0xffffffff, 0.0);
for (tile in atlas.activeTiles) {
if (tile.light == null || !tile.light.visible || tile.light.culledLight
@ -549,7 +549,7 @@ class Inc {
for (i in 0...faces) {
if (faces > 1) path.currentFace = i;
path.setTarget(shadowmap_transparent);
path.clearTarget(0xffffff, 0.0);
path.currentG.clear(0xffffffff, 0.0);
if (l.data.raw.cast_shadow) {
path.drawMeshes("shadowmap_transparent");
}

View File

@ -543,7 +543,7 @@ class RenderPathDeferred {
t2.format = "RGBA64";
path.createRenderTarget(t2);
path.setTarget("empty_shadowmap_transparent");
path.clearTarget(0xffffffff, null);
path.currentG.clear(0xffffffff, null);
#end
}
#end
@ -936,6 +936,80 @@ class RenderPathDeferred {
}
#end
#if rp_ssrefr
{
if (leenkx.data.Config.raw.rp_ssrefr != false)
{
#if (!kha_opengl)
path.setDepthFrom("gbuffer0", "gbuffer1"); // Unbind depth so we can read it
path.depthToRenderTarget.set("main", path.renderTargets.get("tex"));
#end
//save depth
path.setTarget("gbufferD1");
path.bindTarget("_main", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
#if (!kha_opengl)
path.setDepthFrom("gbuffer0", "tex"); // Re-bind depth
path.depthToRenderTarget.set("main", path.renderTargets.get("gbuffer0"));
#end
//save background color
path.setTarget("refr");
path.bindTarget("tex", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
path.setTarget("gbuffer0", ["gbuffer1", "gbuffer_refraction"]);
#if (rp_voxels != "Off")
path.bindTarget("voxelsOut", "voxels");
#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
path.bindTarget("voxelsSDF", "voxelsSDF");
#end
#end
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
#if rp_ssrs
path.bindTarget("_main", "gbufferD");
#end
path.drawMeshes("refraction");
path.setTarget("buf");
path.bindTarget("tex", "tex");
path.bindTarget("gbufferD1", "gbufferD1");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("gbuffer1", "gbuffer1");
path.bindTarget("refr", "tex1");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer_refraction", "gbuffer_refraction");
path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass");
path.setTarget("tex");
path.bindTarget("buf", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
}
}
#end
#if (rp_translucency && !rp_ssrefr && rp_ssr)
{
path.setTarget("tex");
path.drawMeshes("depth");
}
#end
#if rp_ssr
{
if (leenkx.data.Config.raw.rp_ssr != false) {
@ -1016,73 +1090,6 @@ class RenderPathDeferred {
}
#end
#if rp_ssrefr
{
if (leenkx.data.Config.raw.rp_ssrefr != false)
{
#if (!kha_opengl)
path.setDepthFrom("gbuffer0", "gbuffer1"); // Unbind depth so we can read it
path.depthToRenderTarget.set("main", path.renderTargets.get("tex"));
#end
//save depth
path.setTarget("gbufferD1");
path.bindTarget("_main", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
#if (!kha_opengl)
path.setDepthFrom("gbuffer0", "tex"); // Re-bind depth
path.depthToRenderTarget.set("main", path.renderTargets.get("gbuffer0"));
#end
//save background color
path.setTarget("refr");
path.bindTarget("tex", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
path.setTarget("gbuffer0", ["gbuffer1", "gbuffer_refraction"]);
#if (rp_voxels != "Off")
path.bindTarget("voxelsOut", "voxels");
#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
path.bindTarget("voxelsSDF", "voxelsSDF");
#end
#end
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
#if rp_ssrs
path.bindTarget("_main", "gbufferD");
#end
path.drawMeshes("refraction");
path.setTarget("buf");
path.bindTarget("tex", "tex");
path.bindTarget("gbufferD1", "gbufferD1");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("gbuffer1", "gbuffer1");
path.bindTarget("refr", "tex1");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer_refraction", "gbuffer_refraction");
path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass");
path.setTarget("tex");
path.bindTarget("buf", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
}
}
#end
#if rp_chromatic_aberration
{
path.setTarget("buf");

View File

@ -968,6 +968,7 @@ class DebugConsole extends Trait {
ui.unindent();
}
#if js
if (ui.panel(Id.handle({selected: false}), "Console")) {
ui.indent();
var t = ui.textInput(Id.handle());
@ -977,6 +978,7 @@ class DebugConsole extends Trait {
}
ui.unindent();
}
#end
}
if (ui.tab(htab, lastTraces[0] == "" ? "Console" : lastTraces[0].substr(0, 20))) {
#if js

View File

@ -17,5 +17,10 @@ class GetTransformNode(LnxLogicTreeNode):
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement.Identity(self)
return NodeReplacement(
'LNGetTransformNode', self.lnx_version, 'LNGetTransformNode', 2,
in_socket_mapping={0: 0},
out_socket_mapping={0: 0},
input_defaults={1: False},
)

View File

@ -173,6 +173,19 @@ def add_world_defs():
wrd.world_defs += '_Brdf'
assets.add_khafile_def("lnx_brdf")
if rpdat.lnx_diffuse_model == 'Burley':
wrd.world_defs += '_BurleyDiffuse'
assets.add_khafile_def('lnx_burley_diffuse')
elif rpdat.lnx_diffuse_model == 'EON':
wrd.world_defs += '_EONDiffuse'
assets.add_khafile_def('lnx_eon_diffuse')
elif rpdat.lnx_diffuse_model == 'Gotanda':
wrd.world_defs += '_GotandaDiffuse'
assets.add_khafile_def('lnx_gotanda_diffuse')
elif rpdat.lnx_diffuse_model == 'Chan':
wrd.world_defs += '_ChanDiffuse'
assets.add_khafile_def('lnx_chan_diffuse')
def build():
rpdat = lnx.utils.get_rp()
project_path = lnx.utils.get_fp()

View File

@ -247,9 +247,12 @@ def make(context_id, rpasses, shadowmap=False, shadowmap_transparent=False):
if parse_opacity and not shadowmap_transparent:
if mat_state.material.lnx_discard:
opac = mat_state.material.lnx_discard_opacity_shadows
frag.write('if (opacity < {0}) discard;'.format(opac))
elif rpdat.rp_renderer == 'Deferred' and 'translucent' in rpasses and not shadowmap:
pass
else:
opac = '1.0'
frag.write('if (opacity < {0}) discard;'.format(opac))
frag.write('if (opacity < {0}) discard;'.format(opac))
make_finalize.make(con_depth)

View File

@ -737,7 +737,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
if '_Rad' in wrd.world_defs:
frag.write('prefilteredColor = pow(prefilteredColor, vec3(2.2));')
frag.write('envl *= albedo;')
frag.write('envl *= diffuseIBL(albedo, roughness, f0, dotNV);')
if '_Brdf' in wrd.world_defs:
frag.write('envl.rgb *= 1.0 - F;')
@ -771,7 +771,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
if '_VoxelGI' in wrd.world_defs:
frag.write('vec4 diffuse_indirect = traceDiffuse(wposition, n, voxels, clipmaps);')
frag.write('indirect = (diffuse_indirect.rgb * albedo * (1.0 - F) + envl * (1.0 - diffuse_indirect.a)) * voxelgiDiff;')
frag.write('indirect = (diffuse_indirect.rgb * diffuseIBL(albedo, roughness, f0, dotNV) * (1.0 - F) + envl * (1.0 - diffuse_indirect.a)) * voxelgiDiff;')
frag.write('if (roughness < 1.0 && specular > 0.0) {')
frag.write(' indirect += traceSpecular(wposition, n, voxels, voxelsSDF, vVec, roughness * roughness, clipmaps, gl_FragCoord.xy, velocity).rgb * F * voxelgiRefl;')
frag.write('}')
@ -847,7 +847,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
if '_ExtBRDF' in wrd.world_defs:
frag.write('float sunLayerWeight;')
frag.write('vec3 sdirect = applyExtBRDFLayers(')
frag.write(' lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular,')
frag.write(' diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular,')
frag.write(' albedo, f0, roughness, sdotNL, dotNV, sdotNH, sdotVH, n, sunDir, vVec, sh')
if '_ClearCoat' in wrd.world_defs:
frag.write(', clearcoat, clearcoatRough, coatIOR, coatTint, nCoat')
@ -858,7 +858,7 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
frag.write(', sunLayerWeight);')
frag.write('direct += sdirect * sunCol * svisibility;')
else:
frag.write('direct += (lambertDiffuseBRDF(albedo, sdotNL) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;')
frag.write('direct += (diffuseBRDF(albedo, roughness, f0, sdotNL, dotNV, sdotVH) + specularBRDF(f0, roughness, sdotNL, sdotNH, dotNV, sdotVH) * specular) * sunCol * svisibility;')
# sun
if '_SinglePoint' in wrd.world_defs:
@ -880,7 +880,8 @@ def make_forward_base(con_mesh, parse_opacity=False, transluc_pass=False):
else:
frag.add_uniform('vec2 lightProj', link='_lightPlaneProj', included=True)
frag.add_uniform('samplerCubeShadow shadowMapPoint[1]', included=True)
frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True)
if is_transparent_shadows:
frag.add_uniform('samplerCube shadowMapPointTransparent[1]', included=True)
frag.write('direct += sampleLight(')
frag.write(' wposition, n, vVec, dotNV, pointPos, pointCol, albedo, roughness, specular, f0')
if is_shadows:

View File

@ -20,7 +20,7 @@ else:
def make(context_id):
con_refract = mat_state.data.add_context({
'name': context_id,
'depth_write': False,
'depth_write': True,
'compare_mode': 'less',
'cull_mode': 'clockwise',
'blend_source': 'blend_one',

View File

@ -411,7 +411,8 @@ def make_gi(context_id):
frag.add_uniform('vec4 pointLightDataArray[maxLightsCluster]', link='_pointLightsAtlasArray', included=True)
else:
frag.add_uniform('samplerCubeShadow shadowMapPoint[4]', included=True)
frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True)
if is_transparent_shadows:
frag.add_uniform('samplerCube shadowMapPointTransparent[4]', included=True)
vert.add_out('vec4 wvppositionGeom')
vert.add_uniform('mat4 VP', '_viewProjectionMatrix')

View File

@ -55,6 +55,8 @@ def get_rpasses(material):
ar.append('voxel')
if rpdat.rp_renderer == 'Forward' and rpdat.rp_depthprepass and not material.lnx_blending and not material.lnx_particle_flag:
ar.append('depth')
if rpdat.rp_renderer == 'Deferred' and rpdat.rp_ssr and 'translucent' in ar:
ar.append('depth')
if material.lnx_cast_shadow and rpdat.rp_shadows and ('mesh' in ar):
if 'translucent' in ar or 'refraction' in ar:

View File

@ -486,6 +486,14 @@ class LnxRPListItem(bpy.types.PropertyGroup):
('Solid', 'Solid', 'Solid'),
],
name="Materials", description="Material builder", default='Full', update=update_material_model)
lnx_diffuse_model: EnumProperty(
items=[('Lambert', 'Lambert', 'Lambert'),
('Burley', 'Burley', 'Burley with Frostbite energy renormalization'),
('EON', 'Oren-Nayar', 'Energy preserving Oren Nayar with multi scatter compensation'),
('Gotanda', 'Gotanda GGX Diffuse', 'Microfacet GGX diffuse with Fresnel and visibility'),
('Chan', 'Chan Retroreflective', 'GGX microfacet diffuse with retroreflective lobe'),
],
name="Diffuse BRDF", description="Diffuse BRDF model", default='Burley', update=update_material_model)
lnx_rp_displacement: EnumProperty(
items=[('Off', 'Off', 'Off'),
('Vertex', 'Vertex', 'Vertex'),

View File

@ -292,39 +292,38 @@ class LNX_PT_TilesheetPanel(bpy.types.Panel):
bl_label = "Leenkx Tilesheet"
bl_space_type = "PROPERTIES"
bl_region_type = "WINDOW"
bl_context = "render"
bl_context = "object"
bl_options = {'DEFAULT_CLOSED'}
@classmethod
def poll(cls, context):
return context.object is not None and context.object.type == 'MESH'
def draw_header(self, context):
obj = context.object
self.layout.prop(obj, "lnx_tilesheet_enabled", text="")
def draw(self, context):
layout = self.layout
layout.use_property_split = True
layout.use_property_decorate = False
obj = context.object
layout.enabled = obj.lnx_tilesheet_enabled
layout.prop(obj, "lnx_tilesheet_enabled", text="Enable Tilesheet")
body = layout.column()
body.enabled = obj.lnx_tilesheet_enabled
# Start action dropdown
layout.prop_search(obj, "lnx_tilesheet_default_action", obj, "lnx_tilesheet_actionlist", text="Start Action")
body.prop_search(obj, "lnx_tilesheet_default_action", obj, "lnx_tilesheet_actionlist", text="Start Action")
row = layout.row()
row = body.row()
row.prop(obj, "lnx_tilesheet_flipx")
row.prop(obj, "lnx_tilesheet_flipy")
# Actions list
layout.separator()
layout.label(text="Actions")
body.separator()
body.label(text="Actions")
rows = 2
if len(obj.lnx_tilesheet_actionlist) > 1:
rows = 4
row = layout.row()
row = body.row()
row.template_list("LNX_UL_TilesheetActionList", "The_List", obj, "lnx_tilesheet_actionlist", obj, "lnx_tilesheet_actionlist_index", rows=rows)
col = row.column(align=True)
col.operator("lnx_tilesheetactionlist.new_item", icon='ADD', text="")
@ -340,7 +339,7 @@ class LNX_PT_TilesheetPanel(bpy.types.Panel):
# Selected action details (per-action properties)
if obj.lnx_tilesheet_actionlist_index >= 0 and len(obj.lnx_tilesheet_actionlist) > 0:
adat = obj.lnx_tilesheet_actionlist[obj.lnx_tilesheet_actionlist_index]
box = layout.box()
box = body.box()
# Grid dimensions
row = box.row()
row.use_property_split = False

View File

@ -1696,6 +1696,7 @@ class LNX_PT_RenderPathRendererPanel(bpy.types.Panel):
if rpdat.rp_renderer == 'Forward':
layout.prop(rpdat, 'rp_depthprepass')
layout.prop(rpdat, 'lnx_material_model')
layout.prop(rpdat, 'lnx_diffuse_model')
layout.prop(rpdat, 'rp_translucency_state')
layout.prop(rpdat, 'rp_overlays_state')
layout.prop(rpdat, 'rp_decals_state')