forked from LeenkxTeam/LNXSDK
Merge pull request 'main' (#117) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#117
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -3,3 +3,5 @@ __pycache__/
|
|||||||
*.DS_Store
|
*.DS_Store
|
||||||
**/workspace.xml
|
**/workspace.xml
|
||||||
**/vcs.xml
|
**/vcs.xml
|
||||||
|
**/stderr.txt
|
||||||
|
**/kinc.dmp
|
||||||
BIN
Krom/kinc.dmp
BIN
Krom/kinc.dmp
Binary file not shown.
@ -148,10 +148,9 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
vec3(1.0, 0.0, t.y),
|
vec3(1.0, 0.0, t.y),
|
||||||
vec3(0.0, t.z, 0.0),
|
vec3(0.0, t.z, 0.0),
|
||||||
vec3(t.w, 0.0, t.x));
|
vec3(t.w, 0.0, t.x));
|
||||||
const float PI = 3.1415926535;
|
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
|
||||||
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3) / PI;
|
|
||||||
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
||||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3) / PI;
|
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||||
#else
|
#else
|
||||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||||
@ -244,7 +243,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
if (receiveShadow) {
|
if (receiveShadow) {
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||||
direct *= shadowTest(shadowMapSpot[0],
|
direct *= shadowTest(shadowMapSpot[0],
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
shadowMapSpotTransparent[0],
|
shadowMapSpotTransparent[0],
|
||||||
@ -256,7 +255,7 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
direct *= shadowTest(
|
direct *= shadowTest(
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
@ -436,10 +435,9 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
|||||||
vec3(1.0, 0.0, t.y),
|
vec3(1.0, 0.0, t.y),
|
||||||
vec3(0.0, t.z, 0.0),
|
vec3(0.0, t.z, 0.0),
|
||||||
vec3(t.w, 0.0, t.x));
|
vec3(t.w, 0.0, t.x));
|
||||||
const float PI = 3.1415926535;
|
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
|
||||||
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3) / PI;
|
|
||||||
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
|
||||||
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3) / PI;
|
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
|
||||||
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
|
||||||
#else
|
#else
|
||||||
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
|
||||||
@ -454,7 +452,7 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
|||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
if (receiveShadow) {
|
if (receiveShadow) {
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
|
||||||
direct *= shadowTest(shadowMapSpot[0],
|
direct *= shadowTest(shadowMapSpot[0],
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
shadowMapSpotTransparent[0],
|
shadowMapSpotTransparent[0],
|
||||||
@ -466,7 +464,7 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
|
||||||
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
shadowMapSpotTransparent[0],
|
shadowMapSpotTransparent[0],
|
||||||
@ -516,7 +514,7 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
|||||||
#ifdef _ShadowMap
|
#ifdef _ShadowMap
|
||||||
if (receiveShadow) {
|
if (receiveShadow) {
|
||||||
#ifdef _SinglePoint
|
#ifdef _SinglePoint
|
||||||
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
|
||||||
direct *= shadowTest(shadowMapSpot[0],
|
direct *= shadowTest(shadowMapSpot[0],
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
shadowMapSpotTransparent[0],
|
shadowMapSpotTransparent[0],
|
||||||
@ -528,7 +526,7 @@ vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dot
|
|||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
#ifdef _Clusters
|
#ifdef _Clusters
|
||||||
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 2, 1.0);
|
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
|
||||||
#ifdef _ShadowMapAtlas
|
#ifdef _ShadowMapAtlas
|
||||||
direct *= shadowTest(
|
direct *= shadowTest(
|
||||||
#ifdef _ShadowMapTransparent
|
#ifdef _ShadowMapTransparent
|
||||||
|
|||||||
@ -97,12 +97,8 @@ class LightObject extends Object {
|
|||||||
this.shadowMapScale = 1.0;
|
this.shadowMapScale = 1.0;
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
else if (type == "point" || type == "area") {
|
else //if (type == "point" || type == "area" || type == "spot") {
|
||||||
P = Mat4.persp(fov, 1, data.raw.near_plane, data.raw.far_plane);
|
P = Mat4.persp(fov, 1, data.raw.near_plane, data.raw.far_plane);
|
||||||
}
|
|
||||||
else if (type == "spot") {
|
|
||||||
P = Mat4.persp(fov, 1, data.raw.near_plane, data.raw.far_plane);
|
|
||||||
}
|
|
||||||
|
|
||||||
Scene.active.lights.push(this);
|
Scene.active.lights.push(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,12 +19,11 @@ class MeshObject extends Object {
|
|||||||
#if lnx_particles
|
#if lnx_particles
|
||||||
public var particleSystems: Array<ParticleSystem> = null; // Particle owner
|
public var particleSystems: Array<ParticleSystem> = null; // Particle owner
|
||||||
public var render_emitter = true;
|
public var render_emitter = true;
|
||||||
#end
|
|
||||||
#if lnx_gpu_particles
|
#if lnx_gpu_particles
|
||||||
public var particleChildren: Array<MeshObject> = null;
|
|
||||||
public var particleOwner: MeshObject = null; // Particle object
|
public var particleOwner: MeshObject = null; // Particle object
|
||||||
|
public var particleChildren: Array<MeshObject> = null;
|
||||||
public var particleIndex = -1;
|
public var particleIndex = -1;
|
||||||
#end
|
#end #end
|
||||||
public var cameraDistance: Float;
|
public var cameraDistance: Float;
|
||||||
public var cameraList: Array<String> = null;
|
public var cameraList: Array<String> = null;
|
||||||
public var screenSize = 0.0;
|
public var screenSize = 0.0;
|
||||||
|
|||||||
@ -10,6 +10,8 @@ class Inc {
|
|||||||
static var path: RenderPath;
|
static var path: RenderPath;
|
||||||
public static var superSample = 1.0;
|
public static var superSample = 1.0;
|
||||||
|
|
||||||
|
static var pointIndex = 0;
|
||||||
|
static var spotIndex = 0;
|
||||||
static var lastFrame = -1;
|
static var lastFrame = -1;
|
||||||
|
|
||||||
#if lnx_shadowmap_atlas
|
#if lnx_shadowmap_atlas
|
||||||
@ -164,7 +166,7 @@ class Inc {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for(k in 0...6) {
|
for(k in 0...6) {
|
||||||
LightObject.pointLightsData[j ] = light.tileOffsetX[k]; // posx
|
LightObject.pointLightsData[j ] = light.tileOffsetX[k]; // posx
|
||||||
LightObject.pointLightsData[j + 1] = light.tileOffsetY[k]; // posy
|
LightObject.pointLightsData[j + 1] = light.tileOffsetY[k]; // posy
|
||||||
LightObject.pointLightsData[j + 2] = light.tileScale[k]; // tile scale factor relative to atlas
|
LightObject.pointLightsData[j + 2] = light.tileScale[k]; // tile scale factor relative to atlas
|
||||||
LightObject.pointLightsData[j + 3] = 0; // padding
|
LightObject.pointLightsData[j + 3] = 0; // padding
|
||||||
@ -177,39 +179,12 @@ class Inc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static function bindShadowMapAtlas() {
|
public static function bindShadowMapAtlas() {
|
||||||
var hasAtlas = false;
|
|
||||||
|
|
||||||
for (atlas in ShadowMapAtlas.shadowMapAtlases) {
|
for (atlas in ShadowMapAtlas.shadowMapAtlases) {
|
||||||
path.bindTarget(atlas.target, atlas.target);
|
path.bindTarget(atlas.target, atlas.target);
|
||||||
hasAtlas = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasAtlas) {
|
|
||||||
#if lnx_shadowmap_atlas_single_map
|
|
||||||
path.bindTarget("empty_shadowmap", "shadowMapAtlas");
|
|
||||||
#else
|
|
||||||
path.bindTarget("empty_shadowmap", "shadowMapAtlasSun");
|
|
||||||
path.bindTarget("empty_shadowmap", "shadowMapAtlasPoint");
|
|
||||||
path.bindTarget("empty_shadowmap", "shadowMapAtlasSpot");
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
#if rp_shadowmap_transparent
|
#if rp_shadowmap_transparent
|
||||||
var hasAtlasT = false;
|
|
||||||
|
|
||||||
for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) {
|
for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) {
|
||||||
path.bindTarget(atlas.target, atlas.target);
|
path.bindTarget(atlas.target, atlas.target);
|
||||||
hasAtlasT = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!hasAtlasT) {
|
|
||||||
#if lnx_shadowmap_atlas_single_map
|
|
||||||
path.bindTarget("empty_shadowmap_transparent", "shadowMapAtlasTransparent");
|
|
||||||
#else
|
|
||||||
path.bindTarget("empty_shadowmap_transparent", "shadowMapAtlasSunTransparent");
|
|
||||||
path.bindTarget("empty_shadowmap_transparent", "shadowMapAtlasPointTransparent");
|
|
||||||
path.bindTarget("empty_shadowmap_transparent", "shadowMapAtlasSpotTransparent");
|
|
||||||
#end
|
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
@ -271,11 +246,6 @@ class Inc {
|
|||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
}
|
}
|
||||||
// update point light data before rendering
|
|
||||||
updatePointLightAtlasData(false);
|
|
||||||
#if rp_shadowmap_transparent
|
|
||||||
updatePointLightAtlasData(true);
|
|
||||||
#end
|
|
||||||
|
|
||||||
for (atlas in ShadowMapAtlas.shadowMapAtlases) {
|
for (atlas in ShadowMapAtlas.shadowMapAtlases) {
|
||||||
tilesToRemove.resize(0);
|
tilesToRemove.resize(0);
|
||||||
@ -352,6 +322,24 @@ class Inc {
|
|||||||
}
|
}
|
||||||
path.endStream();
|
path.endStream();
|
||||||
path.currentG = null;
|
path.currentG = null;
|
||||||
|
|
||||||
|
updatePointLightAtlasData(false);
|
||||||
|
|
||||||
|
#if lnx_shadowmap_atlas_lod
|
||||||
|
for (tile in tilesToChangeSize) {
|
||||||
|
tilesToRemove.push(tile);
|
||||||
|
|
||||||
|
var newTile = ShadowMapTile.assignTiles(tile.light, atlas, tile);
|
||||||
|
if (newTile != null)
|
||||||
|
atlas.activeTiles.push(newTile);
|
||||||
|
}
|
||||||
|
updatePointLightAtlasData(false);
|
||||||
|
#end
|
||||||
|
|
||||||
|
for (tile in tilesToRemove) {
|
||||||
|
atlas.activeTiles.remove(tile);
|
||||||
|
tile.freeTile();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if rp_shadowmap_transparent
|
#if rp_shadowmap_transparent
|
||||||
@ -432,6 +420,8 @@ class Inc {
|
|||||||
|
|
||||||
path.currentG = null;
|
path.currentG = null;
|
||||||
|
|
||||||
|
updatePointLightAtlasData(true);
|
||||||
|
|
||||||
#if lnx_shadowmap_atlas_lod
|
#if lnx_shadowmap_atlas_lod
|
||||||
for (tile in tilesToChangeSize) {
|
for (tile in tilesToChangeSize) {
|
||||||
tilesToRemove.push(tile);
|
tilesToRemove.push(tile);
|
||||||
@ -461,39 +451,33 @@ class Inc {
|
|||||||
path.bindTarget(n, n);
|
path.bindTarget(n, n);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
var lightIndex = 0;
|
for (i in 0...pointIndex) {
|
||||||
for (l in iron.Scene.active.lights) {
|
var n = "shadowMapPoint[" + i + "]";
|
||||||
if (iron.object.LightObject.discardLightCulled(l)) continue;
|
path.bindTarget(n, n);
|
||||||
|
var n = "shadowMapPointTransparent[" + i + "]";
|
||||||
if (l.data.raw.type == "point") {
|
path.bindTarget(n, n);
|
||||||
var n = "shadowMapPoint[" + lightIndex + "]";
|
}
|
||||||
path.bindTarget(n, n);
|
for (i in 0...spotIndex) {
|
||||||
var n = "shadowMapPointTransparent[" + lightIndex + "]";
|
var n = "shadowMapSpot[" + i + "]";
|
||||||
path.bindTarget(n, n);
|
path.bindTarget(n, n);
|
||||||
}
|
var n = "shadowMapSpotTransparent[" + i + "]";
|
||||||
else if (l.data.raw.type == "spot" || l.data.raw.type == "area") {
|
path.bindTarget(n, n);
|
||||||
var n = "shadowMapSpot[" + lightIndex + "]";
|
|
||||||
path.bindTarget(n, n);
|
|
||||||
var n = "shadowMapSpotTransparent[" + lightIndex + "]";
|
|
||||||
path.bindTarget(n, n);
|
|
||||||
}
|
|
||||||
lightIndex++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static function shadowMapName(light: LightObject, index: Int, transparent: Bool): String {
|
static function shadowMapName(light: LightObject, transparent: Bool): String {
|
||||||
switch (light.data.raw.type) {
|
switch (light.data.raw.type) {
|
||||||
case "sun":
|
case "sun":
|
||||||
return transparent ? "shadowMapTransparent" : "shadowMap";
|
return transparent ? "shadowMapTransparent" : "shadowMap";
|
||||||
case "point":
|
case "point":
|
||||||
return transparent ? "shadowMapPointTransparent[" + index + "]" : "shadowMapPoint[" + index + "]";
|
return transparent ? "shadowMapPointTransparent[" + pointIndex + "]" : "shadowMapPoint[" + pointIndex + "]";
|
||||||
default:
|
default:
|
||||||
return transparent ? "shadowMapSpotTransparent[" + index + "]" : "shadowMapSpot[" + index + "]";
|
return transparent ? "shadowMapSpotTransparent[" + spotIndex + "]" : "shadowMapSpot[" + spotIndex + "]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static function getShadowMap(l: iron.object.LightObject, index: Int, transparent: Bool): String {
|
static function getShadowMap(l: iron.object.LightObject, transparent: Bool): String {
|
||||||
var target = shadowMapName(l, index, transparent);
|
var target = shadowMapName(l, transparent);
|
||||||
var rt = path.renderTargets.get(target);
|
var rt = path.renderTargets.get(target);
|
||||||
// Create shadowmap on the fly
|
// Create shadowmap on the fly
|
||||||
if (rt == null) {
|
if (rt == null) {
|
||||||
@ -536,12 +520,13 @@ class Inc {
|
|||||||
lastFrame = RenderPath.active.frame;
|
lastFrame = RenderPath.active.frame;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
var lightIndex = 0;
|
pointIndex = 0;
|
||||||
|
spotIndex = 0;
|
||||||
for (l in iron.Scene.active.lights) {
|
for (l in iron.Scene.active.lights) {
|
||||||
if (!l.visible) continue;
|
if (!l.visible) continue;
|
||||||
|
|
||||||
path.light = l;
|
path.light = l;
|
||||||
var shadowmap = Inc.getShadowMap(l, lightIndex, false);
|
var shadowmap = Inc.getShadowMap(l, false);
|
||||||
var faces = l.data.raw.shadowmap_cube ? 6 : 1;
|
var faces = l.data.raw.shadowmap_cube ? 6 : 1;
|
||||||
for (i in 0...faces) {
|
for (i in 0...faces) {
|
||||||
if (faces > 1) path.currentFace = i;
|
if (faces > 1) path.currentFace = i;
|
||||||
@ -553,18 +538,18 @@ class Inc {
|
|||||||
}
|
}
|
||||||
path.currentFace = -1;
|
path.currentFace = -1;
|
||||||
|
|
||||||
if (!iron.object.LightObject.discardLightCulled(l)) {
|
if (l.data.raw.type == "point") pointIndex++;
|
||||||
lightIndex++;
|
else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if rp_shadowmap_transparent
|
#if rp_shadowmap_transparent
|
||||||
lightIndex = 0;
|
pointIndex = 0;
|
||||||
|
spotIndex = 0;
|
||||||
for (l in iron.Scene.active.lights) {
|
for (l in iron.Scene.active.lights) {
|
||||||
if (!l.visible) continue;
|
if (!l.visible) continue;
|
||||||
|
|
||||||
path.light = l;
|
path.light = l;
|
||||||
var shadowmap_transparent = Inc.getShadowMap(l, lightIndex, true);
|
var shadowmap_transparent = Inc.getShadowMap(l, true);
|
||||||
var faces = l.data.raw.shadowmap_cube ? 6 : 1;
|
var faces = l.data.raw.shadowmap_cube ? 6 : 1;
|
||||||
for (i in 0...faces) {
|
for (i in 0...faces) {
|
||||||
if (faces > 1) path.currentFace = i;
|
if (faces > 1) path.currentFace = i;
|
||||||
@ -576,9 +561,8 @@ class Inc {
|
|||||||
}
|
}
|
||||||
path.currentFace = -1;
|
path.currentFace = -1;
|
||||||
|
|
||||||
if (!iron.object.LightObject.discardLightCulled(l)) {
|
if (l.data.raw.type == "point") pointIndex++;
|
||||||
lightIndex++;
|
else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
#end // rp_shadowmap
|
#end // rp_shadowmap
|
||||||
|
|||||||
@ -1104,7 +1104,6 @@ class RenderPathDeferred {
|
|||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
path.setTarget(target);
|
path.setTarget(target);
|
||||||
path.clearTarget(0x00000000);
|
|
||||||
|
|
||||||
path.bindTarget("tex", "tex");
|
path.bindTarget("tex", "tex");
|
||||||
#if rp_compositordepth
|
#if rp_compositordepth
|
||||||
|
|||||||
@ -754,7 +754,6 @@ class RenderPathForward {
|
|||||||
}
|
}
|
||||||
#end
|
#end
|
||||||
path.setTarget(target);
|
path.setTarget(target);
|
||||||
path.clearTarget(0x00000000);
|
|
||||||
|
|
||||||
#if rp_compositordepth
|
#if rp_compositordepth
|
||||||
{
|
{
|
||||||
|
|||||||
@ -460,6 +460,9 @@ class RigidBody extends iron.Trait {
|
|||||||
|
|
||||||
transform.loc.set(tx, ty, tz, 1.0);
|
transform.loc.set(tx, ty, tz, 1.0);
|
||||||
transform.rot.set(tRot.x(), tRot.y(), tRot.z(), tRot.w());
|
transform.rot.set(tRot.x(), tRot.y(), tRot.z(), tRot.w());
|
||||||
|
} else {
|
||||||
|
transform.loc.set(currentPos.x(), currentPos.y(), currentPos.z(), 1.0);
|
||||||
|
transform.rot.set(currentRot.x(), currentRot.y(), currentRot.z(), currentRot.w());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object.parent != null) {
|
if (object.parent != null) {
|
||||||
|
|||||||
@ -495,8 +495,11 @@ class RigidBody extends Trait {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var active = physics.bodyInterface.IsActive(bodyId);
|
var active = physics.bodyInterface.IsActive(bodyId);
|
||||||
if (!active)
|
if (!active) {
|
||||||
|
// Activate body if sleeping
|
||||||
|
physics.bodyInterface.ActivateBody(bodyId);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Read position and rotation from Jolt into cached state
|
// Read position and rotation from Jolt into cached state
|
||||||
var p = physics.bodyInterface.GetPosition(bodyId);
|
var p = physics.bodyInterface.GetPosition(bodyId);
|
||||||
|
|||||||
@ -111,6 +111,15 @@ FCURVE_TARGET_NAMES = {
|
|||||||
current_output = None
|
current_output = None
|
||||||
|
|
||||||
|
|
||||||
|
class BuildExportCache:
|
||||||
|
"""Shared cache across all scene exports in a single build.
|
||||||
|
Created once in make.py, passed to each LeenkxExporter instance."""
|
||||||
|
def __init__(self):
|
||||||
|
self.exported_mesh_files: set = set()
|
||||||
|
self.exported_action_files: set = set()
|
||||||
|
self.processed_mesh_names: set = set()
|
||||||
|
|
||||||
|
|
||||||
class LeenkxExporter:
|
class LeenkxExporter:
|
||||||
"""Export to Leenkx format.
|
"""Export to Leenkx format.
|
||||||
|
|
||||||
@ -131,9 +140,11 @@ class LeenkxExporter:
|
|||||||
# Class names of referenced traits
|
# Class names of referenced traits
|
||||||
import_traits: List[str] = []
|
import_traits: List[str] = []
|
||||||
|
|
||||||
def __init__(self, context: bpy.types.Context, filepath: str, scene: bpy.types.Scene = None, depsgraph: bpy.types.Depsgraph = None):
|
def __init__(self, context: bpy.types.Context, filepath: str, scene: bpy.types.Scene = None, depsgraph: bpy.types.Depsgraph = None, build_cache=None):
|
||||||
global current_output
|
global current_output
|
||||||
|
|
||||||
|
self.build_cache = build_cache or BuildExportCache()
|
||||||
|
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
self.scene = context.scene if scene is None else scene
|
self.scene = context.scene if scene is None else scene
|
||||||
self.depsgraph = context.evaluated_depsgraph_get() if depsgraph is None else depsgraph
|
self.depsgraph = context.evaluated_depsgraph_get() if depsgraph is None else depsgraph
|
||||||
@ -185,12 +196,12 @@ class LeenkxExporter:
|
|||||||
LeenkxExporter.preprocess()
|
LeenkxExporter.preprocess()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def export_scene(cls, context: bpy.types.Context, filepath: str, scene: bpy.types.Scene = None, depsgraph: bpy.types.Depsgraph = None) -> None:
|
def export_scene(cls, context: bpy.types.Context, filepath: str, scene: bpy.types.Scene = None, depsgraph: bpy.types.Depsgraph = None, build_cache=None) -> None:
|
||||||
"""Exports the given scene to the given file path. This is the
|
"""Exports the given scene to the given file path. This is the
|
||||||
function that is called in make.py and the entry point of the
|
function that is called in make.py and the entry point of the
|
||||||
exporter."""
|
exporter."""
|
||||||
with lnx.profiler.Profile('profile_exporter.prof', lnx.utils.get_pref_or_default('profile_exporter', False)):
|
with lnx.profiler.Profile('profile_exporter.prof', lnx.utils.get_pref_or_default('profile_exporter', False)):
|
||||||
cls(context, filepath, scene, depsgraph).execute()
|
cls(context, filepath, scene, depsgraph, build_cache).execute()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def preprocess(cls):
|
def preprocess(cls):
|
||||||
@ -473,7 +484,6 @@ class LeenkxExporter:
|
|||||||
if btype is not NodeType.MESH and LeenkxExporter.option_mesh_only:
|
if btype is not NodeType.MESH and LeenkxExporter.option_mesh_only:
|
||||||
return
|
return
|
||||||
|
|
||||||
is_local_to_linked_scene = bobject.name in self.scene.objects and bobject.name not in self.scene.collection.children and self.scene.library
|
|
||||||
if bobject.type == 'CAMERA' and bobject.library:
|
if bobject.type == 'CAMERA' and bobject.library:
|
||||||
struct_name = bobject.name + '_' + (os.path.basename(self.scene.library.filepath) if self.scene.library else self.scene.name)
|
struct_name = bobject.name + '_' + (os.path.basename(self.scene.library.filepath) if self.scene.library else self.scene.name)
|
||||||
else:
|
else:
|
||||||
@ -1149,8 +1159,9 @@ class LeenkxExporter:
|
|||||||
self.export_particle_system_ref(bobject.particle_systems[i], out_object)
|
self.export_particle_system_ref(bobject.particle_systems[i], out_object)
|
||||||
|
|
||||||
aabb = bobject.data.lnx_aabb
|
aabb = bobject.data.lnx_aabb
|
||||||
if aabb[0] == 0 and aabb[1] == 0 and aabb[2] == 0:
|
if oid not in self.build_cache.processed_mesh_names or (aabb[0] == 0 and aabb[1] == 0 and aabb[2] == 0):
|
||||||
self.calc_aabb(bobject)
|
self.calc_aabb(bobject)
|
||||||
|
self.build_cache.processed_mesh_names.add(oid)
|
||||||
out_object['dimensions'] = [aabb[0], aabb[1], aabb[2]]
|
out_object['dimensions'] = [aabb[0], aabb[1], aabb[2]]
|
||||||
|
|
||||||
# shapeKeys = LeenkxExporter.get_shape_keys(objref)
|
# shapeKeys = LeenkxExporter.get_shape_keys(objref)
|
||||||
@ -1295,7 +1306,7 @@ class LeenkxExporter:
|
|||||||
skelobj.animation_data.action = action
|
skelobj.animation_data.action = action
|
||||||
fp = self.get_meshes_file_path('action_' + armatureid + '_' + aname, compressed=LeenkxExporter.compress_enabled)
|
fp = self.get_meshes_file_path('action_' + armatureid + '_' + aname, compressed=LeenkxExporter.compress_enabled)
|
||||||
assets.add(fp)
|
assets.add(fp)
|
||||||
if not bdata.lnx_cached or not os.path.exists(fp):
|
if (not bdata.lnx_cached or not os.path.exists(fp)) and fp not in self.build_cache.exported_action_files:
|
||||||
# Store action to use it after autobake was handled
|
# Store action to use it after autobake was handled
|
||||||
original_action = action
|
original_action = action
|
||||||
|
|
||||||
@ -1357,6 +1368,7 @@ class LeenkxExporter:
|
|||||||
# Save action separately
|
# Save action separately
|
||||||
action_obj = {'name': aname, 'objects': bones}
|
action_obj = {'name': aname, 'objects': bones}
|
||||||
lnx.utils.write_lnx(fp, action_obj)
|
lnx.utils.write_lnx(fp, action_obj)
|
||||||
|
self.build_cache.exported_action_files.add(fp)
|
||||||
|
|
||||||
# Use relative bone constraints
|
# Use relative bone constraints
|
||||||
out_object['relative_bone_constraints'] = bdata.lnx_relative_bone_constraints
|
out_object['relative_bone_constraints'] = bdata.lnx_relative_bone_constraints
|
||||||
@ -1696,6 +1708,7 @@ class LeenkxExporter:
|
|||||||
mesh_obj = {'mesh_datas': [out_mesh]}
|
mesh_obj = {'mesh_datas': [out_mesh]}
|
||||||
lnx.utils.write_lnx(fp, mesh_obj)
|
lnx.utils.write_lnx(fp, mesh_obj)
|
||||||
bobject.data.lnx_cached = True
|
bobject.data.lnx_cached = True
|
||||||
|
self.build_cache.exported_mesh_files.add(fp)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def calc_aabb(bobject):
|
def calc_aabb(bobject):
|
||||||
@ -2057,7 +2070,7 @@ class LeenkxExporter:
|
|||||||
fp = self.get_meshes_file_path('mesh_' + oid, compressed=LeenkxExporter.compress_enabled)
|
fp = self.get_meshes_file_path('mesh_' + oid, compressed=LeenkxExporter.compress_enabled)
|
||||||
assets.add(fp)
|
assets.add(fp)
|
||||||
# No export necessary
|
# No export necessary
|
||||||
if bobject.data.lnx_cached and os.path.exists(fp):
|
if bobject.data.lnx_cached and os.path.exists(fp) or fp in self.build_cache.exported_mesh_files:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Mesh users have different modifier stack
|
# Mesh users have different modifier stack
|
||||||
@ -2227,6 +2240,7 @@ class LeenkxExporter:
|
|||||||
inner_angle = math.atan(math.tan(half_angle) * (1.0 - blend))
|
inner_angle = math.atan(math.tan(half_angle) * (1.0 - blend))
|
||||||
out_light['spot_size'] = outer_cos
|
out_light['spot_size'] = outer_cos
|
||||||
out_light['spot_blend'] = max(0.0001, math.cos(inner_angle) - outer_cos)
|
out_light['spot_blend'] = max(0.0001, math.cos(inner_angle) - outer_cos)
|
||||||
|
out_light['fov'] = light_ref.spot_size
|
||||||
if light_ref.shadow_soft_size > 0.0:
|
if light_ref.shadow_soft_size > 0.0:
|
||||||
out_light['light_size'] = light_ref.shadow_soft_size * 10
|
out_light['light_size'] = light_ref.shadow_soft_size * 10
|
||||||
elif objtype == 'AREA':
|
elif objtype == 'AREA':
|
||||||
@ -2282,7 +2296,6 @@ class LeenkxExporter:
|
|||||||
# outside the collection, then instantiate the full object
|
# outside the collection, then instantiate the full object
|
||||||
# child tree if the collection gets spawned as a whole
|
# child tree if the collection gets spawned as a whole
|
||||||
if bobject.parent is None or bobject.parent.name not in collection.objects:
|
if bobject.parent is None or bobject.parent.name not in collection.objects:
|
||||||
is_local_to_linked_scene = bobject.name in self.scene.objects and bobject.name not in self.scene.collection.children and self.scene.library
|
|
||||||
if bobject.type == 'CAMERA':
|
if bobject.type == 'CAMERA':
|
||||||
asset_name = bobject.name + '_' + (os.path.basename(self.scene.library.filepath) if self.scene.library else self.scene.name)
|
asset_name = bobject.name + '_' + (os.path.basename(self.scene.library.filepath) if self.scene.library else self.scene.name)
|
||||||
else:
|
else:
|
||||||
@ -2925,7 +2938,7 @@ class LeenkxExporter:
|
|||||||
if collection.name.startswith(('RigidBodyWorld', 'Trait|')):
|
if collection.name.startswith(('RigidBodyWorld', 'Trait|')):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self.scene.user_of_id(collection) or collection.library and not self.scene.library or collection in self.referenced_collections:
|
if self.scene.user_of_id(collection) or collection in self.referenced_collections:
|
||||||
if collection not in self.inlined_collections:
|
if collection not in self.inlined_collections:
|
||||||
self.export_collection(collection)
|
self.export_collection(collection)
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import webbrowser
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
from lnx import assets
|
from lnx import assets
|
||||||
|
from lnx.exporter import BuildExportCache
|
||||||
from lnx.exporter import LeenkxExporter
|
from lnx.exporter import LeenkxExporter
|
||||||
import lnx.lib.make_datas
|
import lnx.lib.make_datas
|
||||||
import lnx.lib.server
|
import lnx.lib.server
|
||||||
@ -265,19 +266,21 @@ def export_data_impl(fp, sdk_path):
|
|||||||
continue
|
continue
|
||||||
for o in scene.collection.all_objects:
|
for o in scene.collection.all_objects:
|
||||||
if o.type in ('MESH', 'EMPTY'):
|
if o.type in ('MESH', 'EMPTY'):
|
||||||
if o.name not in export_coll_names:
|
if o.name not in export_coll_names or o.library:
|
||||||
export_coll.objects.link(o)
|
export_coll.objects.link(o)
|
||||||
export_coll_names.add(o.name)
|
export_coll_names.add(o.name)
|
||||||
depsgraph = bpy.context.evaluated_depsgraph_get()
|
depsgraph = bpy.context.evaluated_depsgraph_get()
|
||||||
bpy.data.collections.remove(export_coll) # Destroy the "zoo" collection
|
bpy.data.collections.remove(export_coll) # Destroy the "zoo" collection
|
||||||
|
|
||||||
|
build_cache = BuildExportCache()
|
||||||
|
|
||||||
for scene in bpy.data.scenes:
|
for scene in bpy.data.scenes:
|
||||||
if scene.lnx_export:
|
if scene.lnx_export:
|
||||||
# Reset shader comparison arrays to prevent cross-scene shader merging
|
# Reset shader comparison arrays to prevent cross-scene shader merging
|
||||||
assets.reset_shader_cons()
|
assets.reset_shader_cons()
|
||||||
ext = '.lz4' if LeenkxExporter.compress_enabled else '.lnx'
|
ext = '.lz4' if LeenkxExporter.compress_enabled else '.lnx'
|
||||||
asset_path = build_dir + '/compiled/Assets/' + lnx.utils.safestr(scene.name + "_" + os.path.basename(scene.library.filepath).replace(".blend", "") if scene.library else scene.name) + ext
|
asset_path = build_dir + '/compiled/Assets/' + lnx.utils.safestr(scene.name + "_" + os.path.basename(scene.library.filepath).replace(".blend", "") if scene.library else scene.name) + ext
|
||||||
LeenkxExporter.export_scene(bpy.context, asset_path, scene=scene, depsgraph=depsgraph)
|
LeenkxExporter.export_scene(bpy.context, asset_path, scene=scene, depsgraph=depsgraph, build_cache=build_cache)
|
||||||
if LeenkxExporter.export_physics:
|
if LeenkxExporter.export_physics:
|
||||||
physics_found = True
|
physics_found = True
|
||||||
if LeenkxExporter.export_navigation:
|
if LeenkxExporter.export_navigation:
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import lnx.assets as assets
|
|||||||
import lnx.log as log
|
import lnx.log as log
|
||||||
import lnx.make_state as state
|
import lnx.make_state as state
|
||||||
import lnx.utils
|
import lnx.utils
|
||||||
|
from lnx.props_renderpath import auto_atlas_size
|
||||||
|
|
||||||
if lnx.is_reload(__name__):
|
if lnx.is_reload(__name__):
|
||||||
lnx.api = lnx.reload_module(lnx.api)
|
lnx.api = lnx.reload_module(lnx.api)
|
||||||
@ -68,12 +69,32 @@ def add_world_defs():
|
|||||||
if rpdat.rp_shadowmap_atlas_single_map:
|
if rpdat.rp_shadowmap_atlas_single_map:
|
||||||
assets.add_khafile_def('lnx_shadowmap_atlas_single_map')
|
assets.add_khafile_def('lnx_shadowmap_atlas_single_map')
|
||||||
wrd.world_defs += '_SingleAtlas'
|
wrd.world_defs += '_SingleAtlas'
|
||||||
assets.add_khafile_def('rp_shadowmap_atlas_max_size_point={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size_point)))
|
|
||||||
assets.add_khafile_def('rp_shadowmap_atlas_max_size_spot={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size_spot)))
|
|
||||||
assets.add_khafile_def('rp_shadowmap_atlas_max_size_sun={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size_sun)))
|
|
||||||
assets.add_khafile_def('rp_shadowmap_atlas_max_size={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size)))
|
|
||||||
|
|
||||||
assets.add_khafile_def('rp_max_lights_cluster={0}'.format(int(rpdat.rp_max_lights_cluster)))
|
if rpdat.rp_shadowmap_atlas_auto:
|
||||||
|
max_lights = int(rpdat.rp_max_lights)
|
||||||
|
cube_size = int(rpdat.rp_shadowmap_cube)
|
||||||
|
cascade_size = int(rpdat.rp_shadowmap_cascade)
|
||||||
|
cascades = int(rpdat.rp_shadowmap_cascades)
|
||||||
|
|
||||||
|
auto_point = auto_atlas_size(max_lights, cube_size, 6)
|
||||||
|
auto_spot = auto_atlas_size(max_lights, cascade_size, 1)
|
||||||
|
auto_sun = auto_atlas_size(max_lights, cascade_size, cascades)
|
||||||
|
auto_max = max(auto_point, auto_spot, auto_sun)
|
||||||
|
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size_point={0}'.format(auto_point))
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size_spot={0}'.format(auto_spot))
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size_sun={0}'.format(auto_sun))
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size={0}'.format(auto_max))
|
||||||
|
else:
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size_point={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size_point)))
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size_spot={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size_spot)))
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size_sun={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size_sun)))
|
||||||
|
assets.add_khafile_def('rp_shadowmap_atlas_max_size={0}'.format(int(rpdat.rp_shadowmap_atlas_max_size)))
|
||||||
|
|
||||||
|
if rpdat.rp_shadowmap_atlas_auto:
|
||||||
|
assets.add_khafile_def('rp_max_lights_cluster={0}'.format(int(rpdat.rp_max_lights)))
|
||||||
|
else:
|
||||||
|
assets.add_khafile_def('rp_max_lights_cluster={0}'.format(int(rpdat.rp_max_lights_cluster)))
|
||||||
assets.add_khafile_def('rp_max_lights={0}'.format(int(rpdat.rp_max_lights)))
|
assets.add_khafile_def('rp_max_lights={0}'.format(int(rpdat.rp_max_lights)))
|
||||||
if rpdat.rp_shadowmap_atlas_lod:
|
if rpdat.rp_shadowmap_atlas_lod:
|
||||||
assets.add_khafile_def('lnx_shadowmap_atlas_lod')
|
assets.add_khafile_def('lnx_shadowmap_atlas_lod')
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
import math
|
||||||
import bpy
|
import bpy
|
||||||
from bpy.props import *
|
from bpy.props import *
|
||||||
|
|
||||||
@ -44,6 +45,18 @@ def update_point_atlas_size_options(scene: bpy.types.Scene, context: bpy.types.C
|
|||||||
return atlas_sizes_from_min(int(rpdat.rp_shadowmap_cube) * 2)
|
return atlas_sizes_from_min(int(rpdat.rp_shadowmap_cube) * 2)
|
||||||
|
|
||||||
|
|
||||||
|
def auto_atlas_size(max_lights: int, tile_size: int, tiles_per_light: int) -> int:
|
||||||
|
"""Automatically calculate the minimum atlas texture size needed to fit max_lights of a given type."""
|
||||||
|
tiles_needed = max_lights * tiles_per_light
|
||||||
|
grid_size = math.ceil(math.sqrt(tiles_needed))
|
||||||
|
needed_pixels = grid_size * tile_size
|
||||||
|
for size_entry in atlas_sizes:
|
||||||
|
size = int(size_entry[0])
|
||||||
|
if size >= needed_pixels:
|
||||||
|
return size
|
||||||
|
return int(atlas_sizes[-1][0])
|
||||||
|
|
||||||
|
|
||||||
def update_preset(self, context):
|
def update_preset(self, context):
|
||||||
rpdat = self.lnx_rplist[-1]
|
rpdat = self.lnx_rplist[-1]
|
||||||
|
|
||||||
@ -332,6 +345,7 @@ class LnxRPListItem(bpy.types.PropertyGroup):
|
|||||||
('64', '64', '64'),],
|
('64', '64', '64'),],
|
||||||
name="Max Lights Shadows", description="Max number of rendered shadow maps that can be visible in the screen. Always equal or lower than Max Lights", default='16')
|
name="Max Lights Shadows", description="Max number of rendered shadow maps that can be visible in the screen. Always equal or lower than Max Lights", default='16')
|
||||||
rp_shadowmap_atlas: BoolProperty(name="Shadow Map Atlasing", description="Group shadow maps of lights of the same type in the same texture", default=False, update=update_renderpath)
|
rp_shadowmap_atlas: BoolProperty(name="Shadow Map Atlasing", description="Group shadow maps of lights of the same type in the same texture", default=False, update=update_renderpath)
|
||||||
|
rp_shadowmap_atlas_auto: BoolProperty(name="Automatic Atlasing", description="Automatically compute atlas sizes based on max lights and shadow map sizes", default=True, update=update_renderpath)
|
||||||
rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=False, update=update_renderpath)
|
rp_shadowmap_atlas_single_map: BoolProperty(name="Shadow Map Atlas single map", description="Use a single texture for all different light types.", default=False, update=update_renderpath)
|
||||||
rp_shadowmap_atlas_lod: BoolProperty(name="Shadow Map Atlas LOD (Experimental)", description="When enabled, the size of the shadow map will be determined on runtime based on the distance of the light to the camera", default=False, update=update_renderpath)
|
rp_shadowmap_atlas_lod: BoolProperty(name="Shadow Map Atlas LOD (Experimental)", description="When enabled, the size of the shadow map will be determined on runtime based on the distance of the light to the camera", default=False, update=update_renderpath)
|
||||||
rp_shadowmap_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=False, update=update_renderpath)
|
rp_shadowmap_transparent: BoolProperty(name="Transparency", description="Enable shadows for transparent objects", default=False, update=update_renderpath)
|
||||||
|
|||||||
@ -1745,92 +1745,113 @@ class LNX_PT_RenderPathShadowsPanel(bpy.types.Panel):
|
|||||||
layout.prop(rpdat, 'rp_shadowmap_atlas')
|
layout.prop(rpdat, 'rp_shadowmap_atlas')
|
||||||
colatlas = layout.column()
|
colatlas = layout.column()
|
||||||
colatlas.enabled = rpdat.rp_shadowmap_atlas
|
colatlas.enabled = rpdat.rp_shadowmap_atlas
|
||||||
|
|
||||||
|
colatlas.prop(rpdat, 'rp_shadowmap_atlas_auto')
|
||||||
|
|
||||||
colatlas.prop(rpdat, 'rp_max_lights')
|
colatlas.prop(rpdat, 'rp_max_lights')
|
||||||
colatlas.prop(rpdat, 'rp_max_lights_cluster')
|
|
||||||
|
if not rpdat.rp_shadowmap_atlas_auto:
|
||||||
|
colatlas.prop(rpdat, 'rp_max_lights_cluster')
|
||||||
|
|
||||||
|
if rpdat.rp_shadowmap_atlas_auto:
|
||||||
|
# Automatic mode: compute sizes from max lights
|
||||||
|
max_lights = int(rpdat.rp_max_lights)
|
||||||
|
cube_size = int(rpdat.rp_shadowmap_cube)
|
||||||
|
cascade_size = int(rpdat.rp_shadowmap_cascade)
|
||||||
|
cascades = int(rpdat.rp_shadowmap_cascades)
|
||||||
|
|
||||||
|
auto_point = lnx.props_renderpath.auto_atlas_size(max_lights, cube_size, 6)
|
||||||
|
auto_spot = lnx.props_renderpath.auto_atlas_size(max_lights, cascade_size, 1)
|
||||||
|
auto_sun = lnx.props_renderpath.auto_atlas_size(max_lights, cascade_size, cascades)
|
||||||
|
|
||||||
|
if auto_point > 2048 or auto_spot > 2048 or auto_sun > 2048:
|
||||||
|
size_warning = True
|
||||||
|
|
||||||
colatlas.prop(rpdat, 'rp_shadowmap_atlas_lod')
|
colatlas.prop(rpdat, 'rp_shadowmap_atlas_lod')
|
||||||
|
|
||||||
colatlas_lod = colatlas.column()
|
if rpdat.rp_shadowmap_atlas_lod:
|
||||||
colatlas_lod.enabled = rpdat.rp_shadowmap_atlas_lod
|
colatlas_lod = colatlas.column()
|
||||||
colatlas_lod.prop(rpdat, 'rp_shadowmap_atlas_lod_subdivisions')
|
colatlas_lod.prop(rpdat, 'rp_shadowmap_atlas_lod_subdivisions')
|
||||||
|
|
||||||
colatlas_lod_info = colatlas_lod.row()
|
|
||||||
colatlas_lod_info.alignment = 'RIGHT'
|
|
||||||
subdivs_list = self.compute_subdivs(int(rpdat.rp_shadowmap_cascade), int(rpdat.rp_shadowmap_atlas_lod_subdivisions))
|
|
||||||
subdiv_text = "Subdivisions for spot lights: " + ', '.join(map(str, subdivs_list))
|
|
||||||
colatlas_lod_info.label(text=subdiv_text, icon="IMAGE_ZDEPTH")
|
|
||||||
|
|
||||||
if not rpdat.rp_shadowmap_atlas_single_map:
|
|
||||||
colatlas_lod_info = colatlas_lod.row()
|
colatlas_lod_info = colatlas_lod.row()
|
||||||
colatlas_lod_info.alignment = 'RIGHT'
|
colatlas_lod_info.alignment = 'RIGHT'
|
||||||
subdivs_list = self.compute_subdivs(int(rpdat.rp_shadowmap_cube), int(rpdat.rp_shadowmap_atlas_lod_subdivisions))
|
subdivs_list = self.compute_subdivs(int(rpdat.rp_shadowmap_cascade), int(rpdat.rp_shadowmap_atlas_lod_subdivisions))
|
||||||
subdiv_text = "Subdivisions for point lights: " + ', '.join(map(str, subdivs_list))
|
subdiv_text = "Subdivisions for spot lights: " + ', '.join(map(str, subdivs_list))
|
||||||
colatlas_lod_info.label(text=subdiv_text, icon="IMAGE_ZDEPTH")
|
colatlas_lod_info.label(text=subdiv_text, icon="IMAGE_ZDEPTH")
|
||||||
|
|
||||||
|
if not rpdat.rp_shadowmap_atlas_single_map:
|
||||||
|
colatlas_lod_info = colatlas_lod.row()
|
||||||
|
colatlas_lod_info.alignment = 'RIGHT'
|
||||||
|
subdivs_list = self.compute_subdivs(int(rpdat.rp_shadowmap_cube), int(rpdat.rp_shadowmap_atlas_lod_subdivisions))
|
||||||
|
subdiv_text = "Subdivisions for point lights: " + ', '.join(map(str, subdivs_list))
|
||||||
|
colatlas_lod_info.label(text=subdiv_text, icon="IMAGE_ZDEPTH")
|
||||||
|
|
||||||
size_warning = int(rpdat.rp_shadowmap_cascade) > 2048 or int(rpdat.rp_shadowmap_cube) > 2048
|
size_warning = int(rpdat.rp_shadowmap_cascade) > 2048 or int(rpdat.rp_shadowmap_cube) > 2048
|
||||||
|
|
||||||
colatlas.prop(rpdat, 'rp_shadowmap_atlas_single_map')
|
colatlas.prop(rpdat, 'rp_shadowmap_atlas_single_map')
|
||||||
# show size for single texture
|
if not rpdat.rp_shadowmap_atlas_auto:
|
||||||
if rpdat.rp_shadowmap_atlas_single_map:
|
# show size for single texture
|
||||||
colatlas_single = colatlas.column()
|
if rpdat.rp_shadowmap_atlas_single_map:
|
||||||
colatlas_single.prop(rpdat, 'rp_shadowmap_atlas_max_size')
|
colatlas_single = colatlas.column()
|
||||||
if rpdat.rp_shadowmap_atlas_max_size != '':
|
colatlas_single.prop(rpdat, 'rp_shadowmap_atlas_max_size')
|
||||||
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size)
|
if rpdat.rp_shadowmap_atlas_max_size != '':
|
||||||
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
|
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size)
|
||||||
|
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
|
||||||
|
|
||||||
if shadowmap_size > 2048:
|
if shadowmap_size > 2048:
|
||||||
size_warning = True
|
size_warning = True
|
||||||
|
|
||||||
point_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'point')
|
point_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'point')
|
||||||
spot_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'spot')
|
spot_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'spot')
|
||||||
dir_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'sun')
|
dir_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'sun')
|
||||||
|
|
||||||
col = colatlas_single.row()
|
col = colatlas_single.row()
|
||||||
col.alignment = 'RIGHT'
|
col.alignment = 'RIGHT'
|
||||||
col.label(text=f'Enough space for { point_lights } point lights or { spot_lights } spot lights or { dir_lights } directional lights.')
|
col.label(text=f'Enough space for { point_lights } point lights or { spot_lights } spot lights or { dir_lights } directional lights.')
|
||||||
else:
|
else:
|
||||||
# show size for all types
|
# show size for all types
|
||||||
colatlas_mixed = colatlas.column()
|
colatlas_mixed = colatlas.column()
|
||||||
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_spot')
|
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_spot')
|
||||||
|
|
||||||
if rpdat.rp_shadowmap_atlas_max_size_spot != '':
|
if rpdat.rp_shadowmap_atlas_max_size_spot != '':
|
||||||
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_spot)
|
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_spot)
|
||||||
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
|
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
|
||||||
spot_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'spot')
|
spot_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'spot')
|
||||||
|
|
||||||
if shadowmap_size > 2048:
|
if shadowmap_size > 2048:
|
||||||
size_warning = True
|
size_warning = True
|
||||||
|
|
||||||
col = colatlas_mixed.row()
|
col = colatlas_mixed.row()
|
||||||
col.alignment = 'RIGHT'
|
col.alignment = 'RIGHT'
|
||||||
col.label(text=f'Enough space for {spot_lights} spot lights.')
|
col.label(text=f'Enough space for {spot_lights} spot lights.')
|
||||||
|
|
||||||
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_point')
|
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_point')
|
||||||
|
|
||||||
if rpdat.rp_shadowmap_atlas_max_size_point != '':
|
if rpdat.rp_shadowmap_atlas_max_size_point != '':
|
||||||
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_point)
|
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_point)
|
||||||
shadowmap_size = int(rpdat.rp_shadowmap_cube)
|
shadowmap_size = int(rpdat.rp_shadowmap_cube)
|
||||||
point_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'point')
|
point_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'point')
|
||||||
|
|
||||||
if shadowmap_size > 2048:
|
if shadowmap_size > 2048:
|
||||||
size_warning = True
|
size_warning = True
|
||||||
|
|
||||||
col = colatlas_mixed.row()
|
col = colatlas_mixed.row()
|
||||||
col.alignment = 'RIGHT'
|
col.alignment = 'RIGHT'
|
||||||
col.label(text=f'Enough space for {point_lights} point lights.')
|
col.label(text=f'Enough space for {point_lights} point lights.')
|
||||||
|
|
||||||
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_sun')
|
colatlas_mixed.prop(rpdat, 'rp_shadowmap_atlas_max_size_sun')
|
||||||
|
|
||||||
if rpdat.rp_shadowmap_atlas_max_size_sun != '':
|
if rpdat.rp_shadowmap_atlas_max_size_sun != '':
|
||||||
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_sun)
|
atlas_size = int(rpdat.rp_shadowmap_atlas_max_size_sun)
|
||||||
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
|
shadowmap_size = int(rpdat.rp_shadowmap_cascade)
|
||||||
dir_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'sun')
|
dir_lights = self.lights_number_atlas(rpdat, atlas_size, shadowmap_size, 'sun')
|
||||||
|
|
||||||
if shadowmap_size > 2048:
|
if shadowmap_size > 2048:
|
||||||
size_warning = True
|
size_warning = True
|
||||||
|
|
||||||
col = colatlas_mixed.row()
|
col = colatlas_mixed.row()
|
||||||
col.alignment = 'RIGHT'
|
col.alignment = 'RIGHT'
|
||||||
col.label(text=f'Enough space for {dir_lights} directional lights.')
|
col.label(text=f'Enough space for {dir_lights} directional lights.')
|
||||||
|
|
||||||
# show warning when user picks a size higher than 2048 (arbitrary number).
|
# show warning when user picks a size higher than 2048 (arbitrary number).
|
||||||
if size_warning:
|
if size_warning:
|
||||||
|
|||||||
Reference in New Issue
Block a user