178 Commits
e2002e ... main

Author SHA1 Message Date
cdc425fbcb Update leenkx/Sources/leenkx/logicnode/GetWorldNode.hx 2025-06-10 20:26:59 +00:00
846bb28c86 Merge pull request 't3du [ Repe ] - World Nodes | Resolution PP | Texture Filtering' (#71) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#71
2025-06-10 20:23:04 +00:00
7fabd77ef8 t3du - Resolution post process 2025-06-10 20:12:18 +00:00
fb1a5c88bf t3du - Resolution post process 2025-06-10 20:11:05 +00:00
e05c83a8bb t3du - Resolution post process 2025-06-10 20:08:54 +00:00
ee4f62e881 t3du - Resolution post process 2025-06-10 20:06:49 +00:00
59f8dff22f t3du - Resolution post process 2025-06-10 20:04:37 +00:00
5572226ac5 t3du - Resolution post process 2025-06-10 20:02:59 +00:00
d04874e0b3 t3du - Set / Get World Nodes 2025-06-10 18:55:35 +00:00
ef8b3a99ab t3du - Set / Get World Nodes 2025-06-10 18:52:53 +00:00
1d3254a237 t3du - Set / Get World Nodes 2025-06-10 18:52:26 +00:00
188af4a50f t3du - Set / Get World Nodes 2025-06-10 18:47:00 +00:00
c45baaf396 t3du - Set / Get World Nodes 2025-06-10 18:44:30 +00:00
4b1da08819 t3du - Set / Get World Nodes 2025-06-10 18:42:12 +00:00
aeb353fb20 t3du - Set / Get World Nodes 2025-06-10 18:40:21 +00:00
65961b1593 t3du - Set / Get World Nodes 2025-06-10 18:38:25 +00:00
1c472155e2 t3du - Add material texture filter node 2025-06-10 18:34:09 +00:00
4238f0b2a0 t3du - Add material texture filter node 2025-06-10 18:32:15 +00:00
b40aadf76c t3du - Add material texture filter node 2025-06-10 18:30:27 +00:00
7277987335 Merge pull request 't3du [ Repe ] - Particle Export Option + Dof reference changes' (#68) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#68
2025-06-07 21:15:56 +00:00
a48ec4d034 t3du - Fix DoF references and small changes 2025-06-07 21:12:31 +00:00
7f0153f816 t3du - Fix DoF references and small changes 2025-06-07 21:07:45 +00:00
40d893e139 t3du - Fix DoF references and small changes 2025-06-07 21:06:35 +00:00
9b9289d27d t3du - Fix DoF references and small changes 2025-06-07 20:42:31 +00:00
8786798edd t3du - Fix DoF references and small changes 2025-06-07 20:39:01 +00:00
fa425a98a5 t3du - Add export option for particles 2025-06-07 20:35:01 +00:00
5165769088 Merge pull request 'main' (#67) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#67
2025-06-06 08:22:34 +00:00
feabf446db Update leenkx/Shaders/std/tonemap.glsl 2025-06-06 07:23:55 +00:00
e770120f7d Update leenkx/blender/lnx/write_data.py 2025-06-06 06:46:55 +00:00
7c1b1f2dd9 Merge pull request 't3du [ Repe ] + Moises - Tonemaps / Debugdrawer / Compositor Fixes' (#64) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#64
2025-06-05 17:41:28 +00:00
88a4f0e76a t3du - Clean Compositor 2025-06-05 17:20:09 +00:00
d9e613b3eb moisesjpelaez - Tonemap Fixes 2025-06-05 17:07:50 +00:00
a0c84dc807 moisesjpelaez - CA Fixes 2025-06-05 17:05:08 +00:00
5a92920b1f moisesjpelaez - Tonemap Fixes 2025-06-05 17:03:38 +00:00
30a624c857 Update leenkx/Sources/leenkx/trait/physics/bullet/PhysicsWorld.hx 2025-06-05 00:54:20 +00:00
8153d67eac Update leenkx/Sources/leenkx/trait/physics/bullet/DebugDrawHelper.hx 2025-06-05 00:52:55 +00:00
9963a42c76 Merge pull request 'Shader Fix + moisesjpelaez Aura Fix' (#62) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#62
2025-06-04 19:18:13 +00:00
885385d7cb Update lib/aura/Sources/aura/Time.hx 2025-06-04 19:14:36 +00:00
c433a7f09e Update lib/aura/Sources/aura/threading/Message.hx 2025-06-04 19:13:12 +00:00
c7e2c7d452 Update lib/aura/Sources/aura/dsp/panner/StereoPanner.hx 2025-06-04 19:11:55 +00:00
2a1235b3d8 Update lib/aura/Sources/aura/channels/Html5StreamChannel.hx 2025-06-04 19:10:07 +00:00
074962d158 Update leenkx/blender/lnx/material/cycles_nodes/nodes_shader.py 2025-06-04 19:02:57 +00:00
3ea0d7da9d Merge pull request 't3du [ Repe ] - Post process updates - New nodes - Physics - Chromatic AB' (#60) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#60
2025-06-02 20:07:26 +00:00
00b580a4fa Update leenkx/blender/lnx/logicnode/postprocess/LN_get_auto_exposure_settings.py 2025-06-02 20:06:50 +00:00
f779462f36 t3du - Post Process Updates 2025-06-02 19:51:11 +00:00
2c7343aa31 t3du - Post Process Updates 2025-06-02 19:47:15 +00:00
85912d84fb Add leenkx/blender/lnx/logicnode/postprocess/LN_set_volumetric_light_settings.py 2025-06-02 19:45:39 +00:00
ad0d750dd0 Add leenkx/blender/lnx/logicnode/postprocess/LN_set_volumetric_fog_settings.py 2025-06-02 19:43:52 +00:00
9914d53045 Add leenkx/blender/lnx/logicnode/postprocess/LN_set_sharpen_settings.py 2025-06-02 19:42:36 +00:00
9daf6c15ab Update leenkx/blender/lnx/logicnode/postprocess/LN_set_auto_exposure_settings.py 2025-06-02 19:40:33 +00:00
9ac3de67aa Update leenkx/blender/lnx/logicnode/postprocess/LN_get_volumetric_light_settings.py 2025-06-02 19:40:05 +00:00
fd02f6bca3 Add leenkx/blender/lnx/logicnode/LN_set_auto_exposure_settings.py 2025-06-02 19:39:13 +00:00
2cc0d3db3b Add leenkx/blender/lnx/logicnode/LN_get_volumetric_light_settings.py 2025-06-02 19:38:01 +00:00
fe730a65ee Add leenkx/blender/lnx/logicnode/postprocess/LN_get_volumetric_fog_settings.py 2025-06-02 19:35:27 +00:00
18ec9712fd Add leenkx/blender/lnx/logicnode/postprocess/LN_get_sharpen_settings.py 2025-06-02 19:25:19 +00:00
0d80f3fb6d Add leenkx/blender/lnx/logicnode/postprocess/LN_get_auto_exposure_settings.py 2025-06-02 19:21:53 +00:00
be06b222cb t3du - Post Process Updates 2025-06-02 19:14:54 +00:00
3f0984e227 Update leenkx/blender/lnx/props_ui.py 2025-06-02 19:13:12 +00:00
15a10ea3aa t3du - Post Process Updates 2025-06-02 19:12:33 +00:00
012abfeaf6 t3du - Post Process Updates 2025-06-02 19:11:02 +00:00
dd6cd16661 t3du - Post Process Updates 2025-06-02 19:01:21 +00:00
d8b37efe1b Add leenkx/Sources/leenkx/logicnode/VolumetricLightSetNode.hx 2025-06-02 18:57:18 +00:00
a40a035c03 Add leenkx/Sources/leenkx/logicnode/VolumetricLightGetNode.hx 2025-06-02 18:56:31 +00:00
a318758cbf Add leenkx/Sources/leenkx/logicnode/VolumetricFogSetNode.hx 2025-06-02 18:36:55 +00:00
7c13a25caf Add leenkx/Sources/leenkx/logicnode/VolumetricFogGetNode.hx 2025-06-02 18:36:11 +00:00
141567467f Add leenkx/Sources/leenkx/logicnode/SharpenSetNode.hx 2025-06-02 18:35:24 +00:00
047983a280 Add leenkx/Sources/leenkx/logicnode/SharpenGetNode.hx 2025-06-02 18:34:24 +00:00
48ad4322cf t3du - Post Process Updates 2025-06-02 18:33:21 +00:00
eaa34308d0 Add leenkx/Sources/leenkx/logicnode/AutoExposureSetNode.hx 2025-06-02 18:28:33 +00:00
741a12de78 Add leenkx/Sources/leenkx/logicnode/AutoExposureGetNode.hx 2025-06-02 18:27:31 +00:00
9749467cd7 t3du - Post Process Updates 2025-06-02 18:25:19 +00:00
91ae053346 t3du - Post Process Updates 2025-06-02 18:21:47 +00:00
b7b7edb5e2 t3du - Post Process Updates 2025-06-02 18:19:16 +00:00
dfa99fcb14 t3du - Post Process Updates 2025-06-02 18:18:36 +00:00
bc0bf41b91 t3du - Post Process Updates 2025-06-02 18:17:17 +00:00
535e69dcd0 t3du - Post Process Updates 2025-06-02 18:15:45 +00:00
2eaf83d89c t3du - Post Process Updates 2025-06-02 18:09:31 +00:00
6e62917819 t3du - Post Process Updates 2025-06-02 18:08:41 +00:00
03106eff02 t3du - Particle nodes Update 2025-06-02 18:01:58 +00:00
0c5d71ecd2 t3du - Particle nodes Update 2025-06-02 18:00:15 +00:00
d6a7b7e305 t3du - Particle nodes Update 2025-06-02 17:58:15 +00:00
3d91f2f1e7 t3du - Particle nodes Update 2025-06-02 17:54:31 +00:00
d76c295786 t3du - Krom path condition 2025-06-02 17:48:09 +00:00
79422337ae t3du - CA Updates 2025-06-02 17:35:46 +00:00
b0e624ef75 t3du - CA Updates 2025-06-02 17:34:59 +00:00
9d78aabf35 t3du - CA Updates 2025-06-02 17:33:15 +00:00
a3930d7761 t3du - CA Updates 2025-06-02 17:31:13 +00:00
c958113c94 Update leenkx/blender/lnx/logicnode/postprocess/LN_set_ca_settings.py 2025-06-02 17:27:27 +00:00
385c683fe3 t3du - CA Updates 2025-06-02 17:25:33 +00:00
1050337751 t3du - CA Updates 2025-06-02 17:20:59 +00:00
114bf7544a t3du - CA Updates 2025-06-02 17:14:44 +00:00
0199ee9877 t3du - CA Updates 2025-06-02 17:09:28 +00:00
6e02aeee53 t3du - CA Updates 2025-06-02 17:06:56 +00:00
6c3d71c4c9 t3du - CA Updates 2025-06-02 17:05:30 +00:00
78592b245f t3du - CA Updates 2025-06-02 17:04:55 +00:00
80d4422c90 t3du - CA Updates 2025-06-02 17:03:41 +00:00
32df55d636 t3du - CA Updates 2025-06-02 17:00:57 +00:00
eede86e278 Update leenkx/blender/lnx/props_ui.py 2025-06-02 16:47:43 +00:00
1b855f953f t3du - Ies Texture and Cloud Texture: improvements 2025-06-02 16:46:01 +00:00
59df400b0d t3du - Ies Texture and Cloud Texture: improvements 2025-06-02 16:44:08 +00:00
4af244e3e2 Merge pull request 'moisesjpelaez - Fix pausing and resuming updates' (#59) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#59
2025-06-02 16:35:35 +00:00
ae91f8801f moisesjpelaez - Fix pausing and resuming updates 2025-06-02 16:32:28 +00:00
7f5786d47c moisesjpelaez - Fix pausing and resuming updates 2025-06-02 16:24:22 +00:00
ea12d5b951 moisesjpelaez - Fix pausing and resuming updates 2025-06-02 16:21:25 +00:00
d37468a6ab Merge pull request 'moisesjpelaez - FixedUpdate - Physics Improvements - Private Fields' (#58) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#58
2025-06-02 16:01:44 +00:00
d0b3dc2ff8 moisesjpelaez - Physics Improvements 2025-06-02 07:24:53 +00:00
85bbc10d06 moisesjpelaez - Physics Improvements 2025-06-02 06:31:14 +00:00
2fca73aebd moisesjpelaez - Physics Improvements 2025-06-02 06:26:11 +00:00
8b187940ee moisesjpelaez - Physics Improvements 2025-06-02 06:22:23 +00:00
00369aa90b moisesjpelaez - Physics Improvements 2025-06-02 04:18:44 +00:00
26a10020ac moisesjpelaez - Physics Improvements 2025-06-02 04:12:58 +00:00
421463a642 moisesjpelaez - Physics Improvements 2025-06-02 04:11:02 +00:00
8d9f248d2f moisesjpelaez - Physics Improvements 2025-06-02 04:06:31 +00:00
ed72206a26 moisesjpelaez - Physics Improvements 2025-06-01 23:52:22 +00:00
6b7460dd4c moisesjpelaez - Add particles random size
* Revert
2025-06-01 23:46:05 +00:00
447af740be moisesjpelaez - Framerate and delta fixes 2025-06-01 23:33:30 +00:00
3ff6c32ac9 moisesjpelaez - Framerate and delta fixes 2025-06-01 23:31:49 +00:00
b752d70109 moisesjpelaez - Framerate and delta fixes 2025-06-01 23:29:57 +00:00
a6f83e2d37 moisesjpelaez - Framerate and delta fixes 2025-06-01 23:29:09 +00:00
016e223fb8 moisesjpelaez - Add fixedUpdate for Physics 2025-06-01 23:18:35 +00:00
502601e684 moisesjpelaez - Add fixedUpdate for Physics 2025-06-01 23:17:23 +00:00
29a4bb6803 moisesjpelaez - Add fixedUpdate for Physics 2025-06-01 23:14:43 +00:00
cfbe7c83cb moisesjpelaez - Add fixedUpdate for Physics 2025-06-01 23:09:47 +00:00
a6d9cb9201 moisesjpelaez - Physics Private Fields 2025-06-01 23:02:50 +00:00
32cdbd8c54 moisesjpelaez - Physics Private Fields 2025-06-01 22:57:47 +00:00
1a17b646e4 moisesjpelaez - Physics Private Fields 2025-06-01 22:56:48 +00:00
cdf79de36b moisesjpelaez - Physics Private Fields 2025-06-01 22:55:55 +00:00
2aa6be6496 moisesjpelaez - Physics Private Fields 2025-06-01 22:52:16 +00:00
25c391d244 moisesjpelaez - Physics Improvements 2025-06-01 22:17:30 +00:00
a3c2be4e79 moisesjpelaez - Physics Improvements 2025-06-01 22:16:29 +00:00
3413e10134 moisesjpelaez - Physics Improvements 2025-06-01 22:11:11 +00:00
fa91348428 moisesjpelaez - Physics Improvements 2025-06-01 21:58:58 +00:00
d40d3eb96e moisesjpelaez - Physics Improvements 2025-06-01 21:56:06 +00:00
16e019be26 moisesjpelaez - Physics Improvements 2025-06-01 21:53:31 +00:00
2e77f67683 moisesjpelaez - Physics Improvements 2025-06-01 21:51:09 +00:00
9824dc5a44 moisesjpelaez - General Fixes 2025-06-01 20:52:08 +00:00
1c20e03e0c Update leenkx/blender/lnx/material/cycles_nodes/nodes_converter.py 2025-05-31 06:07:19 +00:00
98f334c883 Merge pull request 'Update get_scene function call' (#57) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#57
2025-05-30 21:43:15 +00:00
8ac8a780e1 Update leenkx/blender/lnx/write_data.py 2025-05-30 21:38:01 +00:00
25e5700084 Update leenkx/blender/lnx/make_renderpath.py 2025-05-30 21:34:37 +00:00
28d60a652b Merge pull request 't3du [ Repe ] - New features + Fixes' (#56) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#56
2025-05-28 23:33:34 +00:00
778be03472 t3du - Fix scene exposure setting 2025-05-28 23:04:39 +00:00
fff8b5c29e t3du - Fix scene exposure setting 2025-05-28 23:02:14 +00:00
a70d0bd601 t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:37:36 +00:00
8fc14ac793 t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:35:28 +00:00
13add8f60b t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:32:37 +00:00
2c1605c855 t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:31:56 +00:00
3524676fcc t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:30:42 +00:00
a577d57263 t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:29:07 +00:00
58440bb347 t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:26:33 +00:00
f3808c4251 t3du - New Image nodes: Draw Sub Image and Write Image 2025-05-28 22:24:50 +00:00
95c08e3424 t3du - Fix draw camera texture node 2025-05-28 22:15:48 +00:00
ce762b3cfa t3du - Fix draw camera texture node 2025-05-28 22:11:50 +00:00
15bcf4a374 t3du - Fix Desc 2025-05-28 22:08:06 +00:00
634aaa0b6a t3du - Fix Desc 2025-05-28 22:07:49 +00:00
69fc090f55 t3du - Conditional Shader Nodes 4.0 + 2025-05-28 21:44:06 +00:00
f42041ccb6 t3du - Delete Traces 2025-05-28 21:35:44 +00:00
a8787bd315 t3du - Delete Traces 2025-05-28 21:34:42 +00:00
b5e77aeef8 t3du - Add Brick Texture 2025-05-28 21:30:38 +00:00
f379685fdd t3du - Add Brick Texture 2025-05-28 21:25:25 +00:00
32ff286691 Merge pull request 't3du [ Repe ] - Lightmapper fix: update ShaderNodeMixRGB to ShaderNodeMix and 4. above support' (#55) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#55
2025-05-28 02:46:47 +00:00
38ab682978 Update leenkx/blender/lnx/lightmapper/utility/utility.py 2025-05-28 02:32:27 +00:00
8efe115698 Update leenkx/blender/lnx/lightmapper/utility/gui/Viewport.py 2025-05-28 02:21:24 +00:00
38f72101eb Update leenkx/blender/lnx/lightmapper/utility/cycles/prepare.py 2025-05-28 02:06:48 +00:00
f6d03b060c Update leenkx/blender/lnx/lightmapper/utility/cycles/nodes.py 2025-05-28 02:05:04 +00:00
f450c00ff1 Merge pull request 't3du (Repe) - New Particle Nodes!' (#54) from Onek8/LNXSDK:main into main
Reviewed-on: LeenkxTeam/LNXSDK#54
2025-05-28 01:54:21 +00:00
751f960b82 Update leenkx/blender/lnx/logicnode/__init__.py 2025-05-22 22:06:41 +00:00
9558ded5c4 Update leenkx/Sources/iron/object/ParticleSystem.hx 2025-05-22 22:03:44 +00:00
8066756605 Update leenkx/Sources/iron/object/ParticleSystem.hx 2025-05-22 22:02:56 +00:00
ac2507e0ae Update leenkx/Sources/iron/object/MeshObject.hx 2025-05-22 22:00:56 +00:00
205d4ccc41 Update leenkx/Sources/iron/Scene.hx 2025-05-22 21:52:06 +00:00
7565818d0e Upload files to "leenkx/Sources/leenkx/logicnode" 2025-05-22 21:47:32 +00:00
fc093eca3e Upload files to "leenkx/Sources/leenkx/logicnode" 2025-05-22 21:46:21 +00:00
61b8f21037 Update leenkx/Sources/leenkx/logicnode/SetParticleSpeedNode.hx 2025-05-22 21:42:53 +00:00
d988ce8c99 Delete leenkx/blender/lnx/logicnode/animation/LN_set_particle_speed.py 2025-05-22 21:39:32 +00:00
727d82f268 Upload files to "leenkx/blender/lnx/logicnode/particle" 2025-05-22 21:39:10 +00:00
c3c89c320b Upload files to "leenkx/blender/lnx/logicnode/particle" 2025-05-22 21:36:22 +00:00
0b5bb877fb Add leenkx/blender/lnx/logicnode/particle/__init__.py 2025-05-22 21:35:22 +00:00
117 changed files with 3136 additions and 309 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,6 +11,8 @@ vec3 uncharted2Tonemap(const vec3 x) {
vec3 tonemapUncharted2(const vec3 color) {
const float W = 11.2;
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 whiteScale = 1.0 / uncharted2Tonemap(vec3(W));
return curr * whiteScale;

View File

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

View File

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

View File

@ -12,6 +12,7 @@ class App {
static var traitInits: Array<Void->Void> = [];
static var traitUpdates: 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 traitRenders2D: Array<kha.graphics2.Graphics->Void> = [];
public static var framebuffer: kha.Framebuffer;
@ -23,6 +24,8 @@ class App {
public static var renderPathTime: Float;
public static var endFrameCallbacks: Array<Void->Void> = [];
#end
static var last = 0.0;
static var time = 0.0;
static var lastw = -1;
static var lasth = -1;
public static var onResize: Void->Void = null;
@ -34,13 +37,14 @@ class App {
function new(done: Void->Void) {
done();
kha.System.notifyOnFrames(render);
kha.Scheduler.addTimeTask(update, 0, iron.system.Time.delta);
kha.Scheduler.addTimeTask(update, 0, iron.system.Time.step);
}
public static function reset() {
traitInits = [];
traitUpdates = [];
traitLateUpdates = [];
traitFixedUpdates = [];
traitRenders = [];
traitRenders2D = [];
if (onResets != null) for (f in onResets) f();
@ -48,6 +52,8 @@ class App {
static function update() {
if (Scene.active == null || !Scene.active.ready) return;
iron.system.Time.update();
if (pauseUpdates) return;
#if lnx_debug
@ -56,6 +62,14 @@ class App {
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 l = traitUpdates.length;
while (i < l) {
@ -106,7 +120,7 @@ class App {
var frame = frames[0];
framebuffer = frame;
iron.system.Time.update();
iron.system.Time.render();
if (Scene.active == null || !Scene.active.ready) {
render2D(frame);
@ -172,6 +186,14 @@ class App {
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) {
traitRenders.push(f);
}

View File

@ -775,6 +775,7 @@ class Scene {
// Attach particle systems
#if lnx_particles
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);
}
#end

View File

@ -16,6 +16,7 @@ class Trait {
var _remove: Array<Void->Void> = null;
var _update: 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 _render2D: Array<kha.graphics2.Graphics->Void> = null;
@ -87,6 +88,23 @@ class Trait {
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.
**/

View File

@ -392,6 +392,8 @@ typedef TParticleData = {
#end
public var name: String;
public var type: Int; // 0 - Emitter, Hair
public var auto_start: Bool;
public var is_unique: Bool;
public var loop: Bool;
public var count: Int;
public var frame_start: FastFloat;

View File

@ -0,0 +1,50 @@
/*
* 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

@ -0,0 +1,122 @@
/*
* 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

@ -0,0 +1,256 @@
/*
* 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

@ -0,0 +1,74 @@
/*
* 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,9 +159,17 @@ class Animation {
if(markerEvents.get(sampler) != null){
for (i in 0...anim.marker_frames.length) {
if (frameIndex == anim.marker_frames[i]) {
var marketAct = markerEvents.get(sampler);
var ar = marketAct.get(anim.marker_names[i]);
var markerAct = markerEvents.get(sampler);
var ar = markerAct.get(anim.marker_names[i]);
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;

View File

@ -21,6 +21,7 @@ class MeshObject extends Object {
public var particleChildren: Array<MeshObject> = null;
public var particleOwner: MeshObject = null; // Particle object
public var particleIndex = -1;
public var render_emitter = true;
#end
public var cameraDistance: Float;
public var screenSize = 0.0;
@ -255,11 +256,11 @@ class MeshObject extends Object {
particleSystems[i].update(particleChildren[i], this);
}
}
if (particleSystems != null && particleSystems.length > 0 && !raw.render_emitter) return;
if (particleSystems != null && particleSystems.length > 0 && !render_emitter) return;
if (particleSystems == null && cullMaterial(context)) return;
#else
if (cullMaterial(context)) return;
#end
if (cullMaterial(context)) return;
// Get lod
var mats = materials;
var lod = this;

View File

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

View File

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

View File

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

View File

@ -1109,6 +1109,26 @@ class Uniforms {
case "_texUnpack": {
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) {

View File

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

View File

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

View File

@ -0,0 +1,99 @@
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

@ -0,0 +1,16 @@
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

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

View File

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

View File

@ -10,6 +10,7 @@ class ChromaticAberrationSetNode extends LogicNode {
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[2] = inputs[3].get();
runOutput(0);
}

View File

@ -2,6 +2,9 @@ package leenkx.logicnode;
import iron.Scene;
import iron.object.CameraObject;
import iron.math.Vec4;
import iron.math.Quat;
import leenkx.math.Helper;
import leenkx.renderpath.RenderPathCreator;
@ -27,11 +30,19 @@ class DrawCameraTextureNode extends LogicNode {
final c = inputs[2].get();
assert(Error, Std.isOfType(c, CameraObject), "Camera must be a camera object!");
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');
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);
runOutput(0);
@ -48,8 +59,20 @@ class DrawCameraTextureNode extends LogicNode {
iron.Scene.active.camera = cam;
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);
#if kha_html5
cam.transform.rot.mult(q);
cam.transform.buildMatrix();
#end
cam.renderTarget = oldRT;
iron.Scene.active.camera = sceneCam;
}

View File

@ -99,8 +99,6 @@ class DrawImageSequenceNode extends LogicNode {
final colorVec = inputs[4].get();
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());
}
}

View File

@ -0,0 +1,59 @@
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

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

View File

@ -0,0 +1,72 @@
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

@ -0,0 +1,38 @@
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,26 +1,12 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
class GetWorldNode 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;
}
return iron.Scene.active.raw.world_ref;
}
}
}

View File

@ -0,0 +1,26 @@
package leenkx.logicnode;
import iron.object.Object;
import iron.math.Vec4;
class GetWorldNode 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

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

View File

@ -0,0 +1,64 @@
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

@ -0,0 +1,16 @@
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

@ -0,0 +1,33 @@
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,6 +20,8 @@ class RpConfigNode extends LogicNode {
on ? leenkx.data.Config.raw.rp_ssrefr = true : leenkx.data.Config.raw.rp_ssrefr = false;
case "Bloom":
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":
on ? leenkx.data.Config.raw.rp_gi = true : leenkx.data.Config.raw.rp_gi = false;
case "Motion Blur":

View File

@ -0,0 +1,55 @@
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

@ -0,0 +1,81 @@
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':
psys.r.factor_random = inputs[3].get();
case 'Weight Gravity':
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

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

View File

@ -0,0 +1,40 @@
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

@ -0,0 +1,17 @@
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

@ -0,0 +1,18 @@
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

@ -0,0 +1,17 @@
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

@ -0,0 +1,18 @@
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

@ -0,0 +1,17 @@
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

@ -0,0 +1,18 @@
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

@ -0,0 +1,105 @@
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

@ -529,22 +529,29 @@ class Inc {
public static function applyConfig() {
#if lnx_config
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
var l = path.light;
if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
var rt = path.renderTargets.get("shadowMap");
if (rt != null) {
rt.unload();
path.renderTargets.remove("shadowMap");
if (l != null){
if (l.data.raw.type == "sun" && l.data.raw.shadowmap_size != config.rp_shadowmap_cascade) {
l.data.raw.shadowmap_size = config.rp_shadowmap_cascade;
var rt = path.renderTargets.get("shadowMap");
if (rt != null) {
rt.unload();
path.renderTargets.remove("shadowMap");
}
}
}
else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) {
l.data.raw.shadowmap_size = config.rp_shadowmap_cube;
var rt = path.renderTargets.get("shadowMapCube");
if (rt != null) {
rt.unload();
path.renderTargets.remove("shadowMapCube");
else if (l.data.raw.shadowmap_size != config.rp_shadowmap_cube) {
l.data.raw.shadowmap_size = config.rp_shadowmap_cube;
var rt = path.renderTargets.get("shadowMapCube");
if (rt != null) {
rt.unload();
path.renderTargets.remove("shadowMapCube");
}
}
}
if (superSample != config.rp_supersample) {
@ -778,7 +785,11 @@ class Inc {
public static inline function getDisplayp(): Null<Int> {
#if rp_resolution_filter // Custom resolution set
#if rp_pp
return leenkx.renderpath.Postprocess.resolution_uniforms[0];
#else
return Main.resolutionSize;
#end
#else
return null;
#end

View File

@ -49,15 +49,20 @@ class Postprocess {
0.01, //4: Fisheye Distortion
1, //5: DoF AutoFocus §§ If true, it ignores the DoF Distance setting
10.0, //6: DoF Distance
160.0, //7: DoF Focal Length mm
50.0, //7: DoF Focal Length mm
128, //8: DoF F-Stop
0, //9: Tonemapping Method
2.0, //10: Distort
2.0, //11: Film Grain
0.25, //12: Sharpen
0.25, //12: Sharpen Strength
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 = [
1.0, //0: Slope
1.0, //1: Toe
@ -102,7 +107,35 @@ class Postprocess {
public static var chromatic_aberration_uniforms = [
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 {
@ -284,6 +317,11 @@ class Postprocess {
v.x = lenstexture_uniforms[2]; //Lum min
v.y = lenstexture_uniforms[3]; //Lum max
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":
v = iron.object.Uniforms.helpVec;
v.x = ssr_uniforms[0]; //Step
@ -297,8 +335,8 @@ class Postprocess {
case "_PPComp11":
v = iron.object.Uniforms.helpVec;
v.x = bloom_uniforms[2]; // Bloom Strength
v.y = 0; // Unused
v.z = 0; // Unused
v.y = volumetric_light_uniforms[2][0]; //Volumetric Light Steps
v.z = volumetric_fog_uniforms[2][0]; //Volumetric Fog Amount B
case "_PPComp12":
v = iron.object.Uniforms.helpVec;
v.x = ssao_uniforms[0]; //SSAO Strength
@ -308,7 +346,8 @@ class Postprocess {
v = iron.object.Uniforms.helpVec;
v.x = chromatic_aberration_uniforms[0]; //CA Strength
v.y = chromatic_aberration_uniforms[1]; //CA Samples
v.z = 0;
v.z = chromatic_aberration_uniforms[2]; //CA Type
v.w = chromatic_aberration_uniforms[3]; //On/Off
case "_PPComp14":
v = iron.object.Uniforms.helpVec;
v.x = camera_uniforms[10]; //Distort
@ -338,6 +377,24 @@ class Postprocess {
v.y = letterbox_uniforms[0][1];
v.z = letterbox_uniforms[0][2];
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;

View File

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

View File

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

View File

@ -2,11 +2,13 @@ package leenkx.trait.physics.bullet;
#if lnx_bullet
import leenkx.math.Helper;
import iron.data.MeshData;
import iron.math.Vec4;
import iron.math.Quat;
import iron.object.Transform;
import iron.object.MeshObject;
import iron.data.MeshData;
import iron.system.Time;
/**
RigidBody is used to allow objects to interact with Physics in your game including collisions and gravity.
@ -76,6 +78,14 @@ class RigidBody extends iron.Trait {
static var triangleMeshCache = new Map<MeshData, bullet.Bt.TriangleMesh>();
static var usersCache = new Map<MeshData, Int>();
// Interpolation
var interpolate: Bool = false;
var time: Float = 0.0;
var currentPos: bullet.Bt.Vector3 = new bullet.Bt.Vector3(0, 0, 0);
var prevPos: bullet.Bt.Vector3 = new bullet.Bt.Vector3(0, 0, 0);
var currentRot: bullet.Bt.Quaternion = new bullet.Bt.Quaternion(0, 0, 0, 1);
var prevRot: bullet.Bt.Quaternion = new bullet.Bt.Quaternion(0, 0, 0, 1);
public function new(shape = Shape.Box, mass = 1.0, friction = 0.5, restitution = 0.0, group = 1, mask = 1,
params: RigidBodyParams = null, flags: RigidBodyFlags = null) {
super();
@ -85,7 +95,7 @@ class RigidBody extends iron.Trait {
vec1 = new bullet.Bt.Vector3(0, 0, 0);
vec2 = new bullet.Bt.Vector3(0, 0, 0);
vec3 = new bullet.Bt.Vector3(0, 0, 0);
quat1 = new bullet.Bt.Quaternion(0, 0, 0, 0);
quat1 = new bullet.Bt.Quaternion(0, 0, 0, 1);
trans1 = new bullet.Bt.Transform();
trans2 = new bullet.Bt.Transform();
}
@ -117,6 +127,7 @@ class RigidBody extends iron.Trait {
animated: false,
trigger: false,
ccd: false,
interpolate: false,
staticObj: false,
useDeactivation: true
};
@ -131,6 +142,7 @@ class RigidBody extends iron.Trait {
this.animated = flags.animated;
this.trigger = flags.trigger;
this.ccd = flags.ccd;
this.interpolate = flags.interpolate;
this.staticObj = flags.staticObj;
this.useDeactivation = flags.useDeactivation;
@ -153,6 +165,7 @@ class RigidBody extends iron.Trait {
if (!Std.isOfType(object, MeshObject)) return; // No mesh data
transform = object.transform;
transform.buildMatrix();
physics = leenkx.trait.physics.PhysicsWorld.active;
if (shape == Shape.Box) {
@ -244,6 +257,9 @@ class RigidBody extends iron.Trait {
quat1.setValue(quat.x, quat.y, quat.z, quat.w);
trans1.setRotation(quat1);
currentPos.setValue(vec1.x(), vec1.y(), vec1.z());
currentRot.setValue(quat.x, quat.y, quat.z, quat.w);
var centerOfMassOffset = trans2;
centerOfMassOffset.setIdentity();
motionState = new bullet.Bt.DefaultMotionState(trans1, centerOfMassOffset);
@ -307,7 +323,8 @@ class RigidBody extends iron.Trait {
physics.addRigidBody(this);
notifyOnRemove(removeFromWorld);
if (!animated) notifyOnUpdate(update);
if (onReady != null) onReady();
#if js
@ -317,26 +334,71 @@ class RigidBody extends iron.Trait {
#end
}
function update() {
if (interpolate) {
time += Time.delta;
while (time >= Time.fixedStep) {
time -= Time.fixedStep;
}
var t: Float = time / Time.fixedStep;
t = Helper.clamp(t, 0, 1);
var tx: Float = prevPos.x() * (1.0 - t) + currentPos.x() * t;
var ty: Float = prevPos.y() * (1.0 - t) + currentPos.y() * t;
var tz: Float = prevPos.z() * (1.0 - t) + currentPos.z() * t;
var tRot: bullet.Bt.Quaternion = nlerp(prevRot, currentRot, t);
transform.loc.set(tx, ty, tz, 1.0);
transform.rot.set(tRot.x(), tRot.y(), tRot.z(), tRot.w());
} else {
transform.loc.set(currentPos.x(), currentPos.y(), currentPos.z(), 1.0);
transform.rot.set(currentRot.x(), currentRot.y(), currentRot.z(), currentRot.w());
}
if (object.parent != null) {
var ptransform = object.parent.transform;
transform.loc.x -= ptransform.worldx();
transform.loc.y -= ptransform.worldy();
transform.loc.z -= ptransform.worldz();
}
transform.buildMatrix();
}
function nlerp(q1: bullet.Bt.Quaternion, q2: bullet.Bt.Quaternion, t: Float): bullet.Bt.Quaternion {
var dot = q1.x() * q2.x() + q1.y() * q2.y() + q1.z() * q2.z() + q1.w() * q2.w();
var _q2 = dot < 0 ? new bullet.Bt.Quaternion(-q2.x(), -q2.y(), -q2.z(), -q2.w()) : q2;
var x = q1.x() * (1.0 - t) + _q2.x() * t;
var y = q1.y() * (1.0 - t) + _q2.y() * t;
var z = q1.z() * (1.0 - t) + _q2.z() * t;
var w = q1.w() * (1.0 - t) + _q2.w() * t;
var len = Math.sqrt(x * x + y * y + z * z + w * w);
return new bullet.Bt.Quaternion(x / len, y / len, z / len, w / len);
}
function physicsUpdate() {
if (!ready) return;
if (animated) {
syncTransform();
}
else {
} else {
if (interpolate) {
prevPos.setValue(currentPos.x(), currentPos.y(), currentPos.z());
prevRot.setValue(currentRot.x(), currentRot.y(), currentRot.z(), currentRot.w());
}
var trans = body.getWorldTransform();
var p = trans.getOrigin();
var q = trans.getRotation();
transform.loc.set(p.x(), p.y(), p.z());
transform.rot.set(q.x(), q.y(), q.z(), q.w());
if (object.parent != null) {
var ptransform = object.parent.transform;
transform.loc.x -= ptransform.worldx();
transform.loc.y -= ptransform.worldy();
transform.loc.z -= ptransform.worldz();
}
transform.clearDelta();
transform.buildMatrix();
// transform.buildMatrix();
currentPos.setValue(p.x(), p.y(), p.z());
currentRot.setValue(q.x(), q.y(), q.z(), q.w());
#if hl
p.delete();
@ -689,6 +751,7 @@ typedef RigidBodyFlags = {
var animated: Bool;
var trigger: Bool;
var ccd: Bool;
var interpolate: Bool;
var staticObj: Bool;
var useDeactivation: Bool;
}

View File

@ -540,7 +540,7 @@ class LeenkxExporter:
o['material_refs'].append(lnx.utils.asset_name(material))
def export_particle_system_ref(self, psys: bpy.types.ParticleSystem, out_object):
if psys.settings.instance_object is None or psys.settings.render_type != 'OBJECT' or not psys.settings.instance_object.lnx_export:
if psys.settings.instance_object is None or psys.settings.render_type != 'OBJECT' or not psys.settings.instance_object.lnx_export or not bpy.data.objects[out_object['name']].modifiers[psys.name].show_render:
return
self.particle_system_array[psys.settings] = {"structName": psys.settings.name}
@ -910,7 +910,8 @@ class LeenkxExporter:
out_object['particle_refs'] = []
out_object['render_emitter'] = bobject.show_instancer_for_render
for i in range(num_psys):
self.export_particle_system_ref(bobject.particle_systems[i], out_object)
if bobject.modifiers[bobject.particle_systems[i].name].show_render:
self.export_particle_system_ref(bobject.particle_systems[i], out_object)
aabb = bobject.data.lnx_aabb
if aabb[0] == 0 and aabb[1] == 0 and aabb[2] == 0:
@ -2280,6 +2281,15 @@ class LeenkxExporter:
if len(self.particle_system_array) > 0:
self.output['particle_datas'] = []
for particleRef in self.particle_system_array.items():
padd = False;
for obj in self.output['objects']:
if 'particle_refs' in obj:
for pref in obj['particle_refs']:
if pref['particle'] == particleRef[1]["structName"]:
if bpy.data.objects[obj['name']].modifiers[pref['name']].show_render == True:
padd = True;
if not padd:
continue;
psettings = particleRef[0]
if psettings is None:
@ -2297,6 +2307,8 @@ class LeenkxExporter:
out_particlesys = {
'name': particleRef[1]["structName"],
'type': 0 if psettings.type == 'EMITTER' else 1, # HAIR
'auto_start': psettings.lnx_auto_start,
'is_unique': psettings.lnx_is_unique,
'loop': psettings.lnx_loop,
# Emission
'count': int(psettings.count * psettings.lnx_count_mult),
@ -2813,6 +2825,7 @@ class LeenkxExporter:
body_flags['animated'] = rb.kinematic
body_flags['trigger'] = bobject.lnx_rb_trigger
body_flags['ccd'] = bobject.lnx_rb_ccd
body_flags['interpolate'] = bobject.lnx_rb_interpolate
body_flags['staticObj'] = is_static
body_flags['useDeactivation'] = rb.use_deactivation
x['parameters'].append(lnx.utils.get_haxe_json_string(body_params))
@ -3037,7 +3050,7 @@ class LeenkxExporter:
rbw = self.scene.rigidbody_world
if rbw is not None and rbw.enabled:
out_trait['parameters'] = [str(rbw.time_scale), str(rbw.substeps_per_frame), str(rbw.solver_iterations)]
out_trait['parameters'] = [str(rbw.time_scale), str(rbw.substeps_per_frame), str(rbw.solver_iterations), str(wrd.lnx_physics_fixed_step)]
if phys_pkg == 'bullet' or phys_pkg == 'oimo':
debug_draw_mode = 1 if wrd.lnx_physics_dbg_draw_wireframe else 0

View File

@ -87,6 +87,7 @@ def on_operator_post(operator_id: str) -> None:
target_obj.lnx_rb_trigger = source_obj.lnx_rb_trigger
target_obj.lnx_rb_deactivation_time = source_obj.lnx_rb_deactivation_time
target_obj.lnx_rb_ccd = source_obj.lnx_rb_ccd
target_obj.lnx_rb_interpolate = source_obj.lnx_rb_interpolate
target_obj.lnx_rb_collision_filter_mask = source_obj.lnx_rb_collision_filter_mask
elif operator_id == "NODE_OT_new_node_tree":

View File

@ -191,7 +191,7 @@ def apply_materials(load_atlas=0):
mainNode = outputNode.inputs[0].links[0].from_node.inputs[0].links[0].from_node
if (mainNode.type == "ShaderNodeMixRGB"):
if (mainNode.type == "ShaderNodeMix"):
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
print("Mix RGB shader found")
@ -199,9 +199,11 @@ def apply_materials(load_atlas=0):
#Add all nodes first
#Add lightmap multipliction texture
mixNode = node_tree.nodes.new(type="ShaderNodeMixRGB")
mixNode = node_tree.nodes.new(type="ShaderNodeMix")
mixNode.name = "Lightmap_Multiplication"
mixNode.location = -800, 300
mixNode.data_type = 'RGBA'
mixNode.inputs[0].default_value = 1
if scene.TLM_EngineProperties.tlm_lighting_mode == "indirect" or scene.TLM_EngineProperties.tlm_lighting_mode == "indirectAO":
mixNode.blend_type = 'MULTIPLY'
else:
@ -312,8 +314,8 @@ def apply_materials(load_atlas=0):
else:
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect decode node to mixnode
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect exposure node to mixnode
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect decode node to mixnode
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect exposure node to mixnode
else:
@ -323,10 +325,10 @@ def apply_materials(load_atlas=0):
else:
mat.node_tree.links.new(lightmapNode.outputs[1], DecodeNode.inputs[1]) #Connect lightmap node to decodenode
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
mat.node_tree.links.new(DecodeNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
mat.node_tree.links.new(mixNode.outputs[2], mainNode.inputs[0]) #Connect mixnode to pbr node
if not scene.TLM_EngineProperties.tlm_target == "vertex":
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
@ -338,11 +340,11 @@ def apply_materials(load_atlas=0):
if(scene.TLM_EngineProperties.tlm_exposure_multiplier > 0):
mat.node_tree.links.new(lightmapNode.outputs[0], ExposureNode.inputs[0]) #Connect lightmap node to mixnode
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
mat.node_tree.links.new(ExposureNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
else:
mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[1]) #Connect lightmap node to mixnode
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[2]) #Connect basecolor to pbr node
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[0]) #Connect mixnode to pbr node
mat.node_tree.links.new(lightmapNode.outputs[0], mixNode.inputs[6]) #Connect lightmap node to mixnode
mat.node_tree.links.new(baseColorNode.outputs[0], mixNode.inputs[7]) #Connect basecolor to pbr node
mat.node_tree.links.new(mixNode.outputs[0], mainNode.inputs[2]) #Connect mixnode to pbr node
if not scene.TLM_EngineProperties.tlm_target == "vertex":
mat.node_tree.links.new(UVLightmap.outputs[0], lightmapNode.inputs[0]) #Connect uvnode to lightmapnode
@ -491,8 +493,9 @@ def applyAOPass():
AOMap.image = AOImage
AOMap.location = -800, 0
AOMult = nodes.new(type="ShaderNodeMixRGB")
AOMult = nodes.new(type="ShaderNodeMix")
AOMult.name = "TLM_AOMult"
AOMult.data_type = 'RGBA'
AOMult.blend_type = 'MULTIPLY'
AOMult.inputs[0].default_value = 1.0
AOMult.location = -300, 300

View File

@ -518,7 +518,7 @@ def configure_meshes(self):
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
print("The material group is not supported!")
if (mainNode.type == "ShaderNodeMixRGB"):
if (mainNode.type == "ShaderNodeMix"):
if bpy.context.scene.TLM_SceneProperties.tlm_verbose:
print("Mix shader found")
@ -811,7 +811,7 @@ def set_settings():
print(bpy.app.version)
if bpy.app.version[0] == 3:
if bpy.app.version[0] == 3 or byp.app.version[0] == 4:
if cycles.device == "GPU":
scene.cycles.tile_size = 256
else:

View File

@ -28,7 +28,11 @@ class ViewportDraw:
w = 400
h = 200
self.shader = gpu.shader.from_builtin('2D_IMAGE')
if bpy.app.version[0] == 3:
self.shader = gpu.shader.from_builtin('2D_IMAGE')
else:
self.shader = gpu.shader.from_builtin('IMAGE')
self.batch = batch_for_shader(
self.shader, 'TRI_FAN',
{

View File

@ -34,7 +34,7 @@ class Shader_Node_Types:
normal = "ShaderNodeNormalMap"
ao = "ShaderNodeAmbientOcclusion"
uv = "ShaderNodeUVMap"
mix = "ShaderNodeMixRGB"
mix = "ShaderNodeMix"
def select_object(self,obj):
C = bpy.context

View File

@ -47,7 +47,8 @@ def init_categories():
lnx_nodes.add_category('Navmesh', icon='UV_VERTEXSEL', section="motion")
lnx_nodes.add_category('Transform', icon='TRANSFORM_ORIGINS', section="motion")
lnx_nodes.add_category('Physics', icon='PHYSICS', section="motion")
lnx_nodes.add_category('Particle', icon='PARTICLE_DATA', section="motion")
lnx_nodes.add_category('Array', icon='MOD_ARRAY', section="values")
lnx_nodes.add_category('Map', icon='SHORTDISPLAY', section="values")
lnx_nodes.add_category('Database', icon='MESH_CYLINDER', section="values")

View File

@ -11,14 +11,15 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
@input Object: Object of which to choose the material in the `Material Slot` input.
@input Material Slot: Index of the material slot of which the diffuse
texture is replaced with the camera's render target.
@input Node: Node name of the Image Texture Node.
@output On Start: Activated after the `Start` input has been activated.
@output On Stop: Activated after the `Stop` input has been activated.
"""
bl_idname = 'LNDrawCameraTextureNode'
bl_label = 'Draw Camera to Texture'
lnx_section = 'draw'
lnx_version = 1
lnx_version = 2
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'Start')
@ -26,6 +27,13 @@ class DrawCameraTextureNode(LnxLogicTreeNode):
self.add_input('LnxNodeSocketObject', 'Camera')
self.add_input('LnxNodeSocketObject', 'Object')
self.add_input('LnxIntSocket', 'Material Slot')
self.add_input('LnxStringSocket', 'Node')
self.add_output('LnxNodeSocketAction', 'On Start')
self.add_output('LnxNodeSocketAction', 'On Stop')
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement.Identity(self)

View File

@ -0,0 +1,44 @@
from lnx.logicnode.lnx_nodes import *
class DrawSubImageNode(LnxLogicTreeNode):
"""Draws an image.
@input Draw: Activate to draw the image on this frame. The input must
be (indirectly) called from an `On Render2D` node.
@input Image: The filename of the image.
@input Color: The color that the image's pixels are multiplied with.
@input Left/Center/Right: Horizontal anchor point of the image.
0 = Left, 1 = Center, 2 = Right
@input Top/Middle/Bottom: Vertical anchor point of the image.
0 = Top, 1 = Middle, 2 = Bottom
@input X/Y: Position of the anchor point in pixels.
@input Width/Height: Size of the sub image in pixels.
@input sX/Y: Position of the sub anchor point in pixels.
@input sWidth/Height: Size of the image in pixels.
@input Angle: Rotation angle in radians. Image will be rotated cloclwiswe
at the anchor point.
@output Out: Activated after the image has been drawn.
@see [`kha.graphics2.Graphics.drawImage()`](http://kha.tech/api/kha/graphics2/Graphics.html#drawImage).
"""
bl_idname = 'LNDrawSubImageNode'
bl_label = 'Draw Sub Image'
lnx_section = 'draw'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'Draw')
self.add_input('LnxStringSocket', 'Image File')
self.add_input('LnxColorSocket', 'Color', default_value=[1.0, 1.0, 1.0, 1.0])
self.add_input('LnxIntSocket', '0/1/2 = Left/Center/Right', default_value=0)
self.add_input('LnxIntSocket', '0/1/2 = Top/Middle/Bottom', default_value=0)
self.add_input('LnxFloatSocket', 'X')
self.add_input('LnxFloatSocket', 'Y')
self.add_input('LnxFloatSocket', 'Width')
self.add_input('LnxFloatSocket', 'Height')
self.add_input('LnxFloatSocket', 'sX')
self.add_input('LnxFloatSocket', 'sY')
self.add_input('LnxFloatSocket', 'sWidth')
self.add_input('LnxFloatSocket', 'sHeight')
self.add_input('LnxFloatSocket', 'Angle')
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -0,0 +1,23 @@
from lnx.logicnode.lnx_nodes import *
class SetMaterialTextureFilterNode(LnxLogicTreeNode):
"""Sets texture filter interpolation."""
bl_idname = 'LNSetMaterialTextureFilterNode'
bl_label = 'Set Object Material Texture Filter'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxNodeSocketObject', 'Object')
self.add_input('LnxDynamicSocket', 'Material')
self.add_input('LnxIntSocket', 'Slot')
self.add_input('LnxStringSocket', 'Node')
self.add_input('LnxIntSocket', 'Texture Filter')
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.label(text='Tex Filter 0: Linear')
layout.label(text='Tex Filter 1: Closest')
layout.label(text='Tex Filter 2: Cubic')
layout.label(text='Tex Filter 3: Smart')

View File

@ -5,8 +5,6 @@ class WriteFileNode(LnxLogicTreeNode):
"""Writes the given string content to the given file. If the file
already exists, the existing content of the file is overwritten.
> **This node is currently only implemented on Krom**
@input File: the name of the file, relative to `Krom.getFilesLocation()`
@input Content: the content to write to the file.

View File

@ -0,0 +1,34 @@
from lnx.logicnode.lnx_nodes import *
class WriteImageNode(LnxLogicTreeNode):
"""Writes the given image to the given file. If the image
already exists, the existing content of the image is overwritten.
Aspect ratio must match display resolution ratio.
@input Image File: the name of the image, relative to `Krom.getFilesLocation()`
@input Camera: the render target image of the camera to write to the image file.
@input Width: width of the image file.
@input Height: heigth of the image file.
@input sX: sub position of first x pixel of the sub image (0 for start).
@input sY: sub position of first y pixel of the sub image (0 for start).
@input sWidth: width of the sub image.
@input sHeight: height of the sub image.
@seeNode Read File
"""
bl_idname = 'LNWriteImageNode'
bl_label = 'Write Image'
lnx_section = 'file'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxStringSocket', 'Image File')
self.add_input('LnxNodeSocketObject', 'Camera')
self.add_input('LnxIntSocket', 'Width')
self.add_input('LnxIntSocket', 'Height')
self.add_input('LnxIntSocket', 'sX')
self.add_input('LnxIntSocket', 'sY')
self.add_input('LnxIntSocket', 'sWidth')
self.add_input('LnxIntSocket', 'sHeight')
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -5,8 +5,6 @@ class WriteJsonNode(LnxLogicTreeNode):
"""Writes the given content to the given JSON file. If the file
already exists, the existing content of the file is overwritten.
> **This node is currently only implemented on Krom**
@input File: the name of the file, relative to `Krom.getFilesLocation()`,
including the file extension.
@input Dynamic: the content to write to the file. Can be any type that can

View File

@ -0,0 +1,41 @@
from lnx.logicnode.lnx_nodes import *
class AddParticleToObjectNode(LnxLogicTreeNode):
"""Sets the speed of the given particle source."""
bl_idname = 'LNAddParticleToObjectNode'
bl_label = 'Add Particle To Object'
lnx_version = 1
def remove_extra_inputs(self, context):
while len(self.inputs) > 1:
self.inputs.remove(self.inputs[-1])
if self.property0 == 'Scene':
self.add_input('LnxStringSocket', 'Scene From Name')
self.add_input('LnxStringSocket', 'Object From Name')
else:
self.add_input('LnxNodeSocketObject', 'Object From')
self.add_input('LnxIntSocket', 'Slot')
self.add_input('LnxNodeSocketObject', 'Object To')
self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
property0: HaxeEnumProperty(
'property0',
items = [('Scene Active', 'Scene Active', 'Scene Active'),
('Scene', 'Scene', 'Scene')],
name='', default='Scene Active', update=remove_extra_inputs)
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxNodeSocketObject', 'Object From')
self.add_input('LnxIntSocket', 'Slot')
self.add_input('LnxNodeSocketObject', 'Object To')
self.add_input('LnxBoolSocket', 'Render Emitter', default_value = True)
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.prop(self, 'property0')

View File

@ -0,0 +1,14 @@
from lnx.logicnode.lnx_nodes import *
class GetParticleNode(LnxLogicTreeNode):
"""Returns the Particle Systems of an object."""
bl_idname = 'LNGetParticleNode'
bl_label = 'Get Particle'
lnx_version = 1
def lnx_init(self, context):
self.inputs.new('LnxNodeSocketObject', 'Object')
self.outputs.new('LnxNodeSocketArray', 'Names')
self.outputs.new('LnxIntSocket', 'Length')
self.outputs.new('LnxBoolSocket', 'Render Emitter')

View File

@ -0,0 +1,34 @@
from lnx.logicnode.lnx_nodes import *
class GetParticleDataNode(LnxLogicTreeNode):
"""Returns the data of the given Particle System."""
bl_idname = 'LNGetParticleDataNode'
bl_label = 'Get Particle Data'
lnx_version = 1
def lnx_init(self, context):
self.inputs.new('LnxNodeSocketObject', 'Object')
self.inputs.new('LnxIntSocket', 'Slot')
self.outputs.new('LnxStringSocket', 'Name')
self.outputs.new('LnxFloatSocket', 'Particle Size')
self.outputs.new('LnxIntSocket', 'Frame Start')
self.outputs.new('LnxIntSocket', 'Frame End')
self.outputs.new('LnxIntSocket', 'Lifetime')
self.outputs.new('LnxFloatSocket', 'Lifetime Random')
self.outputs.new('LnxIntSocket', 'Emit From')
self.outputs.new('LnxBoolSocket', 'Auto Start')
self.outputs.new('LnxBoolSocket', 'Is Unique')
self.outputs.new('LnxBoolSocket', 'Loop')
self.outputs.new('LnxVectorSocket', 'Velocity')
self.outputs.new('LnxFloatSocket', 'Velocity Random')
self.outputs.new('LnxVectorSocket', 'Gravity')
self.outputs.new('LnxFloatSocket', 'Weight Gravity')
self.outputs.new('LnxFloatSocket', 'Speed')
self.outputs.new('LnxFloatSocket', 'Time')
self.outputs.new('LnxFloatSocket', 'Lap')
self.outputs.new('LnxFloatSocket', 'Lap Time')
self.outputs.new('LnxIntSocket', 'Count')

View File

@ -0,0 +1,33 @@
from lnx.logicnode.lnx_nodes import *
class RemoveParticleFromObjectNode(LnxLogicTreeNode):
"""Remove Particle From Object."""
bl_idname = 'LNRemoveParticleFromObjectNode'
bl_label = 'Remove Particle From Object'
lnx_version = 1
def remove_extra_inputs(self, context):
while len(self.inputs) > 2:
self.inputs.remove(self.inputs[-1])
if self.property0 == 'Slot':
self.add_input('LnxIntSocket', 'Slot')
if self.property0 == 'Name':
self.add_input('LnxStringSocket', 'Name')
property0: HaxeEnumProperty(
'property0',
items = [('Slot', 'Slot', 'Slot'),
('Name', 'Name', 'Name'),
('All', 'All', 'All')],
name='', default='Slot', update=remove_extra_inputs)
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxNodeSocketObject', 'Object')
self.add_input('LnxIntSocket', 'Slot')
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.prop(self, 'property0')

View File

@ -0,0 +1,67 @@
from lnx.logicnode.lnx_nodes import *
class SetParticleDataNode(LnxLogicTreeNode):
"""Sets the parameters of the given particle system."""
bl_idname = 'LNSetParticleDataNode'
bl_label = 'Set Particle Data'
lnx_version = 1
def remove_extra_inputs(self, context):
while len(self.inputs) > 3:
self.inputs.remove(self.inputs[-1])
if self.property0 == 'Particle Size':
self.add_input('LnxFloatSocket', 'Particle Size')
if self.property0 == 'Frame End':
self.add_input('LnxIntSocket', 'Frame End')
if self.property0 == 'Frame Start':
self.add_input('LnxIntSocket', 'Frame Start')
if self.property0 == 'Lifetime':
self.add_input('LnxIntSocket', 'Lifetime')
if self.property0 == 'Lifetime Random':
self.add_input('LnxFloatSocket', 'Lifetime Random')
if self.property0 == 'Emit From':
self.add_input('LnxIntSocket', 'Emit From')
if self.property0 == 'Auto Start':
self.add_input('LnxBoolSocket', 'Auto Start')
if self.property0 == 'Is Unique':
self.add_input('LnxBoolSocket', 'Is Unique')
if self.property0 == 'Loop':
self.add_input('LnxBoolSocket', 'Loop')
if self.property0 == 'Velocity':
self.add_input('LnxVectorSocket', 'Velocity')
if self.property0 == 'Velocity Random':
self.add_input('LnxFloatSocket', 'Velocity Random')
if self.property0 == 'Weight Gravity':
self.add_input('LnxFloatSocket', 'Weight Gravity')
if self.property0 == 'Speed':
self.add_input('LnxFloatSocket', 'Speed')
property0: HaxeEnumProperty(
'property0',
items = [('Particle Size', 'Particle Size', 'for the system'),
('Frame Start', 'Frame Start', 'for the system'),
('Frame End', 'Frame End', 'for the system'),
('Lifetime', 'Lifetime', 'for the instance'),
('Lifetime Random', 'Lifetime Random', 'for the system'),
('Emit From', 'Emit From', 'for the system (Vertices:0 Faces:1 Volume: 2)'),
('Auto Start', 'Auto Start', 'for the system'),
('Is Unique', 'Is Unique', 'for the system'),
('Loop', 'Loop', 'for the system'),
('Velocity', 'Velocity', 'for the instance'),
('Velocity Random', 'Velocity Random', 'for the system'),
('Weight Gravity', 'Weight Gravity', 'for the instance'),
('Speed', 'Speed', 'for the instance')],
name='', default='Speed', update=remove_extra_inputs)
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxNodeSocketObject', 'Object')
self.add_input('LnxIntSocket', 'Slot')
self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.prop(self, 'property0')

View File

@ -1,14 +1,22 @@
from lnx.logicnode.lnx_nodes import *
class SetParticleSpeedNode(LnxLogicTreeNode):
"""Sets the speed of the given particle source."""
bl_idname = 'LNSetParticleSpeedNode'
bl_label = 'Set Particle Speed'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxNodeSocketObject', 'Object')
self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
self.add_output('LnxNodeSocketAction', 'Out')
from lnx.logicnode.lnx_nodes import *
class SetParticleSpeedNode(LnxLogicTreeNode):
"""Sets the speed of the given particle source."""
bl_idname = 'LNSetParticleSpeedNode'
bl_label = 'Set Particle Speed'
lnx_version = 2
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxNodeSocketObject', 'Object')
self.add_input('LnxIntSocket', 'Slot')
self.add_input('LnxFloatSocket', 'Speed', default_value=1.0)
self.add_output('LnxNodeSocketAction', 'Out')
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement.Identity(self)

View File

@ -0,0 +1,3 @@
from lnx.logicnode.lnx_nodes import add_node_section
add_node_section(name='default', category='Particle')

View File

@ -0,0 +1,11 @@
from lnx.logicnode.lnx_nodes import *
class AutoExposureGetNode(LnxLogicTreeNode):
"""Returns the auto exposure post-processing settings."""
bl_idname = 'LNAutoExposureGetNode'
bl_label = 'Get Auto Exposure Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxFloatSocket', 'Strength')
self.add_output('LnxFloatSocket', 'Speed')

View File

@ -1,11 +1,20 @@
from lnx.logicnode.lnx_nodes import *
class ChromaticAberrationGetNode(LnxLogicTreeNode):
"""Returns the chromatic aberration post-processing settings."""
"""Returns the chromatic aberration post-processing settings.
Type: Simple 0 Spectral 1.
"""
bl_idname = 'LNChromaticAberrationGetNode'
bl_label = 'Get CA Settings'
lnx_version = 1
lnx_version = 2
def lnx_init(self, context):
self.add_output('LnxFloatSocket', 'Strength')
self.add_output('LnxFloatSocket', 'Samples')
self.add_output('LnxIntSocket', 'Type')
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement.Identity(self)

View File

@ -16,11 +16,12 @@ class CameraGetNode(LnxLogicTreeNode):
self.add_output('LnxFloatSocket', 'DOF Distance')#6
self.add_output('LnxFloatSocket', 'DOF Length')#7
self.add_output('LnxFloatSocket', 'DOF F-Stop')#8
self.add_output('LnxBoolSocket', 'Tonemapping')#9
self.add_output('LnxIntSocket', 'Tonemapping')#9
self.add_output('LnxFloatSocket', 'Distort')#10
self.add_output('LnxFloatSocket', 'Film Grain')#11
self.add_output('LnxFloatSocket', 'Sharpen')#12
self.add_output('LnxFloatSocket', 'Vignette')#13
self.add_output('LnxFloatSocket', 'Exposure')#14
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 3):

View File

@ -0,0 +1,12 @@
from lnx.logicnode.lnx_nodes import *
class ResolutionGetNode(LnxLogicTreeNode):
"""Returns the resolution parameters.
"""
bl_idname = 'LNResolutionGetNode'
bl_label = 'Get Resolution Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxIntSocket', 'Size')
self.add_output('LnxIntSocket', 'Filter')

View File

@ -0,0 +1,12 @@
from lnx.logicnode.lnx_nodes import *
class SharpenGetNode(LnxLogicTreeNode):
"""Returns the sharpen post-processing settings."""
bl_idname = 'LNSharpenGetNode'
bl_label = 'Get Sharpen Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxColorSocket', 'Color')
self.add_output('LnxFloatSocket', 'Size')
self.add_output('LnxFloatSocket', 'Strength')

View File

@ -0,0 +1,12 @@
from lnx.logicnode.lnx_nodes import *
class VolumetricFogGetNode(LnxLogicTreeNode):
"""Returns the volumetric fog post-processing settings."""
bl_idname = 'LNVolumetricFogGetNode'
bl_label = 'Get Volumetric Fog Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxColorSocket', 'Color')
self.add_output('LnxFloatSocket', 'Amount A')
self.add_output('LnxFloatSocket', 'Amount B')

View File

@ -0,0 +1,12 @@
from lnx.logicnode.lnx_nodes import *
class VolumetricLightGetNode(LnxLogicTreeNode):
"""Returns the volumetric light post-processing settings."""
bl_idname = 'LNVolumetricLightGetNode'
bl_label = 'Get Volumetric Light Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxColorSocket', 'Air Color')
self.add_output('LnxFloatSocket', 'Air Turbidity')
self.add_output('LnxIntSocket', 'Steps')

View File

@ -0,0 +1,14 @@
from lnx.logicnode.lnx_nodes import *
class AutoExposureSetNode(LnxLogicTreeNode):
"""Set the sharpen post-processing settings."""
bl_idname = 'LNAutoExposureSetNode'
bl_label = 'Set Auto Exposure Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxFloatSocket', 'Strength', default_value=1)
self.add_input('LnxFloatSocket', 'Speed', default_value=1)
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -1,14 +1,27 @@
from lnx.logicnode.lnx_nodes import *
class ChromaticAberrationSetNode(LnxLogicTreeNode):
"""Set the chromatic aberration post-processing settings."""
"""Set the chromatic aberration post-processing settings.
Type: Simple 0 Spectral 1.
"""
bl_idname = 'LNChromaticAberrationSetNode'
bl_label = 'Set CA Settings'
lnx_version = 1
lnx_version = 2
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxFloatSocket', 'Strength', default_value=2.0)
self.add_input('LnxIntSocket', 'Samples', default_value=32)
self.add_input('LnxIntSocket', 'Type', default_value=0)
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.label(text="Type 0: Simple")
layout.label(text="Type 1: Spectral")
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement.Identity(self)

View File

@ -4,27 +4,81 @@ class CameraSetNode(LnxLogicTreeNode):
"""Set the post-processing effects of a camera."""
bl_idname = 'LNCameraSetNode'
bl_label = 'Set Camera Post Process'
lnx_version = 4
lnx_version = 6
def remove_extra_inputs(self, context):
while len(self.inputs) > 1:
self.inputs.remove(self.inputs[-1])
if self.property0 == 'F-stop':
self.add_input('LnxFloatSocket', 'F-stop', default_value=1.0)#0
if self.property0 == 'Shutter Time':
self.add_input('LnxFloatSocket', 'Shutter Time', default_value=2.8333)#1
if self.property0 == 'ISO':
self.add_input('LnxFloatSocket', 'ISO', default_value=100.0)#2
if self.property0 == 'Exposure Compensation':
self.add_input('LnxFloatSocket', 'Exposure Compensation', default_value=0.0)#3
if self.property0 == 'Fisheye Distortion':
self.add_input('LnxFloatSocket', 'Fisheye Distortion', default_value=0.01)#4
if self.property0 == 'Auto Focus':
self.add_input('LnxBoolSocket', 'Auto Focus', default_value=True)#5
if self.property0 == 'DoF Distance':
self.add_input('LnxFloatSocket', 'DoF Distance', default_value=10.0)#6
if self.property0 == 'DoF Length':
self.add_input('LnxFloatSocket', 'DoF Length', default_value=160.0)#7
if self.property0 == 'DoF F-Stop':
self.add_input('LnxFloatSocket', 'DoF F-Stop', default_value=128.0)#8
if self.property0 == 'Tonemapping':
self.add_input('LnxIntSocket', 'Tonemapping', default_value=5)#9
if self.property0 == 'Distort':
self.add_input('LnxFloatSocket', 'Distort', default_value=2.0)#10
if self.property0 == 'Film Grain':
self.add_input('LnxFloatSocket', 'Film Grain', default_value=2.0)#11
if self.property0 == 'Sharpen':
self.add_input('LnxFloatSocket', 'Sharpen', default_value=0.25)#12
if self.property0 == 'Vignette':
self.add_input('LnxFloatSocket', 'Vignette', default_value=0.7)#13
if self.property0 == 'Exposure':
self.add_input('LnxFloatSocket', 'Exposure', default_value=1)#14
property0: HaxeEnumProperty(
'property0',
items = [('F-stop', 'F-stop', 'F-stop'),
('Shutter Time', 'Shutter Time', 'Shutter Time'),
('ISO', 'ISO', 'ISO'),
('Exposure Compensation', 'Exposure Compensation', 'Exposure Compensation'),
('Fisheye Distortion', 'Fisheye Distortion', 'Fisheye Distortion'),
('Auto Focus', 'Auto Focus', 'Auto Focus'),
('DoF Distance', 'DoF Distance', 'DoF Distance'),
('DoF Length', 'DoF Length', 'DoF Length'),
('DoF F-Stop', 'DoF F-Stop', 'DoF F-Stop'),
('Tonemapping', 'Tonemapping', 'Tonemapping'),
('Distort', 'Distort', 'Distort'),
('Film Grain', 'Film Grain', 'Film Grain'),
('Sharpen', 'Sharpen', 'Sharpen'),
('Vignette', 'Vignette', 'Vignette'),
('Exposure', 'Exposure', 'Exposure')],
name='', default='F-stop', update=remove_extra_inputs)
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxFloatSocket', 'F-stop', default_value=1.0)#0
self.add_input('LnxFloatSocket', 'Shutter Time', default_value=2.8333)#1
self.add_input('LnxFloatSocket', 'ISO', default_value=100.0)#2
self.add_input('LnxFloatSocket', 'Exposure Compensation', default_value=0.0)#3
self.add_input('LnxFloatSocket', 'Fisheye Distortion', default_value=0.01)#4
self.add_input('LnxBoolSocket', 'Auto Focus', default_value=True)#5
self.add_input('LnxFloatSocket', 'DoF Distance', default_value=10.0)#6
self.add_input('LnxFloatSocket', 'DoF Length', default_value=160.0)#7
self.add_input('LnxFloatSocket', 'DoF F-Stop', default_value=128.0)#8
self.add_input('LnxBoolSocket', 'Tonemapping', default_value=False)#9
self.add_input('LnxFloatSocket', 'Distort', default_value=2.0)#10
self.add_input('LnxFloatSocket', 'Film Grain', default_value=2.0)#11
self.add_input('LnxFloatSocket', 'Sharpen', default_value=0.25)#12
self.add_input('LnxFloatSocket', 'Vignette', default_value=0.7)#13
self.add_input('LnxFloatSocket', 'F-stop', default_value=1.0)
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
if self.property0 == 'Tonemapping':
layout.label(text="0: Filmic")
layout.label(text="1: Filmic2")
layout.label(text="2: Reinhard")
layout.label(text="3: Uncharted2")
layout.label(text="5: Agx")
layout.label(text="6: None")
layout.prop(self, 'property0')
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in range(0, 4):
raise LookupError()

View File

@ -0,0 +1,20 @@
from lnx.logicnode.lnx_nodes import *
class ResolutionSetNode(LnxLogicTreeNode):
"""Set the resolution post-processing settings.
Filter 0: Lineal 1: Closest
"""
bl_idname = 'LNResolutionSetNode'
bl_label = 'Set Resolution Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxIntSocket', 'Size', default_value=720)
self.add_input('LnxIntSocket', 'Filter', default_value=0)
self.add_output('LnxNodeSocketAction', 'Out')
def draw_buttons(self, context, layout):
layout.label(text="Type 0: Lineal")
layout.label(text="Type 1: Closest")

View File

@ -0,0 +1,15 @@
from lnx.logicnode.lnx_nodes import *
class SharpenSetNode(LnxLogicTreeNode):
"""Set the sharpen post-processing settings."""
bl_idname = 'LNSharpenSetNode'
bl_label = 'Set Sharpen Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxColorSocket', 'Color', default_value=[0.0, 0.0, 0.0, 1.0])
self.add_input('LnxFloatSocket', 'Size', default_value=2.5)
self.add_input('LnxFloatSocket', 'Strength', default_value=0.25)
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -0,0 +1,15 @@
from lnx.logicnode.lnx_nodes import *
class VolumetricFogSetNode(LnxLogicTreeNode):
"""Set the volumetric fog post-processing settings."""
bl_idname = 'LNVolumetricFogSetNode'
bl_label = 'Set Volumetric Fog Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxColorSocket', 'Color', default_value=[0.5, 0.6, 0.7, 1.0])
self.add_input('LnxFloatSocket', 'Amount A', default_value=0.25)
self.add_input('LnxFloatSocket', 'Amount B', default_value=0.50)
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -0,0 +1,15 @@
from lnx.logicnode.lnx_nodes import *
class VolumetricLightSetNode(LnxLogicTreeNode):
"""Set the volumetric light post-processing settings."""
bl_idname = 'LNVolumetricLightSetNode'
bl_label = 'Set Volumetric Light Settings'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxColorSocket', 'Air Color', default_value=[1.0, 1.0, 1.0, 1.0])
self.add_input('LnxFloatSocket', 'Air Turbidity', default_value=1)
self.add_input('LnxIntSocket', 'Steps', default_value=20)
self.add_output('LnxNodeSocketAction', 'Out')

View File

@ -4,12 +4,13 @@ class RpConfigNode(LnxLogicTreeNode):
"""Sets the post process quality."""
bl_idname = 'LNRpConfigNode'
bl_label = 'Set Post Process Quality'
lnx_version = 1
lnx_version = 2
property0: HaxeEnumProperty(
'property0',
items = [('SSGI', 'SSGI', 'SSGI'),
('SSR', 'SSR', 'SSR'),
('Bloom', 'Bloom', 'Bloom'),
('CA', 'CA', 'CA'),
('GI', 'GI', 'GI'),
('Motion Blur', 'Motion Blur', 'Motion Blur')
],
@ -23,3 +24,10 @@ class RpConfigNode(LnxLogicTreeNode):
def draw_buttons(self, context, layout):
layout.prop(self, 'property0')
def get_replacement_node(self, node_tree: bpy.types.NodeTree):
if self.lnx_version not in (0, 1):
raise LookupError()
return NodeReplacement.Identity(self)

View File

@ -1,8 +1,8 @@
from lnx.logicnode.lnx_nodes import *
class GetWorldNode(LnxLogicTreeNode):
class GetWorldOrientationNode(LnxLogicTreeNode):
"""Returns the world orientation of the given object."""
bl_idname = 'LNGetWorldNode'
bl_idname = 'LNGetWorldOrientationNode'
bl_label = 'Get World Orientation'
lnx_section = 'rotation'
lnx_version = 1

View File

@ -0,0 +1,10 @@
from lnx.logicnode.lnx_nodes import *
class GetWorldNode(LnxLogicTreeNode):
"""Gets the World of the active scene."""
bl_idname = 'LNGetWorldNode'
bl_label = 'Get World'
lnx_version = 1
def lnx_init(self, context):
self.add_output('LnxStringSocket', 'World')

View File

@ -0,0 +1,13 @@
from lnx.logicnode.lnx_nodes import *
class SetWorldNode(LnxLogicTreeNode):
"""Sets the World of the active scene."""
bl_idname = 'LNSetWorldNode'
bl_label = 'Set World'
lnx_version = 1
def lnx_init(self, context):
self.add_input('LnxNodeSocketAction', 'In')
self.add_input('LnxStringSocket', 'World')
self.add_output('LnxNodeSocketAction', 'Out')

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