38 Commits
main ... e2002e

Author SHA1 Message Date
316441b954 merge upstream 2025-05-20 20:00:31 +00:00
9bf83bc49f Update leenkx/blender/lnx/material/make_mesh.py 2025-04-18 22:52:53 +00:00
d88e1f0f42 Update leenkx/blender/lnx/material/make_cluster.py 2025-04-18 22:52:03 +00:00
96f4e29778 Update leenkx/blender/lnx/material/make_mesh.py 2025-04-12 08:49:04 +00:00
1d705d2ca2 Update leenkx/blender/lnx/material/make_cluster.py 2025-04-12 08:48:33 +00:00
0979cd976f Update leenkx/blender/lnx/write_data.py 2025-04-11 22:20:24 +00:00
db6d786ee4 merge upstream 2025-04-11 22:06:01 +00:00
106e36e30d merge upstream 2025-04-10 17:16:12 +00:00
2bb296028f merge upstream 2025-04-09 17:30:27 +00:00
25d7ba3e72 merge upstream 2025-04-08 06:33:53 +00:00
bf7b4416ec Update leenkx/blender/lnx/make_renderpath.py 2025-04-07 17:29:09 +00:00
a2d03cfe6e Update leenkx/Shaders/std/light.glsl 2025-04-07 17:26:00 +00:00
95f0ecfc54 Update leenkx/Sources/leenkx/system/Starter.hx 2025-04-07 17:07:52 +00:00
07f59224fc Update leenkx/blender/lnx/write_data.py 2025-04-07 16:50:46 +00:00
02259985be Update leenkx/blender/lnx/props.py 2025-04-07 16:46:33 +00:00
6b8585c81a Update leenkx/blender/lnx/props_renderpath.py 2025-04-07 16:43:01 +00:00
5d78eabf94 Update leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py 2025-04-07 16:39:49 +00:00
41c1459c4e Update leenkx/blender/lnx/material/make_voxel.py 2025-04-07 16:34:12 +00:00
304a497565 Update leenkx/blender/lnx/make_renderpath.py 2025-04-07 16:27:25 +00:00
9fa399371a Update leenkx/blender/lnx/material/make_mesh.py 2025-04-07 16:25:06 +00:00
4625fdb6b2 Update leenkx/blender/lnx/material/make_cluster.py 2025-04-07 16:13:16 +00:00
79553927aa Update leenkx/Shaders/water_pass/water_pass.frag.glsl 2025-04-07 16:06:53 +00:00
86661c1012 Update leenkx/Shaders/voxel_light/voxel_light.comp.glsl 2025-04-07 16:04:17 +00:00
03967c7a2b Update leenkx/Sources/leenkx/system/Starter.hx 2025-04-07 15:50:41 +00:00
61fd48a12f Update leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl 2025-04-07 15:47:22 +00:00
519039b8b6 Update leenkx/Shaders/std/light.glsl 2025-04-07 15:45:04 +00:00
5244b1b3e8 Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx 2025-04-07 15:41:41 +00:00
7ae3bbe496 Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx 2025-04-07 15:39:38 +00:00
001be2f8da Update leenkx/Sources/leenkx/renderpath/Inc.hx 2025-04-07 15:35:22 +00:00
6a25b3c5d7 Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl 2025-04-07 15:28:46 +00:00
8d4ac7251a Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-04-07 15:22:49 +00:00
ae63b252c6 Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl 2025-04-07 15:19:03 +00:00
ee73823206 Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl 2025-04-07 15:17:43 +00:00
af2850e20c Update leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl 2025-04-07 14:49:37 +00:00
bc4a31d415 Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl 2025-04-07 14:47:58 +00:00
5303ad3ac6 Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl 2025-04-07 14:44:14 +00:00
5153cff790 Update leenkx/Shaders/std/shadows.glsl 2025-04-07 14:41:53 +00:00
abe17870ce Update leenkx/Shaders/std/conetrace.glsl 2025-04-07 14:38:30 +00:00
889 changed files with 1334 additions and 6231 deletions

2
.gitattributes vendored
View File

@ -1,2 +0,0 @@
*.hdr binary
blender/lnx/props.py ident

3
.gitignore vendored
View File

@ -1,3 +0,0 @@
__pycache__/
*.pyc
*.DS_Store

0
Krom/Krom Executable file → Normal file
View File

View File

@ -2,12 +2,10 @@
-cp ../Kha/Backends/Krom -cp ../Kha/Backends/Krom
-cp ../leenkx/Sources -cp ../leenkx/Sources
-cp ../iron/Sources -cp ../iron/Sources
-cp ../lib/aura/Sources
-cp ../lib/haxebullet/Sources -cp ../lib/haxebullet/Sources
-cp ../lib/haxerecast/Sources -cp ../lib/haxerecast/Sources
-cp ../lib/zui/Sources -cp ../lib/zui/Sources
--macro include('iron', true, null, ['../iron/Sources']) --macro include('iron', true, null, ['../iron/Sources'])
--macro include('aura', true, null, ['../lib/aura/Sources'])
--macro include('haxebullet', true, null, ['../lib/haxebullet/Sources']) --macro include('haxebullet', true, null, ['../lib/haxebullet/Sources'])
--macro include('haxerecast', true, null, ['../lib/haxerecast/Sources']) --macro include('haxerecast', true, null, ['../lib/haxerecast/Sources'])
--macro include('leenkx', true, ['leenkx.network'], ['../leenkx/Sources','../iron/Sources']) --macro include('leenkx', true, ['leenkx.network'], ['../leenkx/Sources','../iron/Sources'])

View File

@ -3,10 +3,6 @@
#include "compiled.inc" #include "compiled.inc"
#ifdef _CPostprocess
uniform vec4 PPComp17;
#endif
uniform sampler2D tex; uniform sampler2D tex;
uniform vec2 dir; uniform vec2 dir;
uniform vec2 screenSize; uniform vec2 screenSize;
@ -49,12 +45,6 @@ void main() {
res += factor * col; res += factor * col;
} }
#ifdef _CPostprocess
vec3 AirColor = vec3(PPComp17.x, PPComp17.y, PPComp17.z);
#else
vec3 AirColor = volumAirColor;
#endif
res /= sumfactor; res /= sumfactor;
fragColor = vec4(AirColor * res, 1.0); fragColor = vec4(volumAirColor * res, 1.0);
} }

View File

@ -19,11 +19,6 @@
{ {
"name": "screenSize", "name": "screenSize",
"link": "_screenSize" "link": "_screenSize"
},
{
"name": "PPComp17",
"link": "_PPComp17",
"ifdef": ["_CPostprocess"]
} }
], ],
"texture_params": [], "texture_params": [],

View File

@ -5,7 +5,7 @@
uniform sampler2D tex; uniform sampler2D tex;
#ifdef _CPostprocess #ifdef _CPostprocess
uniform vec4 PPComp13; uniform vec3 PPComp13;
#endif #endif
in vec2 texCoord; in vec2 texCoord;
@ -43,17 +43,13 @@ void main() {
#ifdef _CPostprocess #ifdef _CPostprocess
float max_distort = PPComp13.x; float max_distort = PPComp13.x;
int num_iter = int(PPComp13.y); int num_iter = int(PPComp13.y);
int CAType = int(PPComp13.z);
int on = int(PPComp13.w);
#else #else
float max_distort = compoChromaticStrength; float max_distort = compoChromaticStrength;
int num_iter = compoChromaticSamples; int num_iter = compoChromaticSamples;
int CAType = compoChromaticType;
int on = 1;
#endif #endif
// Spectral // Spectral
if (CAType == 1) { if (compoChromaticType == 1) {
float reci_num_iter_f = 1.0 / float(num_iter); float reci_num_iter_f = 1.0 / float(num_iter);
vec2 resolution = vec2(1,1); vec2 resolution = vec2(1,1);
@ -68,7 +64,7 @@ void main() {
sumcol += w * texture(tex, barrelDistortion(uv, 0.6 * max_distort * t)); sumcol += w * texture(tex, barrelDistortion(uv, 0.6 * max_distort * t));
} }
if (on == 1) fragColor = sumcol / sumw; else fragColor = texture(tex, texCoord); fragColor = sumcol / sumw;
} }
// Simple // Simple
@ -77,7 +73,6 @@ void main() {
col.x = texture(tex, texCoord + ((vec2(0.0, 1.0) * max_distort) / vec2(1000.0))).x; col.x = texture(tex, texCoord + ((vec2(0.0, 1.0) * max_distort) / vec2(1000.0))).x;
col.y = texture(tex, texCoord + ((vec2(-0.85, -0.5) * max_distort) / vec2(1000.0))).y; col.y = texture(tex, texCoord + ((vec2(-0.85, -0.5) * max_distort) / vec2(1000.0))).y;
col.z = texture(tex, texCoord + ((vec2(0.85, -0.5) * max_distort) / vec2(1000.0))).z; col.z = texture(tex, texCoord + ((vec2(0.85, -0.5) * max_distort) / vec2(1000.0))).z;
if (on == 1) fragColor = vec4(col.x, col.y, col.z, fragColor.w); fragColor = vec4(col.x, col.y, col.z, fragColor.w);
else fragColor = texture(tex, texCoord);
} }
} }

View File

@ -62,11 +62,8 @@ uniform vec3 PPComp5;
uniform vec3 PPComp6; uniform vec3 PPComp6;
uniform vec3 PPComp7; uniform vec3 PPComp7;
uniform vec3 PPComp8; uniform vec3 PPComp8;
uniform vec3 PPComp11;
uniform vec3 PPComp14; uniform vec3 PPComp14;
uniform vec4 PPComp15; uniform vec4 PPComp15;
uniform vec4 PPComp16;
uniform vec4 PPComp18;
#endif #endif
// #ifdef _CPos // #ifdef _CPos
@ -109,16 +106,6 @@ in vec2 texCoord;
out vec4 fragColor; out vec4 fragColor;
#ifdef _CFog #ifdef _CFog
#ifdef _CPostprocess
vec3 FogColor = vec3(PPComp18.x, PPComp18.y, PPComp18.z);
float FogAmountA = PPComp18.w;
float FogAmountB = PPComp11.z;
#else
vec3 FogColor = compoFogColor;
float FogAmountA = compoFogAmountA;
float FogAmountB = compoFogAmountB;
#endif
// const vec3 compoFogColor = vec3(0.5, 0.6, 0.7); // const vec3 compoFogColor = vec3(0.5, 0.6, 0.7);
// const float compoFogAmountA = 1.0; // b = 0.01 // const float compoFogAmountA = 1.0; // b = 0.01
// const float compoFogAmountB = 1.0; // c = 0.1 // const float compoFogAmountB = 1.0; // c = 0.1
@ -131,8 +118,8 @@ out vec4 fragColor;
// } // }
vec3 applyFog(vec3 rgb, float distance) { vec3 applyFog(vec3 rgb, float distance) {
// float fogAmount = 1.0 - exp(-distance * compoFogAmountA); // float fogAmount = 1.0 - exp(-distance * compoFogAmountA);
float fogAmount = 1.0 - exp(-distance * (FogAmountA / 100)); float fogAmount = 1.0 - exp(-distance * (compoFogAmountA / 100));
return mix(rgb, FogColor, fogAmount); return mix(rgb, compoFogColor, fogAmount);
} }
#endif #endif
@ -144,7 +131,7 @@ float ConvertEV100ToExposure(float EV100) {
return 1/0.8 * exp2(-EV100); return 1/0.8 * exp2(-EV100);
} }
float ComputeEV(float avgLuminance) { float ComputeEV(float avgLuminance) {
const float sqAperture = PPComp1.x * PPComp1.x; const float sqAperture = PPComp1[0].x * PPComp1.x;
const float shutterTime = 1.0 / PPComp1.y; const float shutterTime = 1.0 / PPComp1.y;
const float ISO = PPComp1.z; const float ISO = PPComp1.z;
const float EC = PPComp2.x; const float EC = PPComp2.x;
@ -362,22 +349,16 @@ void main() {
#ifdef _CSharpen #ifdef _CSharpen
#ifdef _CPostprocess #ifdef _CPostprocess
float strengthSharpen = PPComp14.y; float strengthSharpen = PPComp14.y;
vec3 SharpenColor = vec3(PPComp16.x, PPComp16.y, PPComp16.z);
float SharpenSize = PPComp16.w;
#else #else
float strengthSharpen = compoSharpenStrength; float strengthSharpen = compoSharpenStrength;
vec3 SharpenColor = compoSharpenColor;
float SharpenSize = compoSharpenSize;
#endif #endif
vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * SharpenSize, 0.0).rgb; vec3 col1 = textureLod(tex, texCo + vec2(-texStep.x, -texStep.y) * 1.5, 0.0).rgb;
vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * SharpenSize, 0.0).rgb; vec3 col2 = textureLod(tex, texCo + vec2(texStep.x, -texStep.y) * 1.5, 0.0).rgb;
vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * SharpenSize, 0.0).rgb; vec3 col3 = textureLod(tex, texCo + vec2(-texStep.x, texStep.y) * 1.5, 0.0).rgb;
vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * SharpenSize, 0.0).rgb; vec3 col4 = textureLod(tex, texCo + vec2(texStep.x, texStep.y) * 1.5, 0.0).rgb;
vec3 colavg = (col1 + col2 + col3 + col4) * 0.25; vec3 colavg = (col1 + col2 + col3 + col4) * 0.25;
fragColor.rgb += (fragColor.rgb - colavg) * strengthSharpen;
float edgeMagnitude = length(fragColor.rgb - colavg);
fragColor.rgb = mix(fragColor.rgb, SharpenColor, min(edgeMagnitude * strengthSharpen * 2.0, 1.0));
#endif #endif
#ifdef _CFog #ifdef _CFog
@ -426,11 +407,7 @@ void main() {
#endif #endif
#ifdef _CExposure #ifdef _CExposure
#ifdef _CPostprocess fragColor.rgb += fragColor.rgb * compoExposureStrength;
fragColor.rgb+=fragColor.rgb*PPComp8.x;
#else
fragColor.rgb+= fragColor.rgb*compoExposureStrength;
#endif
#endif #endif
#ifdef _CPostprocess #ifdef _CPostprocess
@ -438,13 +415,8 @@ void main() {
#endif #endif
#ifdef _AutoExposure #ifdef _AutoExposure
#ifdef _CPostprocess
float AEStrength = PPComp8.y;
#else
float AEStrength = autoExposureStrength;
#endif
float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0); float expo = 2.0 - clamp(length(textureLod(histogram, vec2(0.5, 0.5), 0).rgb), 0.0, 1.0);
fragColor.rgb *= pow(expo, AEStrength * 2.0); fragColor.rgb *= pow(expo, autoExposureStrength * 2.0);
#endif #endif
// Clamp color to get rid of INF values that don't work for the tone mapping below // Clamp color to get rid of INF values that don't work for the tone mapping below
@ -508,7 +480,9 @@ fragColor.rgb = min(fragColor.rgb, 65504 * 0.5);
fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma fragColor.rgb = pow(fragColor.rgb, vec3(1.0 / 2.2)); // To gamma
} else if (PPComp4.x == 10){ } else if (PPComp4.x == 10){
fragColor.rgb = tonemapAgXFull(fragColor.rgb); fragColor.rgb = tonemapAgXFull(fragColor.rgb);
} //else { fragColor.rgb = vec3(0,1,0); //ERROR} } else {
fragColor.rgb = vec3(0,1,0); //ERROR
}
#endif #endif
#else #else

View File

@ -235,16 +235,6 @@
"name": "PPComp15", "name": "PPComp15",
"link": "_PPComp15", "link": "_PPComp15",
"ifdef": ["_CPostprocess"] "ifdef": ["_CPostprocess"]
},
{
"name": "PPComp16",
"link": "_PPComp16",
"ifdef": ["_CPostprocess"]
},
{
"name": "PPComp18",
"link": "_PPComp18",
"ifdef": ["_CPostprocess"]
} }
], ],
"texture_params": [], "texture_params": [],

View File

@ -20,7 +20,7 @@ uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1; uniform sampler2D gbuffer1;
#ifdef _gbuffer2 #ifdef _gbuffer2
uniform sampler2D gbuffer2; //!uniform sampler2D gbuffer2;
#endif #endif
#ifdef _EmissionShaded #ifdef _EmissionShaded
uniform sampler2D gbufferEmission; uniform sampler2D gbufferEmission;
@ -286,7 +286,7 @@ void main() {
#ifdef _VoxelGI #ifdef _VoxelGI
vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0); vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0);
fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff; fragColor.rgb = (indirect_diffuse.rgb + envl.rgb * (1.0 - indirect_diffuse.a)) * albedo * voxelgiDiff;
if(roughness < 1.0 && occspec.y > 0.0) if(roughness < 1.0 && occspec.y > 0.0)
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl; fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
#endif #endif
@ -380,7 +380,7 @@ void main() {
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad;
#endif #endif
#ifdef _SSRS #ifdef _SSRS

View File

@ -2,22 +2,13 @@
#include "compiled.inc" #include "compiled.inc"
#ifdef _CPostprocess
uniform vec3 PPComp8;
#endif
uniform sampler2D tex; uniform sampler2D tex;
in vec2 texCoord; in vec2 texCoord;
out vec4 fragColor; out vec4 fragColor;
void main() { void main() {
#ifdef _CPostprocess fragColor.a = 0.01 * autoExposureSpeed;
fragColor.a = 0.01 * PPComp8.z;
#else
fragColor.a = 0.01 * autoExposureSpeed;
#endif
fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb + fragColor.rgb = textureLod(tex, vec2(0.5, 0.5), 0.0).rgb +
textureLod(tex, vec2(0.2, 0.2), 0.0).rgb + textureLod(tex, vec2(0.2, 0.2), 0.0).rgb +
textureLod(tex, vec2(0.8, 0.2), 0.0).rgb + textureLod(tex, vec2(0.8, 0.2), 0.0).rgb +

View File

@ -8,13 +8,7 @@
"blend_source": "source_alpha", "blend_source": "source_alpha",
"blend_destination": "inverse_source_alpha", "blend_destination": "inverse_source_alpha",
"blend_operation": "add", "blend_operation": "add",
"links": [ "links": [],
{
"name": "PPComp8",
"link": "_PPComp8",
"ifdef": ["_CPostprocess"]
}
],
"texture_params": [], "texture_params": [],
"vertex_shader": "../include/pass.vert.glsl", "vertex_shader": "../include/pass.vert.glsl",
"fragment_shader": "histogram_pass.frag.glsl" "fragment_shader": "histogram_pass.frag.glsl"

View File

@ -92,7 +92,7 @@ void main() {
vec3 viewNormal = V3 * n; vec3 viewNormal = V3 * n;
vec3 viewPos = getPosView(viewRay, d, cameraProj); vec3 viewPos = getPosView(viewRay, d, cameraProj);
vec3 reflected = reflect(viewPos, viewNormal); vec3 reflected = reflect(normalize(viewPos), viewNormal);
hitCoord = viewPos; hitCoord = viewPos;
#ifdef _CPostprocess #ifdef _CPostprocess

View File

@ -57,14 +57,17 @@ vec4 binarySearch(vec3 dir) {
} }
vec4 rayCast(vec3 dir) { vec4 rayCast(vec3 dir) {
float ddepth; float ddepth;
dir *= ss_refractionRayStep; dir *= ss_refractionRayStep;
for (int i = 0; i < maxSteps; i++) { for (int i = 0; i < maxSteps; i++) {
hitCoord += dir; hitCoord += dir;
ddepth = getDeltaDepth(hitCoord); ddepth = getDeltaDepth(hitCoord);
if (ddepth > 0.0) return binarySearch(dir); if (ddepth > 0.0)
} return binarySearch(dir);
return vec4(texCoord, 0.0, 1.0); }
// No hit — fallback to projecting the ray to UV space
vec2 fallbackUV = getProjectedCoord(hitCoord);
return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback
} }
void main() { void main() {
@ -74,7 +77,7 @@ void main() {
float ior = gr.x; float ior = gr.x;
float opac = gr.y; float opac = gr.y;
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0;
if (d == 0.0 || d == 1.0 || opac == 1.0 || ior == 1.0) { if (d == 0.0 || opac == 1.0 || ior == 1.0) {
fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb; fragColor.rgb = textureLod(tex1, texCoord, 0.0).rgb;
return; return;
} }

View File

@ -97,9 +97,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
vec3 aniso_direction = -dir; vec3 aniso_direction = -dir;
vec3 face_offset = vec3( vec3 face_offset = vec3(
aniso_direction.x > 0.0 ? 0.0 : 1.0, aniso_direction.x > 0.0 ? 0 : 1,
aniso_direction.y > 0.0 ? 2.0 : 3.0, aniso_direction.y > 0.0 ? 2 : 3,
aniso_direction.z > 0.0 ? 4.0 : 5.0 aniso_direction.z > 0.0 ? 4 : 5
) / (6 + DIFFUSE_CONE_COUNT); ) / (6 + DIFFUSE_CONE_COUNT);
vec3 direction_weight = abs(dir); vec3 direction_weight = abs(dir);
@ -166,7 +166,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels,
} }
vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
vec3 specularDir = reflect(-viewDir, normal); vec3 specularDir = reflect(normalize(-viewDir), normal);
vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
@ -176,9 +176,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels,
return amount * voxelgiOcc; return amount * voxelgiOcc;
} }
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) {
const float transmittance = 1.0; const float transmittance = 1.0 - opacity;
vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior);
vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
@ -201,9 +201,9 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
vec3 aniso_direction = -dir; vec3 aniso_direction = -dir;
vec3 face_offset = vec3( vec3 face_offset = vec3(
aniso_direction.x > 0.0 ? 0.0 : 1.0, aniso_direction.x > 0.0 ? 0 : 1,
aniso_direction.y > 0.0 ? 2.0 : 3.0, aniso_direction.y > 0.0 ? 2 : 3,
aniso_direction.z > 0.0 ? 4.0 : 5.0 aniso_direction.z > 0.0 ? 4 : 5
) / (6 + DIFFUSE_CONE_COUNT); ) / (6 + DIFFUSE_CONE_COUNT);
vec3 direction_weight = abs(dir); vec3 direction_weight = abs(dir);
@ -272,9 +272,9 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
vec3 aniso_direction = -dir; vec3 aniso_direction = -dir;
vec3 face_offset = vec3( vec3 face_offset = vec3(
aniso_direction.x > 0.0 ? 0.0 : 1.0, aniso_direction.x > 0.0 ? 0 : 1,
aniso_direction.y > 0.0 ? 2.0 : 3.0, aniso_direction.y > 0.0 ? 2 : 3,
aniso_direction.z > 0.0 ? 4.0 : 5.0 aniso_direction.z > 0.0 ? 4 : 5
) / (6 + DIFFUSE_CONE_COUNT); ) / (6 + DIFFUSE_CONE_COUNT);
vec3 direction_weight = abs(dir); vec3 direction_weight = abs(dir);
float coneCoefficient = 2.0 * tan(aperture * 0.5); float coneCoefficient = 2.0 * tan(aperture * 0.5);
@ -328,8 +328,8 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
} }
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps);
amount = clamp(amount, 0.0, 1.0); amount = clamp(amount, 0.0, 1.0);
return amount * voxelgiOcc; return amount * voxelgiOcc;

View File

@ -1,239 +1,242 @@
#ifndef _LIGHT_GLSL_ #ifndef _LIGHT_GLSL_
#define _LIGHT_GLSL_ #define _LIGHT_GLSL_
#include "compiled.inc" #include "compiled.inc"
#include "std/brdf.glsl" #include "std/brdf.glsl"
#include "std/math.glsl" #include "std/math.glsl"
#ifdef _ShadowMap #ifdef _ShadowMap
#include "std/shadows.glsl" #include "std/shadows.glsl"
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
#include "std/conetrace.glsl" #include "std/conetrace.glsl"
//!uniform sampler2D voxels_shadows; #endif
#endif #ifdef _gbuffer2
#ifdef _LTC uniform sampler2D gbuffer2;
#include "std/ltc.glsl" #endif
#endif #ifdef _LTC
#ifdef _LightIES #include "std/ltc.glsl"
#include "std/ies.glsl" #endif
#endif #ifdef _LightIES
#ifdef _SSRS #include "std/ies.glsl"
#include "std/ssrs.glsl" #endif
#endif #ifdef _SSRS
#ifdef _Spot #include "std/ssrs.glsl"
#include "std/light_common.glsl" #endif
#endif #ifdef _Spot
#include "std/light_common.glsl"
#ifdef _ShadowMap #endif
#ifdef _SinglePoint
#ifdef _Spot #ifdef _ShadowMap
#ifndef _LTC #ifdef _SinglePoint
uniform sampler2DShadow shadowMapSpot[1]; #ifdef _Spot
uniform sampler2D shadowMapSpotTransparent[1]; #ifndef _LTC
uniform mat4 LWVPSpot[1]; uniform sampler2DShadow shadowMapSpot[1];
#endif uniform sampler2D shadowMapSpotTransparent[1];
#else uniform mat4 LWVPSpot[1];
uniform samplerCubeShadow shadowMapPoint[1]; #endif
uniform samplerCube shadowMapPointTransparent[1]; #else
uniform vec2 lightProj; uniform samplerCubeShadow shadowMapPoint[1];
#endif uniform samplerCube shadowMapPointTransparent[1];
#endif uniform vec2 lightProj;
#ifdef _Clusters #endif
#ifdef _SingleAtlas #endif
//!uniform sampler2DShadow shadowMapAtlas; #ifdef _Clusters
//!uniform sampler2D shadowMapAtlasTransparent; #ifdef _SingleAtlas
#endif //!uniform sampler2DShadow shadowMapAtlas;
uniform vec2 lightProj; //!uniform sampler2D shadowMapAtlasTransparent;
#ifdef _ShadowMapAtlas #endif
#ifndef _SingleAtlas uniform vec2 lightProj;
uniform sampler2DShadow shadowMapAtlasPoint; #ifdef _ShadowMapAtlas
uniform sampler2D shadowMapAtlasPointTransparent; #ifndef _SingleAtlas
#endif uniform sampler2DShadow shadowMapAtlasPoint;
#else uniform sampler2D shadowMapAtlasPointTransparent;
uniform samplerCubeShadow shadowMapPoint[4]; #endif
uniform samplerCube shadowMapPointTransparent[4]; #else
#endif uniform samplerCubeShadow shadowMapPoint[4];
#ifdef _Spot uniform samplerCube shadowMapPointTransparent[4];
#ifdef _ShadowMapAtlas #endif
#ifndef _SingleAtlas #ifdef _Spot
uniform sampler2DShadow shadowMapAtlasSpot; #ifdef _ShadowMapAtlas
uniform sampler2D shadowMapAtlasSpotTransparent; #ifndef _SingleAtlas
#endif uniform sampler2DShadow shadowMapAtlasSpot;
#else uniform sampler2D shadowMapAtlasSpotTransparent;
uniform sampler2DShadow shadowMapSpot[4]; #endif
uniform sampler2D shadowMapSpotTransparent[4]; #else
#endif uniform sampler2DShadow shadowMapSpot[4];
uniform mat4 LWVPSpotArray[maxLightsCluster]; uniform sampler2D shadowMapSpotTransparent[4];
#endif #endif
#endif uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif
#ifdef _LTC #endif
uniform vec3 lightArea0;
uniform vec3 lightArea1; #ifdef _LTC
uniform vec3 lightArea2; uniform vec3 lightArea0;
uniform vec3 lightArea3; uniform vec3 lightArea1;
uniform sampler2D sltcMat; uniform vec3 lightArea2;
uniform sampler2D sltcMag; uniform vec3 lightArea3;
#ifdef _ShadowMap uniform sampler2D sltcMat;
#ifndef _Spot uniform sampler2D sltcMag;
#ifdef _SinglePoint #ifdef _ShadowMap
uniform sampler2DShadow shadowMapSpot[1]; #ifndef _Spot
uniform sampler2D shadowMapSpotTransparent[1]; #ifdef _SinglePoint
uniform mat4 LWVPSpot[1]; uniform sampler2DShadow shadowMapSpot[1];
#endif uniform sampler2D shadowMapSpotTransparent[1];
#ifdef _Clusters uniform mat4 LWVPSpot[1];
uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; #endif
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; #ifdef _Clusters
uniform mat4 LWVPSpotArray[maxLightsCluster]; uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
#endif uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
#endif uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif #endif
#endif
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, #endif
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
, int index, float bias, bool receiveShadow, bool transparent const vec3 albedo, const float rough, const float spec, const vec3 f0
#endif #ifdef _ShadowMap
#ifdef _Spot , int index, float bias, bool receiveShadow, bool transparent
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right #endif
#endif #ifdef _Spot
#ifdef _VoxelShadow , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] #endif
#endif #ifdef _VoxelShadow
#ifdef _MicroShadowing , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount]
, float occ #endif
#endif #ifdef _MicroShadowing
#ifdef _SSRS , float occ
, sampler2D gbufferD, mat4 invVP, vec3 eye #endif
#endif #ifdef _SSRS
) { , sampler2D gbufferD, mat4 invVP, vec3 eye
vec3 ld = lp - p; #endif
vec3 l = normalize(ld); ) {
vec3 h = normalize(v + l); vec3 ld = lp - p;
float dotNH = max(0.0, dot(n, h)); vec3 l = normalize(ld);
float dotVH = max(0.0, dot(v, h)); vec3 h = normalize(v + l);
float dotNL = max(0.0, dot(n, l)); float dotNH = max(0.0, dot(n, h));
float dotVH = max(0.0, dot(v, h));
#ifdef _LTC float dotNL = max(0.0, dot(n, l));
float theta = acos(dotNV);
vec2 tuv = vec2(rough, theta / (0.5 * PI)); #ifdef _LTC
tuv = tuv * LUT_SCALE + LUT_BIAS; float theta = acos(dotNV);
vec4 t = textureLod(sltcMat, tuv, 0.0); vec2 tuv = vec2(rough, theta / (0.5 * PI));
mat3 invM = mat3( tuv = tuv * LUT_SCALE + LUT_BIAS;
vec3(1.0, 0.0, t.y), vec4 t = textureLod(sltcMat, tuv, 0.0);
vec3(0.0, t.z, 0.0), mat3 invM = mat3(
vec3(t.w, 0.0, t.x)); vec3(1.0, 0.0, t.y),
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3); vec3(0.0, t.z, 0.0),
ltcspec *= textureLod(sltcMag, tuv, 0.0).a; vec3(t.w, 0.0, t.x));
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3); float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05; ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
#else float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) + vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec; #else
#endif vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
direct *= attenuate(distance(p, lp)); #endif
direct *= lightCol;
direct *= attenuate(distance(p, lp));
#ifdef _MicroShadowing direct *= lightCol;
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
#endif #ifdef _MicroShadowing
direct *= clamp(dotNL + 2.0 * occ * occ - 1.0, 0.0, 1.0);
#ifdef _SSRS #endif
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
#endif #ifdef _SSRS
direct *= traceShadowSS(l, p, gbufferD, invVP, eye);
#ifdef _VoxelShadow #endif
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad;
#endif #ifdef _VoxelShadow
vec4 g2 = textureLod(gbuffer2, gl_FragCoord.xy, 0.0);
#ifdef _LTC direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy, g2.rg).r) * voxelgiShad;
#ifdef _ShadowMap #endif
if (receiveShadow) {
#ifdef _SinglePoint #ifdef _LTC
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); #ifdef _ShadowMap
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); if (receiveShadow) {
#endif #ifdef _SinglePoint
#ifdef _Clusters vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); #endif
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); #ifdef _Clusters
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
#endif else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
} else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
#endif else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
return direct; #endif
#endif }
#endif
#ifdef _Spot return direct;
if (isSpot) { #endif
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
#ifdef _Spot
#ifdef _ShadowMap if (isSpot) {
if (receiveShadow) { direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
#ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); #ifdef _ShadowMap
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); if (receiveShadow) {
#endif #ifdef _SinglePoint
#ifdef _Clusters vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
#ifdef _ShadowMapAtlas #endif
direct *= shadowTest( #ifdef _Clusters
#ifndef _SingleAtlas vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent #ifdef _ShadowMapAtlas
#else direct *= shadowTest(
shadowMapAtlas, shadowMapAtlasTransparent #ifndef _SingleAtlas
#endif shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
, lPos.xyz / lPos.w, bias, transparent #else
); shadowMapAtlas, shadowMapAtlasTransparent
#else #endif
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); , lPos.xyz / lPos.w, bias, transparent
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); );
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); #else
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent);
#endif else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent);
#endif else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent);
} else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent);
#endif #endif
return direct; #endif
} }
#endif #endif
return direct;
#ifdef _LightIES }
direct *= iesAttenuation(-l); #endif
#endif
#ifdef _LightIES
#ifdef _ShadowMap direct *= iesAttenuation(-l);
if (receiveShadow) { #endif
#ifdef _SinglePoint
#ifndef _Spot #ifdef _ShadowMap
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); if (receiveShadow) {
#endif #ifdef _SinglePoint
#endif #ifndef _Spot
#ifdef _Clusters direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
#ifdef _ShadowMapAtlas #endif
direct *= PCFFakeCube( #endif
#ifndef _SingleAtlas #ifdef _Clusters
shadowMapAtlasPoint, shadowMapAtlasPointTransparent #ifdef _ShadowMapAtlas
#else direct *= PCFFakeCube(
shadowMapAtlas, shadowMapAtlasTransparent #ifndef _SingleAtlas
#endif shadowMapAtlasPoint, shadowMapAtlasPointTransparent
, ld, -l, bias, lightProj, n, index, transparent #else
); shadowMapAtlas, shadowMapAtlasTransparent
#else #endif
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); , ld, -l, bias, lightProj, n, index, transparent
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); );
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); #else
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent);
#endif else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent);
#endif else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent);
} else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent);
#endif #endif
#endif
return direct; }
} #endif
#endif return direct;
}
#endif

View File

@ -87,40 +87,6 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
return zcomp * 0.5 + 0.5; return zcomp * 0.5 + 0.5;
} }
#ifndef _ShadowMapAtlas
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) {
const float s = shadowmapCubePcfSize;
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20;
#ifdef _InvY
ml.y = -ml.y;
#endif
float shadowFactor = 0.0;
shadowFactor = texture(shadowMapCube, vec4(ml, compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
shadowFactor /= 9.0;
vec3 result = vec3(shadowFactor);
if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb;
}
return result;
}
#endif
#ifdef _ShadowMapAtlas
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) { vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) {
const float s = shadowmapCubePcfSize; // TODO: incorrect... const float s = shadowmapCubePcfSize; // TODO: incorrect...
float compare = lpToDepth(lp, lightProj) - bias * 1.5; float compare = lpToDepth(lp, lightProj) - bias * 1.5;
@ -149,7 +115,7 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare
return result; return result;
} }
#ifdef _ShadowMapAtlas
// transform "out-of-bounds" coordinates to the correct face/coordinate system // transform "out-of-bounds" coordinates to the correct face/coordinate system
// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png
vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {

View File

@ -11,8 +11,6 @@ vec3 uncharted2Tonemap(const vec3 x) {
vec3 tonemapUncharted2(const vec3 color) { vec3 tonemapUncharted2(const vec3 color) {
const float W = 11.2; const float W = 11.2;
const float exposureBias = 2.0; const float exposureBias = 2.0;
// TODO - Find out why black world value of 0.0,0.0,0.0 turns to white pixels
if (dot(color, color) < 0.001) return vec3(0.001);
vec3 curr = uncharted2Tonemap(exposureBias * color); vec3 curr = uncharted2Tonemap(exposureBias * color);
vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W)); vec3 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
return curr * whiteScale; return curr * whiteScale;

View File

@ -11,11 +11,6 @@
#include "std/light_common.glsl" #include "std/light_common.glsl"
#endif #endif
#ifdef _CPostprocess
uniform vec3 PPComp11;
uniform vec4 PPComp17;
#endif
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
uniform sampler2D snoise; uniform sampler2D snoise;
@ -92,13 +87,7 @@ out float fragColor;
const float tScat = 0.08; const float tScat = 0.08;
const float tAbs = 0.0; const float tAbs = 0.0;
const float tExt = tScat + tAbs; const float tExt = tScat + tAbs;
#ifdef _CPostprocess const float stepLen = 1.0 / volumSteps;
float stepLen = 1.0 / int(PPComp11.y);
float AirTurbidity = PPComp17.w;
#else
const float stepLen = 1.0 / volumSteps;
float AirTurbidity = volumAirTurbidity;
#endif
const float lighting = 0.4; const float lighting = 0.4;
void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) { void rayStep(inout vec3 curPos, inout float curOpticalDepth, inout float scatteredLightAmount, float stepLenWorld, vec3 viewVecNorm) {
@ -173,5 +162,5 @@ void main() {
rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm); rayStep(curPos, curOpticalDepth, scatteredLightAmount, stepLenWorld, viewVecNorm);
} }
fragColor = scatteredLightAmount * AirTurbidity; fragColor = scatteredLightAmount * volumAirTurbidity;
} }

View File

@ -140,16 +140,6 @@
"link": "_biasLightWorldViewProjectionMatrixSpot3", "link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"], "ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_Spot", "_ShadowMap"] "ifdef": ["_Spot", "_ShadowMap"]
},
{
"name": "PPComp11",
"link": "_PPComp11",
"ifdef": ["_CPostprocess"]
},
{
"name": "PPComp17",
"link": "_PPComp17",
"ifdef": ["_CPostprocess"]
} }
], ],
"texture_params": [], "texture_params": [],

View File

@ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight;
#ifdef _ShadowMap #ifdef _ShadowMap
uniform sampler2DShadow shadowMap; uniform sampler2DShadow shadowMap;
uniform sampler2D shadowMapTransparent;
uniform sampler2DShadow shadowMapSpot; uniform sampler2DShadow shadowMapSpot;
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
uniform sampler2DShadow shadowMapPoint; uniform sampler2DShadow shadowMapPoint;
@ -86,53 +87,51 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
void main() { void main() {
int res = voxelgiResolution.x; int res = voxelgiResolution.x;
for (int i = 0; i < 6; i++) {
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz);
vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution;
P = P * 2.0 - 1.0;
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); float visibility;
dst.y += clipmapLevel * res; vec3 lp = lightPos - P;
vec3 l;
vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; if (lightType == 0) { l = lightDir; visibility = 1.0; }
P = P * 2.0 - 1.0; else { l = normalize(lp); visibility = attenuate(distance(P, lightPos)); }
P *= clipmaps[int(clipmapLevel * 10)];
P *= voxelgiResolution;
P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]);
vec3 visibility;
vec3 lp = lightPos - P;
vec3 l;
if (lightType == 0) { l = lightDir; visibility = vec3(1.0); }
else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); }
#ifdef _ShadowMap #ifdef _ShadowMap
if (lightShadow == 1) { if (lightShadow == 1) {
vec4 lightPosition = LVP * vec4(P, 1.0); vec4 lightPosition = LVP * vec4(P, 1.0);
vec3 lPos = lightPosition.xyz / lightPosition.w; vec3 lPos = lightPosition.xyz / lightPosition.w;
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;
} }
else if (lightShadow == 2) { else if (lightShadow == 2) {
vec4 lightPosition = LVP * vec4(P, 1.0); vec4 lightPosition = LVP * vec4(P, 1.0);
vec3 lPos = lightPosition.xyz / lightPosition.w; vec3 lPos = lightPosition.xyz / lightPosition.w;
visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r;
} }
else if (lightShadow == 3) { else if (lightShadow == 3) {
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
int faceIndex = 0; int faceIndex = 0;
const int lightIndex = index * 6; const int lightIndex = index * 6;
const vec2 uv = sampleCube(-l, faceIndex); const vec2 uv = sampleCube(-l, faceIndex);
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
#ifdef _FlipY #ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif #endif
visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r; visibility *= texture(shadowMapPoint, vec3(uvtiled, lpToDepth(lp, lightProj) - shadowsBias)).r;
#else #else
visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r; visibility *= texture(shadowMapPoint, vec4(-l, lpToDepth(lp, lightProj) - shadowsBias)).r;
#endif #endif
} }
#endif #endif
vec3 uvw_light = (P - vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)])) / (float(clipmaps[int(clipmapLevel * 10)]) * voxelgiResolution);
uvw_light = (uvw_light * 0.5 + 0.5);
if (any(notEqual(uvw_light, clamp(uvw_light, 0.0, 1.0)))) return;
vec3 writecoords_light = floor(uvw_light * voxelgiResolution);
vec3 light = visibility * lightColor; imageAtomicMax(voxelsLight, ivec3(writecoords_light), uint(visibility * lightColor.r * 255));
imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255));
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255)); imageAtomicMax(voxelsLight, ivec3(writecoords_light) + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255));
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255)); }
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255));
} }

View File

@ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
uniform sampler3D voxels; uniform sampler3D voxels;
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; uniform sampler2D gbuffer0;
uniform layout(r8) image2D voxels_ao; uniform layout(r16) image2D voxels_ao;
uniform float clipmaps[voxelgiClipmapCount * 10]; uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP; uniform mat4 InvVP;

View File

@ -33,7 +33,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
uniform sampler3D voxels; uniform sampler3D voxels;
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; uniform sampler2D gbuffer0;
uniform layout(rgba8) image2D voxels_diffuse; uniform layout(rgba16) image2D voxels_diffuse;
uniform float clipmaps[voxelgiClipmapCount * 10]; uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP; uniform mat4 InvVP;
@ -46,7 +46,7 @@ void main() {
const vec2 pixel = gl_GlobalInvocationID.xy; const vec2 pixel = gl_GlobalInvocationID.xy;
vec2 uv = (pixel + 0.5) / postprocess_resolution; vec2 uv = (pixel + 0.5) / postprocess_resolution;
#ifdef _InvY #ifdef _InvY
uv.y = 1.0 - uv.y uv.y = 1.0 - uv.y;
#endif #endif
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;

View File

@ -34,7 +34,7 @@ uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; uniform sampler2D gbuffer0;
uniform sampler3D voxels; uniform sampler3D voxels;
uniform sampler3D voxelsSDF; uniform sampler3D voxelsSDF;
uniform layout(rgba8) image2D voxels_specular; uniform layout(rgba16) image2D voxels_specular;
uniform float clipmaps[voxelgiClipmapCount * 10]; uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP; uniform mat4 InvVP;
@ -71,7 +71,7 @@ void main() {
vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; vec2 velocity = -textureLod(sveloc, uv, 0.0).rg;
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb; vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb;
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
} }

View File

@ -23,8 +23,8 @@ THE SOFTWARE.
#include "compiled.inc" #include "compiled.inc"
uniform layout(r16) image3D input_sdf; uniform layout(r8) image3D input_sdf;
uniform layout(r16) image3D output_sdf; uniform layout(r8) image3D output_sdf;
uniform float jump_size; uniform float jump_size;
uniform int clipmapLevel; uniform int clipmapLevel;

View File

@ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels;
uniform layout(r32ui) uimage3D voxelsLight; uniform layout(r32ui) uimage3D voxelsLight;
uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsB;
uniform layout(rgba8) image3D voxelsOut; uniform layout(rgba8) image3D voxelsOut;
uniform layout(r16) image3D SDF; uniform layout(r8) image3D SDF;
#else #else
#ifdef _VoxelAOvar #ifdef _VoxelAOvar
#ifdef _VoxelShadow #ifdef _VoxelShadow
uniform layout(r16) image3D SDF; uniform layout(r8) image3D SDF;
#endif #endif
uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxels;
uniform layout(r16) image3D voxelsB; uniform layout(r8) image3D voxelsB;
uniform layout(r16) image3D voxelsOut; uniform layout(r8) image3D voxelsOut;
#endif #endif
#endif #endif
@ -80,7 +80,6 @@ void main() {
light.r = float(imageLoad(voxelsLight, src)) / 255; light.r = float(imageLoad(voxelsLight, src)) / 255;
light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255; light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255;
light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255;
light /= 3;
#endif #endif
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
@ -125,7 +124,7 @@ void main() {
envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255;
envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255;
envl /= 3; envl /= 3;
envl *= 100;
//clipmap to world //clipmap to world
vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
@ -137,7 +136,7 @@ void main() {
radiance = basecol; radiance = basecol;
vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps);
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
radiance.rgb *= light + indirect; radiance.rgb *= light / PI + indirect;
radiance.rgb += emission.rgb; radiance.rgb += emission.rgb;
#else #else

View File

@ -75,16 +75,17 @@ vec4 binarySearch(vec3 dir) {
} }
vec4 rayCast(vec3 dir) { vec4 rayCast(vec3 dir) {
#ifdef _CPostprocess float ddepth;
dir *= PPComp9.x; dir *= ss_refractionRayStep;
#else for (int i = 0; i < maxSteps; i++) {
dir *= ssrRayStep; hitCoord += dir;
#endif ddepth = getDeltaDepth(hitCoord);
for (int i = 0; i < maxSteps; i++) { if (ddepth > 0.0)
hitCoord += dir; return binarySearch(dir);
if (getDeltaDepth(hitCoord) > 0.0) return binarySearch(dir); }
} // No hit — fallback to projecting the ray to UV space
return vec4(0.0); vec2 fallbackUV = getProjectedCoord(hitCoord);
return vec4(fallbackUV, 0.0, 0.5); // We set .w lower to indicate fallback
} }
#endif //SSR #endif //SSR

View File

@ -12,7 +12,6 @@ class App {
static var traitInits: Array<Void->Void> = []; static var traitInits: Array<Void->Void> = [];
static var traitUpdates: Array<Void->Void> = []; static var traitUpdates: Array<Void->Void> = [];
static var traitLateUpdates: Array<Void->Void> = []; static var traitLateUpdates: Array<Void->Void> = [];
static var traitFixedUpdates: Array<Void->Void> = [];
static var traitRenders: Array<kha.graphics4.Graphics->Void> = []; static var traitRenders: Array<kha.graphics4.Graphics->Void> = [];
static var traitRenders2D: Array<kha.graphics2.Graphics->Void> = []; static var traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
public static var framebuffer: kha.Framebuffer; public static var framebuffer: kha.Framebuffer;
@ -24,8 +23,6 @@ class App {
public static var renderPathTime: Float; public static var renderPathTime: Float;
public static var endFrameCallbacks: Array<Void->Void> = []; public static var endFrameCallbacks: Array<Void->Void> = [];
#end #end
static var last = 0.0;
static var time = 0.0;
static var lastw = -1; static var lastw = -1;
static var lasth = -1; static var lasth = -1;
public static var onResize: Void->Void = null; public static var onResize: Void->Void = null;
@ -37,14 +34,13 @@ class App {
function new(done: Void->Void) { function new(done: Void->Void) {
done(); done();
kha.System.notifyOnFrames(render); kha.System.notifyOnFrames(render);
kha.Scheduler.addTimeTask(update, 0, iron.system.Time.step); kha.Scheduler.addTimeTask(update, 0, iron.system.Time.delta);
} }
public static function reset() { public static function reset() {
traitInits = []; traitInits = [];
traitUpdates = []; traitUpdates = [];
traitLateUpdates = []; traitLateUpdates = [];
traitFixedUpdates = [];
traitRenders = []; traitRenders = [];
traitRenders2D = []; traitRenders2D = [];
if (onResets != null) for (f in onResets) f(); if (onResets != null) for (f in onResets) f();
@ -52,24 +48,6 @@ class App {
static function update() { static function update() {
if (Scene.active == null || !Scene.active.ready) return; if (Scene.active == null || !Scene.active.ready) return;
iron.system.Time.update();
if (lastw == -1) {
lastw = App.w();
lasth = App.h();
}
if (lastw != App.w() || lasth != App.h()) {
if (onResize != null) onResize();
else {
if (Scene.active != null && Scene.active.camera != null) {
Scene.active.camera.buildProjection();
}
}
}
lastw = App.w();
lasth = App.h();
if (pauseUpdates) return; if (pauseUpdates) return;
#if lnx_debug #if lnx_debug
@ -78,14 +56,6 @@ class App {
Scene.active.updateFrame(); Scene.active.updateFrame();
time += iron.system.Time.delta;
while (time >= iron.system.Time.fixedStep) {
for (f in traitFixedUpdates) f();
time -= iron.system.Time.fixedStep;
}
var i = 0; var i = 0;
var l = traitUpdates.length; var l = traitUpdates.length;
while (i < l) { while (i < l) {
@ -114,13 +84,29 @@ class App {
for (cb in endFrameCallbacks) cb(); for (cb in endFrameCallbacks) cb();
updateTime = kha.Scheduler.realTime() - startTime; updateTime = kha.Scheduler.realTime() - startTime;
#end #end
// Rebuild projection on window resize
if (lastw == -1) {
lastw = App.w();
lasth = App.h();
}
if (lastw != App.w() || lasth != App.h()) {
if (onResize != null) onResize();
else {
if (Scene.active != null && Scene.active.camera != null) {
Scene.active.camera.buildProjection();
}
}
}
lastw = App.w();
lasth = App.h();
} }
static function render(frames: Array<kha.Framebuffer>) { static function render(frames: Array<kha.Framebuffer>) {
var frame = frames[0]; var frame = frames[0];
framebuffer = frame; framebuffer = frame;
iron.system.Time.render(); iron.system.Time.update();
if (Scene.active == null || !Scene.active.ready) { if (Scene.active == null || !Scene.active.ready) {
render2D(frame); render2D(frame);
@ -186,14 +172,6 @@ class App {
traitLateUpdates.remove(f); traitLateUpdates.remove(f);
} }
public static function notifyOnFixedUpdate(f: Void->Void) {
traitFixedUpdates.push(f);
}
public static function removeFixedUpdate(f: Void->Void) {
traitFixedUpdates.remove(f);
}
public static function notifyOnRender(f: kha.graphics4.Graphics->Void) { public static function notifyOnRender(f: kha.graphics4.Graphics->Void) {
traitRenders.push(f); traitRenders.push(f);
} }

View File

@ -518,44 +518,12 @@ class RenderPath {
return Reflect.field(kha.Shaders, handle + "_comp"); return Reflect.field(kha.Shaders, handle + "_comp");
} }
#if lnx_vr #if (kha_krom && lnx_vr)
public function drawStereo(drawMeshes: Void->Void) { public function drawStereo(drawMeshes: Int->Void) {
var vr = kha.vr.VrInterface.instance; for (eye in 0...2) {
var appw = iron.App.w(); Krom.vrBeginRender(eye);
var apph = iron.App.h(); drawMeshes(eye);
var halfw = Std.int(appw / 2); Krom.vrEndRender(eye);
var g = currentG;
if (vr != null && vr.IsPresenting()) {
// Left eye
Scene.active.camera.V.setFrom(Scene.active.camera.leftV);
Scene.active.camera.P.self = vr.GetProjectionMatrix(0);
g.viewport(0, 0, halfw, apph);
drawMeshes();
// Right eye
begin(g, additionalTargets);
Scene.active.camera.V.setFrom(Scene.active.camera.rightV);
Scene.active.camera.P.self = vr.GetProjectionMatrix(1);
g.viewport(halfw, 0, halfw, apph);
drawMeshes();
}
else { // Simulate
Scene.active.camera.buildProjection(halfw / apph);
// Left eye
g.viewport(0, 0, halfw, apph);
drawMeshes();
// Right eye
begin(g, additionalTargets);
Scene.active.camera.transform.move(Scene.active.camera.right(), 0.032);
Scene.active.camera.buildMatrix();
g.viewport(halfw, 0, halfw, apph);
drawMeshes();
Scene.active.camera.transform.move(Scene.active.camera.right(), -0.032);
Scene.active.camera.buildMatrix();
} }
} }
#end #end

View File

@ -775,7 +775,6 @@ class Scene {
// Attach particle systems // Attach particle systems
#if lnx_particles #if lnx_particles
if (o.particle_refs != null) { if (o.particle_refs != null) {
cast(object, MeshObject).render_emitter = o.render_emitter;
for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref); for (ref in o.particle_refs) cast(object, MeshObject).setupParticleSystem(sceneName, ref);
} }
#end #end
@ -783,11 +782,6 @@ class Scene {
if (o.tilesheet_ref != null) { if (o.tilesheet_ref != null) {
cast(object, MeshObject).setupTilesheet(sceneName, o.tilesheet_ref, o.tilesheet_action_ref); cast(object, MeshObject).setupTilesheet(sceneName, o.tilesheet_ref, o.tilesheet_action_ref);
} }
if (o.camera_list != null){
cast(object, MeshObject).cameraList = o.camera_list;
}
returnObject(object, o, done); returnObject(object, o, done);
}); });
} }
@ -887,12 +881,8 @@ class Scene {
var ptype: String = t.props[i * 3 + 1]; var ptype: String = t.props[i * 3 + 1];
var pval: Dynamic = t.props[i * 3 + 2]; var pval: Dynamic = t.props[i * 3 + 2];
if (StringTools.endsWith(ptype, "Object") && pval != "" && pval != null) { if (StringTools.endsWith(ptype, "Object") && pval != "") {
Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval)); Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval));
} else if (ptype == "TSceneFormat" && pval != "") {
Data.getSceneRaw(pval, function (r: TSceneFormat) {
Reflect.setProperty(traitInst, pname, r);
});
} }
else { else {
switch (ptype) { switch (ptype) {

View File

@ -16,7 +16,6 @@ class Trait {
var _remove: Array<Void->Void> = null; var _remove: Array<Void->Void> = null;
var _update: Array<Void->Void> = null; var _update: Array<Void->Void> = null;
var _lateUpdate: Array<Void->Void> = null; var _lateUpdate: Array<Void->Void> = null;
var _fixedUpdate: Array<Void->Void> = null;
var _render: Array<kha.graphics4.Graphics->Void> = null; var _render: Array<kha.graphics4.Graphics->Void> = null;
var _render2D: Array<kha.graphics2.Graphics->Void> = null; var _render2D: Array<kha.graphics2.Graphics->Void> = null;
@ -88,23 +87,6 @@ class Trait {
App.removeLateUpdate(f); App.removeLateUpdate(f);
} }
/**
Add fixed game logic handler.
**/
public function notifyOnFixedUpdate(f: Void->Void) {
if (_fixedUpdate == null) _fixedUpdate = [];
_fixedUpdate.push(f);
App.notifyOnFixedUpdate(f);
}
/**
Remove fixed game logic handler.
**/
public function removeFixedUpdate(f: Void->Void) {
_fixedUpdate.remove(f);
App.removeFixedUpdate(f);
}
/** /**
Add render handler. Add render handler.
**/ **/

View File

@ -392,8 +392,6 @@ typedef TParticleData = {
#end #end
public var name: String; public var name: String;
public var type: Int; // 0 - Emitter, Hair public var type: Int; // 0 - Emitter, Hair
public var auto_start: Bool;
public var is_unique: Bool;
public var loop: Bool; public var loop: Bool;
public var count: Int; public var count: Int;
public var frame_start: FastFloat; public var frame_start: FastFloat;
@ -441,7 +439,6 @@ typedef TObj = {
@:optional public var traits: Array<TTrait>; @:optional public var traits: Array<TTrait>;
@:optional public var properties: Array<TProperty>; @:optional public var properties: Array<TProperty>;
@:optional public var vertex_groups: Array<TVertex_groups>; @:optional public var vertex_groups: Array<TVertex_groups>;
@:optional public var camera_list: Array<String>;
@:optional public var constraints: Array<TConstraint>; @:optional public var constraints: Array<TConstraint>;
@:optional public var dimensions: Float32Array; // Geometry objects @:optional public var dimensions: Float32Array; // Geometry objects
@:optional public var object_actions: Array<String>; @:optional public var object_actions: Array<String>;

View File

@ -1,50 +0,0 @@
/*
* format - Haxe File Formats
*
* BMP File Format
* Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
*
* Copyright (c) 2009, The Haxe Project Contributors
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package iron.format.bmp;
typedef Data = {
var header : iron.format.bmp.Header;
var pixels : haxe.io.Bytes;
#if (haxe_ver < 4)
var colorTable : Null<haxe.io.Bytes>;
#else
var ?colorTable : haxe.io.Bytes;
#end
}
typedef Header = {
var width : Int; // real width (in pixels)
var height : Int; // real height (in pixels)
var paddedStride : Int; // number of bytes in a stride (including padding)
var topToBottom : Bool; // whether the bitmap is stored top to bottom
var bpp : Int; // bits per pixel
var dataLength : Int; // equal to `paddedStride` * `height`
var compression : Int; // which compression is being used, 0 for no compression
}

View File

@ -1,122 +0,0 @@
/*
* format - Haxe File Formats
*
* BMP File Format
* Copyright (C) 2007-2009 Robert Sköld
*
* Copyright (c) 2009, The Haxe Project Contributors
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package iron.format.bmp;
import iron.format.bmp.Data;
class Reader {
var input : haxe.io.Input;
public function new( i ) {
input = i;
}
/**
* Only supports uncompressed 24bpp bitmaps (the most common format).
*
* The returned bytes in `Data.pixels` will be in BGR order, and with padding (if present).
*
* @see https://msdn.microsoft.com/en-us/library/windows/desktop/dd318229(v=vs.85).aspx
* @see https://en.wikipedia.org/wiki/BMP_file_format#Bitmap_file_header
*/
public function read() : format.bmp.Data {
// Read Header
for (b in ["B".code, "M".code]) {
if (input.readByte() != b) throw "Invalid header";
}
var fileSize = input.readInt32();
input.readInt32(); // Reserved
var offset = input.readInt32();
// Read InfoHeader
var infoHeaderSize = input.readInt32(); // InfoHeader size
if (infoHeaderSize != 40) {
throw 'Info headers with size $infoHeaderSize not supported.';
}
var width = input.readInt32(); // Image width (actual, not padded)
var height = input.readInt32(); // Image height
var numPlanes = input.readInt16(); // Number of planes
var bits = input.readInt16(); // Bits per pixel
var compression = input.readInt32(); // Compression type
var dataLength = input.readInt32(); // Image data size (includes padding!)
input.readInt32(); // Horizontal resolution
input.readInt32(); // Vertical resolution
var colorsUsed = input.readInt32(); // Colors used (0 when uncompressed)
input.readInt32(); // Important colors (0 when uncompressed)
// If there's no compression, the dataLength may be 0
if ( compression == 0 && dataLength == 0 ) dataLength = fileSize - offset;
var bytesRead = 54; // total read above
var colorTable : haxe.io.Bytes = null;
if ( bits <= 8 ) {
if ( colorsUsed == 0 ) {
colorsUsed = Tools.getNumColorsForBitDepth(bits);
}
var colorTableLength = 4 * colorsUsed;
colorTable = haxe.io.Bytes.alloc( colorTableLength );
input.readFullBytes( colorTable, 0, colorTableLength );
bytesRead += colorTableLength;
}
input.read( offset - bytesRead );
var p = haxe.io.Bytes.alloc( dataLength );
// Read Raster Data
var paddedStride = Tools.computePaddedStride(width, bits);
var topToBottom = false;
if ( height < 0 ) { // if bitmap is stored top to bottom
topToBottom = true;
height = -height;
}
input.readFullBytes(p, 0, dataLength);
return {
header: {
width: width,
height: height,
paddedStride: paddedStride,
topToBottom: topToBottom,
bpp: bits,
dataLength: dataLength,
compression: compression
},
pixels: p,
colorTable: colorTable
}
}
}

View File

@ -1,256 +0,0 @@
/*
* format - Haxe File Formats
*
* BMP File Format
* Copyright (C) 2007-2009 Trevor McCauley, Baluta Cristian (hx port) & Robert Sköld (format conversion)
*
* Copyright (c) 2009, The Haxe Project Contributors
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package iron.format.bmp;
class Tools {
// a r g b
static var ARGB_MAP(default, never):Array<Int> = [0, 1, 2, 3];
static var BGRA_MAP(default, never):Array<Int> = [3, 2, 1, 0];
static var COLOR_SIZE(default, never):Int = 4;
/**
Extract BMP pixel data (24bpp in BGR format) and expands it to BGRA, removing any padding in the process.
**/
inline static public function extractBGRA( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
return _extract32(bmp, BGRA_MAP, 0xFF);
}
/**
Extract BMP pixel data (24bpp in BGR format) and converts it to ARGB.
**/
inline static public function extractARGB( bmp : iron.format.bmp.Data ) : haxe.io.Bytes {
return _extract32(bmp, ARGB_MAP, 0xFF);
}
/**
Creates BMP data from bytes in BGRA format for each pixel.
**/
inline static public function buildFromBGRA( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
return _buildFrom32(width, height, srcBytes, BGRA_MAP, topToBottom);
}
/**
Creates BMP data from bytes in ARGB format for each pixel.
**/
inline static public function buildFromARGB( width : Int, height : Int, srcBytes : haxe.io.Bytes, topToBottom : Bool = false ) : Data {
return _buildFrom32(width, height, srcBytes, ARGB_MAP, topToBottom);
}
inline static public function computePaddedStride(width:Int, bpp:Int):Int {
return ((((width * bpp) + 31) & ~31) >> 3);
}
/**
* Gets number of colors for indexed palettes
*/
inline static public function getNumColorsForBitDepth(bpp:Int):Int {
return switch (bpp) {
case 1: 2;
case 4: 16;
case 8: 256;
case 16: 65536;
default: throw 'Unsupported bpp $bpp';
}
}
// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
static function _extract32( bmp : iron.format.bmp.Data, channelMap : Array<Int>, alpha : Int = 0xFF) : haxe.io.Bytes {
var srcBytes = bmp.pixels;
var dstLen = bmp.header.width * bmp.header.height * 4;
var dstBytes = haxe.io.Bytes.alloc( dstLen );
var srcPaddedStride = bmp.header.paddedStride;
var yDir = -1;
var dstPos = 0;
var srcPos = srcPaddedStride * (bmp.header.height - 1);
if ( bmp.header.topToBottom ) {
yDir = 1;
srcPos = 0;
}
if ( bmp.header.bpp < 8 || bmp.header.bpp == 16 ) {
throw 'bpp ${bmp.header.bpp} not supported';
}
var colorTable:haxe.io.Bytes = null;
if ( bmp.header.bpp <= 8 ) {
var colorTableLength = getNumColorsForBitDepth(bmp.header.bpp);
colorTable = haxe.io.Bytes.alloc(colorTableLength * COLOR_SIZE);
var definedColorTableLength = Std.int( bmp.colorTable.length / COLOR_SIZE );
for( i in 0...definedColorTableLength ) {
var b = bmp.colorTable.get( i * COLOR_SIZE);
var g = bmp.colorTable.get( i * COLOR_SIZE + 1);
var r = bmp.colorTable.get( i * COLOR_SIZE + 2);
colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
colorTable.set(i * COLOR_SIZE + channelMap[1], r);
colorTable.set(i * COLOR_SIZE + channelMap[2], g);
colorTable.set(i * COLOR_SIZE + channelMap[3], b);
}
// We want to have the table the full length in case indices outside the range are present
colorTable.fill(definedColorTableLength, colorTableLength - definedColorTableLength, 0);
for( i in definedColorTableLength...colorTableLength ) {
colorTable.set(i * COLOR_SIZE + channelMap[0], alpha);
}
}
switch bmp.header.compression {
case 0:
while( dstPos < dstLen ) {
for( i in 0...bmp.header.width ) {
if (bmp.header.bpp == 8) {
var currentSrcPos = srcPos + i;
var index = srcBytes.get(currentSrcPos);
dstBytes.blit( dstPos, colorTable, index * COLOR_SIZE, COLOR_SIZE );
} else if (bmp.header.bpp == 24) {
var currentSrcPos = srcPos + i * 3;
var b = srcBytes.get(currentSrcPos);
var g = srcBytes.get(currentSrcPos + 1);
var r = srcBytes.get(currentSrcPos + 2);
dstBytes.set(dstPos + channelMap[0], alpha);
dstBytes.set(dstPos + channelMap[1], r);
dstBytes.set(dstPos + channelMap[2], g);
dstBytes.set(dstPos + channelMap[3], b);
} else if (bmp.header.bpp == 32) {
var currentSrcPos = srcPos + i * 4;
var b = srcBytes.get(currentSrcPos);
var g = srcBytes.get(currentSrcPos + 1);
var r = srcBytes.get(currentSrcPos + 2);
dstBytes.set(dstPos + channelMap[0], alpha);
dstBytes.set(dstPos + channelMap[1], r);
dstBytes.set(dstPos + channelMap[2], g);
dstBytes.set(dstPos + channelMap[3], b);
}
dstPos += 4;
}
srcPos += yDir * srcPaddedStride;
}
case 1:
srcPos = 0;
var x = 0;
var y = bmp.header.topToBottom ? 0 : bmp.header.height - 1;
while( srcPos < bmp.header.dataLength ) {
var count = srcBytes.get(srcPos++);
var index = srcBytes.get(srcPos++);
if ( count == 0 ) {
if ( index == 0 ) {
x = 0;
y += yDir;
} else if ( index == 1 ) {
break;
} else if ( index == 2 ) {
x += srcBytes.get(srcPos++);
y += srcBytes.get(srcPos++);
} else {
count = index;
for( i in 0...count ) {
index = srcBytes.get(srcPos++);
dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
}
if (srcPos % 2 != 0) srcPos++;
x += count;
}
} else {
for( i in 0...count ) {
dstBytes.blit( COLOR_SIZE * ((x+i) + y * bmp.header.width), colorTable, index * COLOR_SIZE, COLOR_SIZE );
}
x += count;
}
}
default:
throw 'compression ${bmp.header.compression} not supported';
}
return dstBytes;
}
// `channelMap` contains indices to map into ARGB (f.e. the mapping for ARGB is [0,1,2,3], while for BGRA is [3,2,1,0])
static function _buildFrom32( width : Int, height : Int, srcBytes : haxe.io.Bytes, channelMap : Array<Int>, topToBottom : Bool = false ) : Data {
var bpp = 24;
var paddedStride = computePaddedStride(width, bpp);
var bytesBGR = haxe.io.Bytes.alloc(paddedStride * height);
var topToBottom = topToBottom;
var dataLength = bytesBGR.length;
var dstStride = width * 3;
var srcLen = width * height * 4;
var yDir = -1;
var dstPos = dataLength - paddedStride;
var srcPos = 0;
if ( topToBottom ) {
yDir = 1;
dstPos = 0;
}
while( srcPos < srcLen ) {
var i = dstPos;
while( i < dstPos + dstStride ) {
var r = srcBytes.get(srcPos + channelMap[1]);
var g = srcBytes.get(srcPos + channelMap[2]);
var b = srcBytes.get(srcPos + channelMap[3]);
bytesBGR.set(i++, b);
bytesBGR.set(i++, g);
bytesBGR.set(i++, r);
srcPos += 4;
}
dstPos += yDir * paddedStride;
}
return {
header: {
width: width,
height: height,
paddedStride: paddedStride,
topToBottom: topToBottom,
bpp: bpp,
dataLength: dataLength,
compression: 0
},
pixels: bytesBGR,
colorTable: null
}
}
}

View File

@ -1,74 +0,0 @@
/*
* format - Haxe File Formats
*
* BMP File Format
* Copyright (C) 2007-2009 Robert Sköld
*
* Copyright (c) 2009, The Haxe Project Contributors
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package iron.format.bmp;
import iron.format.bmp.Data;
class Writer {
static var DATA_OFFSET : Int = 0x36;
var output : haxe.io.Output;
public function new(o) {
output = o;
}
/**
* Specs: http://s223767089.online.de/en/file-format-bmp
*/
public function write( bmp : Data ) {
// Write Header (14 bytes)
output.writeString( "BM" ); // Signature
output.writeInt32(bmp.pixels.length + DATA_OFFSET ); // FileSize
output.writeInt32( 0 ); // Reserved
output.writeInt32( DATA_OFFSET ); // Offset
// Write InfoHeader (40 bytes)
output.writeInt32( 40 ); // InfoHeader size
output.writeInt32( bmp.header.width ); // Image width
var height = bmp.header.height;
if (bmp.header.topToBottom) height = -height;
output.writeInt32( height ); // Image height
output.writeInt16( 1 ); // Number of planes
output.writeInt16( 24 ); // Bits per pixel (24bit RGB)
output.writeInt32( 0 ); // Compression type (no compression)
output.writeInt32( bmp.header.dataLength ); // Image data size (0 when uncompressed)
output.writeInt32( 0x2e30 ); // Horizontal resolution
output.writeInt32( 0x2e30 ); // Vertical resolution
output.writeInt32( 0 ); // Colors used (0 when uncompressed)
output.writeInt32( 0 ); // Important colors (0 when uncompressed)
// Write Raster Data
output.write(bmp.pixels);
}
}

View File

@ -159,17 +159,9 @@ class Animation {
if(markerEvents.get(sampler) != null){ if(markerEvents.get(sampler) != null){
for (i in 0...anim.marker_frames.length) { for (i in 0...anim.marker_frames.length) {
if (frameIndex == anim.marker_frames[i]) { if (frameIndex == anim.marker_frames[i]) {
var markerAct = markerEvents.get(sampler); var marketAct = markerEvents.get(sampler);
var ar = markerAct.get(anim.marker_names[i]); var ar = marketAct.get(anim.marker_names[i]);
if (ar != null) for (f in ar) f(); if (ar != null) for (f in ar) f();
} else {
for (j in 0...(frameIndex - lastFrameIndex)) {
if (lastFrameIndex + j + 1 == anim.marker_frames[i]) {
var markerAct = markerEvents.get(sampler);
var ar = markerAct.get(anim.marker_names[i]);
if (ar != null) for (f in ar) f();
}
}
} }
} }
lastFrameIndex = frameIndex; lastFrameIndex = frameIndex;

View File

@ -30,22 +30,12 @@ class CameraObject extends Object {
static var sphereCenter = new Vec4(); static var sphereCenter = new Vec4();
static var vcenter = new Vec4(); static var vcenter = new Vec4();
static var vup = new Vec4(); static var vup = new Vec4();
#if lnx_vr
var helpMat = Mat4.identity();
public var leftV = Mat4.identity();
public var rightV = Mat4.identity();
#end
public function new(data: CameraData) { public function new(data: CameraData) {
super(); super();
this.data = data; this.data = data;
#if lnx_vr
iron.system.VR.initButton();
#end
buildProjection(); buildProjection();
V = Mat4.identity(); V = Mat4.identity();
@ -127,26 +117,6 @@ class CameraObject extends Object {
V.getInverse(transform.world); V.getInverse(transform.world);
VP.multmats(P, V); VP.multmats(P, V);
#if lnx_vr
var vr = kha.vr.VrInterface.instance;
if (vr != null && vr.IsPresenting()) {
leftV.setFrom(V);
helpMat.self = vr.GetViewMatrix(0);
leftV.multmat(helpMat);
rightV.setFrom(V);
helpMat.self = vr.GetViewMatrix(1);
rightV.multmat(helpMat);
}
else {
leftV.setFrom(V);
}
VP.multmats(P, leftV);
#else
VP.multmats(P, V);
#end
if (data.raw.frustum_culling) { if (data.raw.frustum_culling) {
buildViewFrustum(VP, frustumPlanes); buildViewFrustum(VP, frustumPlanes);
} }

View File

@ -155,13 +155,8 @@ class LightObject extends Object {
} }
public function setCascade(camera: CameraObject, cascade: Int) { public function setCascade(camera: CameraObject, cascade: Int) {
#if lnx_vr
m.setFrom(camera.leftV);
#else
m.setFrom(camera.V); m.setFrom(camera.V);
#end
#if lnx_csm #if lnx_csm
if (camSlicedP == null) { if (camSlicedP == null) {
camSlicedP = []; camSlicedP = [];

View File

@ -21,10 +21,8 @@ class MeshObject extends Object {
public var particleChildren: Array<MeshObject> = null; public var particleChildren: Array<MeshObject> = null;
public var particleOwner: MeshObject = null; // Particle object public var particleOwner: MeshObject = null; // Particle object
public var particleIndex = -1; public var particleIndex = -1;
public var render_emitter = true;
#end #end
public var cameraDistance: Float; public var cameraDistance: Float;
public var cameraList: Array<String> = null;
public var screenSize = 0.0; public var screenSize = 0.0;
public var frustumCulling = true; public var frustumCulling = true;
public var activeTilesheet: Tilesheet = null; public var activeTilesheet: Tilesheet = null;
@ -236,8 +234,6 @@ class MeshObject extends Object {
if (cullMesh(context, Scene.active.camera, RenderPath.active.light)) return; if (cullMesh(context, Scene.active.camera, RenderPath.active.light)) return;
var meshContext = raw != null ? context == "mesh" : false; var meshContext = raw != null ? context == "mesh" : false;
if (cameraList != null && cameraList.indexOf(Scene.active.camera.name) < 0) return;
#if lnx_particles #if lnx_particles
if (raw != null && raw.is_particle && particleOwner == null) return; // Instancing not yet set-up by particle system owner if (raw != null && raw.is_particle && particleOwner == null) return; // Instancing not yet set-up by particle system owner
if (particleSystems != null && meshContext) { if (particleSystems != null && meshContext) {
@ -248,7 +244,6 @@ class MeshObject extends Object {
Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) { Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
if (o != null) { if (o != null) {
var c: MeshObject = cast o; var c: MeshObject = cast o;
c.cameraList = this.cameraList;
particleChildren.push(c); particleChildren.push(c);
c.particleOwner = this; c.particleOwner = this;
c.particleIndex = particleChildren.length - 1; c.particleIndex = particleChildren.length - 1;
@ -260,11 +255,11 @@ class MeshObject extends Object {
particleSystems[i].update(particleChildren[i], this); particleSystems[i].update(particleChildren[i], this);
} }
} }
if (particleSystems != null && particleSystems.length > 0 && !render_emitter) return; if (particleSystems != null && particleSystems.length > 0 && !raw.render_emitter) return;
if (particleSystems == null && cullMaterial(context)) return;
#else
if (cullMaterial(context)) return;
#end #end
if (cullMaterial(context)) return;
// Get lod // Get lod
var mats = materials; var mats = materials;
var lod = this; var lod = this;

View File

@ -172,10 +172,6 @@ class Object {
for (f in t._init) App.removeInit(f); for (f in t._init) App.removeInit(f);
t._init = null; t._init = null;
} }
if (t._fixedUpdate != null) {
for (f in t._fixedUpdate) App.removeFixedUpdate(f);
t._fixedUpdate = null;
}
if (t._update != null) { if (t._update != null) {
for (f in t._update) App.removeUpdate(f); for (f in t._update) App.removeUpdate(f);
t._update = null; t._update = null;

View File

@ -2,7 +2,6 @@ package iron.object;
#if lnx_particles #if lnx_particles
import kha.FastFloat;
import kha.graphics4.Usage; import kha.graphics4.Usage;
import kha.arrays.Float32Array; import kha.arrays.Float32Array;
import iron.data.Data; import iron.data.Data;
@ -17,12 +16,10 @@ import iron.math.Vec4;
class ParticleSystem { class ParticleSystem {
public var data: ParticleData; public var data: ParticleData;
public var speed = 1.0; public var speed = 1.0;
var currentSpeed = 0.0;
var particles: Array<Particle>; var particles: Array<Particle>;
var ready: Bool; var ready: Bool;
var frameRate = 24; var frameRate = 24;
var lifetime = 0.0; var lifetime = 0.0;
var looptime = 0.0;
var animtime = 0.0; var animtime = 0.0;
var time = 0.0; var time = 0.0;
var spawnRate = 0.0; var spawnRate = 0.0;
@ -49,13 +46,9 @@ class ParticleSystem {
var ownerLoc = new Vec4(); var ownerLoc = new Vec4();
var ownerRot = new Quat(); var ownerRot = new Quat();
var ownerScl = new Vec4(); var ownerScl = new Vec4();
var random = 0.0;
public function new(sceneName: String, pref: TParticleReference) { public function new(sceneName: String, pref: TParticleReference) {
seed = pref.seed; seed = pref.seed;
currentSpeed = speed;
speed = 0;
particles = []; particles = [];
ready = false; ready = false;
@ -72,61 +65,33 @@ class ParticleSystem {
gy = 0; gy = 0;
gz = -9.81 * r.weight_gravity; gz = -9.81 * r.weight_gravity;
} }
alignx = r.object_align_factor[0]; alignx = r.object_align_factor[0] / 2;
aligny = r.object_align_factor[1]; aligny = r.object_align_factor[1] / 2;
alignz = r.object_align_factor[2]; alignz = r.object_align_factor[2] / 2;
looptime = (r.frame_end - r.frame_start) / frameRate;
lifetime = r.lifetime / frameRate; lifetime = r.lifetime / frameRate;
animtime = r.loop ? looptime : looptime + lifetime; animtime = (r.frame_end - r.frame_start) / frameRate;
spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate; spawnRate = ((r.frame_end - r.frame_start) / r.count) / frameRate;
for (i in 0...r.count) { for (i in 0...r.count) {
particles.push(new Particle(i)); var particle = new Particle(i);
particle.sr = 1 - Math.random() * r.size_random;
particles.push(particle);
} }
ready = true; ready = true;
if (r.auto_start){
start();
}
}); });
} }
public function start() {
if (r.is_unique) random = Math.random();
lifetime = r.lifetime / frameRate;
time = 0;
lap = 0;
lapTime = 0;
speed = currentSpeed;
}
public function pause() { public function pause() {
speed = 0; lifetime = 0;
} }
public function resume() { public function resume() {
lifetime = r.lifetime / frameRate; lifetime = r.lifetime / frameRate;
speed = currentSpeed;
} }
// TODO: interrupt smoothly
public function stop() {
end();
}
function end() {
lifetime = 0;
speed = 0;
lap = 0;
}
public function update(object: MeshObject, owner: MeshObject) { public function update(object: MeshObject, owner: MeshObject) {
if (!ready || object == null || speed == 0.0) return; if (!ready || object == null || speed == 0.0) return;
if (iron.App.pauseUpdates) return;
var prevLap = lap;
// Copy owner world transform but discard scale // Copy owner world transform but discard scale
owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl); owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
@ -150,21 +115,17 @@ class ParticleSystem {
} }
// Animate // Animate
time += Time.renderDelta * speed; // realDelta to renderDelta time += Time.delta * speed;
lap = Std.int(time / animtime); lap = Std.int(time / animtime);
lapTime = time - lap * animtime; lapTime = time - lap * animtime;
count = Std.int(lapTime / spawnRate); count = Std.int(lapTime / spawnRate);
if (lap > prevLap && !r.loop) {
end();
}
updateGpu(object, owner); updateGpu(object, owner);
} }
public function getData(): Mat4 { public function getData(): Mat4 {
var hair = r.type == 1; var hair = r.type == 1;
m._00 = animtime; m._00 = r.loop ? animtime : -animtime;
m._01 = hair ? 1 / particles.length : spawnRate; m._01 = hair ? 1 / particles.length : spawnRate;
m._02 = hair ? 1 : lifetime; m._02 = hair ? 1 : lifetime;
m._03 = particles.length; m._03 = particles.length;
@ -172,9 +133,9 @@ class ParticleSystem {
m._11 = hair ? 0 : aligny; m._11 = hair ? 0 : aligny;
m._12 = hair ? 0 : alignz; m._12 = hair ? 0 : alignz;
m._13 = hair ? 0 : r.factor_random; m._13 = hair ? 0 : r.factor_random;
m._20 = hair ? 0 : gx; m._20 = hair ? 0 : gx * r.mass;
m._21 = hair ? 0 : gy; m._21 = hair ? 0 : gy * r.mass;
m._22 = hair ? 0 : gz; m._22 = hair ? 0 : gz * r.mass;
m._23 = hair ? 0 : r.lifetime_random; m._23 = hair ? 0 : r.lifetime_random;
m._30 = tilesx; m._30 = tilesx;
m._31 = tilesy; m._31 = tilesy;
@ -183,25 +144,13 @@ class ParticleSystem {
return m; return m;
} }
public function getSizeRandom(): FastFloat {
return r.size_random;
}
public function getRandom(): FastFloat {
return random;
}
public function getSize(): FastFloat {
return r.particle_size;
}
function updateGpu(object: MeshObject, owner: MeshObject) { function updateGpu(object: MeshObject, owner: MeshObject) {
if (!object.data.geom.instanced) setupGeomGpu(object, owner); if (!object.data.geom.instanced) setupGeomGpu(object, owner);
// GPU particles transform is attached to owner object // GPU particles transform is attached to owner object
} }
function setupGeomGpu(object: MeshObject, owner: MeshObject) { function setupGeomGpu(object: MeshObject, owner: MeshObject) {
var instancedData = new Float32Array(particles.length * 3); var instancedData = new Float32Array(particles.length * 6);
var i = 0; var i = 0;
var normFactor = 1 / 32767; // pa.values are not normalized var normFactor = 1 / 32767; // pa.values are not normalized
@ -220,6 +169,10 @@ class ParticleSystem {
instancedData.set(i, pa.values[j * pa.size ] * normFactor * scaleFactor.x); i++; instancedData.set(i, pa.values[j * pa.size ] * normFactor * scaleFactor.x); i++;
instancedData.set(i, pa.values[j * pa.size + 1] * normFactor * scaleFactor.y); i++; instancedData.set(i, pa.values[j * pa.size + 1] * normFactor * scaleFactor.y); i++;
instancedData.set(i, pa.values[j * pa.size + 2] * normFactor * scaleFactor.z); i++; instancedData.set(i, pa.values[j * pa.size + 2] * normFactor * scaleFactor.z); i++;
instancedData.set(i, p.sr); i++;
instancedData.set(i, p.sr); i++;
instancedData.set(i, p.sr); i++;
} }
case 1: // Face case 1: // Face
@ -243,6 +196,10 @@ class ParticleSystem {
instancedData.set(i, pos.x * normFactor * scaleFactor.x); i++; instancedData.set(i, pos.x * normFactor * scaleFactor.x); i++;
instancedData.set(i, pos.y * normFactor * scaleFactor.y); i++; instancedData.set(i, pos.y * normFactor * scaleFactor.y); i++;
instancedData.set(i, pos.z * normFactor * scaleFactor.z); i++; instancedData.set(i, pos.z * normFactor * scaleFactor.z); i++;
instancedData.set(i, p.sr); i++;
instancedData.set(i, p.sr); i++;
instancedData.set(i, p.sr); i++;
} }
case 2: // Volume case 2: // Volume
@ -253,9 +210,13 @@ class ParticleSystem {
instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.x); i++; instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.x); i++;
instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.y); i++; instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.y); i++;
instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.z); i++; instancedData.set(i, (Math.random() * 2.0 - 1.0) * scaleFactorVolume.z); i++;
instancedData.set(i, p.sr); i++;
instancedData.set(i, p.sr); i++;
instancedData.set(i, p.sr); i++;
} }
} }
object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage); object.data.geom.setupInstanced(instancedData, 3, Usage.StaticUsage);
} }
function fhash(n: Int): Float { function fhash(n: Int): Float {
@ -294,11 +255,10 @@ class ParticleSystem {
class Particle { class Particle {
public var i: Int; public var i: Int;
public var px = 0.0;
public var x = 0.0; public var py = 0.0;
public var y = 0.0; public var pz = 0.0;
public var z = 0.0; public var sr = 1.0; // Size random
public var cameraDistance: Float; public var cameraDistance: Float;
public function new(i: Int) { public function new(i: Int) {

View File

@ -80,7 +80,7 @@ class Tilesheet {
function update() { function update() {
if (!ready || paused || action.start >= action.end) return; if (!ready || paused || action.start >= action.end) return;
time += Time.renderDelta; time += Time.realDelta;
var frameTime = 1 / raw.framerate; var frameTime = 1 / raw.framerate;
var framesToAdvance = 0; var framesToAdvance = 0;

View File

@ -1109,26 +1109,6 @@ class Uniforms {
case "_texUnpack": { case "_texUnpack": {
f = texUnpack != null ? texUnpack : 1.0; f = texUnpack != null ? texUnpack : 1.0;
} }
#if lnx_particles
case "_particleSizeRandom": {
var mo = cast(object, MeshObject);
if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
f = mo.particleOwner.particleSystems[mo.particleIndex].getSizeRandom();
}
}
case "_particleRandom": {
var mo = cast(object, MeshObject);
if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
f = mo.particleOwner.particleSystems[mo.particleIndex].getRandom();
}
}
case "_particleSize": {
var mo = cast(object, MeshObject);
if (mo.particleOwner != null && mo.particleOwner.particleSystems != null) {
f = mo.particleOwner.particleSystems[mo.particleIndex].getSize();
}
}
#end
} }
if (f == null && externalFloatLinks != null) { if (f == null && externalFloatLinks != null) {

View File

@ -1,58 +1,37 @@
package iron.system; package iron.system;
class Time { class Time {
public static var scale = 1.0;
static var frequency: Null<Int> = null;
static function initFrequency() {
frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
}
public static var step(get, never): Float; public static var step(get, never): Float;
static function get_step(): Float { static function get_step(): Float {
if (frequency == null) initFrequency(); if (frequency == null) initFrequency();
return 1 / frequency; return 1 / frequency;
} }
static var _fixedStep: Null<Float> = 1/60;
public static var fixedStep(get, never): Float;
static function get_fixedStep(): Float {
return _fixedStep;
}
public static function initFixedStep(value: Float = 1 / 60) {
_fixedStep = value;
}
static var lastTime = 0.0; public static var scale = 1.0;
static var _delta = 0.0;
public static var delta(get, never): Float; public static var delta(get, never): Float;
static function get_delta(): Float { static function get_delta(): Float {
return _delta; if (frequency == null) initFrequency();
return (1 / frequency) * scale;
} }
static var lastRenderTime = 0.0; static var last = 0.0;
static var _renderDelta = 0.0; public static var realDelta = 0.0;
public static var renderDelta(get, never): Float;
static function get_renderDelta(): Float {
return _renderDelta;
}
public static inline function time(): Float { public static inline function time(): Float {
return kha.Scheduler.time(); return kha.Scheduler.time();
} }
public static inline function realTime(): Float { public static inline function realTime(): Float {
return kha.Scheduler.realTime(); return kha.Scheduler.realTime();
} }
public static function update() { static var frequency: Null<Int> = null;
_delta = realTime() - lastTime;
lastTime = realTime(); static function initFrequency() {
frequency = kha.Display.primary != null ? kha.Display.primary.frequency : 60;
} }
public static function render() { public static function update() {
_renderDelta = realTime() - lastRenderTime; realDelta = realTime() - last;
lastRenderTime = realTime(); last = realTime();
} }
} }

View File

@ -1,52 +0,0 @@
package iron.system;
import iron.math.Mat4;
#if lnx_vr
class VR {
static var undistortionMatrix: Mat4 = null;
public function new() {}
public static function getUndistortionMatrix(): Mat4 {
if (undistortionMatrix == null) {
undistortionMatrix = Mat4.identity();
}
return undistortionMatrix;
}
public static function getMaxRadiusSq(): Float {
return 0.0;
}
public static function initButton() {
function vrDownListener(index: Int, x: Float, y: Float) {
var vr = kha.vr.VrInterface.instance;
if (vr == null || !vr.IsVrEnabled() || vr.IsPresenting()) return;
var w: Float = iron.App.w();
var h: Float = iron.App.h();
if (x < w - 150 || y < h - 150) return;
vr.onVRRequestPresent();
}
function vrRender2D(g: kha.graphics2.Graphics) {
var vr = kha.vr.VrInterface.instance;
if (vr == null || !vr.IsVrEnabled() || vr.IsPresenting()) return;
var w: Float = iron.App.w();
var h: Float = iron.App.h();
g.color = 0xffff0000;
g.fillRect(w - 150, h - 150, 140, 140);
}
kha.input.Mouse.get().notify(vrDownListener, null, null, null);
iron.App.notifyOnRender2D(vrRender2D);
var vr = kha.vr.VrInterface.instance; // Straight to VR (Oculus Carmel)
if (vr != null && vr.IsVrEnabled()) {
vr.onVRRequestPresent();
}
}
}
#end

View File

@ -20,7 +20,6 @@ class Config {
var path = iron.data.Data.dataPath + "config.lnx"; var path = iron.data.Data.dataPath + "config.lnx";
var bytes = haxe.io.Bytes.ofString(haxe.Json.stringify(raw)); var bytes = haxe.io.Bytes.ofString(haxe.Json.stringify(raw));
#if kha_krom #if kha_krom
if (iron.data.Data.dataPath == '') path = Krom.getFilesLocation() + "/config.lnx";
Krom.fileSaveBytes(path, bytes.getData()); Krom.fileSaveBytes(path, bytes.getData());
#elseif kha_kore #elseif kha_kore
sys.io.File.saveBytes(path, bytes); sys.io.File.saveBytes(path, bytes);
@ -48,7 +47,6 @@ typedef TConfig = {
@:optional var rp_ssr: Null<Bool>; @:optional var rp_ssr: Null<Bool>;
@:optional var rp_ssrefr: Null<Bool>; @:optional var rp_ssrefr: Null<Bool>;
@:optional var rp_bloom: Null<Bool>; @:optional var rp_bloom: Null<Bool>;
@:optional var rp_chromatic_aberration: Null<Bool>;
@:optional var rp_motionblur: Null<Bool>; @:optional var rp_motionblur: Null<Bool>;
@:optional var rp_gi: Null<Bool>; // voxelao @:optional var rp_gi: Null<Bool>; // voxelao
@:optional var rp_dynres: Null<Bool>; // dynamic resolution scaling @:optional var rp_dynres: Null<Bool>; // dynamic resolution scaling

View File

@ -1,99 +0,0 @@
package leenkx.logicnode;
import iron.data.SceneFormat.TSceneFormat;
import iron.data.Data;
import iron.object.Object;
class AddParticleToObjectNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if lnx_particles
if (property0 == 'Scene Active'){
var objFrom: Object = inputs[1].get();
var slot: Int = inputs[2].get();
var objTo: Object = inputs[3].get();
if (objFrom == null || objTo == null) return;
var mobjFrom = cast(objFrom, iron.object.MeshObject);
var psys = mobjFrom.particleSystems != null ? mobjFrom.particleSystems[slot] :
mobjFrom.particleOwner != null && mobjFrom.particleOwner.particleSystems != null ? mobjFrom.particleOwner.particleSystems[slot] : null;
if (psys == null) return;
var mobjTo = cast(objTo, iron.object.MeshObject);
mobjTo.setupParticleSystem(iron.Scene.active.raw.name, {name: 'LnxPS', seed: 0, particle: @:privateAccess psys.r.name});
mobjTo.render_emitter = inputs[4].get();
iron.Scene.active.spawnObject(psys.data.raw.instance_object, null, function(o: Object) {
if (o != null) {
var c: iron.object.MeshObject = cast o;
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
mobjTo.particleChildren.push(c);
c.particleOwner = mobjTo;
c.particleIndex = mobjTo.particleChildren.length - 1;
}
});
var oslot: Int = mobjTo.particleSystems.length-1;
var opsys = mobjTo.particleSystems[oslot];
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
} else {
var sceneName: String = inputs[1].get();
var objectName: String = inputs[2].get();
var slot: Int = inputs[3].get();
var mobjTo: Object = inputs[4].get();
var mobjTo = cast(mobjTo, iron.object.MeshObject);
#if lnx_json
sceneName += ".json";
#elseif lnx_compress
sceneName += ".lz4";
#end
Data.getSceneRaw(sceneName, (rawScene: TSceneFormat) -> {
for (obj in rawScene.objects) {
if (obj.name == objectName) {
mobjTo.setupParticleSystem(sceneName, obj.particle_refs[slot]);
mobjTo.render_emitter = inputs[5].get();
iron.Scene.active.spawnObject(rawScene.particle_datas[slot].instance_object, null, function(o: Object) {
if (o != null) {
var c: iron.object.MeshObject = cast o;
if (mobjTo.particleChildren == null) mobjTo.particleChildren = [];
mobjTo.particleChildren.push(c);
c.particleOwner = mobjTo;
c.particleIndex = mobjTo.particleChildren.length - 1;
}
}, true, rawScene);
var oslot: Int = mobjTo.particleSystems.length-1;
var opsys = mobjTo.particleSystems[oslot];
@:privateAccess opsys.setupGeomGpu(mobjTo.particleChildren[oslot], mobjTo);
break;
}
}
});
}
#end
runOutput(0);
}
}

View File

@ -1,16 +0,0 @@
package leenkx.logicnode;
class AutoExposureGetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function get(from:Int):Dynamic {
return switch (from) {
case 0: leenkx.renderpath.Postprocess.auto_exposure_uniforms[0];
case 1: leenkx.renderpath.Postprocess.auto_exposure_uniforms[1];
default: 0.0;
}
}
}

View File

@ -1,15 +0,0 @@
package leenkx.logicnode;
class AutoExposureSetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function run(from:Int) {
leenkx.renderpath.Postprocess.auto_exposure_uniforms[0] = inputs[1].get();
leenkx.renderpath.Postprocess.auto_exposure_uniforms[1] = inputs[2].get();
runOutput(0);
}
}

View File

@ -1,49 +1,26 @@
package leenkx.logicnode; package leenkx.logicnode;
class CameraSetNode extends LogicNode { class CameraSetNode extends LogicNode {
public var property0: String;
public function new(tree:LogicTree) { public function new(tree:LogicTree) {
super(tree); super(tree);
} }
override function run(from:Int) { override function run(from:Int) {
leenkx.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get();//Camera: F-Number
switch (property0) { leenkx.renderpath.Postprocess.camera_uniforms[1] = inputs[2].get();//Camera: Shutter time
case 'F-stop': leenkx.renderpath.Postprocess.camera_uniforms[2] = inputs[3].get();//Camera: ISO
leenkx.renderpath.Postprocess.camera_uniforms[0] = inputs[1].get();//Camera: F-Number leenkx.renderpath.Postprocess.camera_uniforms[3] = inputs[4].get();//Camera: Exposure Compensation
case 'Shutter Time': leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[5].get();//Fisheye Distortion
leenkx.renderpath.Postprocess.camera_uniforms[1] = inputs[1].get();//Camera: Shutter time leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[6].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting
case 'ISO': leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[7].get();//DoF Distance
leenkx.renderpath.Postprocess.camera_uniforms[2] = inputs[1].get();//Camera: ISO leenkx.renderpath.Postprocess.camera_uniforms[7] = inputs[8].get();//DoF Focal Length mm
case 'Exposure Compensation': leenkx.renderpath.Postprocess.camera_uniforms[8] = inputs[9].get();//DoF F-Stop
leenkx.renderpath.Postprocess.camera_uniforms[3] = inputs[1].get();//Camera: Exposure Compensation leenkx.renderpath.Postprocess.camera_uniforms[9] = inputs[10].get();//Tonemapping Method
case 'Fisheye Distortion': leenkx.renderpath.Postprocess.camera_uniforms[10] = inputs[11].get();//Distort
leenkx.renderpath.Postprocess.camera_uniforms[4] = inputs[1].get();//Fisheye Distortion leenkx.renderpath.Postprocess.camera_uniforms[11] = inputs[12].get();//Film Grain
case 'Auto Focus': leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[13].get();//Sharpen
leenkx.renderpath.Postprocess.camera_uniforms[5] = inputs[1].get();//DoF AutoFocus §§ If true, it ignores the DoF Distance setting leenkx.renderpath.Postprocess.camera_uniforms[13] = inputs[14].get();//Vignette
case 'DoF Distance':
leenkx.renderpath.Postprocess.camera_uniforms[6] = inputs[1].get();//DoF Distance
case 'DoF Length':
leenkx.renderpath.Postprocess.camera_uniforms[7] = inputs[1].get();//DoF Focal Length mm
case 'DoF F-Stop':
leenkx.renderpath.Postprocess.camera_uniforms[8] = inputs[1].get();//DoF F-Stop
case 'Tonemapping':
leenkx.renderpath.Postprocess.camera_uniforms[9] = inputs[1].get();//Tonemapping Method
case 'Distort':
leenkx.renderpath.Postprocess.camera_uniforms[10] = inputs[1].get();//Distort
case 'Film Grain':
leenkx.renderpath.Postprocess.camera_uniforms[11] = inputs[1].get();//Film Grain
case 'Sharpen':
leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[1].get();//Sharpen
case 'Vignette':
leenkx.renderpath.Postprocess.camera_uniforms[13] = inputs[1].get();//Vignette
case 'Exposure':
leenkx.renderpath.Postprocess.exposure_uniforms[0] = inputs[1].get();//Exposure
default:
null;
}
runOutput(0); runOutput(0);
} }

View File

@ -10,7 +10,6 @@ class ChromaticAberrationGetNode extends LogicNode {
return switch (from) { return switch (from) {
case 0: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0]; case 0: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0];
case 1: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1]; case 1: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1];
case 2: leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[2];
default: 0.0; default: 0.0;
} }
} }

View File

@ -10,7 +10,6 @@ class ChromaticAberrationSetNode extends LogicNode {
leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0] = inputs[1].get(); leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[0] = inputs[1].get();
leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1] = inputs[2].get(); leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[1] = inputs[2].get();
leenkx.renderpath.Postprocess.chromatic_aberration_uniforms[2] = inputs[3].get();
runOutput(0); runOutput(0);
} }

View File

@ -2,9 +2,6 @@ package leenkx.logicnode;
import iron.Scene; import iron.Scene;
import iron.object.CameraObject; import iron.object.CameraObject;
import iron.math.Vec4;
import iron.math.Quat;
import leenkx.math.Helper;
import leenkx.renderpath.RenderPathCreator; import leenkx.renderpath.RenderPathCreator;
@ -30,19 +27,11 @@ class DrawCameraTextureNode extends LogicNode {
final c = inputs[2].get(); final c = inputs[2].get();
assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!"); assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!");
cam = cast(c, CameraObject); cam = cast(c, CameraObject);
rt = kha.Image.createRenderTarget(iron.App.w(), iron.App.h(), rt = kha.Image.createRenderTarget(iron.App.w(), iron.App.h());
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
assert(Error, mo.materials[matSlot].contexts[0].textures != null, 'Object "${mo.name}" has no diffuse texture to render to'); assert(Error, mo.materials[matSlot].contexts[0].textures != null, 'Object "${mo.name}" has no diffuse texture to render to');
mo.materials[matSlot].contexts[0].textures[0] = rt; // Override diffuse texture
final n = inputs[5].get();
for (i => node in mo.materials[matSlot].contexts[0].raw.bind_textures){
if (node.name == n){
mo.materials[matSlot].contexts[0].textures[i] = rt; // Override diffuse texture
break;
}
}
tree.notifyOnRender(render); tree.notifyOnRender(render);
runOutput(0); runOutput(0);
@ -59,20 +48,8 @@ class DrawCameraTextureNode extends LogicNode {
iron.Scene.active.camera = cam; iron.Scene.active.camera = cam;
cam.renderTarget = rt; cam.renderTarget = rt;
#if kha_html5
var q: Quat = new Quat();
q.fromAxisAngle(new Vec4(0, 0, 1, 1), Helper.degToRad(180));
cam.transform.rot.mult(q);
cam.transform.buildMatrix();
#end
cam.renderFrame(g); cam.renderFrame(g);
#if kha_html5
cam.transform.rot.mult(q);
cam.transform.buildMatrix();
#end
cam.renderTarget = oldRT; cam.renderTarget = oldRT;
iron.Scene.active.camera = sceneCam; iron.Scene.active.camera = sceneCam;
} }

View File

@ -99,6 +99,8 @@ class DrawImageSequenceNode extends LogicNode {
final colorVec = inputs[4].get(); final colorVec = inputs[4].get();
g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w); g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
trace(currentImgIdx);
g.drawScaledImage(images[currentImgIdx], inputs[5].get(), inputs[6].get(), inputs[7].get(), inputs[8].get()); g.drawScaledImage(images[currentImgIdx], inputs[5].get(), inputs[6].get(), inputs[7].get(), inputs[8].get());
} }
} }

View File

@ -62,7 +62,7 @@ class DrawStringNode extends LogicNode {
override function get(from: Int): Dynamic { override function get(from: Int): Dynamic {
return from == 1 ? RenderToTexture.g.font.width(RenderToTexture.g.fontSize, string) : RenderToTexture.g.font.height(RenderToTexture.g.fontSize); return from == 1 ? RenderToTexture.g.font.height(RenderToTexture.g.fontSize) : RenderToTexture.g.font.width(RenderToTexture.g.fontSize, string);
} }
} }

View File

@ -1,59 +0,0 @@
package leenkx.logicnode;
import iron.math.Vec4;
import kha.Image;
import kha.Color;
import leenkx.renderpath.RenderToTexture;
class DrawSubImageNode extends LogicNode {
var img: Image;
var lastImgName = "";
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
RenderToTexture.ensure2DContext("DrawImageNode");
final imgName: String = inputs[1].get();
final colorVec: Vec4 = inputs[2].get();
final anchorH: Int = inputs[3].get();
final anchorV: Int = inputs[4].get();
final x: Float = inputs[5].get();
final y: Float = inputs[6].get();
final width: Float = inputs[7].get();
final height: Float = inputs[8].get();
final sx: Float = inputs[9].get();
final sy: Float = inputs[10].get();
final swidth: Float = inputs[11].get();
final sheight: Float = inputs[12].get();
final angle: Float = inputs[13].get();
final drawx = x - 0.5 * width * anchorH;
final drawy = y - 0.5 * height * anchorV;
final sdrawx = sx - 0.5 * swidth * anchorH;
final sdrawy = sy - 0.5 * sheight * anchorV;
RenderToTexture.g.rotate(angle, x, y);
if (imgName != lastImgName) {
// Load new image
lastImgName = imgName;
iron.data.Data.getImage(imgName, (image: Image) -> {
img = image;
});
}
if (img == null) {
runOutput(0);
return;
}
RenderToTexture.g.color = Color.fromFloats(colorVec.x, colorVec.y, colorVec.z, colorVec.w);
RenderToTexture.g.drawScaledSubImage(img, sdrawx, sdrawy, swidth, sheight, drawx, drawy, width, height);
RenderToTexture.g.rotate(-angle, x, y);
runOutput(0);
}
}

View File

@ -1,17 +0,0 @@
package leenkx.logicnode;
import aura.Aura;
import aura.Types;
class GetAudioPositionNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var audio = inputs[0].get();
if (audio == null || audio.channel == null) return 0.0;
return audio.channel.floatPosition / audio.channel.sampleRate;
}
}

View File

@ -1,19 +0,0 @@
package leenkx.logicnode;
import iron.object.MeshObject;
import iron.object.CameraObject;
class GetCameraRenderFilterNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var mo: MeshObject = cast inputs[0].get();
if (mo == null) return null;
return mo.cameraList;
}
}

View File

@ -8,7 +8,7 @@ class GetFPSNode extends LogicNode {
override function get(from: Int): Dynamic { override function get(from: Int): Dynamic {
if (from == 0) { if (from == 0) {
var fps = Math.round(1 / iron.system.Time.renderDelta); var fps = Math.round(1 / iron.system.Time.realDelta);
if ((fps == Math.POSITIVE_INFINITY) || (fps == Math.NEGATIVE_INFINITY) || (Math.isNaN(fps))) { if ((fps == Math.POSITIVE_INFINITY) || (fps == Math.NEGATIVE_INFINITY) || (Math.isNaN(fps))) {
return 0; return 0;
} }

View File

@ -1,72 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
class GetParticleDataNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
var slot: Int = inputs[1].get();
if (object == null) return null;
#if lnx_particles
var mo = cast(object, iron.object.MeshObject);
var psys = mo.particleSystems != null ? mo.particleSystems[slot] :
mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null;
if (psys == null) return null;
return switch (from) {
case 0:
@:privateAccess psys.r.name;
case 1:
@:privateAccess psys.r.particle_size;
case 2:
@:privateAccess psys.r.frame_start;
case 3:
@:privateAccess psys.r.frame_end;
case 4:
@:privateAccess psys.lifetime;
case 5:
@:privateAccess psys.r.lifetime;
case 6:
@:privateAccess psys.r.emit_from;
case 7:
@:privateAccess psys.r.auto_start;
case 8:
@:privateAccess psys.r.is_unique;
case 9:
@:privateAccess psys.r.loop;
case 10:
new iron.math.Vec3(@:privateAccess psys.alignx, @:privateAccess psys.aligny, @:privateAccess psys.alignz);
case 11:
@:privateAccess psys.r.factor_random;
case 12:
new iron.math.Vec3(@:privateAccess psys.gx, @:privateAccess psys.gy, @:privateAccess psys.gz);
case 13:
@:privateAccess psys.r.weight_gravity;
case 14:
psys.speed;
case 15:
@:privateAccess psys.time;
case 16:
@:privateAccess psys.lap;
case 17:
@:privateAccess psys.lapTime;
case 18:
@:privateAccess psys.count;
default:
null;
}
#end
return null;
}
}

View File

@ -1,38 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
class GetParticleNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
if (object == null) return null;
#if lnx_particles
var mo = cast(object, iron.object.MeshObject);
switch (from) {
case 0:
var names: Array<String> = [];
if (mo.particleSystems != null)
for (psys in mo.particleSystems)
names.push(@:privateAccess psys.r.name);
return names;
case 1:
return mo.particleSystems != null ? mo.particleSystems.length : 0;
case 2:
return mo.render_emitter;
default:
null;
}
#end
return null;
}
}

View File

@ -1,33 +0,0 @@
package leenkx.logicnode;
#if lnx_audio
import iron.object.SpeakerObject;
import kha.audio1.AudioChannel;
#end
class GetPositionSpeakerNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
#if lnx_audio
var object: SpeakerObject = cast(inputs[0].get(), SpeakerObject);
if (object == null || object.sound == null) return 0.0;
if (object.channels.length == 0) return 0.0;
var channel = object.channels[0];
var position = 0.0;
if (channel != null) {
position = @:privateAccess channel.get_position();
}
return position;
#else
return 0.0;
#end
}
}

View File

@ -1,12 +1,26 @@
package leenkx.logicnode; package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
class GetWorldNode extends LogicNode { class GetWorldNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) { public function new(tree: LogicTree) {
super(tree); super(tree);
} }
override function get(from: Int): Dynamic { override function get(from: Int): Dynamic {
return iron.Scene.active.raw.world_ref; var object: Object = inputs[0].get();
if (object == null) return null;
return switch (property0) {
case "Right": object.transform.world.right();
case "Look": object.transform.world.look();
case "Up": object.transform.world.up();
default: null;
}
} }
} }

View File

@ -1,26 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
class GetWorldOrientationNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var object: Object = inputs[0].get();
if (object == null) return null;
return switch (property0) {
case "Right": object.transform.world.right();
case "Look": object.transform.world.look();
case "Up": object.transform.world.up();
default: null;
}
}
}

View File

@ -1,233 +0,0 @@
package leenkx.logicnode;
import iron.math.Vec4;
import iron.system.Input;
import iron.object.Object;
import kha.System;
import kha.FastFloat;
/**
* MouseLookNode - FPS-style mouse look camera controller
*
* This node provides smooth, resolution-independent mouse look functionality for
* first-person perspective controls. It supports separate body and head objects,
* allowing for realistic FPS camera movement where the body rotates horizontally
* and the head/camera rotates vertically.
*
* Key Features:
* - Resolution-adaptive scaling for consistent feel across different screen sizes
* - Configurable axis orientations (X, Y, Z as front)
* - Optional mouse cursor locking and hiding
* - Invertible X/Y axes
* - Rotation capping/limiting for both horizontal and vertical movement
* - Smoothing support for smoother camera movement
* - Physics integration with automatic rigid body synchronization
* - Support for both local and world space head rotation
*/
class MouseLookNode extends LogicNode {
// Configuration properties (set from Blender node interface)
public var property0: String; // Front axis: "X", "Y", or "Z"
public var property1: Bool; // Hide Locked: auto-lock mouse cursor
public var property2: Bool; // Invert X: invert horizontal mouse movement
public var property3: Bool; // Invert Y: invert vertical mouse movement
public var property4: Bool; // Cap Left/Right: limit horizontal rotation
public var property5: Bool; // Cap Up/Down: limit vertical rotation
public var property6: Bool; // Head Local Space: use local space for head rotation
// Smoothing state variables - maintain previous frame values for interpolation
var smoothX: Float = 0.0; // Smoothed horizontal mouse delta
var smoothY: Float = 0.0; // Smoothed vertical mouse delta
// Rotation limits (in radians)
var maxHorizontal: Float = Math.PI; // Maximum horizontal rotation (180 degrees)
var maxVertical: Float = Math.PI / 2; // Maximum vertical rotation (90 degrees)
// Current rotation tracking for capping calculations
var currentHorizontal: Float = 0.0; // Accumulated horizontal rotation
var currentVertical: Float = 0.0; // Accumulated vertical rotation
// Resolution scaling reference - base resolution for consistent sensitivity
var baseResolutionWidth: Float = 1920.0;
// Sensitivity scaling constants
static inline var BASE_SCALE: Float = 1500.0; // Base sensitivity scale factor
static var RADIAN_SCALING_FACTOR: Float = Math.PI * 50.0 / 180.0; // Degrees to radians conversion with sensitivity scaling
public function new(tree: LogicTree) {
super(tree);
}
/**
* Main execution function called every frame when the node is active
*
* Input connections:
* [0] - Action trigger (not used in current implementation)
* [1] - Body Object: the main object that rotates horizontally
* [2] - Head Object: optional object that rotates vertically (typically camera)
* [3] - Sensitivity: mouse sensitivity multiplier
* [4] - Smoothing: movement smoothing factor (0.0 = no smoothing, 0.99 = maximum smoothing)
*/
override function run(from: Int) {
// Get input values from connected nodes
var bodyObject: Object = inputs[1].get();
var headObject: Object = inputs[2].get();
var sensitivity: FastFloat = inputs[3].get();
var smoothing: FastFloat = inputs[4].get();
// Early exit if no body object is provided
if (bodyObject == null) {
runOutput(0);
return;
}
// Get mouse input state
var mouse = Input.getMouse();
// Handle automatic mouse cursor locking for FPS controls
if (property1) {
if (mouse.started() && !mouse.locked) {
mouse.lock(); // Center and hide cursor, enable unlimited movement
}
}
// Only process mouse look when cursor is locked or mouse button is held
// This prevents unwanted camera movement when UI elements are being used
if (!mouse.locked && !mouse.down()) {
runOutput(0);
return;
}
// Get raw mouse movement delta (pixels moved since last frame)
var deltaX: Float = mouse.movementX;
var deltaY: Float = mouse.movementY;
// Apply axis inversion if configured
if (property2) deltaX = -deltaX; // Invert horizontal movement
if (property3) deltaY = -deltaY; // Invert vertical movement
// Calculate resolution-adaptive scaling to maintain consistent sensitivity
// across different screen resolutions. Higher resolutions will have proportionally
// higher scaling to compensate for increased pixel density.
var resolutionMultiplier: Float = System.windowWidth() / baseResolutionWidth;
// Apply movement smoothing if enabled
// This creates a weighted average between current and previous movement values
// to reduce jittery camera movement, especially useful for low framerates
if (smoothing > 0.0) {
var smoothingFactor: Float = Math.min(smoothing, 0.99); // Cap smoothing to prevent complete freeze
smoothX = smoothX * smoothingFactor + deltaX * (1.0 - smoothingFactor);
smoothY = smoothY * smoothingFactor + deltaY * (1.0 - smoothingFactor);
deltaX = smoothX;
deltaY = smoothY;
}
// Define rotation axes based on the configured front axis
// These determine which 3D axes are used for horizontal and vertical rotation
var horizontalAxis = new Vec4(); // Axis for left/right body rotation
var verticalAxis = new Vec4(); // Axis for up/down head rotation
switch (property0) {
case "X": // X-axis forward (e.g., for side-scrolling or specific orientations)
horizontalAxis.set(0, 0, 1); // Z-axis for horizontal rotation
verticalAxis.set(0, 1, 0); // Y-axis for vertical rotation
case "Y": // Y-axis forward (most common for 3D games)
#if lnx_yaxisup
// Y-up coordinate system (Blender default)
horizontalAxis.set(0, 0, 1); // Z-axis for horizontal rotation
verticalAxis.set(1, 0, 0); // X-axis for vertical rotation
#else
// Z-up coordinate system
horizontalAxis.set(0, 0, 1); // Z-axis for horizontal rotation
verticalAxis.set(1, 0, 0); // X-axis for vertical rotation
#end
case "Z": // Z-axis forward (top-down or specific orientations)
horizontalAxis.set(0, 1, 0); // Y-axis for horizontal rotation
verticalAxis.set(1, 0, 0); // X-axis for vertical rotation
}
// Calculate final sensitivity scaling combining base scale and resolution adaptation
var finalScale: Float = BASE_SCALE * resolutionMultiplier;
// Apply user-defined sensitivity multiplier
deltaX *= sensitivity;
deltaY *= sensitivity;
// Convert pixel movement to rotation angles (radians)
// Negative values ensure natural movement direction (moving mouse right rotates right)
var horizontalRotation: Float = (-deltaX / finalScale) * RADIAN_SCALING_FACTOR;
var verticalRotation: Float = (-deltaY / finalScale) * RADIAN_SCALING_FACTOR;
// Apply horizontal rotation capping if enabled
// This prevents the character from rotating beyond specified limits
if (property4) {
currentHorizontal += horizontalRotation;
// Clamp rotation to maximum horizontal range and adjust current frame rotation
if (currentHorizontal > maxHorizontal) {
horizontalRotation -= (currentHorizontal - maxHorizontal);
currentHorizontal = maxHorizontal;
} else if (currentHorizontal < -maxHorizontal) {
horizontalRotation -= (currentHorizontal + maxHorizontal);
currentHorizontal = -maxHorizontal;
}
}
// Apply vertical rotation capping if enabled
// This prevents looking too far up or down (like human neck limitations)
if (property5) {
currentVertical += verticalRotation;
// Clamp rotation to maximum vertical range and adjust current frame rotation
if (currentVertical > maxVertical) {
verticalRotation -= (currentVertical - maxVertical);
currentVertical = maxVertical;
} else if (currentVertical < -maxVertical) {
verticalRotation -= (currentVertical + maxVertical);
currentVertical = -maxVertical;
}
}
// Apply horizontal rotation to body object (character turning left/right)
if (horizontalRotation != 0.0) {
bodyObject.transform.rotate(horizontalAxis, horizontalRotation);
// Synchronize physics rigid body if present
// This ensures physics simulation stays in sync with visual transform
#if lnx_physics
var rigidBody = bodyObject.getTrait(leenkx.trait.physics.RigidBody);
if (rigidBody != null) rigidBody.syncTransform();
#end
}
// Apply vertical rotation to head object (camera looking up/down)
if (headObject != null && verticalRotation != 0.0) {
if (property6) {
// Local space rotation - recommended when head is a child of body
// This prevents gimbal lock and rotation inheritance issues
headObject.transform.rotate(verticalAxis, verticalRotation);
} else {
// World space rotation - uses head object's current right vector
// More accurate for independent head objects but can cause issues with parenting
var headVerticalAxis = headObject.transform.world.right();
headObject.transform.rotate(headVerticalAxis, verticalRotation);
}
// Synchronize head physics rigid body if present
#if lnx_physics
var headRigidBody = headObject.getTrait(leenkx.trait.physics.RigidBody);
if (headRigidBody != null) headRigidBody.syncTransform();
#end
} else if (headObject == null && verticalRotation != 0.0) {
// Fallback: if no separate head object, apply vertical rotation to body
// This creates a simpler single-object camera control
bodyObject.transform.rotate(verticalAxis, verticalRotation);
// Synchronize body physics rigid body
#if lnx_physics
var rigidBody = bodyObject.getTrait(leenkx.trait.physics.RigidBody);
if (rigidBody != null) rigidBody.syncTransform();
#end
}
// Continue to next connected node in the logic tree
runOutput(0);
}
}

View File

@ -1,23 +0,0 @@
package leenkx.logicnode;
class OnceNode extends LogicNode {
var triggered:Bool = false;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
if(from == 1){
triggered = false;
return;
}
if (!triggered) {
triggered = true;
runOutput(0);
}
}
}

View File

@ -9,38 +9,19 @@ import iron.Scene;
class PlayAnimationTreeNode extends LogicNode { class PlayAnimationTreeNode extends LogicNode {
var object: Object;
var action: Dynamic;
var init: Bool = false;
public function new(tree: LogicTree) { public function new(tree: LogicTree) {
super(tree); super(tree);
} }
override function run(from: Int) { override function run(from: Int) {
object = inputs[1].get(); var object: Object = inputs[1].get();
action = inputs[2].get(); var action: Dynamic = inputs[2].get();
assert(Error, object != null, "The object input not be null"); assert(Error, object != null, "The object input not be null");
init = true;
tree.notifyOnUpdate(playAnim);
// TO DO: Investigate AnimAction get and PlayAnimationTree notifiers
}
function playAnim() {
if (init = false) return;
init = false;
tree.removeUpdate(playAnim);
var animation = object.animation; var animation = object.animation;
if(animation == null) { if(animation == null) {
#if lnx_skin #if lnx_skin
animation = object.getBoneAnimation(object.uid); animation = object.getBoneAnimation(object.uid);
if (animation == null) {
tree.notifyOnUpdate(playAnim);
init = true;
return;
}
cast(animation, BoneAnimation).setAnimationLoop(function f(mats) { cast(animation, BoneAnimation).setAnimationLoop(function f(mats) {
action(mats); action(mats);
}); });
@ -51,6 +32,7 @@ class PlayAnimationTreeNode extends LogicNode {
action(mats); action(mats);
}); });
} }
runOutput(0); runOutput(0);
} }
} }

View File

@ -18,6 +18,7 @@ class ProbabilisticOutputNode extends LogicNode {
} }
if (sum > 1){ if (sum > 1){
trace(sum);
for (p in 0...probs.length) for (p in 0...probs.length)
probs[p] /= sum; probs[p] /= sum;
} }

View File

@ -1,64 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
class RemoveParticleFromObjectNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if lnx_particles
var object: Object = inputs[1].get();
if (object == null) return;
var mo = cast(object, iron.object.MeshObject);
if (mo.particleSystems == null) return;
if (property0 == 'All'){
mo.particleSystems = null;
for (c in mo.particleChildren) c.remove();
mo.particleChildren = null;
mo.particleOwner = null;
mo.render_emitter = true;
}
else {
var slot: Int = -1;
if (property0 == 'Name'){
var name: String = inputs[2].get();
for (i => psys in mo.particleSystems){
if (@:privateAccess psys.r.name == name){ slot = i; break; }
}
}
else slot = inputs[2].get();
if (mo.particleSystems.length > slot){
for (i in slot+1...mo.particleSystems.length){
var mi = cast(mo.particleChildren[i], iron.object.MeshObject);
mi.particleIndex = mi.particleIndex - 1;
}
mo.particleSystems.splice(slot, 1);
mo.particleChildren[slot].remove();
mo.particleChildren.splice(slot, 1);
}
if (slot == 0){
mo.particleSystems = null;
mo.particleChildren = null;
mo.particleOwner = null;
mo.render_emitter = true;
}
}
#end
runOutput(0);
}
}

View File

@ -1,16 +0,0 @@
package leenkx.logicnode;
class ResolutionGetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function get(from:Int):Dynamic {
return switch (from) {
case 0: leenkx.renderpath.Postprocess.resolution_uniforms[0];
case 1: leenkx.renderpath.Postprocess.resolution_uniforms[1];
default: 0;
}
}
}

View File

@ -1,33 +0,0 @@
package leenkx.logicnode;
import kha.graphics4.TextureFilter;
class ResolutionSetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function run(from:Int) {
var size: Int = inputs[1].get();
var filter: Int = inputs[2].get();
#if rp_resolution_filter
if (filter == 0)
iron.object.Uniforms.defaultFilter = TextureFilter.LinearFilter;
else
iron.object.Uniforms.defaultFilter = TextureFilter.PointFilter;
leenkx.renderpath.Postprocess.resolution_uniforms[0] = size;
leenkx.renderpath.Postprocess.resolution_uniforms[1] = filter;
var npath = leenkx.renderpath.RenderPathCreator.get();
var world = iron.Scene.active.raw.world_ref;
npath.loadShader("shader_datas/World_" + world + "/World_" + world);
iron.RenderPath.setActive(npath);
#end
runOutput(0);
}
}

View File

@ -20,8 +20,6 @@ class RpConfigNode extends LogicNode {
on ? leenkx.data.Config.raw.rp_ssrefr = true : leenkx.data.Config.raw.rp_ssrefr = false; on ? leenkx.data.Config.raw.rp_ssrefr = true : leenkx.data.Config.raw.rp_ssrefr = false;
case "Bloom": case "Bloom":
on ? leenkx.data.Config.raw.rp_bloom = true : leenkx.data.Config.raw.rp_bloom = false; on ? leenkx.data.Config.raw.rp_bloom = true : leenkx.data.Config.raw.rp_bloom = false;
case "CA":
on ? leenkx.data.Config.raw.rp_chromatic_aberration = true : leenkx.data.Config.raw.rp_chromatic_aberration = false;
case "GI": case "GI":
on ? leenkx.data.Config.raw.rp_gi = true : leenkx.data.Config.raw.rp_gi = false; on ? leenkx.data.Config.raw.rp_gi = true : leenkx.data.Config.raw.rp_gi = false;
case "Motion Blur": case "Motion Blur":

View File

@ -1,23 +0,0 @@
package leenkx.logicnode;
import aura.Aura;
import aura.Types;
class SetAudioPositionNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var audio = inputs[1].get();
if (audio == null) return;
var positionInSeconds:Float = inputs[2].get();
if (positionInSeconds < 0.0) positionInSeconds = 0.0;
audio.channel.floatPosition = positionInSeconds * audio.channel.sampleRate;
runOutput(0);
}
}

View File

@ -1,38 +0,0 @@
package leenkx.logicnode;
import iron.object.MeshObject;
import iron.object.CameraObject;
class SetCameraRenderFilterNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var mo: MeshObject = cast inputs[1].get();
var camera: CameraObject = inputs[2].get();
assert(Error, Std.isOfType(camera, CameraObject), "Camera must be a camera object!");
if (camera == null || mo == null) return;
if (property0 == 'Add'){
if (mo.cameraList == null || mo.cameraList.indexOf(camera.name) == -1){
if (mo.cameraList == null) mo.cameraList = [];
mo.cameraList.push(camera.name);
}
}
else{
if (mo.cameraList != null){
mo.cameraList.remove(camera.name);
if (mo.cameraList.length == 0)
mo.cameraList = null;
}
}
runOutput(0);
}
}

View File

@ -1,21 +0,0 @@
package leenkx.logicnode;
import iron.object.LightObject;
class SetLightShadowNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var light: LightObject = inputs[1].get();
var shadow: Bool = inputs[2].get();
if (light == null) return;
light.data.raw.cast_shadow = shadow;
runOutput(0);
}
}

View File

@ -1,206 +0,0 @@
package leenkx.logicnode;
import iron.math.Vec4;
import iron.math.Quat;
import iron.math.Mat4;
import iron.object.Object;
class SetLookAtRotationNode extends LogicNode {
public var property0: String; // Axis to align
public var property1: String; // Use vector for target (true/false)
public var property2: String; // Use vector for source (true/false)
public var property3: String; // Damping value (backward compatibility, now input socket)
public var property4: String; // Disable rotation on aligning axis (true/false)
public var property5: String; // Use local space (true/false)
// Store the calculated rotation for output
var calculatedRotation: Quat = null;
// Store the previous rotation for smooth interpolation
var previousRotation: Quat = null;
public function new(tree: LogicTree) {
super(tree);
previousRotation = new Quat();
}
override function run(from: Int): Void {
// Determine if we're using a vector or an object as source
var useSourceVector: Bool = property2 == "true";
var objectToUse: Object = null;
var objectLoc: Vec4 = null;
if (useSourceVector) {
// Use tree.object as the object to rotate
objectToUse = tree.object;
if (objectToUse == null) {
runOutput(0);
return;
}
// Get the source location directly
objectLoc = inputs[1].get();
if (objectLoc == null) {
runOutput(0);
return;
}
} else {
// Get the source object (or fallback to tree.object)
objectToUse = (inputs.length > 1 && inputs[1] != null) ? inputs[1].get() : tree.object;
if (objectToUse == null) {
runOutput(0);
return;
}
// Get source object's WORLD position (important for child objects)
objectLoc = new Vec4(objectToUse.transform.worldx(), objectToUse.transform.worldy(), objectToUse.transform.worldz());
}
// Determine if we're using a vector or an object as target
var useTargetVector: Bool = property1 == "true";
var targetLoc: Vec4 = null;
if (useTargetVector) {
// Get the target location directly
targetLoc = inputs[2].get();
if (targetLoc == null) {
runOutput(0);
return;
}
} else {
// Get the target object
var targetObject: Object = inputs[2].get();
if (targetObject == null) {
runOutput(0);
return;
}
// Get target object's WORLD position (important for child objects)
targetLoc = new Vec4(targetObject.transform.worldx(), targetObject.transform.worldy(), targetObject.transform.worldz());
}
// Calculate direction to target
var direction = new Vec4(
targetLoc.x - objectLoc.x,
targetLoc.y - objectLoc.y,
targetLoc.z - objectLoc.z
);
direction.normalize();
// Calculate target rotation based on selected axis
calculatedRotation = new Quat();
switch (property0) {
case "X":
calculatedRotation.fromTo(new Vec4(1, 0, 0), direction);
case "-X":
calculatedRotation.fromTo(new Vec4(-1, 0, 0), direction);
case "Y":
calculatedRotation.fromTo(new Vec4(0, 1, 0), direction);
case "-Y":
calculatedRotation.fromTo(new Vec4(0, -1, 0), direction);
case "Z":
calculatedRotation.fromTo(new Vec4(0, 0, 1), direction);
case "-Z":
calculatedRotation.fromTo(new Vec4(0, 0, -1), direction);
}
// If disable rotation on aligning axis is enabled, constrain the target rotation
if (property4 == "true") {
// Apply constraint to the target rotation BEFORE damping to avoid jiggling
var eulerAngles = calculatedRotation.toEulerOrdered("XYZ");
// Set the rotation around the selected axis to 0
switch (property0) {
case "X", "-X":
eulerAngles.x = 0.0;
case "Y", "-Y":
eulerAngles.y = 0.0;
case "Z", "-Z":
eulerAngles.z = 0.0;
}
// Convert back to quaternion
calculatedRotation.fromEulerOrdered(eulerAngles, "XYZ");
}
// Convert world rotation to local rotation if local space is enabled and object has a parent
var targetRotation = new Quat();
if (property5 == "true" && objectToUse.parent != null) {
// Get parent's world rotation
var parentWorldLoc = new Vec4();
var parentWorldRot = new Quat();
var parentWorldScale = new Vec4();
objectToUse.parent.transform.world.decompose(parentWorldLoc, parentWorldRot, parentWorldScale);
// Convert world rotation to local space by removing parent's rotation influence
// local_rotation = inverse(parent_world_rotation) * world_rotation
var invParentRot = new Quat().setFrom(parentWorldRot);
invParentRot.x = -invParentRot.x;
invParentRot.y = -invParentRot.y;
invParentRot.z = -invParentRot.z;
targetRotation.multquats(invParentRot, calculatedRotation);
} else {
// No local space conversion needed, use world rotation directly
targetRotation.setFrom(calculatedRotation);
}
// Apply rotation with damping
var dampingValue: Float = 0.0;
// Try to get damping from input socket first (index 3), fallback to property
if (inputs.length > 3 && inputs[3] != null) {
var dampingInput: Dynamic = inputs[3].get();
if (dampingInput != null) {
dampingValue = dampingInput;
}
} else {
// Fallback to property for backward compatibility
dampingValue = Std.parseFloat(property3);
}
if (dampingValue > 0.0) {
// Create a fixed interpolation rate that never reaches exactly 1.0
// Higher damping = slower rotation (smaller step)
var step = Math.max(0.001, (1.0 - dampingValue) * 0.2); // 0.001 to 0.2 range
// Get current local rotation as quaternion
var currentLocalRot = new Quat().setFrom(objectToUse.transform.rot);
// Calculate the difference between current and target rotation
var diffQuat = new Quat();
// q1 * inverse(q2) gives the rotation from q2 to q1
var invCurrent = new Quat().setFrom(currentLocalRot);
invCurrent.x = -invCurrent.x;
invCurrent.y = -invCurrent.y;
invCurrent.z = -invCurrent.z;
diffQuat.multquats(targetRotation, invCurrent);
// Convert to axis-angle representation
var axis = new Vec4();
var angle = diffQuat.toAxisAngle(axis);
// Apply only a portion of this rotation (step)
var partialAngle = angle * step;
// Create partial rotation quaternion
var partialRot = new Quat().fromAxisAngle(axis, partialAngle);
// Apply this partial rotation to current local rotation
var newLocalRot = new Quat();
newLocalRot.multquats(partialRot, currentLocalRot);
// Apply the new local rotation
objectToUse.transform.rot.setFrom(newLocalRot);
} else {
// No damping, apply instant rotation
objectToUse.transform.rot.setFrom(targetRotation);
}
objectToUse.transform.buildMatrix();
runOutput(0);
}
// No output sockets needed - this node only performs actions
}

View File

@ -1,55 +0,0 @@
package leenkx.logicnode;
import iron.object.MeshObject;
import iron.data.MaterialData;
class SetMaterialTextureFilterNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var object: MeshObject = inputs[1].get();
var mat: MaterialData = inputs[2].get();
var slot: Int = inputs[3].get();
var name: String = inputs[4].get();
var filter: Int = inputs[5].get();
if (object == null) return;
if (slot >= object.materials.length) return;
var mo = cast(object, iron.object.MeshObject);
for (i => node in mo.materials[slot].contexts[0].raw.bind_textures)
if (node.name == name){
var moImgt = mo.materials[slot].contexts[0].raw.bind_textures[i];
switch(filter){
case 0: //Linear
moImgt.min_filter = null;
moImgt.mag_filter = null;
moImgt.mipmap_filter = null;
moImgt.generate_mipmaps = null;
case 1: //Closest
moImgt.min_filter = 'point';
moImgt.mag_filter = 'point';
moImgt.mipmap_filter = null;
moImgt.generate_mipmaps = null;
case 2: //Cubic
moImgt.min_filter = null;
moImgt.mag_filter = null;
moImgt.mipmap_filter = 'linear';
moImgt.generate_mipmaps = true;
case 3: //Smart
moImgt.min_filter = 'anisotropic';
moImgt.mag_filter = null;
moImgt.mipmap_filter = 'linear';
moImgt.generate_mipmaps = true;
}
break;
}
runOutput(0);
}
}

View File

@ -1,74 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
import iron.math.Mat4;
import iron.system.Time;
class SetObjectDelayedLocationNode extends LogicNode {
public var use_local_space: Bool = false;
private var initialOffset: Vec4 = null;
private var targetPos: Vec4 = new Vec4();
private var currentPos: Vec4 = new Vec4();
private var deltaVec: Vec4 = new Vec4();
private var tempVec: Vec4 = new Vec4();
private var lastParent: Object = null;
private var invParentMatrix: Mat4 = null;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var follower: Object = inputs[1].get();
var target: Object = inputs[2].get();
var delay: Float = inputs[3].get();
if (follower == null || target == null) return runOutput(0);
if (initialOffset == null) {
initialOffset = new Vec4();
var followerPos = follower.transform.world.getLoc();
var targetPos = target.transform.world.getLoc();
initialOffset.setFrom(followerPos);
initialOffset.sub(targetPos);
}
targetPos.setFrom(target.transform.world.getLoc());
currentPos.setFrom(follower.transform.world.getLoc());
tempVec.setFrom(targetPos).add(initialOffset);
deltaVec.setFrom(tempVec).sub(currentPos);
if (deltaVec.length() < 0.001 && delay < 0.01) {
runOutput(0);
return;
}
if (delay == 0.0) {
currentPos.setFrom(tempVec);
} else {
var smoothFactor = Math.exp(-Time.delta / Math.max(0.0001, delay));
currentPos.x = tempVec.x + (currentPos.x - tempVec.x) * smoothFactor;
currentPos.y = tempVec.y + (currentPos.y - tempVec.y) * smoothFactor;
currentPos.z = tempVec.z + (currentPos.z - tempVec.z) * smoothFactor;
}
if (use_local_space && follower.parent != null) {
if (follower.parent != lastParent || invParentMatrix == null) {
lastParent = follower.parent;
invParentMatrix = Mat4.identity();
invParentMatrix.getInverse(follower.parent.transform.world);
}
tempVec.setFrom(currentPos);
tempVec.applymat(invParentMatrix);
follower.transform.loc.set(tempVec.x, tempVec.y, tempVec.z);
} else {
follower.transform.loc.set(currentPos.x, currentPos.y, currentPos.z);
}
follower.transform.buildMatrix();
runOutput(0);
}
}

View File

@ -1,81 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
class SetParticleDataNode extends LogicNode {
public var property0: String;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if lnx_particles
var object: Object = inputs[1].get();
var slot: Int = inputs[2].get();
if (object == null) return;
var mo = cast(object, iron.object.MeshObject);
var psys = mo.particleSystems != null ? mo.particleSystems[slot] :
mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null; if (psys == null) return;
switch (property0) {
case 'Particle Size':
@:privateAccess psys.r.particle_size = inputs[3].get();
case 'Frame Start':
@:privateAccess psys.r.frame_start = inputs[3].get();
@:privateAccess psys.animtime = (@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.frameRate;
@:privateAccess psys.spawnRate = ((@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.count) / @:privateAccess psys.frameRate;
case 'Frame End':
@:privateAccess psys.r.frame_end = inputs[3].get();
@:privateAccess psys.animtime = (@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.frameRate;
@:privateAccess psys.spawnRate = ((@:privateAccess psys.r.frame_end - @:privateAccess psys.r.frame_start) / @:privateAccess psys.count) / @:privateAccess psys.frameRate;
case 'Lifetime':
@:privateAccess psys.lifetime = inputs[3].get() / @:privateAccess psys.frameRate;
case 'Lifetime Random':
@:privateAccess psys.r.lifetime_random = inputs[3].get();
case 'Emit From':
var emit_from: Int = inputs[3].get();
if (emit_from == 0 || emit_from == 1 || emit_from == 2) {
@:privateAccess psys.r.emit_from = emit_from;
@:privateAccess psys.setupGeomGpu(mo.particleChildren != null ? mo.particleChildren[slot] : cast(iron.Scene.active.getChild(@:privateAccess psys.data.raw.instance_object), iron.object.MeshObject), mo);
}
case 'Auto Start':
@:privateAccess psys.r.auto_start = inputs[3].get();
case 'Is Unique':
@:privateAccess psys.r.is_unique = inputs[3].get();
case 'Loop':
@:privateAccess psys.r.loop = inputs[3].get();
case 'Velocity':
var vel: iron.math.Vec3 = inputs[3].get();
@:privateAccess psys.alignx = vel.x;
@:privateAccess psys.aligny = vel.y;
@:privateAccess psys.alignz = vel.z;
case 'Velocity Random':
@:privateAccess psys.r.factor_random = inputs[3].get();
case 'Weight Gravity':
@:privateAccess psys.r.weight_gravity = inputs[3].get();
if (iron.Scene.active.raw.gravity != null) {
@:privateAccess psys.gx = iron.Scene.active.raw.gravity[0] * @:privateAccess psys.r.weight_gravity;
@:privateAccess psys.gy = iron.Scene.active.raw.gravity[1] * @:privateAccess psys.r.weight_gravity;
@:privateAccess psys.gz = iron.Scene.active.raw.gravity[2] * @:privateAccess psys.r.weight_gravity;
}
else {
@:privateAccess psys.gx = 0;
@:privateAccess psys.gy = 0;
@:privateAccess psys.gz = -9.81 * @:privateAccess psys.r.weight_gravity;
}
case 'Speed':
psys.speed = inputs[3].get();
default:
null;
}
#end
runOutput(0);
}
}

View File

@ -1,23 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
class SetParticleRenderEmitterNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if lnx_particles
var object: Object = inputs[1].get();
if (object == null) return;
cast(object, iron.object.MeshObject).render_emitter = inputs[2].get();
#end
runOutput(0);
}
}

View File

@ -11,16 +11,13 @@ class SetParticleSpeedNode extends LogicNode {
override function run(from: Int) { override function run(from: Int) {
#if lnx_particles #if lnx_particles
var object: Object = inputs[1].get(); var object: Object = inputs[1].get();
var slot: Int = inputs[2].get(); var speed: Float = inputs[2].get();
var speed: Float = inputs[3].get();
if (object == null) return; if (object == null) return;
var mo = cast(object, iron.object.MeshObject); var mo = cast(object, iron.object.MeshObject);
var psys = mo.particleSystems != null ? mo.particleSystems[slot] : var psys = mo.particleSystems.length > 0 ? mo.particleSystems[0] : null;
mo.particleOwner != null && mo.particleOwner.particleSystems != null ? mo.particleOwner.particleSystems[slot] : null; if (psys == null) mo.particleOwner.particleSystems[0];
if (psys == null) return;
psys.speed = speed; psys.speed = speed;

View File

@ -1,39 +0,0 @@
package leenkx.logicnode;
#if lnx_audio
import iron.object.SpeakerObject;
import kha.audio1.AudioChannel;
import iron.system.Audio;
#end
class SetPositionSpeakerNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
#if lnx_audio
var object: SpeakerObject = cast(inputs[1].get(), SpeakerObject);
if (object == null || object.sound == null) return;
var positionInSeconds:Float = inputs[2].get();
if (positionInSeconds < 0) positionInSeconds = 0;
var volume = object.data.volume;
var loop = object.data.loop;
var stream = object.data.stream;
object.stop();
var channel = Audio.play(object.sound, loop, stream);
if (channel != null) {
object.channels.push(channel);
channel.volume = volume;
@:privateAccess channel.set_position(positionInSeconds);
}
#end
runOutput(0);
}
}

View File

@ -1,40 +0,0 @@
package leenkx.logicnode;
class SetWorldNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
var world: String = inputs[1].get();
if (world != null){
//check if world shader data exists
var file: String = 'World_'+world+'_data';
#if lnx_json
file += ".json";
#elseif lnx_compress
file += ".lz4";
#else
file += '.lnx';
#end
var exists: Bool = false;
iron.data.Data.getBlob(file, function(b: kha.Blob) {
if (b != null) exists = true;
});
assert(Error, exists == true, "World must be either associated to a scene or have fake user");
iron.Scene.active.raw.world_ref = world;
var npath = leenkx.renderpath.RenderPathCreator.get();
npath.loadShader("shader_datas/World_" + world + "/World_" + world);
iron.RenderPath.setActive(npath);
}
runOutput(0);
}
}

View File

@ -1,17 +0,0 @@
package leenkx.logicnode;
class SharpenGetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function get(from:Int):Dynamic {
return switch (from) {
case 0: leenkx.renderpath.Postprocess.sharpen_uniforms[0];
case 1: leenkx.renderpath.Postprocess.sharpen_uniforms[1][0];
case 2: leenkx.renderpath.Postprocess.camera_uniforms[12];
default: 0.0;
}
}
}

View File

@ -1,18 +0,0 @@
package leenkx.logicnode;
class SharpenSetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function run(from:Int) {
leenkx.renderpath.Postprocess.sharpen_uniforms[0][0] = inputs[1].get().x;
leenkx.renderpath.Postprocess.sharpen_uniforms[0][1] = inputs[1].get().y;
leenkx.renderpath.Postprocess.sharpen_uniforms[0][2] = inputs[1].get().z;
leenkx.renderpath.Postprocess.sharpen_uniforms[1][0] = inputs[2].get();
leenkx.renderpath.Postprocess.camera_uniforms[12] = inputs[3].get();
runOutput(0);
}
}

View File

@ -1,17 +0,0 @@
package leenkx.logicnode;
class VolumetricFogGetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function get(from:Int):Dynamic {
return switch (from) {
case 0: leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0];
case 1: leenkx.renderpath.Postprocess.volumetric_fog_uniforms[1][0];
case 2: leenkx.renderpath.Postprocess.volumetric_fog_uniforms[2][0];
default: 0.0;
}
}
}

View File

@ -1,18 +0,0 @@
package leenkx.logicnode;
class VolumetricFogSetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function run(from:Int) {
leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0][0] = inputs[1].get().x;
leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0][1] = inputs[1].get().y;
leenkx.renderpath.Postprocess.volumetric_fog_uniforms[0][2] = inputs[1].get().z;
leenkx.renderpath.Postprocess.volumetric_fog_uniforms[1][0] = inputs[2].get();
leenkx.renderpath.Postprocess.volumetric_fog_uniforms[2][0] = inputs[3].get();
runOutput(0);
}
}

View File

@ -1,17 +0,0 @@
package leenkx.logicnode;
class VolumetricLightGetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function get(from:Int):Dynamic {
return switch (from) {
case 0: leenkx.renderpath.Postprocess.volumetric_light_uniforms[0];
case 1: leenkx.renderpath.Postprocess.volumetric_light_uniforms[1][0];
case 2: leenkx.renderpath.Postprocess.volumetric_light_uniforms[2][0];
default: 0.0;
}
}
}

View File

@ -1,18 +0,0 @@
package leenkx.logicnode;
class VolumetricLightSetNode extends LogicNode {
public function new(tree:LogicTree) {
super(tree);
}
override function run(from:Int) {
leenkx.renderpath.Postprocess.volumetric_light_uniforms[0][0] = inputs[1].get().x;
leenkx.renderpath.Postprocess.volumetric_light_uniforms[0][1] = inputs[1].get().y;
leenkx.renderpath.Postprocess.volumetric_light_uniforms[0][2] = inputs[1].get().z;
leenkx.renderpath.Postprocess.volumetric_light_uniforms[1][0] = inputs[2].get();
leenkx.renderpath.Postprocess.volumetric_light_uniforms[2][0] = inputs[3].get();
runOutput(0);
}
}

View File

@ -1,105 +0,0 @@
package leenkx.logicnode;
import iron.object.CameraObject;
class WriteImageNode extends LogicNode {
var file: String;
var camera: CameraObject;
var renderTarget: kha.Image;
public function new(tree: LogicTree) {
super(tree);
}
override function run(from: Int) {
// Relative or absolute path to file
file = inputs[1].get();
assert(Error, iron.App.w() % inputs[3].get() == 0 && iron.App.h() % inputs[4].get() == 0, "Aspect ratio must match display resolution ratio");
camera = inputs[2].get();
renderTarget = kha.Image.createRenderTarget(inputs[3].get(), inputs[4].get(),
kha.graphics4.TextureFormat.RGBA32,
kha.graphics4.DepthStencilFormat.NoDepthAndStencil);
tree.notifyOnRender(render);
}
function render(g: kha.graphics4.Graphics) {
var ready = false;
final sceneCam = iron.Scene.active.camera;
final oldRT = camera.renderTarget;
iron.Scene.active.camera = camera;
camera.renderTarget = renderTarget;
camera.renderFrame(g);
var tex = camera.renderTarget;
camera.renderTarget = oldRT;
iron.Scene.active.camera = sceneCam;
var pixels = tex.getPixels();
for (i in 0...pixels.length){
if (pixels.get(i) != 0){ ready = true; break; }
}
//wait for getPixels ready
if (ready) {
var tx = inputs[5].get();
var ty = inputs[6].get();
var tw = inputs[7].get();
var th = inputs[8].get();
var bo = new haxe.io.BytesOutput();
var rgb = haxe.io.Bytes.alloc(tw * th * 4);
for (j in ty...ty + th) {
for (i in tx...tx + tw) {
var k = j * tex.width + i;
var m = (j - ty) * tw + i - tx;
#if kha_krom
var l = k;
#elseif kha_html5
var l = (tex.height - j) * tex.width + i;
#end
//ARGB 0xff
rgb.set(m * 4 + 0, pixels.get(l * 4 + 3));
rgb.set(m * 4 + 1, pixels.get(l * 4 + 0));
rgb.set(m * 4 + 2, pixels.get(l * 4 + 1));
rgb.set(m * 4 + 3, pixels.get(l * 4 + 2));
}
}
var imgwriter = new iron.format.bmp.Writer(bo);
imgwriter.write(iron.format.bmp.Tools.buildFromARGB(tw, th, rgb));
#if kha_krom
Krom.fileSaveBytes(Krom.getFilesLocation() + "/" + file, bo.getBytes().getData());
#elseif kha_html5
var blob = new js.html.Blob([bo.getBytes().getData()], {type: "application"});
var url = js.html.URL.createObjectURL(blob);
var a = cast(js.Browser.document.createElement("a"), js.html.AnchorElement);
a.href = url;
a.download = file;
a.click();
js.html.URL.revokeObjectURL(url);
#end
runOutput(0);
tree.removeRender(render);
}
}
}

View File

@ -77,6 +77,9 @@ class Inc {
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
static var voxel_sh5:kha.compute.Shader = null; static var voxel_sh5:kha.compute.Shader = null;
static var voxel_ta5:kha.compute.TextureUnit; static var voxel_ta5:kha.compute.TextureUnit;
static var voxel_te5:kha.compute.TextureUnit;
static var voxel_tf5:kha.compute.TextureUnit;
static var voxel_tg5:kha.compute.TextureUnit;
static var voxel_ca5:kha.compute.ConstantLocation; static var voxel_ca5:kha.compute.ConstantLocation;
static var voxel_cb5:kha.compute.ConstantLocation; static var voxel_cb5:kha.compute.ConstantLocation;
static var voxel_cc5:kha.compute.ConstantLocation; static var voxel_cc5:kha.compute.ConstantLocation;
@ -529,29 +532,22 @@ class Inc {
public static function applyConfig() { public static function applyConfig() {
#if lnx_config #if lnx_config
var config = leenkx.data.Config.raw; var config = leenkx.data.Config.raw;
#if rp_chromatic_aberration
Postprocess.chromatic_aberration_uniforms[3] = config.rp_chromatic_aberration == true ? 1 : 0;
#end
// Resize shadow map // Resize shadow map
var l = path.light; var l = path.light;
if (l != null){ if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) { l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
l.data.raw.shadowmap_size = config.rp_shadowmap_cascade; var rt = path.renderTargets.get("shadowMap");
var rt = path.renderTargets.get("shadowMap"); if (rt != null) {
if (rt != null) { rt.unload();
rt.unload(); path.renderTargets.remove("shadowMap");
path.renderTargets.remove("shadowMap");
}
} }
else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) { }
l.data.raw.shadowmap_size = config.rp_shadowmap_cube; else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) {
var rt = path.renderTargets.get("shadowMapCube"); l.data.raw.shadowmap_size = config.rp_shadowmap_cube;
if (rt != null) { var rt = path.renderTargets.get("shadowMapCube");
rt.unload(); if (rt != null) {
path.renderTargets.remove("shadowMapCube"); rt.unload();
} path.renderTargets.remove("shadowMapCube");
} }
} }
if (superSample != config.rp_supersample) { if (superSample != config.rp_supersample) {
@ -684,7 +680,7 @@ class Inc {
} }
else { else {
if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") {
t.format = "R16"; t.format = "R8";
t.width = res; t.width = res;
t.height = res * Main.voxelgiClipmapCount; t.height = res * Main.voxelgiClipmapCount;
t.depth = res; t.depth = res;
@ -693,7 +689,7 @@ class Inc {
#if (rp_voxels == "Voxel AO") #if (rp_voxels == "Voxel AO")
{ {
if (t.name == "voxelsOut" || t.name == "voxelsOutB") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") {
t.format = "R16"; t.format = "R8";
t.width = res * (6 + 16); t.width = res * (6 + 16);
t.height = res * Main.voxelgiClipmapCount; t.height = res * Main.voxelgiClipmapCount;
t.depth = res; t.depth = res;
@ -785,11 +781,7 @@ class Inc {
public static inline function getDisplayp(): Null<Int> { public static inline function getDisplayp(): Null<Int> {
#if rp_resolution_filter // Custom resolution set #if rp_resolution_filter // Custom resolution set
#if rp_pp
return leenkx.renderpath.Postprocess.resolution_uniforms[0];
#else
return Main.resolutionSize; return Main.resolutionSize;
#end
#else #else
return null; return null;
#end #end
@ -903,7 +895,9 @@ class Inc {
{ {
voxel_sh5 = path.getComputeShader("voxel_light"); voxel_sh5 = path.getComputeShader("voxel_light");
voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight"); voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight");
voxel_te5 = voxel_sh5.getTextureUnit("voxels");
voxel_tf5 = voxel_sh5.getTextureUnit("voxelsSampler");
voxel_tg5 = voxel_sh5.getTextureUnit("voxelsSDFSampler");
voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps"); voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps");
voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel"); voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel");
@ -1224,7 +1218,7 @@ class Inc {
kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image);
kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write);
//kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image);
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
for (i in 0...Main.voxelgiClipmapCount) { for (i in 0...Main.voxelgiClipmapCount) {
@ -1299,7 +1293,9 @@ class Inc {
kha.compute.Compute.setShader(voxel_sh5); kha.compute.Compute.setShader(voxel_sh5);
kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write);
kha.compute.Compute.setTexture(voxel_te5, rts.get("voxels").image, kha.compute.Access.Read);
kha.compute.Compute.setSampledTexture(voxel_tf5, rts.get("voxelsOut").image);
kha.compute.Compute.setSampledTexture(voxel_tg5, rts.get("voxelsSDF").image);
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
for (i in 0...Main.voxelgiClipmapCount) { for (i in 0...Main.voxelgiClipmapCount) {
fa[i * 10] = clipmaps[i].voxelSize; fa[i * 10] = clipmaps[i].voxelSize;

View File

@ -49,20 +49,15 @@ class Postprocess {
0.01, //4: Fisheye Distortion 0.01, //4: Fisheye Distortion
1, //5: DoF AutoFocus §§ If true, it ignores the DoF Distance setting 1, //5: DoF AutoFocus §§ If true, it ignores the DoF Distance setting
10.0, //6: DoF Distance 10.0, //6: DoF Distance
50.0, //7: DoF Focal Length mm 160.0, //7: DoF Focal Length mm
128, //8: DoF F-Stop 128, //8: DoF F-Stop
0, //9: Tonemapping Method 0, //9: Tonemapping Method
2.0, //10: Distort 2.0, //10: Distort
2.0, //11: Film Grain 2.0, //11: Film Grain
0.25, //12: Sharpen Strength 0.25, //12: Sharpen
0.7 //13: Vignette 0.7 //13: Vignette
]; ];
public static var sharpen_uniforms = [
[0.0, 0.0, 0.0], //0: Sharpen Color
[2.5] //1: Sharpen Size
];
public static var tonemapper_uniforms = [ public static var tonemapper_uniforms = [
1.0, //0: Slope 1.0, //0: Slope
1.0, //1: Toe 1.0, //1: Toe
@ -107,35 +102,7 @@ class Postprocess {
public static var chromatic_aberration_uniforms = [ public static var chromatic_aberration_uniforms = [
2.0, //0: Strength 2.0, //0: Strength
32, //1: Samples 32 //1: Samples
0, //2: Type
1 //3: On/Off
];
public static var exposure_uniforms = [
1 //0: Exposure
];
public static var auto_exposure_uniforms = [
1, //0: Auto Exposure Strength
1 //1: Auto Exposure Speed
];
public static var volumetric_light_uniforms = [
[1.0, 1.0, 1.0], //0: Volumetric Light Air Color
[1.0], //1: Volumetric Light Air Turbidity
[20.0] //2: Volumetric Light Steps
];
public static var volumetric_fog_uniforms = [
[0.5, 0.6, 0.7], //0: Volumetric Fog Color
[0.25], //1: Volumetric Fog Amount A
[50.0] //2: Volumetric Fog Amount B
];
public static var resolution_uniforms = [
720, //0: Size
0 //1: Filter
]; ];
public static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 { public static function vec3Link(object: Object, mat: MaterialData, link: String): iron.math.Vec4 {
@ -317,11 +284,6 @@ class Postprocess {
v.x = lenstexture_uniforms[2]; //Lum min v.x = lenstexture_uniforms[2]; //Lum min
v.y = lenstexture_uniforms[3]; //Lum max v.y = lenstexture_uniforms[3]; //Lum max
v.z = lenstexture_uniforms[4]; //Expo v.z = lenstexture_uniforms[4]; //Expo
case "_PPComp8":
v = iron.object.Uniforms.helpVec;
v.x = exposure_uniforms[0]; //Exposure
v.y = auto_exposure_uniforms[0]; //Auto Exposure Strength
v.z = auto_exposure_uniforms[1]; //Auto Exposure Speed
case "_PPComp9": case "_PPComp9":
v = iron.object.Uniforms.helpVec; v = iron.object.Uniforms.helpVec;
v.x = ssr_uniforms[0]; //Step v.x = ssr_uniforms[0]; //Step
@ -335,8 +297,8 @@ class Postprocess {
case "_PPComp11": case "_PPComp11":
v = iron.object.Uniforms.helpVec; v = iron.object.Uniforms.helpVec;
v.x = bloom_uniforms[2]; // Bloom Strength v.x = bloom_uniforms[2]; // Bloom Strength
v.y = volumetric_light_uniforms[2][0]; //Volumetric Light Steps v.y = 0; // Unused
v.z = volumetric_fog_uniforms[2][0]; //Volumetric Fog Amount B v.z = 0; // Unused
case "_PPComp12": case "_PPComp12":
v = iron.object.Uniforms.helpVec; v = iron.object.Uniforms.helpVec;
v.x = ssao_uniforms[0]; //SSAO Strength v.x = ssao_uniforms[0]; //SSAO Strength
@ -346,8 +308,7 @@ class Postprocess {
v = iron.object.Uniforms.helpVec; v = iron.object.Uniforms.helpVec;
v.x = chromatic_aberration_uniforms[0]; //CA Strength v.x = chromatic_aberration_uniforms[0]; //CA Strength
v.y = chromatic_aberration_uniforms[1]; //CA Samples v.y = chromatic_aberration_uniforms[1]; //CA Samples
v.z = chromatic_aberration_uniforms[2]; //CA Type v.z = 0;
v.w = chromatic_aberration_uniforms[3]; //On/Off
case "_PPComp14": case "_PPComp14":
v = iron.object.Uniforms.helpVec; v = iron.object.Uniforms.helpVec;
v.x = camera_uniforms[10]; //Distort v.x = camera_uniforms[10]; //Distort
@ -377,24 +338,6 @@ class Postprocess {
v.y = letterbox_uniforms[0][1]; v.y = letterbox_uniforms[0][1];
v.z = letterbox_uniforms[0][2]; v.z = letterbox_uniforms[0][2];
v.w = letterbox_uniforms[1][0]; //Size v.w = letterbox_uniforms[1][0]; //Size
case "_PPComp16":
v = iron.object.Uniforms.helpVec;
v.x = sharpen_uniforms[0][0]; //Color
v.y = sharpen_uniforms[0][1];
v.z = sharpen_uniforms[0][2];
v.w = sharpen_uniforms[1][0]; //Size
case "_PPComp17":
v = iron.object.Uniforms.helpVec;
v.x = volumetric_light_uniforms[0][0]; //Air Color
v.y = volumetric_light_uniforms[0][1];
v.z = volumetric_light_uniforms[0][2];
v.w = volumetric_light_uniforms[1][0]; //Air Turbidity
case "_PPComp18":
v = iron.object.Uniforms.helpVec;
v.x = volumetric_fog_uniforms[0][0]; //Color
v.y = volumetric_fog_uniforms[0][1];
v.z = volumetric_fog_uniforms[0][2];
v.w = volumetric_fog_uniforms[1][0]; //Amount A
} }
return v; return v;

View File

@ -368,7 +368,7 @@ class RenderPathDeferred {
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
path.createRenderTarget(t); path.createRenderTarget(t);
// holds background depth // holds background color
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "refr"; t.name = "refr";
t.width = 0; t.width = 0;
@ -473,6 +473,13 @@ class RenderPathDeferred {
} }
#end #end
#if rp_ssrefr
{
path.setTarget("gbuffer_refraction");
path.clearTarget(0xffffff00);
}
#end
RenderPathCreator.setTargetMeshes(); RenderPathCreator.setTargetMeshes();
#if rp_dynres #if rp_dynres
@ -837,7 +844,7 @@ class RenderPathDeferred {
{ {
path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsOut", "voxels");
path.bindTarget("voxelsSDF", "voxelsSDF"); path.bindTarget("voxelsSDF", "voxelsSDF");
path.bindTarget("gbuffer2", "sveloc"); path.bindTarget("gbuffer2", "gbuffer2");
} }
#end #end

View File

@ -522,6 +522,17 @@ class RenderPathForward {
path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]);
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
#if (rp_voxels != "Off") #if (rp_voxels != "Off")
path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsOut", "voxels");
path.bindTarget("voxelsSDF", "voxelsSDF"); path.bindTarget("voxelsSDF", "voxelsSDF");
@ -641,20 +652,18 @@ class RenderPathForward {
var framebuffer = ""; var framebuffer = "";
#end #end
RenderPathCreator.finalTarget = path.currentTarget; #if ((rp_antialiasing == "Off") || (rp_antialiasing == "FXAA"))
var target = "";
#if ((rp_antialiasing == "Off") || (rp_antialiasing == "FXAA") || (!rp_render_to_texture))
{ {
target = framebuffer; RenderPathCreator.finalTarget = path.currentTarget;
path.setTarget(framebuffer);
} }
#else #else
{ {
target = "buf"; path.setTarget("buf");
RenderPathCreator.finalTarget = path.currentTarget;
} }
#end #end
path.setTarget(target);
#if rp_compositordepth #if rp_compositordepth
{ {
path.bindTarget("_main", "gbufferD"); path.bindTarget("_main", "gbufferD");
@ -673,15 +682,6 @@ class RenderPathForward {
} }
#end #end
#if rp_overlays
{
path.setTarget(target);
path.clearTarget(null, 1.0);
path.drawMeshes("overlay");
}
#end
#if ((rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA")) #if ((rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA"))
{ {
path.setTarget("bufa"); path.setTarget("bufa");
@ -712,6 +712,12 @@ class RenderPathForward {
} }
#end #end
#if rp_overlays
{
path.clearTarget(null, 1.0);
path.drawMeshes("overlay");
}
#end
} }
public static function setupDepthTexture() { public static function setupDepthTexture() {

View File

@ -41,7 +41,11 @@ class Starter {
try { try {
#end #end
kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {
#if lnx_render_viewport
visible: false,
#end
mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) {
iron.App.init(function() { iron.App.init(function() {
#if lnx_loadscreen #if lnx_loadscreen

View File

@ -73,17 +73,7 @@ class PhysicsBreak extends Trait {
collisionMargin: 0.04, collisionMargin: 0.04,
linearDeactivationThreshold: 0.0, linearDeactivationThreshold: 0.0,
angularDeactivationThrshold: 0.0, angularDeactivationThrshold: 0.0,
deactivationTime: 0.0, deactivationTime: 0.0
linearVelocityMin: 0.0,
linearVelocityMax: 0.0,
angularVelocityMin: 0.0,
angularVelocityMax: 0.0,
lockTranslationX: false,
lockTranslationY: false,
lockTranslationZ: false,
lockRotationX: false,
lockRotationY: false,
lockRotationZ: false
}; };
o.addTrait(new RigidBody(Shape.ConvexHull, ud.mass, ud.friction, 0, 1, params)); o.addTrait(new RigidBody(Shape.ConvexHull, ud.mass, ud.friction, 0, 1, params));
if (cast(o, MeshObject).data.geom.positions.values.length < 600) { if (cast(o, MeshObject).data.geom.positions.values.length < 600) {

View File

@ -280,11 +280,7 @@ class DebugConsole extends Trait {
function drawObjectNameInList(object: iron.object.Object, selected: Bool) { function drawObjectNameInList(object: iron.object.Object, selected: Bool) {
var _y = ui._y; var _y = ui._y;
ui.text(object.uid+'_'+object.name);
if (object.parent.name == 'Root' && object.raw == null)
ui.text(object.uid+'_'+object.name+' ('+iron.Scene.active.raw.world_ref+')');
else
ui.text(object.uid+'_'+object.name);
if (object == iron.Scene.active.camera) { if (object == iron.Scene.active.camera) {
var tagWidth = 100; var tagWidth = 100;

View File

@ -45,7 +45,7 @@ class DebugDrawHelper {
iron.App.notifyOnRender2D(onRender); iron.App.notifyOnRender2D(onRender);
if (debugDrawMode & DrawRayCast != 0) { if (debugDrawMode & DrawRayCast != 0) {
iron.App.notifyOnFixedUpdate(function () { iron.App.notifyOnUpdate(function () {
rayCasts.resize(0); rayCasts.resize(0);
}); });
} }

View File

@ -101,7 +101,7 @@ class PhysicsWorld extends Trait {
public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, fixedStep = 1 / 60, debugDrawMode: DebugDrawMode = NoDebug) { public function new(timeScale = 1.0, maxSteps = 10, solverIterations = 10, debugDrawMode: DebugDrawMode = NoDebug) {
super(); super();
if (nullvec) { if (nullvec) {
@ -120,7 +120,6 @@ class PhysicsWorld extends Trait {
this.timeScale = timeScale; this.timeScale = timeScale;
this.maxSteps = maxSteps; this.maxSteps = maxSteps;
this.solverIterations = solverIterations; this.solverIterations = solverIterations;
Time.initFixedStep(fixedStep);
// First scene // First scene
if (active == null) { if (active == null) {
@ -137,10 +136,10 @@ class PhysicsWorld extends Trait {
conMap = new Map(); conMap = new Map();
active = this; active = this;
// Ensure physics are updated first in the fixedUpdate list // Ensure physics are updated first in the lateUpdate list
_fixedUpdate = [fixedUpdate]; _lateUpdate = [lateUpdate];
@:privateAccess iron.App.traitFixedUpdates.insert(0, fixedUpdate); @:privateAccess iron.App.traitLateUpdates.insert(0, lateUpdate);
setDebugDrawMode(debugDrawMode); setDebugDrawMode(debugDrawMode);
iron.Scene.active.notifyOnRemove(function() { iron.Scene.active.notifyOnRemove(function() {
@ -299,8 +298,8 @@ class PhysicsWorld extends Trait {
return rb; return rb;
} }
function fixedUpdate() { function lateUpdate() {
var t = Time.fixedStep * timeScale * Time.scale; var t = Time.delta * timeScale;
if (t == 0.0) return; // Simulation paused if (t == 0.0) return; // Simulation paused
#if lnx_debug #if lnx_debug
@ -309,10 +308,13 @@ class PhysicsWorld extends Trait {
if (preUpdates != null) for (f in preUpdates) f(); if (preUpdates != null) for (f in preUpdates) f();
//This condition must be satisfied to not loose time //Bullet physics fixed timescale
var currMaxSteps = t < (Time.fixedStep * maxSteps) ? maxSteps : 1; var fixedTime = 1.0 / 60;
world.stepSimulation(t, currMaxSteps, Time.fixedStep); //This condition must be satisfied to not loose time
var currMaxSteps = t < (fixedTime * maxSteps) ? maxSteps : 1;
world.stepSimulation(t, currMaxSteps, fixedTime);
updateContacts(); updateContacts();
for (rb in rbMap) @:privateAccess rb.physicsUpdate(); for (rb in rbMap) @:privateAccess rb.physicsUpdate();
@ -434,8 +436,8 @@ class PhysicsWorld extends Trait {
from: from, from: from,
to: to, to: to,
hasHit: rc.hasHit(), hasHit: rc.hasHit(),
hitPoint: hitPointWorld.clone(), hitPoint: hitPointWorld,
hitNormal: hitNormalWorld.clone() hitNormal: hitNormalWorld
}); });
} }

Some files were not shown because too many files have changed in this diff Show More