Compare commits

128 Commits

Author SHA1 Message Date
88c7c5b99e merge upstream 2025-06-13 15:18:22 +00:00
2434ad07f2 merge upstream 2025-06-10 20:28:46 +00:00
00493bed9c merge upstream 2025-06-07 21:35:02 +00:00
7b17633c28 Update leenkx/blender/lnx/material/make_cluster.py 2025-06-07 19:47:12 +00:00
1ef805eb0b Update leenkx/blender/lnx/material/make_mesh.py 2025-06-06 20:01:29 +00:00
cb7b041fea merge upstream 2025-06-06 19:44:32 +00:00
a0e8e1a1a6 merge upstream 2025-06-05 17:49:54 +00:00
846c3b2c11 Update leenkx/blender/lnx/material/make_mesh.py 2025-06-03 16:18:05 +00:00
b5af208766 Update leenkx/Shaders/std/shadows.glsl 2025-06-03 03:09:32 +00:00
63565052e3 Disable BayerMatrix momentaraily 2025-06-02 20:37:45 +00:00
38eb66a0b5 Update leenkx/blender/lnx/material/make_cluster.py 2025-06-02 20:35:28 +00:00
908efdd554 Update leenkx/blender/lnx/material/make_mesh.py 2025-06-02 20:33:49 +00:00
e014484d27 merge upstream 2025-06-02 20:16:04 +00:00
872433cafb Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-06-01 03:42:22 +00:00
74bbb6ca87 Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl 2025-06-01 03:41:14 +00:00
cbbd6fe495 Update leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl 2025-06-01 03:40:37 +00:00
45a48acf8a Update leenkx/Sources/leenkx/renderpath/Inc.hx 2025-06-01 03:39:35 +00:00
c769b3ca26 merge upstream 2025-05-30 21:46:34 +00:00
c4378be891 Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-05-30 19:19:33 +00:00
6ad615a961 Update leenkx/Shaders/std/constants.glsl 2025-05-30 19:18:06 +00:00
1e4510ba56 Update leenkx/Shaders/std/conetrace.glsl 2025-05-30 19:16:59 +00:00
a2714bf101 merge upstream 2025-05-30 19:10:59 +00:00
5639234eb9 Update leenkx/Shaders/std/light.glsl 2025-05-29 21:22:25 +00:00
1591ccdae5 Update leenkx/Shaders/deferred_light/deferred_light.json 2025-05-29 16:56:38 +00:00
9cb5232187 Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl 2025-05-29 16:53:10 +00:00
6b25d8c8ad revert 13ca31f480
revert Update leenkx/Sources/leenkx/renderpath/Inc.hx
2025-05-28 01:36:04 +00:00
13ca31f480 Update leenkx/Sources/leenkx/renderpath/Inc.hx 2025-05-28 01:28:14 +00:00
d102e59040 Update leenkx/blender/lnx/material/make_voxel.py 2025-05-27 18:53:36 +00:00
df0e24c307 Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-05-27 18:42:41 +00:00
2df86850f8 Update leenkx/Shaders/std/constants.glsl 2025-05-27 17:51:56 +00:00
02ff259860 Update leenkx/blender/lnx/material/make_finalize.py 2025-05-27 17:23:03 +00:00
2e6de515ef Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-05-26 23:29:54 +00:00
41b840212c Update leenkx/blender/lnx/props_ui.py 2025-05-26 23:25:50 +00:00
429e6d6768 Update leenkx/Shaders/std/constants.glsl 2025-05-22 19:30:19 +00:00
2d8bfbf181 Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx 2025-05-22 03:07:01 +00:00
1ad7e0eaf4 Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx 2025-05-22 03:03:50 +00:00
ae72401657 Update leenkx/Sources/leenkx/renderpath/Inc.hx 2025-05-22 02:57:45 +00:00
58b9000305 Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-05-22 02:27:46 +00:00
0cc86c41b8 Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl 2025-05-22 02:25:46 +00:00
25f8c5f64c Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl 2025-05-22 02:24:58 +00:00
109544cea9 Update leenkx/Shaders/std/light.glsl 2025-05-22 02:20:28 +00:00
4c92c4bcc9 Update leenkx/Shaders/std/conetrace.glsl 2025-05-22 02:16:35 +00:00
3433afb1c3 Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl 2025-05-22 02:14:06 +00:00
e22b522059 Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl 2025-05-22 02:10:45 +00:00
200af34740 Update leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl 2025-05-22 02:07:44 +00:00
6d7b0078b4 Update leenkx/blender/lnx/props_renderpath.py 2025-05-21 23:26:42 +00:00
fa501cb09b Update leenkx/blender/lnx/write_data.py 2025-05-21 23:18:53 +00:00
62a4bbb714 Update leenkx/blender/lnx/props_ui.py 2025-05-21 23:14:37 +00:00
eab3e3b30c Update leenkx/blender/lnx/props_renderpath.py 2025-05-21 23:07:11 +00:00
3be7528a6c Update leenkx/blender/lnx/material/make_voxel.py 2025-05-21 22:58:06 +00:00
c9dd46c5e3 Update leenkx/blender/lnx/material/make_shader.py 2025-05-21 22:56:05 +00:00
99806b8069 revert e98bfb125d
revert Update leenkx/blender/lnx/material/make_shader.py
2025-05-21 22:51:16 +00:00
e98bfb125d Update leenkx/blender/lnx/material/make_shader.py 2025-05-21 22:47:03 +00:00
c4c0e2beaa Delete leenkx/blender/lnx/material/make_refraction_buffer.py 2025-05-21 22:43:18 +00:00
36cbc934ba Update leenkx/blender/lnx/material/make_finalize.py 2025-05-21 22:42:11 +00:00
210d5ea532 Update leenkx/blender/lnx/material/make_finalize.py 2025-05-21 22:39:52 +00:00
dab9a38424 Update leenkx/blender/lnx/material/make_mesh.py 2025-05-21 22:37:15 +00:00
b7bbe40348 Update leenkx/blender/lnx/material/make_cluster.py 2025-05-21 22:33:01 +00:00
8b084156ff Update leenkx/blender/lnx/make_world.py 2025-05-21 22:29:40 +00:00
538c364f33 Update leenkx/blender/lnx/make_renderpath.py 2025-05-21 22:26:58 +00:00
09eee93ac9 Update leenkx/Sources/iron/object/Uniforms.hx 2025-05-21 16:25:58 +00:00
8b5a77c001 Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx 2025-05-21 16:23:20 +00:00
436b7fac02 Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx 2025-05-21 16:21:05 +00:00
9ef9f5a637 Update leenkx/Sources/leenkx/renderpath/Inc.hx 2025-05-21 16:15:50 +00:00
b8ca4be56a Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-05-21 16:08:14 +00:00
29e4993f06 Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl 2025-05-21 16:05:53 +00:00
4134352688 Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl 2025-05-21 02:10:21 +00:00
25cf758a33 Update leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl 2025-05-21 02:08:50 +00:00
23af038a16 Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl 2025-05-21 02:07:21 +00:00
7f7878aaa6 Update leenkx/Shaders/voxel_offsetprev/voxel_offsetprev.comp.glsl 2025-05-21 02:05:33 +00:00
d7e076fb56 Add leenkx/Shaders/voxel_light/voxel_light.comp.glsl 2025-05-21 02:02:05 +00:00
dab915b60d Delete leenkx/Shaders/voxel_light.comp.glsl 2025-05-21 02:01:43 +00:00
74389ba76a Add leenkx/Shaders/voxel_light.comp.glsl 2025-05-21 02:01:35 +00:00
bd5afc797d Update leenkx/Shaders/std/shadows.glsl 2025-05-21 01:05:37 +00:00
27b4ec42a8 Update leenkx/Shaders/std/light.glsl 2025-05-21 01:04:30 +00:00
ab7edaa9e3 Update leenkx/Shaders/std/constants.glsl 2025-05-21 01:02:56 +00:00
27540ac7e9 Update leenkx/Shaders/std/conetrace.glsl 2025-05-21 01:01:47 +00:00
a5b512f20b Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl 2025-05-21 00:55:14 +00:00
f8d0e67f33 Update leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl 2025-05-21 00:51:33 +00:00
915118617d Update leenkx/Shaders/ssgi_pass/ssgi_pass.json 2025-05-21 00:50:45 +00:00
ea69511e67 Update leenkx/Shaders/ssgi_pass/ssgi_pass.frag.glsl 2025-05-21 00:47:22 +00:00
3926a7f83e Update leenkx/Shaders/deferred_light/deferred_light.json 2025-05-21 00:42:00 +00:00
0eafd14ae2 Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl 2025-05-21 00:40:56 +00:00
08614512d7 Update leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl 2025-05-21 00:19:31 +00:00
08261a9335 Update leenkx/Shaders/blur_edge_pass/blur_edge_pass.frag.glsl 2025-05-21 00:16:55 +00:00
ce3c1cea6a Delete leenkx/Shaders/voxel_resolve_shadows/voxel_resolve_shadows.comp.glsl 2025-05-21 00:00:40 +00:00
392d12a816 Delete leenkx/Shaders/voxel_resolve_refraction/voxel_resolve_refraction.comp.glsl 2025-05-21 00:00:32 +00:00
6b423038d4 Delete leenkx/Shaders/voxel_light/voxel_light.comp.glsl 2025-05-21 00:00:02 +00:00
76628fc010 Add leenkx/Shaders/std/aabb.glsl 2025-05-20 23:57:25 +00:00
99f687b10c Update leenkx/Shaders/std/constants.glsl 2025-05-20 23:55:32 +00:00
316441b954 merge upstream 2025-05-20 20:00:31 +00:00
9bf83bc49f Update leenkx/blender/lnx/material/make_mesh.py 2025-04-18 22:52:53 +00:00
d88e1f0f42 Update leenkx/blender/lnx/material/make_cluster.py 2025-04-18 22:52:03 +00:00
96f4e29778 Update leenkx/blender/lnx/material/make_mesh.py 2025-04-12 08:49:04 +00:00
1d705d2ca2 Update leenkx/blender/lnx/material/make_cluster.py 2025-04-12 08:48:33 +00:00
0979cd976f Update leenkx/blender/lnx/write_data.py 2025-04-11 22:20:24 +00:00
db6d786ee4 merge upstream 2025-04-11 22:06:01 +00:00
106e36e30d merge upstream 2025-04-10 17:16:12 +00:00
2bb296028f merge upstream 2025-04-09 17:30:27 +00:00
25d7ba3e72 merge upstream 2025-04-08 06:33:53 +00:00
bf7b4416ec Update leenkx/blender/lnx/make_renderpath.py 2025-04-07 17:29:09 +00:00
a2d03cfe6e Update leenkx/Shaders/std/light.glsl 2025-04-07 17:26:00 +00:00
95f0ecfc54 Update leenkx/Sources/leenkx/system/Starter.hx 2025-04-07 17:07:52 +00:00
07f59224fc Update leenkx/blender/lnx/write_data.py 2025-04-07 16:50:46 +00:00
02259985be Update leenkx/blender/lnx/props.py 2025-04-07 16:46:33 +00:00
6b8585c81a Update leenkx/blender/lnx/props_renderpath.py 2025-04-07 16:43:01 +00:00
5d78eabf94 Update leenkx/blender/lnx/material/cycles_nodes/nodes_texture.py 2025-04-07 16:39:49 +00:00
41c1459c4e Update leenkx/blender/lnx/material/make_voxel.py 2025-04-07 16:34:12 +00:00
304a497565 Update leenkx/blender/lnx/make_renderpath.py 2025-04-07 16:27:25 +00:00
9fa399371a Update leenkx/blender/lnx/material/make_mesh.py 2025-04-07 16:25:06 +00:00
4625fdb6b2 Update leenkx/blender/lnx/material/make_cluster.py 2025-04-07 16:13:16 +00:00
79553927aa Update leenkx/Shaders/water_pass/water_pass.frag.glsl 2025-04-07 16:06:53 +00:00
86661c1012 Update leenkx/Shaders/voxel_light/voxel_light.comp.glsl 2025-04-07 16:04:17 +00:00
03967c7a2b Update leenkx/Sources/leenkx/system/Starter.hx 2025-04-07 15:50:41 +00:00
61fd48a12f Update leenkx/Shaders/ssr_pass/ssr_pass.frag.glsl 2025-04-07 15:47:22 +00:00
519039b8b6 Update leenkx/Shaders/std/light.glsl 2025-04-07 15:45:04 +00:00
5244b1b3e8 Update leenkx/Sources/leenkx/renderpath/RenderPathForward.hx 2025-04-07 15:41:41 +00:00
7ae3bbe496 Update leenkx/Sources/leenkx/renderpath/RenderPathDeferred.hx 2025-04-07 15:39:38 +00:00
001be2f8da Update leenkx/Sources/leenkx/renderpath/Inc.hx 2025-04-07 15:35:22 +00:00
6a25b3c5d7 Update leenkx/Shaders/deferred_light/deferred_light.frag.glsl 2025-04-07 15:28:46 +00:00
8d4ac7251a Update leenkx/Shaders/voxel_temporal/voxel_temporal.comp.glsl 2025-04-07 15:22:49 +00:00
ae63b252c6 Update leenkx/Shaders/voxel_sdf_jumpflood/voxel_sdf_jumpflood.comp.glsl 2025-04-07 15:19:03 +00:00
ee73823206 Update leenkx/Shaders/voxel_resolve_specular/voxel_resolve_specular.comp.glsl 2025-04-07 15:17:43 +00:00
af2850e20c Update leenkx/Shaders/voxel_resolve_diffuse/voxel_resolve_diffuse.comp.glsl 2025-04-07 14:49:37 +00:00
bc4a31d415 Update leenkx/Shaders/voxel_resolve_ao/voxel_resolve_ao.comp.glsl 2025-04-07 14:47:58 +00:00
5303ad3ac6 Update leenkx/Shaders/ssrefr_pass/ssrefr_pass.frag.glsl 2025-04-07 14:44:14 +00:00
5153cff790 Update leenkx/Shaders/std/shadows.glsl 2025-04-07 14:41:53 +00:00
abe17870ce Update leenkx/Shaders/std/conetrace.glsl 2025-04-07 14:38:30 +00:00
845 changed files with 4659 additions and 6291 deletions

2
.gitattributes vendored
View File

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

3
.gitignore vendored
View File

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

0
Krom/Krom Executable file → Normal file
View File

View File

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

View File

@ -24,7 +24,7 @@ import textwrap
import threading import threading
import traceback import traceback
import typing import typing
from typing import Callable, Optional, List from typing import Callable, Optional
import webbrowser import webbrowser
import bpy import bpy
@ -33,12 +33,6 @@ from bpy.props import *
from bpy.types import Operator, AddonPreferences from bpy.types import Operator, AddonPreferences
if bpy.app.version < (2, 90, 0):
ListType = List
else:
ListType = list
class SDKSource(IntEnum): class SDKSource(IntEnum):
PREFS = 0 PREFS = 0
LOCAL = 1 LOCAL = 1
@ -79,7 +73,6 @@ def detect_sdk_path():
area = win.screen.areas[0] area = win.screen.areas[0]
area_type = area.type area_type = area.type
area.type = "INFO" area.type = "INFO"
if bpy.app.version >= (2, 92, 0):
with bpy.context.temp_override(window=win, screen=win.screen, area=area): with bpy.context.temp_override(window=win, screen=win.screen, area=area):
bpy.ops.info.select_all(action='SELECT') bpy.ops.info.select_all(action='SELECT')
bpy.ops.info.report_copy() bpy.ops.info.report_copy()
@ -92,7 +85,6 @@ def detect_sdk_path():
if match: if match:
addon_prefs.sdk_path = os.path.dirname(match[-1]) addon_prefs.sdk_path = os.path.dirname(match[-1])
def get_link_web_server(self): def get_link_web_server(self):
return self.get('link_web_server', 'http://localhost/') return self.get('link_web_server', 'http://localhost/')
@ -566,7 +558,7 @@ def remove_readonly(func, path, excinfo):
func(path) func(path)
def run_proc(cmd: ListType[str], done: Optional[Callable[[bool], None]] = None): def run_proc(cmd: list[str], done: Optional[Callable[[bool], None]] = None):
def fn(p, done): def fn(p, done):
p.wait() p.wait()
if done is not None: if done is not None:
@ -847,12 +839,6 @@ def update_leenkx_py(sdk_path: str, force_relink=False):
raise err raise err
else: else:
raise err raise err
else:
if bpy.app.version < (2, 92, 0):
try:
lnx_module_file.unlink()
except FileNotFoundError:
pass
else: else:
lnx_module_file.unlink(missing_ok=True) lnx_module_file.unlink(missing_ok=True)
shutil.copy(Path(sdk_path) / 'leenkx.py', lnx_module_file) shutil.copy(Path(sdk_path) / 'leenkx.py', lnx_module_file)

View File

@ -29,10 +29,11 @@ uniform sampler2D gbuffer1;
#ifdef _VoxelGI #ifdef _VoxelGI
uniform sampler2D voxels_diffuse; uniform sampler2D voxels_diffuse;
uniform sampler2D voxels_specular; uniform sampler2D voxels_specular;
#endif #else
#ifdef _VoxelAOvar #ifdef _VoxelAOvar
uniform sampler2D voxels_ao; uniform sampler2D voxels_ao;
#endif #endif
#endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
uniform sampler3D voxels; uniform sampler3D voxels;
uniform sampler3D voxelsSDF; uniform sampler3D voxelsSDF;
@ -56,6 +57,10 @@ uniform vec3 backgroundCol;
#ifdef _SSAO #ifdef _SSAO
uniform sampler2D ssaotex; uniform sampler2D ssaotex;
#else
#ifdef _SSGI
uniform sampler2D ssaotex;
#endif
#endif #endif
#ifdef _SSS #ifdef _SSS
@ -113,11 +118,15 @@ uniform vec2 cameraPlane;
#ifdef _SinglePoint #ifdef _SinglePoint
#ifdef _Spot #ifdef _Spot
//!uniform sampler2DShadow shadowMapSpot[1]; //!uniform sampler2DShadow shadowMapSpot[1];
#ifdef _ShadowMapTransparent
//!uniform sampler2D shadowMapSpotTransparent[1]; //!uniform sampler2D shadowMapSpotTransparent[1];
#endif
//!uniform mat4 LWVPSpot[1]; //!uniform mat4 LWVPSpot[1];
#else #else
//!uniform samplerCubeShadow shadowMapPoint[1]; //!uniform samplerCubeShadow shadowMapPoint[1];
#ifdef _ShadowMapTransparent
//!uniform samplerCube shadowMapPointTransparent[1]; //!uniform samplerCube shadowMapPointTransparent[1];
#endif
//!uniform vec2 lightProj; //!uniform vec2 lightProj;
#endif #endif
#endif #endif
@ -125,30 +134,40 @@ uniform vec2 cameraPlane;
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifdef _SingleAtlas #ifdef _SingleAtlas
uniform sampler2DShadow shadowMapAtlas; uniform sampler2DShadow shadowMapAtlas;
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapAtlasTransparent; uniform sampler2D shadowMapAtlasTransparent;
#endif #endif
#endif #endif
#endif
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasPoint; //!uniform sampler2DShadow shadowMapAtlasPoint;
#ifdef _ShadowMapTransparent
//!uniform sampler2D shadowMapAtlasPointTransparent; //!uniform sampler2D shadowMapAtlasPointTransparent;
#endif #endif
//!uniform vec4 pointLightDataArray[4]; #endif
//!uniform vec4 pointLightDataArray[maxLightsCluster * 6];
#else #else
//!uniform samplerCubeShadow shadowMapPoint[4]; //!uniform samplerCubeShadow shadowMapPoint[4];
#ifdef _ShadowMapTransparent
//!uniform samplerCube shadowMapPointTransparent[4]; //!uniform samplerCube shadowMapPointTransparent[4];
#endif #endif
#endif
//!uniform vec2 lightProj; //!uniform vec2 lightProj;
#ifdef _Spot #ifdef _Spot
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlasSpot; //!uniform sampler2DShadow shadowMapAtlasSpot;
#ifdef _ShadowMapTransparent
//!uniform sampler2D shadowMapAtlasSpotTransparent; //!uniform sampler2D shadowMapAtlasSpotTransparent;
#endif #endif
#endif
#else #else
//!uniform sampler2DShadow shadowMapSpot[4]; //!uniform sampler2DShadow shadowMapSpot[4];
#ifdef _ShadowMapTransparent
//!uniform sampler2D shadowMapSpotTransparent[4]; //!uniform sampler2D shadowMapSpotTransparent[4];
#endif #endif
#endif
//!uniform mat4 LWVPSpotArray[maxLightsCluster]; //!uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif #endif
@ -161,12 +180,16 @@ uniform vec3 sunCol;
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun; uniform sampler2DShadow shadowMapAtlasSun;
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapAtlasSunTransparent; uniform sampler2D shadowMapAtlasSunTransparent;
#endif #endif
#endif
#else #else
uniform sampler2DShadow shadowMap; uniform sampler2DShadow shadowMap;
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapTransparent; uniform sampler2D shadowMapTransparent;
#endif #endif
#endif
uniform float shadowsBias; uniform float shadowsBias;
#ifdef _CSM #ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4]; //!uniform vec4 casData[shadowmapCascades * 4 + 4];
@ -227,17 +250,22 @@ void main() {
vec4 g2 = textureLod(gbuffer2, texCoord, 0.0); vec4 g2 = textureLod(gbuffer2, texCoord, 0.0);
#endif #endif
#ifdef _MicroShadowing #ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
#endif #endif
#ifdef _Brdf #ifdef _Brdf
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy; vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
vec3 F = f0 * envBRDF.x + envBRDF.y;
#else
vec3 F = f0;
#endif #endif
#ifndef _VoxelAOvar
#ifndef _VoxelGI
// Envmap // Envmap
#ifdef _Irr #ifdef _Irr
vec3 envl = shIrradiance(n, shirr); vec3 envl = shIrradiance(n, shirr);
#ifdef _gbuffer2 #ifdef _gbuffer2
@ -271,33 +299,33 @@ void main() {
envl.rgb *= albedo; envl.rgb *= albedo;
#ifdef _Brdf #ifdef _Brdf
envl.rgb *= 1.0 - (f0 * envBRDF.x + envBRDF.y); //LV: We should take refracted light into account envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
#endif #endif
#ifdef _Rad // Indirect specular #ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * (f0 * envBRDF.x + envBRDF.y); //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
#else #else
#ifdef _EnvCol #ifdef _EnvCol
envl.rgb += backgroundCol * (f0 * envBRDF.x + envBRDF.y); //LV: Eh, what's the point of weighting it only by F0? envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0?
#endif #endif
#endif #endif
envl.rgb *= envmapStrength * occspec.x; envl.rgb *= envmapStrength * occspec.x;
#ifdef _VoxelGI
vec4 indirect_diffuse = textureLod(voxels_diffuse, texCoord, 0.0);
fragColor.rgb = (indirect_diffuse.rgb * albedo + envl.rgb * (1.0 - indirect_diffuse.a)) * voxelgiDiff;
if(roughness < 1.0 && occspec.y > 0.0)
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * occspec.y * voxelgiRefl;
#endif
#ifdef _VoxelAOvar
envl.rgb *= textureLod(voxels_ao, texCoord, 0.0).r;
#endif
#ifndef _VoxelGI
fragColor.rgb = envl; fragColor.rgb = envl;
#endif #endif
#endif
#ifdef _VoxelGI
fragColor.rgb = textureLod(voxels_diffuse, texCoord, 0.0).rgb * voxelgiDiff;
if(roughness < 1.0 && occspec.y > 0.0)
fragColor.rgb += textureLod(voxels_specular, texCoord, 0.0).rgb * F * voxelgiRefl;
#else
#ifdef _VoxelAOvar
fragColor.rgb = textureLod(voxels_ao, texCoord, 0.0).rgb * voxelgiOcc;
#endif
#endif
// Show voxels // Show voxels
// vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99); // vec3 origin = vec3(texCoord * 2.0 - 1.0, 0.99);
// vec3 direction = vec3(0.0, 0.0, -1.0); // vec3 direction = vec3(0.0, 0.0, -1.0);
@ -317,6 +345,10 @@ void main() {
// #else // #else
fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r; fragColor.rgb *= textureLod(ssaotex, texCoord, 0.0).r;
// #endif // #endif
#else
#ifdef _SSGI
fragColor.rgb += textureLod(ssaotex, texCoord, 0.0).rgb;
#endif
#endif #endif
#ifdef _EmissionShadeless #ifdef _EmissionShadeless
@ -350,37 +382,67 @@ void main() {
#ifdef _CSM #ifdef _CSM
svisibility = shadowTestCascade( svisibility = shadowTestCascade(
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas #ifndef _SingleAtlas
shadowMapAtlasSun, shadowMapAtlasSunTransparent shadowMapAtlasSun, shadowMapAtlasSunTransparent
#else #else
shadowMapAtlas, shadowMapAtlasTransparent shadowMapAtlas, shadowMapAtlasTransparent
#endif #endif
#else #else
shadowMap, shadowMapTransparent #ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#endif
#else
#ifdef _ShadowMapTransparent
shadowMap, shadowMapTransparent
#else
shadowMap
#endif
#endif
, eye, p + n * shadowsBias * 10, shadowsBias
#ifdef _ShadowMapTransparent
, false
#endif #endif
, eye, p + n * shadowsBias * 10, shadowsBias, false
); );
#else #else
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0); vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) { if (lPos.w > 0.0) {
svisibility = shadowTest( svisibility = shadowTest(
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas #ifndef _SingleAtlas
shadowMapAtlasSun, shadowMapAtlasSunTransparent shadowMapAtlasSun, shadowMapAtlasSunTransparent
#else #else
shadowMapAtlas, shadowMapAtlasTransparent shadowMapAtlas, shadowMapAtlasTransparent
#endif #endif
#else #else
shadowMap, shadowMapTransparent #ifndef _SingleAtlas
shadowMapAtlasSun
#else
shadowMapAtlas
#endif
#endif
#else
#ifdef _ShadowMapTransparent
shadowMap, shadowMapTransparent
#else
shadowMap
#endif
#endif
, lPos.xyz / lPos.w, shadowsBias
#ifdef _ShadowMapTransparent
, false
#endif #endif
, lPos.xyz / lPos.w, shadowsBias, false
); );
} }
#endif #endif
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; svisibility *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, sunDir, clipmaps, gl_FragCoord.xy, -g2.rg).r) * voxelgiShad;
#endif #endif
#ifdef _SSRS #ifdef _SSRS
@ -439,13 +501,16 @@ void main() {
fragColor.rgb += sampleLight( fragColor.rgb += sampleLight(
p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0 p, n, v, dotNV, pointPos, pointCol, albedo, roughness, occspec.y, f0
#ifdef _ShadowMap #ifdef _ShadowMap
, 0, pointBias, true, false , 0, pointBias, true
#ifdef _ShadowMapTransparent
, false
#endif
#endif #endif
#ifdef _Spot #ifdef _Spot
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight , true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
, voxels, voxelsSDF, clipmaps , voxels, voxelsSDF, clipmaps, -g2.rg
#endif #endif
#ifdef _MicroShadowing #ifdef _MicroShadowing
, occspec.x , occspec.x
@ -492,7 +557,10 @@ void main() {
f0 f0
#ifdef _ShadowMap #ifdef _ShadowMap
// light index, shadow bias, cast_shadows // light index, shadow bias, cast_shadows
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false , li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0
#ifdef _ShadowMapTransparent
, false
#endif
#endif #endif
#ifdef _Spot #ifdef _Spot
, lightsArray[li * 3 + 2].y != 0.0 , lightsArray[li * 3 + 2].y != 0.0
@ -503,7 +571,7 @@ void main() {
, lightsArraySpot[li * 2 + 1].xyz // right , lightsArraySpot[li * 2 + 1].xyz // right
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
, voxels, voxelsSDF, clipmaps , voxels, voxelsSDF, clipmaps, -g2.rg
#endif #endif
#ifdef _MicroShadowing #ifdef _MicroShadowing
, occspec.x , occspec.x
@ -514,14 +582,5 @@ void main() {
); );
} }
#endif // _Clusters #endif // _Clusters
/*
#ifdef _VoxelRefract
if(opac < 1.0) {
vec3 refraction = traceRefraction(p, n, voxels, v, ior, roughness, eye) * voxelgiRefr;
fragColor.rgb = mix(refraction, fragColor.rgb, opac);
}
#endif
*/
fragColor.a = 1.0; // Mark as opaque fragColor.a = 1.0; // Mark as opaque
} }

View File

@ -1,107 +1,506 @@
#version 450 #version 450
#include "compiled.inc" #include "compiled.inc"
#include "std/math.glsl"
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
#include "std/brdf.glsl"
#include "std/math.glsl"
#ifdef _Clusters
#include "std/clusters.glsl"
#endif
#ifdef _ShadowMap
#include "std/shadows.glsl"
#endif
#ifdef _LTC
#include "std/ltc.glsl"
#endif
#ifdef _LightIES
#include "std/ies.glsl"
#endif
#ifdef _Spot
#include "std/light_common.glsl"
#endif
#include "std/constants.glsl"
uniform sampler2D gbuffer0;
uniform sampler2D gbuffer1;
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; // Normal #ifdef _EmissionShaded
// #ifdef _RTGI uniform sampler2D gbufferEmission;
// uniform sampler2D gbuffer1; // Basecol #endif
// #endif uniform sampler2D sveloc;
uniform mat4 P;
uniform mat3 V3;
uniform vec2 cameraProj; uniform vec2 cameraProj;
uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec2 screenSize;
uniform mat4 invVP;
const float angleMix = 0.5f; in vec2 texCoord;
#ifdef _SSGICone9 in vec3 viewRay;
const float strength = 2.0 * (1.0 / ssgiStrength); out vec3 fragColor;
#else
const float strength = 2.0 * (1.0 / ssgiStrength) * 1.8; float metallic;
uint matid;
#ifdef _SMSizeUniform
//!uniform vec2 smSizeUniform;
#endif #endif
in vec3 viewRay; #ifdef _Clusters
in vec2 texCoord; uniform vec4 lightsArray[maxLights * 3];
out float fragColor; #ifdef _Spot
uniform vec4 lightsArraySpot[maxLights * 2];
vec3 hitCoord;
vec2 coord;
float depth;
// #ifdef _RTGI
// vec3 col = vec3(0.0);
// #endif
vec3 vpos;
vec2 getProjectedCoord(vec3 hitCoord) {
vec4 projectedCoord = P * vec4(hitCoord, 1.0);
projectedCoord.xy /= projectedCoord.w;
projectedCoord.xy = projectedCoord.xy * 0.5 + 0.5;
#ifdef _InvY
projectedCoord.y = 1.0 - projectedCoord.y;
#endif #endif
return projectedCoord.xy; uniform sampler2D clustersData;
} uniform vec2 cameraPlane;
#endif
float getDeltaDepth(vec3 hitCoord) { #ifdef _SinglePoint // Fast path for single light
coord = getProjectedCoord(hitCoord); uniform vec3 pointPos;
depth = textureLod(gbufferD, coord, 0.0).r * 2.0 - 1.0; uniform vec3 pointCol;
vec3 p = getPosView(viewRay, depth, cameraProj); #ifdef _ShadowMap
return p.z - hitCoord.z; uniform float pointBias;
} #endif
#ifdef _Spot
uniform vec3 spotDir;
uniform vec3 spotRight;
uniform vec4 spotData;
#endif
#endif
void rayCast(vec3 dir) { #ifdef _CPostprocess
hitCoord = vpos; uniform vec3 PPComp12;
dir *= ssgiRayStep * 2; #endif
float dist = 0.15;
for (int i = 0; i < ssgiMaxSteps; i++) { #ifdef _ShadowMap
hitCoord += dir; #ifdef _SinglePoint
float delta = getDeltaDepth(hitCoord); #ifdef _Spot
if (delta > 0.0 && delta < 0.2) { #ifndef _LTC
dist = distance(vpos, hitCoord); uniform sampler2DShadow shadowMapSpot[1];
break; uniform sampler2D shadowMapSpotTransparent[1];
uniform mat4 LWVPSpot[1];
#endif
#else
uniform samplerCubeShadow shadowMapPoint[1];
uniform samplerCube shadowMapPointTransparent[1];
uniform vec2 lightProj;
#endif
#endif
#ifdef _Clusters
#ifdef _SingleAtlas
uniform sampler2DShadow shadowMapAtlas;
uniform sampler2D shadowMapAtlasTransparent;
#endif
uniform vec2 lightProj;
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint;
uniform sampler2D shadowMapAtlasPointTransparent;
//!uniform vec4 pointLightDataArray[maxLightsCluster * 6];
#else
uniform samplerCubeShadow shadowMapPoint[4];
uniform samplerCube shadowMapPointTransparent[4];
#endif
#endif
#ifdef _Spot
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSpot;
uniform sampler2D shadowMapAtlasSpotTransparent;
#endif
#else
uniform sampler2DShadow shadowMapSpot[4];
uniform sampler2D shadowMapSpotTransparent[4];
#endif
uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif
#endif
#endif
#ifdef _LTC
uniform vec3 lightArea0;
uniform vec3 lightArea1;
uniform vec3 lightArea2;
uniform vec3 lightArea3;
uniform sampler2D sltcMat;
uniform sampler2D sltcMag;
#ifdef _ShadowMap
#ifndef _Spot
#ifdef _SinglePoint
uniform sampler2DShadow shadowMapSpot[1];
uniform sampler2D shadowMapSpotTransparent[1];
uniform mat4 LWVPSpot[1];
#endif
#ifdef _Clusters
uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif
#endif
#endif
#endif
#ifdef _Sun
uniform vec3 sunDir;
uniform vec3 sunCol;
#ifdef _ShadowMap
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSun;
uniform sampler2D shadowMapAtlasSunTransparent;
#endif
#else
uniform sampler2DShadow shadowMap;
uniform sampler2D shadowMapTransparent;
#endif
uniform float shadowsBias;
#ifdef _CSM
//!uniform vec4 casData[shadowmapCascades * 4 + 4];
#else
uniform mat4 LWVP;
#endif
#endif // _ShadowMap
#endif
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 lp, const vec3 lightCol
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow, bool transparent
#endif
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
) {
vec3 ld = lp - p;
vec3 l = normalize(ld);
vec3 visibility = lightCol;
visibility *= attenuate(distance(p, lp));
#ifdef _LTC
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
visibility *= shadowTest(shadowMapSpot[0],
shadowMapSpotTransparent[0],
lPos.xyz / lPos.w, bias, transparent);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
if (index == 0) visibility *= shadowTest(shadowMapSpot[0],
shadowMapSpotTransparent[0],
lPos.xyz / lPos.w, bias, transparent);
else if (index == 1) visibility *= shadowTest(shadowMapSpot[1],
shadowMapSpotTransparent[1],
, lPos.xyz / lPos.w, bias, transparent);
else if (index == 2) visibility *= shadowTest(shadowMapSpot[2],
shadowMapSpotTransparent[2],
lPos.xyz / lPos.w, bias, transparent);
else if (index == 3) visibility *= shadowTest(shadowMapSpot[3],
shadowMapSpotTransparent[3],
lPos.xyz / lPos.w, bias, transparent);
#endif
} }
#endif
return visibility;
#endif
#ifdef _Spot
if (isSpot) {
visibility *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
visibility *= shadowTest(shadowMapSpot[0],
shadowMapSpotTransparent[0],
lPos.xyz / lPos.w, bias, transparent);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
visibility *= shadowTest(
#ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
, lPos.xyz / lPos.w, bias, transparent
);
#else
if (index == 0) visibility *= shadowTest(shadowMapSpot[0],
shadowMapSpotTransparent[0],
lPos.xyz / lPos.w, bias, transparent);
else if (index == 1) visibility *= shadowTest(shadowMapSpot[1],
shadowMapSpotTransparent[1],
lPos.xyz / lPos.w, bias, transparent);
else if (index == 2) visibility *= shadowTest(shadowMapSpot[2],
shadowMapSpotTransparent[2],
lPos.xyz / lPos.w, bias, transparent);
else if (index == 3) visibility *= shadowTest(shadowMapSpot[3],
shadowMapSpotTransparent[3],
lPos.xyz / lPos.w, bias, transparent);
#endif
#endif
} }
fragColor += dist; #endif
// #ifdef _RTGI return visibility;
// col += textureLod(gbuffer1, coord, 0.0).rgb * ((ssgiRayStep * ssgiMaxSteps) - dist); }
// #endif #endif
#ifdef _LightIES
visibility *= iesAttenuation(-l);
#endif
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
#ifndef _Spot
visibility *= PCFCube(shadowMapPoint[0],
shadowMapPointTransparent[0],
ld, -l, bias, lightProj, n, transparent);
#endif
#endif
#ifdef _Clusters
#ifdef _ShadowMapAtlas
visibility *= PCFFakeCube(
#ifndef _SingleAtlas
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
, ld, -l, bias, lightProj, n, index, transparent
);
#else
if (index == 0) visibility *= PCFCube(shadowMapPoint[0],
shadowMapPointTransparent[0],
ld, -l, bias, lightProj, n, transparent);
else if (index == 1) visibility *= PCFCube(shadowMapPoint[1],
shadowMapPointTransparent[1],
ld, -l, bias, lightProj, n, transparent);
else if (index == 2) visibility *= PCFCube(shadowMapPoint[2],
shadowMapPointTransparent[2],
ld, -l, bias, lightProj, n, transparent);
else if (index == 3) visibility *= PCFCube(shadowMapPoint[3],
shadowMapPointTransparent[3],
ld, -l, bias, lightProj, n, transparent);
#endif
#endif
}
#endif
return visibility;
} }
vec3 tangent(const vec3 n) { vec3 getVisibility(vec3 p, vec3 n, float depth, vec2 uv) {
vec3 t1 = cross(n, vec3(0, 0, 1)); vec3 visibility = vec3(0.0);
vec3 t2 = cross(n, vec3(0, 1, 0)); #ifdef _Sun
if (length(t1) > length(t2)) return normalize(t1); #ifdef _ShadowMap
else return normalize(t2); #ifdef _CSM
visibility = shadowTestCascade(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun, shadowMapAtlasSunTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
shadowMap, shadowMapTransparent
#endif
, eye, p + n * shadowsBias * 10, shadowsBias, false
);
#else
vec4 lPos = LWVP * vec4(p + n * shadowsBias * 100, 1.0);
if (lPos.w > 0.0) {
visibility = shadowTest(
#ifdef _ShadowMapAtlas
#ifndef _SingleAtlas
shadowMapAtlasSun, shadowMapAtlasSunTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
shadowMap, shadowMapTransparent
#endif
, lPos.xyz / lPos.w, shadowsBias, false
);
}
#endif
#endif
#endif
#ifdef _SinglePoint
visibility += sampleLight(
p, n, pointPos, pointCol
#ifdef _ShadowMap
, 0, pointBias, true, false
#endif
#ifdef _Spot
, true, spotData.x, spotData.y, spotDir, spotData.zw, spotRight
#endif
);
#endif
#ifdef _Clusters
float viewz = linearize(depth, cameraProj);
int clusterI = getClusterI(uv, viewz, cameraPlane);
int numLights = int(texelFetch(clustersData, ivec2(clusterI, 0), 0).r * 255);
#ifdef HLSL
viewz += textureLod(clustersData, vec2(0.0), 0.0).r * 1e-9; // TODO: krafix bug, needs to generate sampler
#endif
#ifdef _Spot
int numSpots = int(texelFetch(clustersData, ivec2(clusterI, 1 + maxLightsCluster), 0).r * 255);
int numPoints = numLights - numSpots;
#endif
for (int i = 0; i < min(numLights, maxLightsCluster); i++) {
int li = int(texelFetch(clustersData, ivec2(clusterI, i + 1), 0).r * 255);
visibility += sampleLight(
p,
n,
lightsArray[li * 3].xyz, // lp
lightsArray[li * 3 + 1].xyz // lightCol
#ifdef _ShadowMap
// light index, shadow bias, cast_shadows
, li, lightsArray[li * 3 + 2].x, lightsArray[li * 3 + 2].z != 0.0, false
#endif
#ifdef _Spot
, lightsArray[li * 3 + 2].y != 0.0
, lightsArray[li * 3 + 2].y // spot size (cutoff)
, lightsArraySpot[li * 2].w // spot blend (exponent)
, lightsArraySpot[li * 2].xyz // spotDir
, vec2(lightsArray[li * 3].w, lightsArray[li * 3 + 1].w) // scale
, lightsArraySpot[li * 2 + 1].xyz // right
#endif
);
}
#endif // _Clusters
return visibility;
} }
void main() { vec3 getWorldPos(vec2 uv, float depth) {
fragColor = 0; vec4 pos = invVP * vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); return pos.xyz / pos.w;
float d = textureLod(gbufferD, texCoord, 0.0).r * 2.0 - 1.0; }
vec3 getNormal(vec2 uv) {
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
vec2 enc = g0.rg; vec2 enc = g0.rg;
vec3 n; vec3 n;
n.z = 1.0 - abs(enc.x) - abs(enc.y); n.z = 1.0 - abs(enc.x) - abs(enc.y);
n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy); n.xy = n.z >= 0.0 ? enc.xy : octahedronWrap(enc.xy);
n = normalize(V3 * n); return normalize(n);
}
vpos = getPosView(viewRay, d, cameraProj);
vec3 calculateIndirectLight(vec2 uv, vec3 pos, vec3 normal, float depth) {
rayCast(n); // Simplified visibility - replace with your full visibility function if needed
vec3 o1 = normalize(tangent(n)); vec3 sampleColor = textureLod(gbuffer1, uv, 0.0).rgb * getVisibility(pos, normal, depth, uv);
vec3 o2 = (cross(o1, n));
vec3 c1 = 0.5f * (o1 + o2); #ifdef _EmissionShadeless
vec3 c2 = 0.5f * (o1 - o2); if (matid == 1) { // pure emissive material, color stored in basecol
rayCast(mix(n, o1, angleMix)); sampleColor += textureLod(gbuffer1, uv, 0.0).rgb;
rayCast(mix(n, o2, angleMix)); }
rayCast(mix(n, -c1, angleMix)); #endif
rayCast(mix(n, -c2, angleMix)); #ifdef _EmissionShaded
#ifdef _EmissionShadeless
#ifdef _SSGICone9 else {
rayCast(mix(n, -o1, angleMix)); #endif
rayCast(mix(n, -o2, angleMix)); vec3 sampleEmission = textureLod(gbufferEmission, uv, 0.0).rgb;
rayCast(mix(n, c1, angleMix)); sampleColor += sampleEmission; // Emission should be added directly
rayCast(mix(n, c2, angleMix)); #ifdef _EmissionShadeless
#endif }
#endif
#endif
return sampleColor;
}
// Improved sampling parameters
const float GOLDEN_ANGLE = 2.39996323;
const float MAX_DEPTH_DIFFERENCE = 0.9; // More conservative depth threshold
const float SAMPLE_BIAS = 0.01; // Small offset to avoid self-occlusion
void main() {
float depth = textureLod(gbufferD, texCoord, 0.0).r;
if (depth >= 1.0) {
fragColor = vec3(0.0);
return;
}
vec4 g0 = textureLod(gbuffer0, texCoord, 0.0); // Normal.xy, roughness, metallic/matid
unpackFloatInt16(g0.a, metallic, matid);
vec2 velocity = -textureLod(sveloc, texCoord, 0.0).rg;
vec3 n;
n.z = 1.0 - abs(g0.x) - abs(g0.y);
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n);
vec3 pos = getWorldPos(texCoord, depth);
vec3 normal = getNormal(texCoord);
vec3 centerColor = textureLod(gbuffer1, texCoord, 0.0).rgb;
float radius = ssaoRadius;
vec3 gi = vec3(0.0);
float totalWeight = 0.0;
float angle = fract(sin(dot(texCoord, vec2(12.9898, 78.233))) * 100.0);
for (int i = 0; i < ssgiSamples; i++) {
// Use quasi-random sequence for better coverage
float r = sqrt((float(i) + 0.5) / float(ssgiSamples)) * radius;
float a = (float(i) * GOLDEN_ANGLE) + angle;
vec2 offset = vec2(cos(a), sin(a)) * r * radius;
vec2 sampleUV = clamp(texCoord + offset * (BayerMatrix8[int(gl_FragCoord.x + velocity.x) % 8][int(gl_FragCoord.y + velocity.y) % 8] - 0.5) / screenSize, vec2(0.001), vec2(0.999));
float sampleDepth = textureLod(gbufferD, sampleUV, 0.0).r;
if (sampleDepth >= 1.0) continue;
vec3 samplePos = getWorldPos(sampleUV, sampleDepth);
vec3 sampleNormal = getNormal(sampleUV);
// Apply small bias to sample position to avoid self-occlusion
samplePos += sampleNormal * SAMPLE_BIAS;
vec3 dir = pos - samplePos;
float dist = length(dir);
if (abs(pos.z - samplePos.z) > MAX_DEPTH_DIFFERENCE) continue;;
vec3 sampleColor = calculateIndirectLight(sampleUV, samplePos, sampleNormal, sampleDepth);
float weight = 1.0 / (1.0 + dist * dist * 2.0) * max(dot(sampleNormal, n), 0.0);
gi += sampleColor * weight;
totalWeight += weight;
}
// Normalize and apply intensity
if (totalWeight > 0.0) {
gi /= totalWeight;
#ifdef _CPostprocess
gi *= PPComp12.x;
#else
gi *= ssaoStrength;
#endif
}
#ifdef _EmissionShadeless
if (matid == 1) { // pure emissive material, color stored in basecol
gi += textureLod(gbuffer1, texCoord, 0.0).rgb;
}
#endif
#ifdef _EmissionShaded
#ifdef _EmissionShadeless
else {
#endif
gi += textureLod(gbufferEmission, texCoord, 0.0).rgb;
#ifdef _EmissionShadeless
}
#endif
#endif
fragColor = gi / (gi + vec3(1.0)); // Reinhard tone mapping
} }

View File

@ -6,6 +6,10 @@
"compare_mode": "always", "compare_mode": "always",
"cull_mode": "none", "cull_mode": "none",
"links": [ "links": [
{
"name": "invVP",
"link": "_inverseViewProjectionMatrix"
},
{ {
"name": "P", "name": "P",
"link": "_projectionMatrix" "link": "_projectionMatrix"
@ -15,16 +19,180 @@
"link": "_viewMatrix3" "link": "_viewMatrix3"
}, },
{ {
"name": "invP", "name": "eye",
"link": "_inverseProjectionMatrix" "link": "_cameraPosition"
},
{
"name": "eyeLook",
"link": "_cameraLook"
}, },
{ {
"name": "cameraProj", "name": "cameraProj",
"link": "_cameraPlaneProj" "link": "_cameraPlaneProj"
},
{
"name": "screenSize",
"link": "_screenSize"
},
{
"name": "PPComp12",
"link": "_PPComp12",
"ifdef": ["_CPostprocess"]
},
{
"name": "lightsArraySpot",
"link": "_lightsArraySpot",
"ifdef": ["_Clusters", "_Spot"]
},
{
"name": "lightsArray",
"link": "_lightsArray",
"ifdef": ["_Clusters"]
},
{
"name": "clustersData",
"link": "_clustersData",
"ifdef": ["_Clusters"]
},
{
"name": "cameraPlane",
"link": "_cameraPlane",
"ifdef": ["_Clusters"]
},
{
"name": "sunDir",
"link": "_sunDirection",
"ifdef": ["_Sun"]
},
{
"name": "sunCol",
"link": "_sunColor",
"ifdef": ["_Sun"]
},
{
"name": "shadowsBias",
"link": "_sunShadowsBias",
"ifdef": ["_Sun", "_ShadowMap"]
},
{
"name": "LWVP",
"link": "_biasLightWorldViewProjectionMatrixSun",
"ifndef": ["_CSM"],
"ifdef": ["_Sun", "_ShadowMap"]
},
{
"name": "casData",
"link": "_cascadeData",
"ifdef": ["_Sun", "_ShadowMap", "_CSM"]
},
{
"name": "lightArea0",
"link": "_lightArea0",
"ifdef": ["_LTC"]
},
{
"name": "lightArea1",
"link": "_lightArea1",
"ifdef": ["_LTC"]
},
{
"name": "lightArea2",
"link": "_lightArea2",
"ifdef": ["_LTC"]
},
{
"name": "lightArea3",
"link": "_lightArea3",
"ifdef": ["_LTC"]
},
{
"name": "sltcMat",
"link": "_ltcMat",
"ifdef": ["_LTC"]
},
{
"name": "sltcMag",
"link": "_ltcMag",
"ifdef": ["_LTC"]
},
{
"name": "smSizeUniform",
"link": "_shadowMapSize",
"ifdef": ["_SMSizeUniform"]
},
{
"name": "lightProj",
"link": "_lightPlaneProj",
"ifdef": ["_ShadowMap"]
},
{
"name": "pointPos",
"link": "_pointPosition",
"ifdef": ["_SinglePoint"]
},
{
"name": "pointCol",
"link": "_pointColor",
"ifdef": ["_SinglePoint"]
},
{
"name": "pointBias",
"link": "_pointShadowsBias",
"ifdef": ["_SinglePoint", "_ShadowMap"]
},
{
"name": "spotDir",
"link": "_spotDirection",
"ifdef": ["_SinglePoint", "_Spot"]
},
{
"name": "spotData",
"link": "_spotData",
"ifdef": ["_SinglePoint", "_Spot"]
},
{
"name": "spotRight",
"link": "_spotRight",
"ifdef": ["_SinglePoint", "_Spot"]
},
{
"name": "LWVPSpotArray",
"link": "_biasLightWorldViewProjectionMatrixSpotArray",
"ifdef": ["_Clusters", "_ShadowMap", "_Spot"]
},
{
"name": "pointLightDataArray",
"link": "_pointLightsAtlasArray",
"ifdef": ["_Clusters", "_ShadowMap", "_ShadowMapAtlas"]
},
{
"name": "LWVPSpot[0]",
"link": "_biasLightWorldViewProjectionMatrixSpot0",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot[1]",
"link": "_biasLightWorldViewProjectionMatrixSpot1",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot[2]",
"link": "_biasLightWorldViewProjectionMatrixSpot2",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
},
{
"name": "LWVPSpot[3]",
"link": "_biasLightWorldViewProjectionMatrixSpot3",
"ifndef": ["_ShadowMapAtlas"],
"ifdef": ["_LTC", "_ShadowMap"]
} }
], ],
"texture_params": [], "texture_params": [],
"vertex_shader": "../include/pass_viewray2.vert.glsl", "vertex_shader": "../include/pass_viewray.vert.glsl",
"fragment_shader": "ssgi_pass.frag.glsl" "fragment_shader": "ssgi_pass.frag.glsl"
} }
] ]

View File

@ -64,7 +64,7 @@ vec4 rayCast(vec3 dir) {
ddepth = getDeltaDepth(hitCoord); ddepth = getDeltaDepth(hitCoord);
if (ddepth > 0.0) return binarySearch(dir); if (ddepth > 0.0) return binarySearch(dir);
} }
return vec4(texCoord, 0.0, 1.0); return vec4(getProjectedCoord(hitCoord), 0.0, 1.0);
} }
void main() { void main() {
@ -86,7 +86,7 @@ void main() {
vec3 viewNormal = V3 * n; vec3 viewNormal = V3 * n;
vec3 viewPos = getPosView(viewRay, d, cameraProj); vec3 viewPos = getPosView(viewRay, d, cameraProj);
vec3 refracted = refract(normalize(viewPos), viewNormal, 1.0 / ior); vec3 refracted = refract(viewPos, viewNormal, 1.0 / ior);
hitCoord = viewPos; hitCoord = viewPos;
vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0; vec3 dir = refracted * (1.0 - rand(texCoord) * ss_refractionJitter * roughness) * 2.0;

View File

@ -0,0 +1,18 @@
#ifndef _AABB_GLSL
#define _AABB_GLSL
bool IntersectAABB(vec3[2] a, vec3[2] b) {
const float EPSILON = 0.001; // Small tolerance to prevent false negatives
if (abs(a[0].x - b[0].x) > (a[1].x + b[1].x + EPSILON)) return false;
if (abs(a[0].y - b[0].y) > (a[1].y + b[1].y + EPSILON)) return false;
if (abs(a[0].z - b[0].z) > (a[1].z + b[1].z + EPSILON)) return false;
return true;
}
void AABBfromMinMax(inout vec3[2] aabb, vec3 _min, vec3 _max)
{
aabb[0] = (_min + _max) * 0.5f;
aabb[1] = abs(_max - aabb[0]);
}
#endif

View File

@ -22,7 +22,7 @@ THE SOFTWARE.
#ifndef _CONETRACE_GLSL_ #ifndef _CONETRACE_GLSL_
#define _CONETRACE_GLSL_ #define _CONETRACE_GLSL_
#include "std/voxels_constants.glsl" #include "std/constants.glsl"
// References // References
// https://github.com/Friduric/voxel-cone-tracing // https://github.com/Friduric/voxel-cone-tracing
@ -92,14 +92,14 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
float dist = voxelSize0; float dist = voxelSize0;
float step_dist = dist; float step_dist = dist;
vec3 samplePos; vec3 samplePos;
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; vec3 start_pos = origin + n * voxelSize0;
int clipmap_index0 = 0; int clipmap_index0 = 0;
vec3 aniso_direction = -dir; vec3 aniso_direction = -dir;
vec3 face_offset = vec3( vec3 face_offset = vec3(
aniso_direction.x > 0.0 ? 0.0 : 1.0, aniso_direction.x > 0.0 ? 0 : 1,
aniso_direction.y > 0.0 ? 2.0 : 3.0, aniso_direction.y > 0.0 ? 2 : 3,
aniso_direction.z > 0.0 ? 4.0 : 5.0 aniso_direction.z > 0.0 ? 4 : 5
) / (6 + DIFFUSE_CONE_COUNT); ) / (6 + DIFFUSE_CONE_COUNT);
vec3 direction_weight = abs(dir); vec3 direction_weight = abs(dir);
@ -125,7 +125,7 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) { if(clipmap_blend > 0.0 && clipmap_index < voxelgiClipmapCount - 1) {
vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight); vec4 mipSampleNext = sampleVoxel(voxels, p0, clipmaps, clipmap_index + 1.0, step_dist, precomputed_direction, face_offset, direction_weight);
mipSample = mix(mipSample, mipSampleNext, smoothstep(0.0, 1.0, clipmap_blend)); mipSample = mix(mipSample, mipSampleNext, clipmap_blend);
} }
sampleCol += (1.0 - sampleCol.a) * mipSample; sampleCol += (1.0 - sampleCol.a) * mipSample;
@ -148,8 +148,9 @@ vec4 traceCone(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 ori
vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) { vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels, const float clipmaps[voxelgiClipmapCount * 10]) {
float sum = 0.0; float sum = 0.0;
vec4 amount = vec4(0.0); vec4 amount = vec4(0.0);
mat3 TBN = makeTangentBasis(normal);
for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) { for (int i = 0; i < DIFFUSE_CONE_COUNT; ++i) {
vec3 coneDir = DIFFUSE_CONE_DIRECTIONS[i]; vec3 coneDir = TBN * DIFFUSE_CONE_DIRECTIONS[i];
const float cosTheta = dot(normal, coneDir); const float cosTheta = dot(normal, coneDir);
if (cosTheta <= 0) if (cosTheta <= 0)
continue; continue;
@ -166,7 +167,7 @@ vec4 traceDiffuse(const vec3 origin, const vec3 normal, const sampler3D voxels,
} }
vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 viewDir, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
vec3 specularDir = reflect(-viewDir, normal); vec3 specularDir = reflect(normalize(-viewDir), normal);
vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep; vec3 P = origin + specularDir * ((BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5)) * voxelgiStep;
vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps); vec4 amount = traceCone(voxels, voxelsSDF, P, normal, specularDir, 0, true, roughness, voxelgiStep, clipmaps);
@ -176,9 +177,9 @@ vec4 traceSpecular(const vec3 origin, const vec3 normal, const sampler3D voxels,
return amount * voxelgiOcc; return amount * voxelgiOcc;
} }
vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) { vec4 traceRefraction(const vec3 origin, const vec3 normal, sampler3D voxels, sampler3D voxelsSDF, const vec3 viewDir, const float ior, const float roughness, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity, const float opacity) {
const float transmittance = 1.0; const float transmittance = 1.0 - opacity;
vec3 refractionDir = refract(-viewDir, normal, 1.0 / ior); vec3 refractionDir = refract(normalize(-viewDir), normal, 1.0 / ior);
vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep; vec3 P = origin + refractionDir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps); vec4 amount = transmittance * traceCone(voxels, voxelsSDF, P, normal, refractionDir, 0, true, roughness, voxelgiStep, clipmaps);
@ -196,14 +197,14 @@ float traceConeAO(const sampler3D voxels, const vec3 origin, const vec3 n, const
float dist = voxelSize0; float dist = voxelSize0;
float step_dist = dist; float step_dist = dist;
vec3 samplePos; vec3 samplePos;
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; vec3 start_pos = origin + n * voxelSize0;
int clipmap_index0 = 0; int clipmap_index0 = 0;
vec3 aniso_direction = -dir; vec3 aniso_direction = -dir;
vec3 face_offset = vec3( vec3 face_offset = vec3(
aniso_direction.x > 0.0 ? 0.0 : 1.0, aniso_direction.x > 0.0 ? 0 : 1,
aniso_direction.y > 0.0 ? 2.0 : 3.0, aniso_direction.y > 0.0 ? 2 : 3,
aniso_direction.z > 0.0 ? 4.0 : 5.0 aniso_direction.z > 0.0 ? 4 : 5
) / (6 + DIFFUSE_CONE_COUNT); ) / (6 + DIFFUSE_CONE_COUNT);
vec3 direction_weight = abs(dir); vec3 direction_weight = abs(dir);
@ -259,7 +260,6 @@ float traceAO(const vec3 origin, const vec3 normal, const sampler3D voxels, cons
} }
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) { float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const vec3 origin, const vec3 n, const vec3 dir, const float aperture, const float step_size, const float clipmaps[voxelgiClipmapCount * 10]) {
float sampleCol = 0.0; float sampleCol = 0.0;
@ -267,14 +267,14 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
float dist = voxelSize0; float dist = voxelSize0;
float step_dist = dist; float step_dist = dist;
vec3 samplePos; vec3 samplePos;
vec3 start_pos = origin + n * voxelSize0 * voxelgiOffset; vec3 start_pos = origin + n * voxelSize0;
int clipmap_index0 = 0; int clipmap_index0 = 0;
vec3 aniso_direction = -dir; vec3 aniso_direction = -dir;
vec3 face_offset = vec3( vec3 face_offset = vec3(
aniso_direction.x > 0.0 ? 0.0 : 1.0, aniso_direction.x > 0.0 ? 0 : 1,
aniso_direction.y > 0.0 ? 2.0 : 3.0, aniso_direction.y > 0.0 ? 2 : 3,
aniso_direction.z > 0.0 ? 4.0 : 5.0 aniso_direction.z > 0.0 ? 4 : 5
) / (6 + DIFFUSE_CONE_COUNT); ) / (6 + DIFFUSE_CONE_COUNT);
vec3 direction_weight = abs(dir); vec3 direction_weight = abs(dir);
float coneCoefficient = 2.0 * tan(aperture * 0.5); float coneCoefficient = 2.0 * tan(aperture * 0.5);
@ -287,7 +287,7 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
float clipmap_blend = fract(lod); float clipmap_blend = fract(lod);
vec3 p0 = start_pos + dir * dist; vec3 p0 = start_pos + dir * dist;
samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution.x); samplePos = (p0 - vec3(clipmaps[int(clipmap_index * 10 + 4)], clipmaps[int(clipmap_index * 10 + 5)], clipmaps[int(clipmap_index * 10 + 6)])) / (float(clipmaps[int(clipmap_index * 10)]) * voxelgiResolution);
samplePos = samplePos * 0.5 + 0.5; samplePos = samplePos * 0.5 + 0.5;
if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) { if ((any(notEqual(samplePos, clamp(samplePos, 0.0, 1.0))))) {
@ -328,9 +328,9 @@ float traceConeShadow(const sampler3D voxels, const sampler3D voxelsSDF, const v
} }
float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel) { float traceShadow(const vec3 origin, const vec3 normal, const sampler3D voxels, const sampler3D voxelsSDF, const vec3 dir, const float clipmaps[voxelgiClipmapCount * 10], const vec2 pixel, const vec2 velocity) {
vec3 P = origin + dir * (BayerMatrix8[int(pixel.x) % 8][int(pixel.y) % 8] - 0.5) * voxelgiStep; vec3 P = origin + dir * (BayerMatrix8[int(pixel.x + velocity.x) % 8][int(pixel.y + velocity.y) % 8] - 0.5) * voxelgiStep;
float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, DIFFUSE_CONE_APERTURE, voxelgiStep, clipmaps); float amount = traceConeShadow(voxels, voxelsSDF, P, normal, dir, SHADOW_CONE_APERTURE, voxelgiStep, clipmaps);
amount = clamp(amount, 0.0, 1.0); amount = clamp(amount, 0.0, 1.0);
return amount * voxelgiOcc; return amount * voxelgiOcc;
} }

View File

@ -21,29 +21,42 @@ THE SOFTWARE.
*/ */
const int DIFFUSE_CONE_COUNT = 16; const int DIFFUSE_CONE_COUNT = 16;
const float DIFFUSE_CONE_APERTURE = radians(45.0);
const vec3 DIFFUSE_CONE_DIRECTIONS[16] = { const float SHADOW_CONE_APERTURE = radians(15.0);
vec3(0.0000, 0.0000, 1.0000), // Central direction
vec3(0.3827, 0.0000, 0.9239), // Ring 1
vec3(-0.3827, 0.0000, 0.9239),
vec3(0.0000, 0.3827, 0.9239),
vec3(0.0000, -0.3827, 0.9239),
vec3(0.2706, 0.2706, 0.9239), // Ring 2
vec3(-0.2706, 0.2706, 0.9239),
vec3(0.2706, -0.2706, 0.9239),
vec3(-0.2706, -0.2706, 0.9239),
vec3(0.1802, 0.3604, 0.9239), // Ring 3
vec3(-0.1802, 0.3604, 0.9239),
vec3(0.1802, -0.3604, 0.9239),
vec3(-0.1802, -0.3604, 0.9239),
vec3(0.3604, 0.1802, 0.9239),
vec3(-0.3604, 0.1802, 0.9239),
vec3(0.3604, -0.1802, 0.9239)
};
const float DIFFUSE_CONE_APERTURE = radians(50.0);
const float BayerMatrix8[8][8] = const vec3 DIFFUSE_CONE_DIRECTIONS[DIFFUSE_CONE_COUNT] = vec3[](
vec3(0.0, 0.0, 1.0), // center
vec3(0.0, 0.5, 0.866),
vec3(0.5, 0.0, 0.866),
vec3(0.0, -0.5, 0.866),
vec3(-0.5, 0.0, 0.866),
vec3(0.353, 0.353, 0.866),
vec3(0.353, -0.353, 0.866),
vec3(-0.353, -0.353, 0.866),
vec3(-0.353, 0.353, 0.866),
vec3(0.707, 0.0, 0.707),
vec3(0.0, 0.707, 0.707),
vec3(-0.707, 0.0, 0.707),
vec3(0.0, -0.707, 0.707),
vec3(0.5, 0.5, 0.707),
vec3(-0.5, 0.5, 0.707),
vec3(-0.5, -0.5, 0.707)
);
mat3 makeTangentBasis(vec3 normal) {
vec3 tangent = normalize(abs(normal.y) < 0.999 ? cross(normal, vec3(0, 1, 0)) : cross(normal, vec3(1, 0, 0)));
vec3 bitangent = cross(normal, tangent);
return mat3(tangent, bitangent, normal);
}
// TO DO - Disabled momentarily instead of changing formulas
const float off_BayerMatrix8[8][8] =
{ {
{ 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 }, { 1.0 / 65.0, 49.0 / 65.0, 13.0 / 65.0, 61.0 / 65.0, 4.0 / 65.0, 52.0 / 65.0, 16.0 / 65.0, 64.0 / 65.0 },
{ 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 }, { 33.0 / 65.0, 17.0 / 65.0, 45.0 / 65.0, 29.0 / 65.0, 36.0 / 65.0, 20.0 / 65.0, 48.0 / 65.0, 32.0 / 65.0 },
@ -54,3 +67,15 @@ const float BayerMatrix8[8][8] =
{ 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 }, { 11.0 / 65.0, 59.0 / 65.0, 7.0 / 65.0, 55.0 / 65.0, 10.0 / 65.0, 58.0 / 65.0, 6.0 / 65.0, 54.0 / 65.0 },
{ 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 } { 43.0 / 65.0, 27.0 / 65.0, 39.0 / 65.0, 23.0 / 65.0, 42.0 / 65.0, 26.0 / 65.0, 38.0 / 65.0, 22.0 / 65.0 }
}; };
const float BayerMatrix8[8][8] =
{
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 },
{ 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0 }
};

View File

@ -9,7 +9,6 @@
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
#include "std/conetrace.glsl" #include "std/conetrace.glsl"
//!uniform sampler2D voxels_shadows;
#endif #endif
#ifdef _LTC #ifdef _LTC
#include "std/ltc.glsl" #include "std/ltc.glsl"
@ -23,46 +22,63 @@
#ifdef _Spot #ifdef _Spot
#include "std/light_common.glsl" #include "std/light_common.glsl"
#endif #endif
#ifdef _VoxelShadow
#include "std/conetrace.glsl"
#endif
#ifdef _ShadowMap #ifdef _ShadowMap
#ifdef _SinglePoint #ifdef _SinglePoint
#ifdef _Spot #ifdef _Spot
#ifndef _LTC #ifndef _LTC
uniform sampler2DShadow shadowMapSpot[1]; uniform sampler2DShadow shadowMapSpot[1];
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapSpotTransparent[1]; uniform sampler2D shadowMapSpotTransparent[1];
uniform mat4 LWVPSpot[1]; #endif
uniform mat4 LWVPSpotArray[1];
#endif #endif
#else #else
uniform samplerCubeShadow shadowMapPoint[1]; uniform samplerCubeShadow shadowMapPoint[1];
#ifdef _ShadowMapTransparent
uniform samplerCube shadowMapPointTransparent[1]; uniform samplerCube shadowMapPointTransparent[1];
#endif
uniform vec2 lightProj; uniform vec2 lightProj;
#endif #endif
#endif #endif
#ifdef _Clusters #ifdef _Clusters
#ifdef _SingleAtlas #ifdef _SingleAtlas
//!uniform sampler2DShadow shadowMapAtlas; //!uniform sampler2DShadow shadowMapAtlas;
#ifdef _ShadowMapTransparent
//!uniform sampler2D shadowMapAtlasTransparent; //!uniform sampler2D shadowMapAtlasTransparent;
#endif #endif
#endif
uniform vec2 lightProj; uniform vec2 lightProj;
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasPoint; uniform sampler2DShadow shadowMapAtlasPoint;
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapAtlasPointTransparent; uniform sampler2D shadowMapAtlasPointTransparent;
#endif #endif
#endif
#else #else
uniform samplerCubeShadow shadowMapPoint[4]; uniform samplerCubeShadow shadowMapPoint[4];
#ifdef _ShadowMapTransparent
uniform samplerCube shadowMapPointTransparent[4]; uniform samplerCube shadowMapPointTransparent[4];
#endif #endif
#endif
#ifdef _Spot #ifdef _Spot
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
#ifndef _SingleAtlas #ifndef _SingleAtlas
uniform sampler2DShadow shadowMapAtlasSpot; uniform sampler2DShadow shadowMapAtlasSpot;
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapAtlasSpotTransparent; uniform sampler2D shadowMapAtlasSpotTransparent;
#endif #endif
#endif
#else #else
uniform sampler2DShadow shadowMapSpot[4]; uniform sampler2DShadow shadowMapSpot[4];
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapSpotTransparent[4]; uniform sampler2D shadowMapSpotTransparent[4];
#endif #endif
#endif
uniform mat4 LWVPSpotArray[maxLightsCluster]; uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif #endif
@ -79,28 +95,35 @@ uniform sampler2D sltcMag;
#ifndef _Spot #ifndef _Spot
#ifdef _SinglePoint #ifdef _SinglePoint
uniform sampler2DShadow shadowMapSpot[1]; uniform sampler2DShadow shadowMapSpot[1];
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapSpotTransparent[1]; uniform sampler2D shadowMapSpotTransparent[1];
uniform mat4 LWVPSpot[1]; #endif
uniform mat4 LWVPSpotArray[1];
#endif #endif
#ifdef _Clusters #ifdef _Clusters
uniform sampler2DShadow shadowMapSpot[maxLightsCluster]; uniform sampler2DShadow shadowMapSpot[maxLightsCluster];
#ifdef _ShadowMapTransparent
uniform sampler2D shadowMapSpotTransparent[maxLightsCluster]; uniform sampler2D shadowMapSpotTransparent[maxLightsCluster];
#endif
uniform mat4 LWVPSpotArray[maxLightsCluster]; uniform mat4 LWVPSpotArray[maxLightsCluster];
#endif #endif
#endif #endif
#endif #endif
#endif #endif
vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol, vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0 const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap #ifdef _ShadowMap
, int index, float bias, bool receiveShadow, bool transparent , int index, float bias, bool receiveShadow
#ifdef _ShadowMapTransparent
, bool transparent
#endif
#endif #endif
#ifdef _Spot #ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right , const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
, sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount] , sampler3D voxels, sampler3D voxelsSDF, float clipmaps[10 * voxelgiClipmapCount], vec2 velocity
#endif #endif
#ifdef _MicroShadowing #ifdef _MicroShadowing
, float occ , float occ
@ -146,22 +169,67 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#endif #endif
#ifdef _VoxelShadow #ifdef _VoxelShadow
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, l, clipmaps, gl_FragCoord.xy).r) * voxelgiShad; vec3 lightDir = l;
#ifdef _Spot
if (isSpot)
lightDir = spotDir;
#endif
direct *= (1.0 - traceShadow(p, n, voxels, voxelsSDF, lightDir, clipmaps, gl_FragCoord.xy, velocity).r) * voxelgiShad;
#endif #endif
#ifdef _LTC #ifdef _LTC
#ifdef _ShadowMap #ifdef _ShadowMap
if (receiveShadow) { if (receiveShadow) {
#ifdef _SinglePoint #ifdef _SinglePoint
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0); vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif #endif
#ifdef _Clusters #ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); if (index == 0) direct *= shadowTest(shadowMapSpot[0],
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); #ifdef _ShadowMapTransparent
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); shadowMapSpotTransparent[0],
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); #endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[1],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[2],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[3],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif #endif
} }
#endif #endif
@ -175,25 +243,76 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
#ifdef _ShadowMap #ifdef _ShadowMap
if (receiveShadow) { if (receiveShadow) {
#ifdef _SinglePoint #ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0); vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif #endif
#ifdef _Clusters #ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0); vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
direct *= shadowTest( direct *= shadowTest(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas #ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else #else
shadowMapAtlas, shadowMapAtlasTransparent shadowMapAtlas, shadowMapAtlasTransparent
#endif #endif
, lPos.xyz / lPos.w, bias, transparent #else
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
#endif
, lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
); );
#else #else
if (index == 0) direct *= shadowTest(shadowMapSpot[0], shadowMapSpotTransparent[0], lPos.xyz / lPos.w, bias, transparent); if (index == 0) direct *= shadowTest(shadowMapSpot[0],
else if (index == 1) direct *= shadowTest(shadowMapSpot[1], shadowMapSpotTransparent[1], lPos.xyz / lPos.w, bias, transparent); #ifdef _ShadowMapTransparent
else if (index == 2) direct *= shadowTest(shadowMapSpot[2], shadowMapSpotTransparent[2], lPos.xyz / lPos.w, bias, transparent); shadowMapSpotTransparent[0],
else if (index == 3) direct *= shadowTest(shadowMapSpot[3], shadowMapSpotTransparent[3], lPos.xyz / lPos.w, bias, transparent); #endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[1],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[2],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[3],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif #endif
#endif #endif
} }
@ -210,24 +329,75 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
if (receiveShadow) { if (receiveShadow) {
#ifdef _SinglePoint #ifdef _SinglePoint
#ifndef _Spot #ifndef _Spot
direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); direct *= PCFCube(shadowMapPoint[0],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[0],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif #endif
#endif #endif
#ifdef _Clusters #ifdef _Clusters
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
direct *= PCFFakeCube( direct *= PCFFakeCube(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas #ifndef _SingleAtlas
shadowMapAtlasPoint, shadowMapAtlasPointTransparent shadowMapAtlasPoint, shadowMapAtlasPointTransparent
#else #else
shadowMapAtlas, shadowMapAtlasTransparent shadowMapAtlas, shadowMapAtlasTransparent
#endif #endif
, ld, -l, bias, lightProj, n, index, transparent #else
#ifndef _SingleAtlas
shadowMapAtlasPoint
#else
shadowMapAtlas
#endif
#endif
, ld, -l, bias, lightProj, n, index
#ifdef _ShadowMapTransparent
, transparent
#endif
); );
#else #else
if (index == 0) direct *= PCFCube(shadowMapPoint[0], shadowMapPointTransparent[0], ld, -l, bias, lightProj, n, transparent); if (index == 0) direct *= PCFCube(shadowMapPoint[0],
else if (index == 1) direct *= PCFCube(shadowMapPoint[1], shadowMapPointTransparent[1], ld, -l, bias, lightProj, n, transparent); #ifdef _ShadowMapTransparent
else if (index == 2) direct *= PCFCube(shadowMapPoint[2], shadowMapPointTransparent[2], ld, -l, bias, lightProj, n, transparent); shadowMapPointTransparent[0],
else if (index == 3) direct *= PCFCube(shadowMapPoint[3], shadowMapPointTransparent[3], ld, -l, bias, lightProj, n, transparent); #endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[1],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[2],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[3],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif #endif
#endif #endif
} }
@ -236,4 +406,274 @@ vec3 sampleLight(const vec3 p, const vec3 n, const vec3 v, const float dotNV, co
return direct; return direct;
} }
#ifdef _VoxelGI
vec3 sampleLightVoxels(const vec3 p, const vec3 n, const vec3 v, const float dotNV, const vec3 lp, const vec3 lightCol,
const vec3 albedo, const float rough, const float spec, const vec3 f0
#ifdef _ShadowMap
, int index, float bias, bool receiveShadow
#ifdef _ShadowMapTransparent
, bool transparent
#endif
#endif
#ifdef _Spot
, const bool isSpot, const float spotSize, float spotBlend, vec3 spotDir, vec2 scale, vec3 right
#endif
) {
vec3 ld = lp - p;
vec3 l = normalize(ld);
vec3 h = normalize(v + l);
float dotNH = max(0.0, dot(n, h));
float dotVH = max(0.0, dot(v, h));
float dotNL = max(0.0, dot(n, l));
#ifdef _LTC
float theta = acos(dotNV);
vec2 tuv = vec2(rough, theta / (0.5 * PI));
tuv = tuv * LUT_SCALE + LUT_BIAS;
vec4 t = textureLod(sltcMat, tuv, 0.0);
mat3 invM = mat3(
vec3(1.0, 0.0, t.y),
vec3(0.0, t.z, 0.0),
vec3(t.w, 0.0, t.x));
float ltcspec = ltcEvaluate(n, v, dotNV, p, invM, lightArea0, lightArea1, lightArea2, lightArea3);
ltcspec *= textureLod(sltcMag, tuv, 0.0).a;
float ltcdiff = ltcEvaluate(n, v, dotNV, p, mat3(1.0), lightArea0, lightArea1, lightArea2, lightArea3);
vec3 direct = albedo * ltcdiff + ltcspec * spec * 0.05;
#else
vec3 direct = lambertDiffuseBRDF(albedo, dotNL) +
specularBRDF(f0, rough, dotNL, dotNH, dotNV, dotVH) * spec;
#endif
direct *= attenuate(distance(p, lp));
direct *= lightCol;
#ifdef _LTC
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpot[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpot[index] * vec4(p + n * bias * 10, 1.0);
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[1],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[2],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[3],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
}
#endif
return direct;
#endif
#ifdef _Spot
if (isSpot) {
direct *= spotlightMask(l, spotDir, right, scale, spotSize, spotBlend);
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
vec4 lPos = LWVPSpotArray[0] * vec4(p + n * bias * 10, 1.0);
direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#ifdef _Clusters
vec4 lPos = LWVPSpotArray[index] * vec4(p + n * bias * 10, 1.0);
#ifdef _ShadowMapAtlas
direct *= shadowTest(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasSpot, shadowMapAtlasSpotTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasSpot
#else
shadowMapAtlas
#endif
#endif
, lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
if (index == 0) direct *= shadowTest(shadowMapSpot[0],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[0],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= shadowTest(shadowMapSpot[1],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[1],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= shadowTest(shadowMapSpot[2],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[2],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= shadowTest(shadowMapSpot[3],
#ifdef _ShadowMapTransparent
shadowMapSpotTransparent[3],
#endif
lPos.xyz / lPos.w, bias
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#endif
}
#endif
return direct;
}
#endif
#ifdef _LightIES
direct *= iesAttenuation(-l);
#endif
#ifdef _ShadowMap
if (receiveShadow) {
#ifdef _SinglePoint
#ifndef _Spot
direct *= PCFCube(shadowMapPoint[0],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[0],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#endif
#ifdef _Clusters
#ifdef _ShadowMapAtlas
direct *= PCFFakeCube(
#ifdef _ShadowMapTransparent
#ifndef _SingleAtlas
shadowMapAtlasPoint, shadowMapAtlasPointTransparent
#else
shadowMapAtlas, shadowMapAtlasTransparent
#endif
#else
#ifndef _SingleAtlas
shadowMapAtlasPoint
#else
shadowMapAtlas
#endif
#endif
, ld, -l, bias, lightProj, n, index
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#else
if (index == 0) direct *= PCFCube(shadowMapPoint[0],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[0],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 1) direct *= PCFCube(shadowMapPoint[1],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[1],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 2) direct *= PCFCube(shadowMapPoint[2],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[2],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
else if (index == 3) direct *= PCFCube(shadowMapPoint[3],
#ifdef _ShadowMapTransparent
shadowMapPointTransparent[3],
#endif
ld, -l, bias, lightProj, n
#ifdef _ShadowMapTransparent
, transparent
#endif
);
#endif
#endif
}
#endif
return direct;
}
#endif
#endif #endif

View File

@ -58,7 +58,15 @@ vec2 sampleCube(vec3 dir, out int faceIndex) {
} }
#endif #endif
vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 uv, const float compare, const vec2 smSize, const bool transparent) { vec3 PCF(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
sampler2D shadowMapTransparent,
#endif
const vec2 uv, const float compare, const vec2 smSize
#ifdef _ShadowMapTransparent
, const bool transparent
#endif
) {
vec3 result = vec3(0.0); vec3 result = vec3(0.0);
result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare)); result.x = texture(shadowMap, vec3(uv + (vec2(-1.0, -1.0) / smSize), compare));
result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare)); result.x += texture(shadowMap, vec3(uv + (vec2(-1.0, 0.0) / smSize), compare));
@ -71,11 +79,13 @@ vec3 PCF(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec2 u
result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare)); result.x += texture(shadowMap, vec3(uv + (vec2(1.0, 1.0) / smSize), compare));
result = result.xxx / 9.0; result = result.xxx / 9.0;
#ifdef _ShadowMapTransparent
if (transparent == false) { if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapTransparent, uv); vec4 shadowmap_transparent = texture(shadowMapTransparent, uv);
if (shadowmap_transparent.a < compare) if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb; result *= shadowmap_transparent.rgb;
} }
#endif
return result; return result;
} }
@ -87,41 +97,15 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
return zcomp * 0.5 + 0.5; return zcomp * 0.5 + 0.5;
} }
#ifndef _ShadowMapAtlas vec3 PCFCube(samplerCubeShadow shadowMapCube,
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, vec3 lp, vec3 ml, float bias, vec2 lightProj, vec3 n, const bool transparent) { #ifdef _ShadowMapTransparent
const float s = shadowmapCubePcfSize; samplerCube shadowMapCubeTransparent,
float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20;
#ifdef _InvY
ml.y = -ml.y;
#endif #endif
const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n
float shadowFactor = 0.0; #ifdef _ShadowMapTransparent
shadowFactor = texture(shadowMapCube, vec4(ml, compare)); , const bool transparent
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, s), compare)); #endif
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, s), compare)); ) {
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, s, -s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(s, -s, -s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, s, -s), compare));
shadowFactor += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
shadowFactor /= 9.0;
vec3 result = vec3(shadowFactor);
if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb;
}
return result;
}
#endif
#ifdef _ShadowMapAtlas
vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const bool transparent) {
const float s = shadowmapCubePcfSize; // TODO: incorrect... const float s = shadowmapCubePcfSize; // TODO: incorrect...
float compare = lpToDepth(lp, lightProj) - bias * 1.5; float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20; ml = ml + n * bias * 20;
@ -140,16 +124,18 @@ vec3 PCFCube(samplerCubeShadow shadowMapCube, samplerCube shadowMapCubeTranspare
result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare)); result.x += texture(shadowMapCube, vec4(ml + vec3(-s, -s, -s), compare));
result = result.xxx / 9.0; result = result.xxx / 9.0;
#ifdef _ShadowMapTransparent
if (transparent == false) { if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml); vec4 shadowmap_transparent = texture(shadowMapCubeTransparent, ml);
if (shadowmap_transparent.a < compare) if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb; result *= shadowmap_transparent.rgb;
} }
#endif
return result; return result;
} }
#ifdef _ShadowMapAtlas
// transform "out-of-bounds" coordinates to the correct face/coordinate system // transform "out-of-bounds" coordinates to the correct face/coordinate system
// https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png // https://www.khronos.org/opengl/wiki/File:CubeMapAxes.png
vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) { vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
@ -243,89 +229,50 @@ vec2 transformOffsetedUV(const int faceIndex, out int newFaceIndex, vec2 uv) {
return uv; return uv;
} }
vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index, const bool transparent) { vec3 PCFFakeCube(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
sampler2D shadowMapTransparent,
#endif
const vec3 lp, vec3 ml, const float bias, const vec2 lightProj, const vec3 n, const int index
#ifdef _ShadowMapTransparent
, const bool transparent
#endif
) {
const vec2 smSize = smSizeUniform; // TODO: incorrect... const vec2 smSize = smSizeUniform; // TODO: incorrect...
const float compare = lpToDepth(lp, lightProj) - bias * 1.5; const float compare = lpToDepth(lp, lightProj) - bias * 1.5;
ml = ml + n * bias * 20; ml = ml + n * bias * 20;
int faceIndex = 0; int faceIndex = 0;
const int lightIndex = index * 6; const int lightIndex = index * 6;
const vec2 uv = sampleCube(ml, faceIndex); const vec2 uv = sampleCube(ml, faceIndex);
vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas vec4 pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy; vec2 uvtiled = pointLightTile.z * uv + pointLightTile.xy;
#ifdef _FlipY #ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif #endif
if (any(lessThan(uvtiled, vec2(0.0))) || any(greaterThan(uvtiled, vec2(1.0)))) {
return vec3(1.0); // Or handle edge cases differently
}
vec3 result = vec3(0.0); vec3 result = vec3(0.0);
result.x += texture(shadowMap, vec3(uvtiled, compare)); // In PCFFakeCube(), modify the sampling pattern to be more robust:
// soft shadowing const vec2 offsets[9] = vec2[](
int newFaceIndex = 0; vec2(0, 0),
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 0.0) / smSize))); vec2(1, 0), vec2(-1, 0), vec2(0, 1), vec2(0, -1),
vec2(1, 1), vec2(-1, 1), vec2(1, -1), vec2(-1, -1)
);
for (int i = 0; i < 9; i++) {
vec2 sampleUV = uv + offsets[i] / smSize;
int newFaceIndex;
vec2 transformedUV = transformOffsetedUV(faceIndex, newFaceIndex, sampleUV);
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex]; pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy; uvtiled = pointLightTile.z * transformedUV + pointLightTile.xy;
#ifdef _FlipY #ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system uvtiled.y = 1.0 - uvtiled.y;
#endif #endif
result.x += texture(shadowMap, vec3(uvtiled, compare)); result.x += texture(shadowMap, vec3(uvtiled, compare));
}
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, 1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, -1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(-1.0, -1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(0.0, 1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, -1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 0.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
uvtiled = transformOffsetedUV(faceIndex, newFaceIndex, vec2(uv + (vec2(1.0, 1.0) / smSize)));
pointLightTile = pointLightDataArray[lightIndex + newFaceIndex];
uvtiled = pointLightTile.z * uvtiled + pointLightTile.xy;
#ifdef _FlipY
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif
result.x += texture(shadowMap, vec3(uvtiled, compare));
result = result.xxx / 9.0; result = result.xxx / 9.0;
pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas pointLightTile = pointLightDataArray[lightIndex + faceIndex]; // x: tile X offset, y: tile Y offset, z: tile size relative to atlas
@ -334,30 +281,47 @@ vec3 PCFFakeCube(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, cons
uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system uvtiled.y = 1.0 - uvtiled.y; // invert Y coordinates for direct3d coordinate system
#endif #endif
#ifdef _ShadowMapTransparent
if (transparent == false) { if (transparent == false) {
vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled); vec4 shadowmap_transparent = texture(shadowMapTransparent, uvtiled);
if (shadowmap_transparent.a < compare) if (shadowmap_transparent.a < compare)
result *= shadowmap_transparent.rgb; result *= shadowmap_transparent.rgb;
} }
#endif
return result; return result;
} }
#endif #endif
vec3 shadowTest(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 lPos, const float shadowsBias, const bool transparent) { vec3 shadowTest(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
sampler2D shadowMapTransparent,
#endif
const vec3 lPos, const float shadowsBias
#ifdef _ShadowMapTransparent
, const bool transparent
#endif
) {
#ifdef _SMSizeUniform #ifdef _SMSizeUniform
vec2 smSize = smSizeUniform; vec2 smSize = smSizeUniform;
#else #else
const vec2 smSize = shadowmapSize; const vec2 smSize = shadowmapSize;
#endif #endif
if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0); if (lPos.x < 0.0 || lPos.y < 0.0 || lPos.x > 1.0 || lPos.y > 1.0) return vec3(1.0);
return PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); return PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos.xy, lPos.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
} }
#ifdef _CSM #ifdef _CSM
mat4 getCascadeMat(const float d, out int casi, out int casIndex) { mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
const int c = shadowmapCascades; const int c = shadowmapCascades;
// Get cascade index // Get cascade index
// TODO: use bounding box slice selection instead of sphere // TODO: use bounding box slice selection instead of sphere
const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3)); const vec4 ci = vec4(float(c > 0), float(c > 1), float(c > 2), float(c > 3));
@ -373,21 +337,26 @@ mat4 getCascadeMat(const float d, out int casi, out int casIndex) {
float(d > casData[c * 4].z), float(d > casData[c * 4].z),
float(d > casData[c * 4].w)); float(d > casData[c * 4].w));
casi = int(min(dot(ci, comp), c)); casi = int(min(dot(ci, comp), c));
// Get cascade mat // Get cascade mat
casIndex = casi * 4; casIndex = casi * 4;
return mat4( return mat4(
casData[casIndex ], casData[casIndex ],
casData[casIndex + 1], casData[casIndex + 1],
casData[casIndex + 2], casData[casIndex + 2],
casData[casIndex + 3]); casData[casIndex + 3]);
// if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]); // if (casIndex == 0) return mat4(casData[0], casData[1], casData[2], casData[3]);
// .. // ..
} }
vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent, const vec3 eye, const vec3 p, const float shadowsBias, const bool transparent) { vec3 shadowTestCascade(sampler2DShadow shadowMap,
#ifdef _ShadowMapTransparent
sampler2D shadowMapTransparent,
#endif
const vec3 eye, const vec3 p, const float shadowsBias
#ifdef _ShadowMapTransparent
, const bool transparent
#endif
) {
#ifdef _SMSizeUniform #ifdef _SMSizeUniform
vec2 smSize = smSizeUniform; vec2 smSize = smSizeUniform;
#else #else
@ -395,16 +364,22 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent
#endif #endif
const int c = shadowmapCascades; const int c = shadowmapCascades;
float d = distance(eye, p); float d = distance(eye, p);
int casi; int casi;
int casIndex; int casIndex;
mat4 LWVP = getCascadeMat(d, casi, casIndex); mat4 LWVP = getCascadeMat(d, casi, casIndex);
vec4 lPos = LWVP * vec4(p, 1.0); vec4 lPos = LWVP * vec4(p, 1.0);
lPos.xyz /= lPos.w; lPos.xyz /= lPos.w;
vec3 visibility = vec3(1.0); vec3 visibility = vec3(1.0);
if (lPos.w > 0.0) visibility = PCF(shadowMap, shadowMapTransparent, lPos.xy, lPos.z - shadowsBias, smSize, transparent); if (lPos.w > 0.0) visibility = PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos.xy, lPos.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
// Blend cascade // Blend cascade
// https://github.com/TheRealMJP/Shadows // https://github.com/TheRealMJP/Shadows
@ -423,13 +398,20 @@ vec3 shadowTestCascade(sampler2DShadow shadowMap, sampler2D shadowMapTransparent
vec4 lPos2 = LWVP2 * vec4(p, 1.0); vec4 lPos2 = LWVP2 * vec4(p, 1.0);
lPos2.xyz /= lPos2.w; lPos2.xyz /= lPos2.w;
vec3 visibility2 = vec3(1.0); vec3 visibility2 = vec3(1.0);
if (lPos2.w > 0.0) visibility2 = PCF(shadowMap, shadowMapTransparent, lPos2.xy, lPos2.z - shadowsBias, smSize, transparent); if (lPos2.w > 0.0) visibility2 = PCF(shadowMap,
#ifdef _ShadowMapTransparent
shadowMapTransparent,
#endif
lPos.xy, lPos.z - shadowsBias, smSize
#ifdef _ShadowMapTransparent
, transparent
#endif
);
float lerpAmt = smoothstep(0.0, blendThres, splitDist); float lerpAmt = smoothstep(0.0, blendThres, splitDist);
return mix(visibility2, visibility, lerpAmt); return mix(visibility2, visibility, lerpAmt);
} }
return visibility; return visibility;
// Visualize cascades // Visualize cascades
// if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0); // if (ci == 0) albedo.rgb = vec3(1.0, 0.0, 0.0);
// if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0); // if (ci == 4) albedo.rgb = vec3(0.0, 1.0, 0.0);

View File

@ -33,6 +33,7 @@ uniform layout(r32ui) uimage3D voxelsLight;
#ifdef _ShadowMap #ifdef _ShadowMap
uniform sampler2DShadow shadowMap; uniform sampler2DShadow shadowMap;
uniform sampler2D shadowMapTransparent;
uniform sampler2DShadow shadowMapSpot; uniform sampler2DShadow shadowMapSpot;
#ifdef _ShadowMapAtlas #ifdef _ShadowMapAtlas
uniform sampler2DShadow shadowMapPoint; uniform sampler2DShadow shadowMapPoint;
@ -86,30 +87,28 @@ float lpToDepth(vec3 lp, const vec2 lightProj) {
void main() { void main() {
int res = voxelgiResolution.x; int res = voxelgiResolution.x;
ivec3 dst = ivec3(gl_GlobalInvocationID.xyz); ivec3 dst = ivec3(gl_GlobalInvocationID.xyz);
dst.y += clipmapLevel * res;
vec3 P = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution; vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
P = P * 2.0 - 1.0; wposition = wposition * 2.0 - 1.0;
P *= clipmaps[int(clipmapLevel * 10)]; wposition *= float(clipmaps[int(clipmapLevel * 10)]);
P *= voxelgiResolution; wposition *= voxelgiResolution.x;
P += vec3(clipmaps[int(clipmapLevel * 10 + 4)], clipmaps[int(clipmapLevel * 10 + 5)], clipmaps[int(clipmapLevel * 10 + 6)]); wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]);
vec3 visibility; float visibility;
vec3 lp = lightPos - P; vec3 lp = lightPos -wposition;
vec3 l; vec3 l;
if (lightType == 0) { l = lightDir; visibility = vec3(1.0); } if (lightType == 0) { l = lightDir; visibility = 1.0; }
else { l = normalize(lp); visibility = vec3(attenuate(distance(P, lightPos))); } else { l = normalize(lp); visibility = attenuate(distance(wposition, lightPos)); }
#ifdef _ShadowMap #ifdef _ShadowMap
if (lightShadow == 1) { if (lightShadow == 1) {
vec4 lightPosition = LVP * vec4(P, 1.0); vec4 lightPosition = LVP * vec4(wposition, 1.0);
vec3 lPos = lightPosition.xyz / lightPosition.w; vec3 lPos = lightPosition.xyz / lightPosition.w;
visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).rrr; visibility = texture(shadowMap, vec3(lPos.xy, lPos.z - shadowsBias)).r;
} }
else if (lightShadow == 2) { else if (lightShadow == 2) {
vec4 lightPosition = LVP * vec4(P, 1.0); vec4 lightPosition = LVP * vec4(wposition, 1.0);
vec3 lPos = lightPosition.xyz / lightPosition.w; vec3 lPos = lightPosition.xyz / lightPosition.w;
visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r; visibility *= texture(shadowMapSpot, vec3(lPos.xy, lPos.z - shadowsBias)).r;
} }
@ -130,9 +129,7 @@ void main() {
} }
#endif #endif
vec3 light = visibility * lightColor; imageAtomicAdd(voxelsLight, dst, uint(visibility * lightColor.r * 255));
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(visibility * lightColor.g * 255));
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, 0), uint(light.r * 255)); imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(visibility * lightColor.b * 255));
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x), uint(light.g * 255));
imageAtomicAdd(voxelsLight, dst + ivec3(0, 0, voxelgiResolution.x * 2), uint(light.b * 255));
} }

View File

@ -27,14 +27,14 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 8) in;
#include "std/math.glsl" #include "std/math.glsl"
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
#include "std/imageatomic.glsl" #include "std/imageatomic.glsl"
#include "std/voxels_constants.glsl" #include "std/constants.glsl"
#ifdef _VoxelGI #ifdef _VoxelGI
uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsB;
uniform layout(rgba8) image3D voxelsOut; uniform layout(rgba8) image3D voxelsOut;
#else #else
uniform layout(r16) image3D voxelsB; uniform layout(r8) image3D voxelsB;
uniform layout(r16) image3D voxelsOut; uniform layout(r8) image3D voxelsOut;
#endif #endif
uniform int clipmapLevel; uniform int clipmapLevel;

View File

@ -29,19 +29,38 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
#include "std/imageatomic.glsl" #include "std/imageatomic.glsl"
#include "std/conetrace.glsl" #include "std/conetrace.glsl"
#include "std/brdf.glsl"
#include "std/shirr.glsl"
uniform sampler3D voxels; uniform sampler3D voxels;
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; uniform sampler2D gbuffer0;
uniform layout(r8) image2D voxels_ao; uniform layout(rgba8) image2D voxels_ao;
uniform float clipmaps[voxelgiClipmapCount * 10]; uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP; uniform mat4 InvVP;
uniform vec2 cameraProj;
uniform vec3 eye; uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec2 postprocess_resolution; uniform vec2 postprocess_resolution;
uniform sampler2D gbuffer1;
#ifdef _gbuffer2
uniform sampler2D gbuffer2;
#endif
uniform float envmapStrength;
#ifdef _Irr
uniform float shirr[7 * 4];
#endif
#ifdef _Brdf
uniform sampler2D senvmapBrdf;
#endif
#ifdef _Rad
uniform sampler2D senvmapRadiance;
uniform int envmapNumMipmaps;
#endif
#ifdef _EnvCol
uniform vec3 backgroundCol;
#endif
void main() { void main() {
const vec2 pixel = gl_GlobalInvocationID.xy; const vec2 pixel = gl_GlobalInvocationID.xy;
vec2 uv = (pixel + 0.5) / postprocess_resolution; vec2 uv = (pixel + 0.5) / postprocess_resolution;
@ -54,12 +73,11 @@ void main() {
float x = uv.x * 2 - 1; float x = uv.x * 2 - 1;
float y = uv.y * 2 - 1; float y = uv.y * 2 - 1;
vec4 v = vec4(x, y, 1.0, 1.0); vec4 clipPos = vec4(x, y, depth, 1.0);
v = vec4(InvVP * v); vec4 worldPos = InvVP * clipPos;
v.xyz /= v.w; vec3 P = worldPos.xyz / worldPos.w;
vec3 viewRay = v.xyz - eye;
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj); vec3 v = normalize(eye - P);
vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec4 g0 = textureLod(gbuffer0, uv, 0.0);
vec3 n; vec3 n;
@ -67,7 +85,89 @@ void main() {
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n); n = normalize(n);
float occ = 1.0 - traceAO(P, n, voxels, clipmaps); float roughness = g0.b;
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
imageStore(voxels_ao, ivec2(pixel), vec4(occ)); vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ
vec2 occspec = unpackFloat2(g1.a);
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
vec3 f0 = surfaceF0(g1.rgb, metallic);
float dotNV = max(dot(n, v), 0.0);
#ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, uv, 0.0);
#endif
#ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
#endif
#ifdef _Brdf
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
vec3 F = f0 * envBRDF.x + envBRDF.y;
#endif
// Envmap
#ifdef _Irr
vec4 shPacked[7];
for (int i = 0; i < 7; i++) {
int base = i * 4;
shPacked[i] = vec4(
shirr[base],
shirr[base + 1],
shirr[base + 2],
shirr[base + 3]
);
}
vec3 envl = shIrradiance(n, shPacked);
#ifdef _gbuffer2
if (g2.b < 0.5) {
envl = envl;
} else {
envl = vec3(0.0);
}
#endif
#ifdef _EnvTex
envl /= PI;
#endif
#else
vec3 envl = vec3(0.0);
#endif
#ifdef _Rad
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
#endif
#ifdef _EnvLDR
envl.rgb = pow(envl.rgb, vec3(2.2));
#ifdef _Rad
prefilteredColor = pow(prefilteredColor, vec3(2.2));
#endif
#endif
envl.rgb *= albedo;
#ifdef _Brdf
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
#endif
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
#else
#ifdef _EnvCol
envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0?
#endif
#endif
envl.rgb *= envmapStrength * occspec.x;
vec3 occ = envl * (1.0 - traceAO(P, n, voxels, clipmaps));
imageStore(voxels_ao, ivec2(pixel), vec4(occ, 1.0));
} }

View File

@ -29,6 +29,8 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
#include "std/imageatomic.glsl" #include "std/imageatomic.glsl"
#include "std/conetrace.glsl" #include "std/conetrace.glsl"
#include "std/brdf.glsl"
#include "std/shirr.glsl"
uniform sampler3D voxels; uniform sampler3D voxels;
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
@ -37,29 +39,44 @@ uniform layout(rgba8) image2D voxels_diffuse;
uniform float clipmaps[voxelgiClipmapCount * 10]; uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP; uniform mat4 InvVP;
uniform vec2 cameraProj;
uniform vec3 eye; uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec2 postprocess_resolution; uniform vec2 postprocess_resolution;
uniform sampler2D gbuffer1;
#ifdef _gbuffer2
uniform sampler2D gbuffer2;
#endif
uniform float envmapStrength;
#ifdef _Irr
uniform float shirr[7 * 4];
#endif
#ifdef _Brdf
uniform sampler2D senvmapBrdf;
#endif
#ifdef _Rad
uniform sampler2D senvmapRadiance;
uniform int envmapNumMipmaps;
#endif
#ifdef _EnvCol
uniform vec3 backgroundCol;
#endif
void main() { void main() {
const vec2 pixel = gl_GlobalInvocationID.xy; const vec2 pixel = gl_GlobalInvocationID.xy;
vec2 uv = (pixel + 0.5) / postprocess_resolution; vec2 uv = (pixel + 0.5) / postprocess_resolution;
#ifdef _InvY #ifdef _InvY
uv.y = 1.0 - uv.y uv.y = 1.0 - uv.y;
#endif #endif
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0; float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
if (depth == 0) return; if (depth == 0.0) return;
float x = uv.x * 2 - 1; float x = uv.x * 2 - 1;
float y = uv.y * 2 - 1; float y = uv.y * 2 - 1;
vec4 v = vec4(x, y, 1.0, 1.0); vec4 clipPos = vec4(x, y, depth, 1.0);
v = vec4(InvVP * v); vec4 worldPos = InvVP * clipPos;
v.xyz /= v.w; vec3 P = worldPos.xyz / worldPos.w;
vec3 viewRay = v.xyz - eye; vec3 v = normalize(eye - P);
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec4 g0 = textureLod(gbuffer0, uv, 0.0);
vec3 n; vec3 n;
@ -67,7 +84,91 @@ void main() {
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy); n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n); n = normalize(n);
vec4 color = traceDiffuse(P, n, voxels, clipmaps); float roughness = g0.b;
float metallic;
uint matid;
unpackFloatInt16(g0.a, metallic, matid);
imageStore(voxels_diffuse, ivec2(pixel), color); vec4 g1 = textureLod(gbuffer1, uv, 0.0); // Basecolor.rgb, spec/occ
vec2 occspec = unpackFloat2(g1.a);
vec3 albedo = surfaceAlbedo(g1.rgb, metallic); // g1.rgb - basecolor
vec3 f0 = surfaceF0(g1.rgb, metallic);
float dotNV = max(dot(n, v), 0.0);
#ifdef _gbuffer2
vec4 g2 = textureLod(gbuffer2, uv, 0.0);
#endif
#ifdef _MicroShadowing
occspec.x = mix(1.0, occspec.x, dotNV); // AO Fresnel
#endif
#ifdef _Brdf
vec2 envBRDF = texelFetch(senvmapBrdf, ivec2(vec2(dotNV, 1.0 - roughness) * 256.0), 0).xy;
vec3 F = f0 * envBRDF.x + envBRDF.y;
#endif
// Envmap
#ifdef _Irr
vec4 shPacked[7];
for (int i = 0; i < 7; i++) {
int base = i * 4;
shPacked[i] = vec4(
shirr[base],
shirr[base + 1],
shirr[base + 2],
shirr[base + 3]
);
}
vec3 envl = shIrradiance(n, shPacked);
#ifdef _gbuffer2
if (g2.b < 0.5) {
envl = envl;
} else {
envl = vec3(0.0);
}
#endif
#ifdef _EnvTex
envl /= PI;
#endif
#else
vec3 envl = vec3(0.0);
#endif
#ifdef _Rad
vec3 reflectionWorld = reflect(-v, n);
float lod = getMipFromRoughness(roughness, envmapNumMipmaps);
vec3 prefilteredColor = textureLod(senvmapRadiance, envMapEquirect(reflectionWorld), lod).rgb;
#endif
#ifdef _EnvLDR
envl.rgb = pow(envl.rgb, vec3(2.2));
#ifdef _Rad
prefilteredColor = pow(prefilteredColor, vec3(2.2));
#endif
#endif
envl.rgb *= albedo;
#ifdef _Brdf
envl.rgb *= 1.0 - F; //LV: We should take refracted light into account
#endif
#ifdef _Rad // Indirect specular
envl.rgb += prefilteredColor * F; //LV: Removed "1.5 * occspec.y". Specular should be weighted only by FV LUT
#else
#ifdef _EnvCol
envl.rgb += backgroundCol * F; //LV: Eh, what's the point of weighting it only by F0?
#endif
#endif
envl.rgb *= envmapStrength * occspec.x;
vec4 trace = traceDiffuse(P, n, voxels, clipmaps);
vec3 color = trace.rgb * albedo * (1.0 - F);
color += envl * (1.0 - trace.a);
imageStore(voxels_diffuse, ivec2(pixel), vec4(color, 1.0));
} }

View File

@ -1,79 +0,0 @@
/*
Copyright (c) 2024 Turánszki János
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#version 450
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#include "compiled.inc"
#include "std/math.glsl"
#include "std/gbuffer.glsl"
#include "std/imageatomic.glsl"
#include "std/conetrace.glsl"
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform sampler3D voxels;
uniform sampler3D voxelsSDF;
uniform sampler2D gbuffer_refraction;
uniform layout(rgba8) image2D voxels_refraction;
uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP;
uniform vec2 cameraProj;
uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec2 postprocess_resolution;
void main() {
const vec2 pixel = gl_GlobalInvocationID.xy;
vec2 uv = (pixel + 0.5) / postprocess_resolution;
#ifdef _InvY
uv.y = 1.0 - uv.y
#endif
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
if (depth == 0) return;
vec2 ior_opac = textureLod(gbuffer_refraction, uv, 0.0).xy;
float x = uv.x * 2 - 1;
float y = uv.y * 2 - 1;
vec4 v = vec4(x, y, 1.0, 1.0);
v = vec4(InvVP * v);
v.xyz /= v.w;
vec3 viewRay = v.xyz - eye;
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
vec3 n;
n.z = 1.0 - abs(g0.x) - abs(g0.y);
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n);
vec3 color = vec3(0.0);
if(ior_opac.y < 1.0)
color = traceRefraction(P, n, voxels, voxelsSDF, normalize(eye - P), ior_opac.x, g0.b, clipmaps, pixel).rgb;
imageStore(voxels_refraction, ivec2(pixel), vec4(color, 1.0));
}

View File

@ -1,75 +0,0 @@
/*
Copyright (c) 2024 Turánszki János
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#version 450
layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#include "compiled.inc"
#include "std/math.glsl"
#include "std/gbuffer.glsl"
#include "std/imageatomic.glsl"
#include "std/conetrace.glsl"
uniform sampler3D voxels;
uniform sampler3D voxelsSDF;
uniform sampler2D gbufferD;
uniform sampler2D gbuffer0;
uniform layout(r16) image2D voxels_shadows;
uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP;
uniform vec2 cameraProj;
uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec2 postprocess_resolution;
uniform vec3 lPos;
void main() {
const vec2 pixel = gl_GlobalInvocationID.xy;
vec2 uv = (pixel + 0.5) / postprocess_resolution;
#ifdef _InvY
uv.y = 1.0 - uv.y;
#endif
float depth = textureLod(gbufferD, uv, 0.0).r * 2.0 - 1.0;
if (depth == 0) return;
float x = uv.x * 2 - 1;
float y = uv.y * 2 - 1;
vec4 v = vec4(x, y, 1.0, 1.0);
v = vec4(InvVP * v);
v.xyz /= v.w;
vec3 viewRay = v.xyz - eye;
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec4 g0 = textureLod(gbuffer0, uv, 0.0);
vec3 n;
n.z = 1.0 - abs(g0.x) - abs(g0.y);
n.xy = n.z >= 0.0 ? g0.xy : octahedronWrap(g0.xy);
n = normalize(n);
float occ = 1.0 - traceShadow(P, n, voxels, voxelsSDF, normalize(lPos - P), clipmaps, pixel);
imageStore(voxels_shadows, ivec2(pixel), vec4(occ));
}

View File

@ -29,6 +29,7 @@ layout (local_size_x = 8, local_size_y = 8, local_size_z = 1) in;
#include "std/gbuffer.glsl" #include "std/gbuffer.glsl"
#include "std/imageatomic.glsl" #include "std/imageatomic.glsl"
#include "std/conetrace.glsl" #include "std/conetrace.glsl"
#include "std/brdf.glsl"
uniform sampler2D gbufferD; uniform sampler2D gbufferD;
uniform sampler2D gbuffer0; uniform sampler2D gbuffer0;
@ -38,9 +39,7 @@ uniform layout(rgba8) image2D voxels_specular;
uniform float clipmaps[voxelgiClipmapCount * 10]; uniform float clipmaps[voxelgiClipmapCount * 10];
uniform mat4 InvVP; uniform mat4 InvVP;
uniform vec2 cameraProj;
uniform vec3 eye; uniform vec3 eye;
uniform vec3 eyeLook;
uniform vec2 postprocess_resolution; uniform vec2 postprocess_resolution;
uniform sampler2D sveloc; uniform sampler2D sveloc;
@ -56,12 +55,10 @@ void main() {
float x = uv.x * 2 - 1; float x = uv.x * 2 - 1;
float y = uv.y * 2 - 1; float y = uv.y * 2 - 1;
vec4 v = vec4(x, y, 1.0, 1.0); vec4 clipPos = vec4(x, y, depth, 1.0);
v = vec4(InvVP * v); vec4 worldPos = InvVP * clipPos;
v.xyz /= v.w; vec3 P = worldPos.xyz / worldPos.w;
vec3 viewRay = v.xyz - eye;
vec3 P = getPos(eye, eyeLook, normalize(viewRay), depth, cameraProj);
vec4 g0 = textureLod(gbuffer0, uv, 0.0); vec4 g0 = textureLod(gbuffer0, uv, 0.0);
vec3 n; vec3 n;
@ -71,7 +68,7 @@ void main() {
vec2 velocity = -textureLod(sveloc, uv, 0.0).rg; vec2 velocity = -textureLod(sveloc, uv, 0.0).rg;
vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z, clipmaps, pixel, velocity).rgb; vec3 color = traceSpecular(P, n, voxels, voxelsSDF, normalize(eye - P), g0.z * g0.z, clipmaps, pixel, velocity).rgb;
imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0)); imageStore(voxels_specular, ivec2(pixel), vec4(color, 1.0));
} }

View File

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

View File

@ -46,15 +46,15 @@ uniform layout(r32ui) uimage3D voxels;
uniform layout(r32ui) uimage3D voxelsLight; uniform layout(r32ui) uimage3D voxelsLight;
uniform layout(rgba8) image3D voxelsB; uniform layout(rgba8) image3D voxelsB;
uniform layout(rgba8) image3D voxelsOut; uniform layout(rgba8) image3D voxelsOut;
uniform layout(r16) image3D SDF; uniform layout(r8) image3D SDF;
#else #else
#ifdef _VoxelAOvar #ifdef _VoxelAOvar
#ifdef _VoxelShadow #ifdef _VoxelShadow
uniform layout(r16) image3D SDF; uniform layout(r8) image3D SDF;
#endif #endif
uniform layout(r32ui) uimage3D voxels; uniform layout(r32ui) uimage3D voxels;
uniform layout(r16) image3D voxelsB; uniform layout(r8) image3D voxelsB;
uniform layout(r16) image3D voxelsOut; uniform layout(r8) image3D voxelsOut;
#endif #endif
#endif #endif
@ -74,14 +74,8 @@ void main() {
#endif #endif
#endif #endif
ivec3 src = ivec3(gl_GlobalInvocationID.xyz); mat3 TBN = mat3(1.0);
#ifdef _VoxelGI vec3 avgNormal = vec3(0.0);
vec3 light = vec3(0.0);
light.r = float(imageLoad(voxelsLight, src)) / 255;
light.g = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x))) / 255;
light.b = float(imageLoad(voxelsLight, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255;
light /= 3;
#endif
for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++) for (int i = 0; i < 6 + DIFFUSE_CONE_COUNT; i++)
{ {
@ -91,7 +85,7 @@ void main() {
float aniso_colors[6]; float aniso_colors[6];
#endif #endif
src = ivec3(gl_GlobalInvocationID.xyz); ivec3 src = ivec3(gl_GlobalInvocationID.xyz);
src.x += i * res; src.x += i * res;
ivec3 dst = src; ivec3 dst = src;
dst.y += clipmapLevel * res; dst.y += clipmapLevel * res;
@ -104,28 +98,39 @@ void main() {
if (i < 6) { if (i < 6) {
#ifdef _VoxelGI #ifdef _VoxelGI
int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 15)));
if (count > 0) {
vec4 basecol = vec4(0.0); vec4 basecol = vec4(0.0);
basecol.r = float(imageLoad(voxels, src)) / 255; basecol.r = float(imageLoad(voxels, src)) / 255;
basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255; basecol.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x))) / 255;
basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255; basecol.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 2))) / 255;
basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255; basecol.a = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 3))) / 255;
basecol /= 4; basecol /= count;
vec3 emission = vec3(0.0); vec3 emission = vec3(0.0);
emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255; emission.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 4))) / 255;
emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255; emission.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 5))) / 255;
emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255; emission.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 6))) / 255;
emission /= 3; emission /= count;
vec3 N = vec3(0.0); vec3 N = vec3(0.0);
N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255; N.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 7))) / 255;
N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255; N.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 8))) / 255;
N /= 2; N /= count;
vec3 wnormal = decode_oct(N.rg * 2 - 1); N = decode_oct(N.rg * 2.0 - 1.0);
avgNormal += N;
if (i == 5)
TBN = makeTangentBasis(normalize(avgNormal));
vec3 envl = vec3(0.0); vec3 envl = vec3(0.0);
envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255; envl.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 9))) / 255;
envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255; envl.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 10))) / 255;
envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255; envl.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 11))) / 255;
envl /= 3; envl /= count;
envl *= 100; vec3 light = vec3(0.0);
light.r = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 12))) / 255;
light.g = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 13))) / 255;
light.b = float(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x * 14))) / 255;
light /= count;
//clipmap to world //clipmap to world
vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x; vec3 wposition = (gl_GlobalInvocationID.xyz + 0.5) / voxelgiResolution.x;
@ -135,13 +140,17 @@ void main() {
wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]); wposition += vec3(clipmaps[clipmapLevel * 10 + 4], clipmaps[clipmapLevel * 10 + 5], clipmaps[clipmapLevel * 10 + 6]);
radiance = basecol; radiance = basecol;
vec4 trace = traceDiffuse(wposition, wnormal, voxelsSampler, clipmaps); vec4 trace = traceDiffuse(wposition, N, voxelsSampler, clipmaps);
vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a); vec3 indirect = trace.rgb + envl.rgb * (1.0 - trace.a);
radiance.rgb *= light + indirect; radiance.rgb *= light + indirect;
radiance.rgb += emission.rgb; radiance.rgb += emission.rgb;
}
#else #else
int count = int(imageLoad(voxels, src + ivec3(0, 0, voxelgiResolution.x)));
if (count > 0) {
opac = float(imageLoad(voxels, src)) / 255; opac = float(imageLoad(voxels, src)) / 255;
opac /= count;
}
#endif #endif
#ifdef _VoxelGI #ifdef _VoxelGI
@ -195,7 +204,7 @@ void main() {
} }
else { else {
// precompute cone sampling: // precompute cone sampling:
vec3 coneDirection = DIFFUSE_CONE_DIRECTIONS[i - 6]; vec3 coneDirection = TBN * DIFFUSE_CONE_DIRECTIONS[i - 6];
vec3 aniso_direction = -coneDirection; vec3 aniso_direction = -coneDirection;
uvec3 face_offsets = uvec3( uvec3 face_offsets = uvec3(
aniso_direction.x > 0 ? 0 : 1, aniso_direction.x > 0 ? 0 : 1,

View File

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

View File

@ -54,22 +54,6 @@ class App {
if (Scene.active == null || !Scene.active.ready) return; if (Scene.active == null || !Scene.active.ready) return;
iron.system.Time.update(); iron.system.Time.update();
if (lastw == -1) {
lastw = App.w();
lasth = App.h();
}
if (lastw != App.w() || lasth != App.h()) {
if (onResize != null) onResize();
else {
if (Scene.active != null && Scene.active.camera != null) {
Scene.active.camera.buildProjection();
}
}
}
lastw = App.w();
lasth = App.h();
if (pauseUpdates) return; if (pauseUpdates) return;
#if lnx_debug #if lnx_debug
@ -114,6 +98,22 @@ class App {
for (cb in endFrameCallbacks) cb(); for (cb in endFrameCallbacks) cb();
updateTime = kha.Scheduler.realTime() - startTime; updateTime = kha.Scheduler.realTime() - startTime;
#end #end
// Rebuild projection on window resize
if (lastw == -1) {
lastw = App.w();
lasth = App.h();
}
if (lastw != App.w() || lasth != App.h()) {
if (onResize != null) onResize();
else {
if (Scene.active != null && Scene.active.camera != null) {
Scene.active.camera.buildProjection();
}
}
}
lastw = App.w();
lasth = App.h();
} }
static function render(frames: Array<kha.Framebuffer>) { static function render(frames: Array<kha.Framebuffer>) {

View File

@ -331,18 +331,15 @@ class RenderPath {
}); });
} }
public static function sortMeshesIndex(meshes: Array<MeshObject>) { public static function sortMeshesShader(meshes: Array<MeshObject>) {
meshes.sort(function(a, b): Int { meshes.sort(function(a, b): Int {
#if rp_depth_texture #if rp_depth_texture
var depthDiff = boolToInt(a.depthRead) - boolToInt(b.depthRead); var depthDiff = boolToInt(a.depthRead) - boolToInt(b.depthRead);
if (depthDiff != 0) return depthDiff; if (depthDiff != 0) return depthDiff;
#end #end
if (a.data.sortingIndex != b.data.sortingIndex) { return a.materials[0].name >= b.materials[0].name ? 1 : -1;
return a.data.sortingIndex > b.data.sortingIndex ? 1 : -1; });
}
return a.data.name >= b.data.name ? 1 : -1; });
} }
public function drawMeshes(context: String) { public function drawMeshes(context: String) {
@ -402,7 +399,7 @@ class RenderPath {
#if lnx_batch #if lnx_batch
sortMeshesDistance(Scene.active.meshBatch.nonBatched); sortMeshesDistance(Scene.active.meshBatch.nonBatched);
#else #else
drawOrder == DrawOrder.Index ? sortMeshesIndex(meshes) : sortMeshesDistance(meshes); drawOrder == DrawOrder.Shader ? sortMeshesShader(meshes) : sortMeshesDistance(meshes);
#end #end
meshesSorted = true; meshesSorted = true;
} }
@ -521,44 +518,12 @@ class RenderPath {
return Reflect.field(kha.Shaders, handle + "_comp"); return Reflect.field(kha.Shaders, handle + "_comp");
} }
#if lnx_vr #if (kha_krom && lnx_vr)
public function drawStereo(drawMeshes: Void->Void) { public function drawStereo(drawMeshes: Int->Void) {
var vr = kha.vr.VrInterface.instance; for (eye in 0...2) {
var appw = iron.App.w(); Krom.vrBeginRender(eye);
var apph = iron.App.h(); drawMeshes(eye);
var halfw = Std.int(appw / 2); Krom.vrEndRender(eye);
var g = currentG;
if (vr != null && vr.IsPresenting()) {
// Left eye
Scene.active.camera.V.setFrom(Scene.active.camera.leftV);
Scene.active.camera.P.self = vr.GetProjectionMatrix(0);
g.viewport(0, 0, halfw, apph);
drawMeshes();
// Right eye
begin(g, additionalTargets);
Scene.active.camera.V.setFrom(Scene.active.camera.rightV);
Scene.active.camera.P.self = vr.GetProjectionMatrix(1);
g.viewport(halfw, 0, halfw, apph);
drawMeshes();
}
else { // Simulate
Scene.active.camera.buildProjection(halfw / apph);
// Left eye
g.viewport(0, 0, halfw, apph);
drawMeshes();
// Right eye
begin(g, additionalTargets);
Scene.active.camera.transform.move(Scene.active.camera.right(), 0.032);
Scene.active.camera.buildMatrix();
g.viewport(halfw, 0, halfw, apph);
drawMeshes();
Scene.active.camera.transform.move(Scene.active.camera.right(), -0.032);
Scene.active.camera.buildMatrix();
} }
} }
#end #end
@ -917,6 +882,6 @@ class CachedShaderContext {
@:enum abstract DrawOrder(Int) from Int { @:enum abstract DrawOrder(Int) from Int {
var Distance = 0; // Early-z var Distance = 0; // Early-z
var Index = 1; // Less state changes var Shader = 1; // Less state changes
// var Mix = 2; // Distance buckets sorted by shader // var Mix = 2; // Distance buckets sorted by shader
} }

View File

@ -887,12 +887,8 @@ class Scene {
var ptype: String = t.props[i * 3 + 1]; var ptype: String = t.props[i * 3 + 1];
var pval: Dynamic = t.props[i * 3 + 2]; var pval: Dynamic = t.props[i * 3 + 2];
if (StringTools.endsWith(ptype, "Object") && pval != "" && pval != null) { if (StringTools.endsWith(ptype, "Object") && pval != "") {
Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval)); Reflect.setProperty(traitInst, pname, Scene.active.getChild(pval));
} else if (ptype == "TSceneFormat" && pval != "") {
Data.getSceneRaw(pval, function (r: TSceneFormat) {
Reflect.setProperty(traitInst, pname, r);
});
} }
else { else {
switch (ptype) { switch (ptype) {

View File

@ -9,7 +9,6 @@ import iron.data.SceneFormat;
class MeshData { class MeshData {
public var name: String; public var name: String;
public var sortingIndex: Int;
public var raw: TMeshData; public var raw: TMeshData;
public var format: TSceneFormat; public var format: TSceneFormat;
public var geom: Geometry; public var geom: Geometry;
@ -24,7 +23,6 @@ class MeshData {
public function new(raw: TMeshData, done: MeshData->Void) { public function new(raw: TMeshData, done: MeshData->Void) {
this.raw = raw; this.raw = raw;
this.name = raw.name; this.name = raw.name;
this.sortingIndex = raw.sorting_index;
if (raw.scale_pos != null) scalePos = raw.scale_pos; if (raw.scale_pos != null) scalePos = raw.scale_pos;
if (raw.scale_tex != null) scaleTex = raw.scale_tex; if (raw.scale_tex != null) scaleTex = raw.scale_tex;

View File

@ -49,7 +49,6 @@ typedef TMeshData = {
@:structInit class TMeshData { @:structInit class TMeshData {
#end #end
public var name: String; public var name: String;
public var sorting_index: Int;
public var vertex_arrays: Array<TVertexArray>; public var vertex_arrays: Array<TVertexArray>;
public var index_arrays: Array<TIndexArray>; public var index_arrays: Array<TIndexArray>;
@:optional public var dynamic_usage: Null<Bool>; @:optional public var dynamic_usage: Null<Bool>;
@ -223,7 +222,6 @@ typedef TShaderData = {
@:structInit class TShaderData { @:structInit class TShaderData {
#end #end
public var name: String; public var name: String;
public var next_pass: String;
public var contexts: Array<TShaderContext>; public var contexts: Array<TShaderContext>;
} }
@ -395,7 +393,6 @@ typedef TParticleData = {
public var name: String; public var name: String;
public var type: Int; // 0 - Emitter, Hair public var type: Int; // 0 - Emitter, Hair
public var auto_start: Bool; public var auto_start: Bool;
public var dynamic_emitter: Bool;
public var is_unique: Bool; public var is_unique: Bool;
public var loop: Bool; public var loop: Bool;
public var count: Int; public var count: Int;

View File

@ -22,7 +22,6 @@ using StringTools;
class ShaderData { class ShaderData {
public var name: String; public var name: String;
public var nextPass: String;
public var raw: TShaderData; public var raw: TShaderData;
public var contexts: Array<ShaderContext> = []; public var contexts: Array<ShaderContext> = [];
@ -34,7 +33,6 @@ class ShaderData {
public function new(raw: TShaderData, done: ShaderData->Void, overrideContext: TShaderOverride = null) { public function new(raw: TShaderData, done: ShaderData->Void, overrideContext: TShaderOverride = null) {
this.raw = raw; this.raw = raw;
this.name = raw.name; this.name = raw.name;
this.nextPass = raw.next_pass;
for (c in raw.contexts) contexts.push(null); for (c in raw.contexts) contexts.push(null);
var contextsLoaded = 0; var contextsLoaded = 0;

View File

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

View File

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

View File

@ -302,10 +302,6 @@ class MeshObject extends Object {
// Render mesh // Render mesh
var ldata = lod.data; var ldata = lod.data;
// Next pass rendering first (inverse order)
renderNextPass(g, context, bindParams, lod);
for (i in 0...ldata.geom.indexBuffers.length) { for (i in 0...ldata.geom.indexBuffers.length) {
var mi = ldata.geom.materialIndices[i]; var mi = ldata.geom.materialIndices[i];
@ -409,85 +405,4 @@ class MeshObject extends Object {
} }
} }
} }
function renderNextPass(g: Graphics, context: String, bindParams: Array<String>, lod: MeshObject) {
var ldata = lod.data;
for (i in 0...ldata.geom.indexBuffers.length) {
var mi = ldata.geom.materialIndices[i];
if (mi >= materials.length) continue;
var currentMaterial: MaterialData = materials[mi];
if (currentMaterial == null || currentMaterial.shader == null) continue;
var nextPassName: String = currentMaterial.shader.nextPass;
if (nextPassName == null || nextPassName == "") continue;
var nextMaterial: MaterialData = null;
for (mat in materials) {
// First try exact match
if (mat.name == nextPassName) {
nextMaterial = mat;
break;
}
// If no exact match, try to match base name for linked materials
if (mat.name.indexOf("_") > 0 && mat.name.substr(mat.name.length - 6) == ".blend") {
var baseName = mat.name.substring(0, mat.name.indexOf("_"));
if (baseName == nextPassName) {
nextMaterial = mat;
break;
}
}
}
if (nextMaterial == null) continue;
var nextMaterialContext: MaterialContext = null;
var nextShaderContext: ShaderContext = null;
for (j in 0...nextMaterial.raw.contexts.length) {
if (nextMaterial.raw.contexts[j].name.substr(0, context.length) == context) {
nextMaterialContext = nextMaterial.contexts[j];
nextShaderContext = nextMaterial.shader.getContext(context);
break;
}
}
if (nextShaderContext == null) continue;
if (skipContext(context, nextMaterial)) continue;
var elems = nextShaderContext.raw.vertex_elements;
// Uniforms
if (nextShaderContext.pipeState != lastPipeline) {
g.setPipeline(nextShaderContext.pipeState);
lastPipeline = nextShaderContext.pipeState;
}
Uniforms.setContextConstants(g, nextShaderContext, bindParams);
Uniforms.setObjectConstants(g, nextShaderContext, this);
Uniforms.setMaterialConstants(g, nextShaderContext, nextMaterialContext);
// VB / IB
#if lnx_deinterleaved
g.setVertexBuffers(ldata.geom.get(elems));
#else
if (ldata.geom.instancedVB != null) {
g.setVertexBuffers([ldata.geom.get(elems), ldata.geom.instancedVB]);
}
else {
g.setVertexBuffer(ldata.geom.get(elems));
}
#end
g.setIndexBuffer(ldata.geom.indexBuffers[i]);
// Draw next pass for this specific geometry section
if (ldata.geom.instanced) {
g.drawIndexedVerticesInstanced(ldata.geom.instanceCount, ldata.geom.start, ldata.geom.count);
}
else {
g.drawIndexedVertices(ldata.geom.start, ldata.geom.count);
}
}
}
} }

View File

@ -24,9 +24,6 @@ class ObjectAnimation extends Animation {
public var transformMap: Map<String, FastFloat>; public var transformMap: Map<String, FastFloat>;
var defaultSampler: ActionSampler = null;
static inline var DEFAULT_SAMPLER_ID = "__object_default_action__";
public static var trackNames: Array<String> = [ "xloc", "yloc", "zloc", public static var trackNames: Array<String> = [ "xloc", "yloc", "zloc",
"xrot", "yrot", "zrot", "xrot", "yrot", "zrot",
"qwrot", "qxrot", "qyrot", "qzrot", "qwrot", "qxrot", "qyrot", "qzrot",
@ -42,6 +39,7 @@ class ObjectAnimation extends Animation {
isSkinned = false; isSkinned = false;
super(); super();
} }
function getAction(action: String): TObj { function getAction(action: String): TObj {
for (a in oactions) if (a != null && a.objects[0].name == action) return a.objects[0]; for (a in oactions) if (a != null && a.objects[0].name == action) return a.objects[0];
return null; return null;
@ -49,29 +47,10 @@ class ObjectAnimation extends Animation {
override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) { override public function play(action = "", onComplete: Void->Void = null, blendTime = 0.0, speed = 1.0, loop = true) {
super.play(action, onComplete, blendTime, speed, loop); super.play(action, onComplete, blendTime, speed, loop);
if (this.action == "" && oactions != null && oactions[0] != null){ if (this.action == "" && oactions[0] != null) this.action = oactions[0].objects[0].name;
this.action = oactions[0].objects[0].name;
}
oaction = getAction(this.action); oaction = getAction(this.action);
if (oaction != null) { if (oaction != null) {
isSampled = oaction.sampled != null && oaction.sampled; isSampled = oaction.sampled != null && oaction.sampled;
if (defaultSampler != null) {
deRegisterAction(DEFAULT_SAMPLER_ID);
}
var callbacks = onComplete != null ? [onComplete] : null;
defaultSampler = new ActionSampler(this.action, speed, loop, false, callbacks);
registerAction(DEFAULT_SAMPLER_ID, defaultSampler);
if (paused) defaultSampler.paused = true;
updateAnimation = function(map: Map<String, FastFloat>) {
sampleAction(defaultSampler, map);
};
}
else {
if (defaultSampler != null) {
deRegisterAction(DEFAULT_SAMPLER_ID);
defaultSampler = null;
}
updateAnimation = null;
} }
} }
@ -82,13 +61,12 @@ class ObjectAnimation extends Animation {
Animation.beginProfile(); Animation.beginProfile();
#end #end
if (transformMap == null) transformMap = new Map(); if(transformMap == null) transformMap = new Map();
transformMap = initTransformMap(); transformMap = initTransformMap();
super.update(delta); super.update(delta);
if (defaultSampler != null) defaultSampler.paused = paused;
if (paused) return; if (paused) return;
if (updateAnimation == null) return; if(updateAnimation == null) return;
if (!isSkinned) updateObjectAnimation(); if (!isSkinned) updateObjectAnimation();
#if lnx_debug #if lnx_debug

View File

@ -8,8 +8,6 @@ import kha.arrays.Float32Array;
import iron.data.Data; import iron.data.Data;
import iron.data.ParticleData; import iron.data.ParticleData;
import iron.data.SceneFormat; import iron.data.SceneFormat;
import iron.data.Geometry;
import iron.data.MeshData;
import iron.system.Time; import iron.system.Time;
import iron.math.Mat4; import iron.math.Mat4;
import iron.math.Quat; import iron.math.Quat;
@ -19,7 +17,6 @@ import iron.math.Vec4;
class ParticleSystem { class ParticleSystem {
public var data: ParticleData; public var data: ParticleData;
public var speed = 1.0; public var speed = 1.0;
public var dynamicEmitter: Bool = true;
var currentSpeed = 0.0; var currentSpeed = 0.0;
var particles: Array<Particle>; var particles: Array<Particle>;
var ready: Bool; var ready: Bool;
@ -55,12 +52,6 @@ class ParticleSystem {
var random = 0.0; var random = 0.0;
var tmpV4 = new Vec4();
var instancedData: Float32Array = null;
var lastSpawnedCount: Int = 0;
var hasUniqueGeom: Bool = false;
public function new(sceneName: String, pref: TParticleReference) { public function new(sceneName: String, pref: TParticleReference) {
seed = pref.seed; seed = pref.seed;
currentSpeed = speed; currentSpeed = speed;
@ -71,12 +62,6 @@ class ParticleSystem {
Data.getParticle(sceneName, pref.particle, function(b: ParticleData) { Data.getParticle(sceneName, pref.particle, function(b: ParticleData) {
data = b; data = b;
r = data.raw; r = data.raw;
var dyn: Null<Bool> = r.dynamic_emitter;
var dynValue: Bool = true;
if (dyn != null) {
dynValue = dyn;
}
dynamicEmitter = dynValue;
if (Scene.active.raw.gravity != null) { if (Scene.active.raw.gravity != null) {
gx = Scene.active.raw.gravity[0] * r.weight_gravity; gx = Scene.active.raw.gravity[0] * r.weight_gravity;
gy = Scene.active.raw.gravity[1] * r.weight_gravity; gy = Scene.active.raw.gravity[1] * r.weight_gravity;
@ -113,8 +98,6 @@ class ParticleSystem {
lap = 0; lap = 0;
lapTime = 0; lapTime = 0;
speed = currentSpeed; speed = currentSpeed;
lastSpawnedCount = 0;
instancedData = null;
} }
public function pause() { public function pause() {
@ -147,13 +130,8 @@ class ParticleSystem {
// Copy owner world transform but discard scale // Copy owner world transform but discard scale
owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl); owner.transform.world.decompose(ownerLoc, ownerRot, ownerScl);
if (dynamicEmitter) {
object.transform.loc.x = 0; object.transform.loc.y = 0; object.transform.loc.z = 0;
object.transform.rot = new Quat();
} else {
object.transform.loc = ownerLoc; object.transform.loc = ownerLoc;
object.transform.rot = ownerRot; object.transform.rot = ownerRot;
}
// Set particle size per particle system // Set particle size per particle system
object.transform.scale = new Vec4(r.particle_size, r.particle_size, r.particle_size, 1); object.transform.scale = new Vec4(r.particle_size, r.particle_size, r.particle_size, 1);
@ -181,17 +159,12 @@ class ParticleSystem {
end(); end();
} }
if (lap > prevLap && r.loop) {
lastSpawnedCount = 0;
}
updateGpu(object, owner); updateGpu(object, owner);
} }
public function getData(): Mat4 { public function getData(): Mat4 {
var hair = r.type == 1; var hair = r.type == 1;
// Store loop flag in the sign: positive -> loop, negative -> no loop m._00 = animtime;
m._00 = r.loop ? animtime : -animtime;
m._01 = hair ? 1 / particles.length : spawnRate; m._01 = hair ? 1 / particles.length : spawnRate;
m._02 = hair ? 1 : lifetime; m._02 = hair ? 1 : lifetime;
m._03 = particles.length; m._03 = particles.length;
@ -214,26 +187,17 @@ class ParticleSystem {
return r.size_random; return r.size_random;
} }
public inline function getRandom(): FastFloat { public function getRandom(): FastFloat {
return random; return random;
} }
public inline function getSize(): FastFloat { public function getSize(): FastFloat {
return r.particle_size; return r.particle_size;
} }
function updateGpu(object: MeshObject, owner: MeshObject) { function updateGpu(object: MeshObject, owner: MeshObject) {
if (dynamicEmitter) {
if (!hasUniqueGeom) ensureUniqueGeom(object);
var needSetup = instancedData == null || object.data.geom.instancedVB == null;
if (needSetup) setupGeomGpuDynamic(object, owner);
updateSpawnedInstances(object, owner);
}
else {
if (!hasUniqueGeom) ensureUniqueGeom(object);
if (!object.data.geom.instanced) setupGeomGpu(object, owner); if (!object.data.geom.instanced) setupGeomGpu(object, owner);
} // GPU particles transform is attached to owner object
// GPU particles transform is attached to owner object in static mode
} }
function setupGeomGpu(object: MeshObject, owner: MeshObject) { function setupGeomGpu(object: MeshObject, owner: MeshObject) {
@ -294,128 +258,12 @@ class ParticleSystem {
object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage); object.data.geom.setupInstanced(instancedData, 1, Usage.StaticUsage);
} }
// allocate instanced VB once for this object function fhash(n: Int): Float {
function setupGeomGpuDynamic(object: MeshObject, owner: MeshObject) {
if (instancedData == null) instancedData = new Float32Array(particles.length * 3);
lastSpawnedCount = 0;
// Create instanced VB once if missing (seed with our instancedData)
if (object.data.geom.instancedVB == null) {
object.data.geom.setupInstanced(instancedData, 1, Usage.DynamicUsage);
}
}
function ensureUniqueGeom(object: MeshObject) {
if (hasUniqueGeom) return;
var newData: MeshData = null;
new MeshData(object.data.raw, function(dat: MeshData) {
dat.scalePos = object.data.scalePos;
dat.scaleTex = object.data.scaleTex;
dat.format = object.data.format;
newData = dat;
});
if (newData != null) object.setData(newData);
hasUniqueGeom = true;
}
function updateSpawnedInstances(object: MeshObject, owner: MeshObject) {
if (instancedData == null) return;
var targetCount = count;
if (targetCount > particles.length) targetCount = particles.length;
if (targetCount <= lastSpawnedCount) return;
var normFactor = 1 / 32767;
var scalePosOwner = owner.data.scalePos;
var scalePosParticle = object.data.scalePos;
var particleSize = r.particle_size;
var base = 1.0 / (particleSize * scalePosParticle);
switch (r.emit_from) {
case 0: // Vert
var pa = owner.data.geom.positions;
var osx = owner.transform.scale.x;
var osy = owner.transform.scale.y;
var osz = owner.transform.scale.z;
var pCount = Std.int(pa.values.length / pa.size);
for (idx in lastSpawnedCount...targetCount) {
var j = Std.int(fhash(idx) * pCount);
var lx = pa.values[j * pa.size ] * normFactor * scalePosOwner * osx;
var ly = pa.values[j * pa.size + 1] * normFactor * scalePosOwner * osy;
var lz = pa.values[j * pa.size + 2] * normFactor * scalePosOwner * osz;
tmpV4.x = lx; tmpV4.y = ly; tmpV4.z = lz; tmpV4.w = 1;
tmpV4.applyQuat(ownerRot);
var o = idx * 3;
instancedData.set(o , (tmpV4.x + ownerLoc.x) * base);
instancedData.set(o + 1, (tmpV4.y + ownerLoc.y) * base);
instancedData.set(o + 2, (tmpV4.z + ownerLoc.z) * base);
}
case 1: // Face
var positions = owner.data.geom.positions.values;
var osx1 = owner.transform.scale.x;
var osy1 = owner.transform.scale.y;
var osz1 = owner.transform.scale.z;
for (idx in lastSpawnedCount...targetCount) {
var ia = owner.data.geom.indices[Std.random(owner.data.geom.indices.length)];
var faceIndex = Std.random(Std.int(ia.length / 3));
var i0 = ia[faceIndex * 3 + 0];
var i1 = ia[faceIndex * 3 + 1];
var i2 = ia[faceIndex * 3 + 2];
var v0x = positions[i0 * 4 ], v0y = positions[i0 * 4 + 1], v0z = positions[i0 * 4 + 2];
var v1x = positions[i1 * 4 ], v1y = positions[i1 * 4 + 1], v1z = positions[i1 * 4 + 2];
var v2x = positions[i2 * 4 ], v2y = positions[i2 * 4 + 1], v2z = positions[i2 * 4 + 2];
var rx = Math.random(); var ry = Math.random(); if (rx + ry > 1) { rx = 1 - rx; ry = 1 - ry; }
var pxs = v0x + rx * (v1x - v0x) + ry * (v2x - v0x);
var pys = v0y + rx * (v1y - v0y) + ry * (v2y - v0y);
var pzs = v0z + rx * (v1z - v0z) + ry * (v2z - v0z);
var px = pxs * normFactor * scalePosOwner * osx1;
var py = pys * normFactor * scalePosOwner * osy1;
var pz = pzs * normFactor * scalePosOwner * osz1;
tmpV4.x = px; tmpV4.y = py; tmpV4.z = pz; tmpV4.w = 1;
tmpV4.applyQuat(ownerRot);
var o1 = idx * 3;
instancedData.set(o1 , (tmpV4.x + ownerLoc.x) * base);
instancedData.set(o1 + 1, (tmpV4.y + ownerLoc.y) * base);
instancedData.set(o1 + 2, (tmpV4.z + ownerLoc.z) * base);
}
case 2: // Volume
var dim = object.transform.dim;
for (idx in lastSpawnedCount...targetCount) {
tmpV4.x = (Math.random() * 2.0 - 1.0) * (dim.x * 0.5);
tmpV4.y = (Math.random() * 2.0 - 1.0) * (dim.y * 0.5);
tmpV4.z = (Math.random() * 2.0 - 1.0) * (dim.z * 0.5);
tmpV4.w = 1;
tmpV4.applyQuat(ownerRot);
var o2 = idx * 3;
instancedData.set(o2 , (tmpV4.x + ownerLoc.x) * base);
instancedData.set(o2 + 1, (tmpV4.y + ownerLoc.y) * base);
instancedData.set(o2 + 2, (tmpV4.z + ownerLoc.z) * base);
}
}
// Upload full active range [0..targetCount) to this object's instanced VB
var geom = object.data.geom;
if (geom.instancedVB == null) {
geom.setupInstanced(instancedData, 1, Usage.DynamicUsage);
}
var vb = geom.instancedVB.lock();
var totalFloats = targetCount * 3; // xyz per instance
var i = 0;
while (i < totalFloats) {
vb.setFloat32(i * 4, instancedData[i]);
i++;
}
geom.instancedVB.unlock();
geom.instanceCount = targetCount;
lastSpawnedCount = targetCount;
}
inline function fhash(n: Int): Float {
var s = n + 1.0; var s = n + 1.0;
s *= 9301.0 % s; s *= 9301.0 % s;
s = (s * 9301.0 + 49297.0) % 233280.0; s = (s * 9301.0 + 49297.0) % 233280.0;
return s / 233280.0; return s / 233280.0;
} }
public function remove() {} public function remove() {}

View File

@ -181,11 +181,15 @@ class Uniforms {
// Multiple voxel volumes, always set params // Multiple voxel volumes, always set params
g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D g.setImageTexture(context.textureUnits[j], rt.image); // image2D/3D
if (rt.raw.name.startsWith("voxels_")) { if (rt.raw.name.startsWith("voxels_")) {
g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter); g.setTextureParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.LinearMipFilter);
}
else if (rt.raw.name.startsWith("voxelsSDF"))
{
g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.PointFilter, TextureFilter.PointFilter, MipMapFilter.NoMipFilter);
} }
else if (rt.raw.name.startsWith("voxels")) else if (rt.raw.name.startsWith("voxels"))
{ {
g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.NoMipFilter); g.setTexture3DParameters(context.textureUnits[j], TextureAddressing.Clamp, TextureAddressing.Clamp, TextureAddressing.Clamp, TextureFilter.LinearFilter, TextureFilter.LinearFilter, MipMapFilter.PointMipFilter);
} }
else else
{ {

View File

@ -14,7 +14,7 @@ class Time {
return 1 / frequency; return 1 / frequency;
} }
static var _fixedStep: Null<Float> = 1/60; static var _fixedStep: Null<Float>;
public static var fixedStep(get, never): Float; public static var fixedStep(get, never): Float;
static function get_fixedStep(): Float { static function get_fixedStep(): Float {
return _fixedStep; return _fixedStep;
@ -39,11 +39,11 @@ class Time {
} }
public static inline function time(): Float { public static inline function time(): Float {
return kha.Scheduler.time() * scale; return kha.Scheduler.time();
} }
public static inline function realTime(): Float { public static inline function realTime(): Float {
return kha.Scheduler.realTime() * scale; return kha.Scheduler.realTime();
} }
public static function update() { public static function update() {

View File

@ -94,34 +94,34 @@ class Tween {
// Way too much Reflect trickery.. // Way too much Reflect trickery..
var ps = Reflect.fields(a.props); var ps = Reflect.fields(a.props);
for (j in 0...ps.length) { for (i in 0...ps.length) {
var p = ps[j]; var p = ps[i];
var k = a._time / a.duration; var k = a._time / a.duration;
if (k > 1) k = 1; if (k > 1) k = 1;
if (a._comps[j] == 1) { if (a._comps[i] == 1) {
var fromVal: Float = a._x[j]; var fromVal: Float = a._x[i];
var toVal: Float = Reflect.getProperty(a.props, p); var toVal: Float = Reflect.getProperty(a.props, p);
var val: Float = fromVal + (toVal - fromVal) * eases[a.ease](k); var val: Float = fromVal + (toVal - fromVal) * eases[a.ease](k);
Reflect.setProperty(a.target, p, val); Reflect.setProperty(a.target, p, val);
} }
else { // _comps[j] == 4 else { // _comps[i] == 4
var obj = Reflect.getProperty(a.props, p); var obj = Reflect.getProperty(a.props, p);
var toX: Float = Reflect.getProperty(obj, "x"); var toX: Float = Reflect.getProperty(obj, "x");
var toY: Float = Reflect.getProperty(obj, "y"); var toY: Float = Reflect.getProperty(obj, "y");
var toZ: Float = Reflect.getProperty(obj, "z"); var toZ: Float = Reflect.getProperty(obj, "z");
var toW: Float = Reflect.getProperty(obj, "w"); var toW: Float = Reflect.getProperty(obj, "w");
if (a._normalize[j]) { if (a._normalize[i]) {
var qdot = (a._x[j] * toX) + (a._y[j] * toY) + (a._z[j] * toZ) + (a._w[j] * toW); var qdot = (a._x[i] * toX) + (a._y[i] * toY) + (a._z[i] * toZ) + (a._w[i] * toW);
if (qdot < 0.0) { if (qdot < 0.0) {
toX = -toX; toY = -toY; toZ = -toZ; toW = -toW; toX = -toX; toY = -toY; toZ = -toZ; toW = -toW;
} }
} }
var x: Float = a._x[j] + (toX - a._x[j]) * eases[a.ease](k); var x: Float = a._x[i] + (toX - a._x[i]) * eases[a.ease](k);
var y: Float = a._y[j] + (toY - a._y[j]) * eases[a.ease](k); var y: Float = a._y[i] + (toY - a._y[i]) * eases[a.ease](k);
var z: Float = a._z[j] + (toZ - a._z[j]) * eases[a.ease](k); var z: Float = a._z[i] + (toZ - a._z[i]) * eases[a.ease](k);
var w: Float = a._w[j] + (toW - a._w[j]) * eases[a.ease](k); var w: Float = a._w[i] + (toW - a._w[i]) * eases[a.ease](k);
if (a._normalize[j]) { if (a._normalize[i]) {
var l = Math.sqrt(x * x + y * y + z * z + w * w); var l = Math.sqrt(x * x + y * y + z * z + w * w);
if (l > 0.0) { if (l > 0.0) {
l = 1.0 / l; l = 1.0 / l;

View File

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

View File

@ -1,48 +0,0 @@
package leenkx.logicnode;
import iron.object.Object;
#if lnx_physics
import leenkx.trait.physics.PhysicsCache;
import leenkx.trait.physics.RigidBody;
#end
class AnyContactNode extends LogicNode {
public var property0: String;
var lastContact = false;
public function new(tree: LogicTree) {
super(tree);
tree.notifyOnUpdate(update);
}
function update() {
var object1: Object = inputs[0].get();
if (object1 == null) object1 = tree.object;
if (object1 == null) return;
var contact = false;
#if lnx_physics
var rb1 = PhysicsCache.getCachedRigidBody(object1);
if (rb1 != null) {
var rbs = PhysicsCache.getCachedContacts(rb1);
contact = (rbs != null && rbs.length > 0);
}
#end
var shouldTrigger = false;
switch (property0) {
case "begin":
shouldTrigger = contact && !lastContact;
case "overlap":
shouldTrigger = contact;
case "end":
shouldTrigger = !contact && lastContact;
}
lastContact = contact;
if (shouldTrigger) runOutput(0);
}
}

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ package leenkx.logicnode;
import iron.object.Object; import iron.object.Object;
import iron.math.Vec4; import iron.math.Vec4;
class GetWorldOrientationNode extends LogicNode { class GetWorldNode extends LogicNode {
public var property0: String; public var property0: String;

View File

@ -1,10 +1,7 @@
package leenkx.logicnode; package leenkx.logicnode;
import iron.object.Object;
#if lnx_physics import iron.object.Object;
import leenkx.trait.physics.PhysicsCache;
import leenkx.trait.physics.RigidBody; import leenkx.trait.physics.RigidBody;
#end
class HasContactNode extends LogicNode { class HasContactNode extends LogicNode {
@ -18,15 +15,12 @@ class HasContactNode extends LogicNode {
if (object1 == null || object2 == null) return false; if (object1 == null || object2 == null) return false;
#if lnx_physics #if lnx_physics
var rb1 = PhysicsCache.getCachedRigidBody(object1); var physics = leenkx.trait.physics.PhysicsWorld.active;
var rb2 = PhysicsCache.getCachedRigidBody(object2); var rb2 = object2.getTrait(RigidBody);
var rbs = physics.getContacts(object1.getTrait(RigidBody));
if (rb1 != null && rb2 != null) { if (rbs != null) for (rb in rbs) if (rb == rb2) return true;
var rbs = PhysicsCache.getCachedContacts(rb1); #end
return PhysicsCache.hasContactWith(rbs, rb2);
}
#end
return false; return false;
} }
} }

View File

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

View File

@ -1,11 +1,7 @@
package leenkx.logicnode; package leenkx.logicnode;
import iron.object.Object; import iron.object.Object;
#if lnx_physics
import leenkx.trait.physics.PhysicsCache;
import leenkx.trait.physics.RigidBody; import leenkx.trait.physics.RigidBody;
#end
class OnContactNode extends LogicNode { class OnContactNode extends LogicNode {
@ -27,15 +23,22 @@ class OnContactNode extends LogicNode {
var contact = false; var contact = false;
#if lnx_physics #if lnx_physics
var rb1 = PhysicsCache.getCachedRigidBody(object1); var physics = leenkx.trait.physics.PhysicsWorld.active;
var rb2 = PhysicsCache.getCachedRigidBody(object2); var rb1 = object1.getTrait(RigidBody);
if (rb1 != null) {
if (rb1 != null && rb2 != null) { var rbs = physics.getContacts(rb1);
var rbs = PhysicsCache.getCachedContacts(rb1); if (rbs != null) {
contact = PhysicsCache.hasContactWith(rbs, rb2); var rb2 = object2.getTrait(RigidBody);
for (rb in rbs) {
if (rb == rb2) {
contact = true;
break;
} }
#end }
}
}
#end
var b = false; var b = false;
switch (property0) { switch (property0) {

View File

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

View File

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

View File

@ -1,41 +0,0 @@
package leenkx.logicnode;
class ProbabilisticIndexNode extends LogicNode {
public function new(tree: LogicTree) {
super(tree);
}
override function get(from: Int): Dynamic {
var probs: Array<Float> = [];
var probs_acum: Array<Float> = [];
var sum: Float = 0;
for (p in 0...inputs.length){
probs.push(inputs[p].get());
sum += probs[p];
}
if (sum > 1){
for (p in 0...probs.length)
probs[p] /= sum;
}
sum = 0;
for (p in 0...probs.length){
sum += probs[p];
probs_acum.push(sum);
}
var rand: Float = Math.random();
for (p in 0...probs.length){
if (p == 0 && rand <= probs_acum[p]) return p;
else if (0 < p && p < probs.length-1 && probs_acum[p-1] < rand && rand <= probs_acum[p]) return p;
else if (p == probs.length-1 && probs_acum[p-1] < rand) return p;
}
return null;
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -55,9 +55,9 @@ class SetParticleDataNode extends LogicNode {
@:privateAccess psys.aligny = vel.y; @:privateAccess psys.aligny = vel.y;
@:privateAccess psys.alignz = vel.z; @:privateAccess psys.alignz = vel.z;
case 'Velocity Random': case 'Velocity Random':
@:privateAccess psys.r.factor_random = inputs[3].get(); psys.r.factor_random = inputs[3].get();
case 'Weight Gravity': case 'Weight Gravity':
@:privateAccess psys.r.weight_gravity = inputs[3].get(); psys.r.weight_gravity = inputs[3].get();
if (iron.Scene.active.raw.gravity != null) { if (iron.Scene.active.raw.gravity != null) {
@:privateAccess psys.gx = iron.Scene.active.raw.gravity[0] * @:privateAccess psys.r.weight_gravity; @: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.gy = iron.Scene.active.raw.gravity[1] * @:privateAccess psys.r.weight_gravity;

View File

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

View File

@ -1,7 +1,5 @@
package leenkx.logicnode; package leenkx.logicnode;
import iron.data.SceneFormat;
class SetWorldNode extends LogicNode { class SetWorldNode extends LogicNode {
public function new(tree: LogicTree) { public function new(tree: LogicTree) {
@ -12,6 +10,25 @@ class SetWorldNode extends LogicNode {
var world: String = inputs[1].get(); var world: String = inputs[1].get();
if (world != null){ 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; iron.Scene.active.raw.world_ref = world;
var npath = leenkx.renderpath.RenderPathCreator.get(); var npath = leenkx.renderpath.RenderPathCreator.get();
npath.loadShader("shader_datas/World_" + world + "/World_" + world); npath.loadShader("shader_datas/World_" + world + "/World_" + world);

View File

@ -34,10 +34,10 @@ class Inc {
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
static var voxel_td1:kha.compute.TextureUnit; static var voxel_td1:kha.compute.TextureUnit;
static var voxel_te1:kha.compute.TextureUnit; static var voxel_te1:kha.compute.TextureUnit;
static var voxel_tf1:kha.compute.TextureUnit; static var voxel_cc1:kha.compute.ConstantLocation;
#else #else
#if lnx_voxelgi_shadows #if lnx_voxelgi_shadows
static var voxel_tf1:kha.compute.TextureUnit; static var voxel_te1:kha.compute.TextureUnit;
#end #end
#end #end
#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") #if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI")
@ -53,12 +53,28 @@ class Inc {
static var voxel_tb3:kha.compute.TextureUnit; static var voxel_tb3:kha.compute.TextureUnit;
static var voxel_tc3:kha.compute.TextureUnit; static var voxel_tc3:kha.compute.TextureUnit;
static var voxel_td3:kha.compute.TextureUnit; static var voxel_td3:kha.compute.TextureUnit;
static var voxel_te3:kha.compute.TextureUnit;
static var voxel_tf3:kha.compute.TextureUnit;
#if lnx_brdf
static var voxel_tg3:kha.compute.TextureUnit;
#end
#if lnx_radiance
static var voxel_th3:kha.compute.TextureUnit;
#end
static var voxel_ca3:kha.compute.ConstantLocation; static var voxel_ca3:kha.compute.ConstantLocation;
static var voxel_cb3:kha.compute.ConstantLocation; static var voxel_cb3:kha.compute.ConstantLocation;
static var voxel_cc3:kha.compute.ConstantLocation; static var voxel_cc3:kha.compute.ConstantLocation;
static var voxel_cd3:kha.compute.ConstantLocation; static var voxel_cd3:kha.compute.ConstantLocation;
static var voxel_ce3:kha.compute.ConstantLocation; static var voxel_ce3:kha.compute.ConstantLocation;
#if lnx_irradiance
static var voxel_cf3:kha.compute.ConstantLocation; static var voxel_cf3:kha.compute.ConstantLocation;
#end
#if lnx_radiance
static var voxel_cg3:kha.compute.ConstantLocation;
#end
#if lnx_envcol
static var voxel_ch3:kha.compute.ConstantLocation;
#end
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
static var voxel_sh4:kha.compute.Shader = null; static var voxel_sh4:kha.compute.Shader = null;
static var voxel_ta4:kha.compute.TextureUnit; static var voxel_ta4:kha.compute.TextureUnit;
@ -71,33 +87,6 @@ class Inc {
static var voxel_cb4:kha.compute.ConstantLocation; static var voxel_cb4:kha.compute.ConstantLocation;
static var voxel_cc4:kha.compute.ConstantLocation; static var voxel_cc4:kha.compute.ConstantLocation;
static var voxel_cd4:kha.compute.ConstantLocation; static var voxel_cd4:kha.compute.ConstantLocation;
static var voxel_ce4:kha.compute.ConstantLocation;
static var voxel_cf4:kha.compute.ConstantLocation;
#end
#if (rp_voxels == "Voxel GI")
static var voxel_sh5:kha.compute.Shader = null;
static var voxel_ta5:kha.compute.TextureUnit;
static var voxel_ca5:kha.compute.ConstantLocation;
static var voxel_cb5:kha.compute.ConstantLocation;
static var voxel_cc5:kha.compute.ConstantLocation;
static var voxel_cd5:kha.compute.ConstantLocation;
static var voxel_ce5:kha.compute.ConstantLocation;
static var voxel_cf5:kha.compute.ConstantLocation;
static var voxel_cg5:kha.compute.ConstantLocation;
#if rp_shadowmap
static var voxel_tb5:kha.compute.TextureUnit;
static var voxel_tc5:kha.compute.TextureUnit;
static var voxel_td5:kha.compute.TextureUnit;
static var voxel_ch5:kha.compute.ConstantLocation;
static var voxel_ci5:kha.compute.ConstantLocation;
static var voxel_cj5:kha.compute.ConstantLocation;
static var voxel_ck5:kha.compute.ConstantLocation;
static var voxel_cl5:kha.compute.ConstantLocation;
static var voxel_cm5:kha.compute.ConstantLocation;
#if lnx_shadowmap_atlas
static var m2 = iron.math.Mat4.identity();
#end
#end
#end #end
#end //rp_voxels #end //rp_voxels
@ -163,9 +152,11 @@ class Inc {
for (atlas in ShadowMapAtlas.shadowMapAtlases) { for (atlas in ShadowMapAtlas.shadowMapAtlases) {
path.bindTarget(atlas.target, atlas.target); path.bindTarget(atlas.target, atlas.target);
} }
#if rp_shadowmap_transparent
for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) {
path.bindTarget(atlas.target, atlas.target); path.bindTarget(atlas.target, atlas.target);
} }
#end
} }
static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String { static function getShadowMapAtlas(atlas:ShadowMapAtlas, transparent: Bool):String {
@ -206,24 +197,30 @@ class Inc {
for (atlas in ShadowMapAtlas.shadowMapAtlases) { for (atlas in ShadowMapAtlas.shadowMapAtlases) {
atlas.rejectedLights = []; atlas.rejectedLights = [];
} }
#if rp_shadowmap_transparent
for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) {
atlas.rejectedLights = []; atlas.rejectedLights = [];
} }
#end #end
#end
for (light in iron.Scene.active.lights) { for (light in iron.Scene.active.lights) {
if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0 if (!light.lightInAtlas && !light.culledLight && light.visible && light.shadowMapScale > 0.0
&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) {
ShadowMapAtlas.addLight(light, false); ShadowMapAtlas.addLight(light, false);
} }
#if rp_shadowmap_transparent
if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0 if (!light.lightInAtlasTransparent && !light.culledLight && light.visible && light.shadowMapScale > 0.0
&& light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) { && light.data.raw.strength > 0.0 && light.data.raw.cast_shadow) {
ShadowMapAtlas.addLight(light, true); ShadowMapAtlas.addLight(light, true);
} }
#end
} }
// update point light data before rendering // update point light data before rendering
updatePointLightAtlasData(true);
updatePointLightAtlasData(false); updatePointLightAtlasData(false);
#if rp_shadowmap_transparent
updatePointLightAtlasData(true);
#end
for (atlas in ShadowMapAtlas.shadowMapAtlases) { for (atlas in ShadowMapAtlas.shadowMapAtlases) {
var tilesToRemove = []; var tilesToRemove = [];
@ -301,6 +298,7 @@ class Inc {
path.endStream(); path.endStream();
} }
#if rp_shadowmap_transparent
for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) { for (atlas in ShadowMapAtlas.shadowMapAtlasesTransparent) {
var tilesToRemove = []; var tilesToRemove = [];
#if lnx_shadowmap_atlas_lod #if lnx_shadowmap_atlas_lod
@ -395,10 +393,8 @@ class Inc {
tile.freeTile(); tile.freeTile();
} }
} }
#if lnx_debug
endShadowsLogicProfile();
#end #end
#end // rp_shadowmap #end
} }
#else #else
public static function bindShadowMap() { public static function bindShadowMap() {
@ -501,6 +497,7 @@ class Inc {
else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++;
} }
#if rp_shadowmap_transparent
pointIndex = 0; pointIndex = 0;
spotIndex = 0; spotIndex = 0;
for (l in iron.Scene.active.lights) { for (l in iron.Scene.active.lights) {
@ -522,6 +519,7 @@ class Inc {
if (l.data.raw.type == "point") pointIndex++; if (l.data.raw.type == "point") pointIndex++;
else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++; else if (l.data.raw.type == "spot" || l.data.raw.type == "area") spotIndex++;
} }
#end
#end // rp_shadowmap #end // rp_shadowmap
} }
#end #end
@ -589,7 +587,7 @@ class Inc {
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = getDisplayp(); t.displayp = getDisplayp();
t.format = "R32"; t.format = "R16";
t.scale = getSuperSampling(); t.scale = getSuperSampling();
t.depth_buffer = "main"; t.depth_buffer = "main";
path.createRenderTarget(t); path.createRenderTarget(t);
@ -615,10 +613,14 @@ class Inc {
#end #end
#if (rp_voxels != "Off") #if (rp_voxels != "Off")
{
path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsOut", "voxels");
#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
path.bindTarget("voxelsSDF", "voxelsSDF"); path.bindTarget("voxelsSDF", "voxelsSDF");
} #end
#end
#if rp_ssrs
path.bindTarget("_main", "gbufferD");
#end #end
path.drawMeshes("translucent"); path.drawMeshes("translucent");
@ -679,12 +681,11 @@ class Inc {
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = getDisplayp(); t.displayp = getDisplayp();
//t.scale = Inc.getSuperSampling(); t.format = "RGBA32";
t.format = t.name == "voxels_ao" ? "R8" : "RGBA32";
} }
else { else {
if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") { if (t.name == "voxelsSDF" || t.name == "voxelsSDFtmp") {
t.format = "R16"; t.format = "R8";
t.width = res; t.width = res;
t.height = res * Main.voxelgiClipmapCount; t.height = res * Main.voxelgiClipmapCount;
t.depth = res; t.depth = res;
@ -693,16 +694,16 @@ class Inc {
#if (rp_voxels == "Voxel AO") #if (rp_voxels == "Voxel AO")
{ {
if (t.name == "voxelsOut" || t.name == "voxelsOutB") { if (t.name == "voxelsOut" || t.name == "voxelsOutB") {
t.format = "R16"; t.format = "R8";
t.width = res * (6 + 16); t.width = res * (6 + 16);
t.height = res * Main.voxelgiClipmapCount; t.height = res * Main.voxelgiClipmapCount;
t.depth = res; t.depth = res;
} }
else { else {
t.format = "R32"; t.format = "R32UI";
t.width = res * 6; t.width = res * 6;
t.height = res; t.height = res;
t.depth = res; t.depth = res * 2;
} }
} }
#else #else
@ -713,17 +714,11 @@ class Inc {
t.height = res * Main.voxelgiClipmapCount; t.height = res * Main.voxelgiClipmapCount;
t.depth = res; t.depth = res;
} }
else if (t.name == "voxelsLight") {
t.format = "R32";
t.width = res;
t.height = res;
t.depth = res * 3;
}
else { else {
t.format = "R32"; t.format = "R32UI";
t.width = res * 6; t.width = res * 6;
t.height = res; t.height = res;
t.depth = res * 12; t.depth = res * 16;
} }
} }
#end #end
@ -835,14 +830,15 @@ class Inc {
voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps"); voxel_ca1 = voxel_sh1.getConstantLocation("clipmaps");
voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel"); voxel_cb1 = voxel_sh1.getConstantLocation("clipmapLevel");
voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength");
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler"); voxel_td1 = voxel_sh1.getTextureUnit("voxelsSampler");
voxel_te1 = voxel_sh1.getTextureUnit("voxelsLight"); voxel_te1 = voxel_sh1.getTextureUnit("SDF");
voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); voxel_cc1 = voxel_sh1.getConstantLocation("envmapStrength");
#else #else
#if lnx_voxelgi_shadows #if lnx_voxelgi_shadows
voxel_tf1 = voxel_sh1.getTextureUnit("SDF"); voxel_te1 = voxel_sh1.getTextureUnit("SDF");
#end #end
#end #end
} }
@ -873,12 +869,28 @@ class Inc {
#else #else
voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse"); voxel_td3 = voxel_sh3.getTextureUnit("voxels_diffuse");
#end #end
voxel_te3 = voxel_sh3.getTextureUnit("gbuffer1");
voxel_tf3 = voxel_sh3.getTextureUnit("gbuffer2");
#if lnx_brdf
voxel_tg3 = voxel_sh3.getTextureUnit("senvmapBrdf");
#end
#if lnx_radiance
voxel_th3 = voxel_sh3.getTextureUnit("senvmapRadiance");
#end
voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps"); voxel_ca3 = voxel_sh3.getConstantLocation("clipmaps");
voxel_cb3 = voxel_sh3.getConstantLocation("InvVP"); voxel_cb3 = voxel_sh3.getConstantLocation("InvVP");
voxel_cc3 = voxel_sh3.getConstantLocation("cameraProj"); voxel_cc3 = voxel_sh3.getConstantLocation("eye");
voxel_cd3 = voxel_sh3.getConstantLocation("eye"); voxel_cd3 = voxel_sh3.getConstantLocation("postprocess_resolution");
voxel_ce3 = voxel_sh3.getConstantLocation("eyeLook"); voxel_ce3 = voxel_sh3.getConstantLocation("envmapStrength");
voxel_cf3 = voxel_sh3.getConstantLocation("postprocess_resolution"); #if lnx_irradiance
voxel_cf3 = voxel_sh3.getConstantLocation("shirr");
#end
#if lnx_radiance
voxel_cg3 = voxel_sh3.getConstantLocation("envmapNumMipmaps");
#end
#if lnx_envcol
voxel_ch3 = voxel_sh3.getConstantLocation("backgroundCol");
#end
} }
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
if (voxel_sh4 == null) if (voxel_sh4 == null)
@ -892,40 +904,8 @@ class Inc {
voxel_tf4 = voxel_sh4.getTextureUnit("sveloc"); voxel_tf4 = voxel_sh4.getTextureUnit("sveloc");
voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps"); voxel_ca4 = voxel_sh4.getConstantLocation("clipmaps");
voxel_cb4 = voxel_sh4.getConstantLocation("InvVP"); voxel_cb4 = voxel_sh4.getConstantLocation("InvVP");
voxel_cc4 = voxel_sh4.getConstantLocation("cameraProj"); voxel_cc4 = voxel_sh4.getConstantLocation("eye");
voxel_cd4 = voxel_sh4.getConstantLocation("eye"); voxel_cd4 = voxel_sh4.getConstantLocation("postprocess_resolution");
voxel_ce4 = voxel_sh4.getConstantLocation("eyeLook");
voxel_cf4 = voxel_sh4.getConstantLocation("postprocess_resolution");
}
#end
#if (rp_voxels == "Voxel GI")
if (voxel_sh5 == null)
{
voxel_sh5 = path.getComputeShader("voxel_light");
voxel_ta5 = voxel_sh5.getTextureUnit("voxelsLight");
voxel_ca5 = voxel_sh5.getConstantLocation("clipmaps");
voxel_cb5 = voxel_sh5.getConstantLocation("clipmapLevel");
voxel_cc5 = voxel_sh5.getConstantLocation("lightPos");
voxel_cd5 = voxel_sh5.getConstantLocation("lightColor");
voxel_ce5 = voxel_sh5.getConstantLocation("lightType");
voxel_cf5 = voxel_sh5.getConstantLocation("lightDir");
voxel_cg5 = voxel_sh5.getConstantLocation("spotData");
#if rp_shadowmap
voxel_tb5 = voxel_sh5.getTextureUnit("shadowMap");
voxel_tc5 = voxel_sh5.getTextureUnit("shadowMapSpot");
voxel_td5 = voxel_sh5.getTextureUnit("shadowMapPoint");
voxel_ch5 = voxel_sh5.getConstantLocation("lightShadow");
voxel_ci5 = voxel_sh5.getConstantLocation("lightProj");
voxel_cj5 = voxel_sh5.getConstantLocation("LVP");
voxel_ck5 = voxel_sh5.getConstantLocation("shadowsBias");
#if lnx_shadowmap_atlas
voxel_cl5 = voxel_sh5.getConstantLocation("index");
voxel_cm5 = voxel_sh5.getConstantLocation("pointLightDataArray");
#end
#end
} }
#end #end
} }
@ -976,11 +956,11 @@ class Inc {
kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_tc1, rts.get("voxelsOut").image, kha.compute.Access.Write);
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image); kha.compute.Compute.setSampledTexture(voxel_td1, rts.get("voxelsOutB").image);
kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsLight").image, kha.compute.Access.Read); kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write);
kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength);
#else #else
#if lnx_voxelgi_shadows #if lnx_voxelgi_shadows
kha.compute.Compute.setTexture(voxel_tf1, rts.get("voxelsSDF").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_te1, rts.get("voxelsSDF").image, kha.compute.Access.Write);
#end #end
#end #end
@ -1002,6 +982,8 @@ class Inc {
kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel); kha.compute.Compute.setInt(voxel_cb1, iron.RenderPath.clipmapLevel);
kha.compute.Compute.setFloat(voxel_cc1, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength);
kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8)); kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8));
} }
@ -1054,6 +1036,7 @@ class Inc {
} }
} }
#end #end
#if (rp_voxels == "Voxel AO") #if (rp_voxels == "Voxel AO")
public static function resolveAO() { public static function resolveAO() {
var rts = path.renderTargets; var rts = path.renderTargets;
@ -1066,13 +1049,20 @@ class Inc {
kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image);
kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image);
#if lnx_deferred
kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image);
#else
kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image);
#end
kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_ao").image, kha.compute.Access.Write);
kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image);
#if rp_gbuffer2
kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image);
#end
#if lnx_brdf
kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png"));
#end
#if lnx_radiance
kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance);
#end
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
for (i in 0...Main.voxelgiClipmapCount) { for (i in 0...Main.voxelgiClipmapCount) {
fa[i * 10] = clipmaps[i].voxelSize; fa[i * 10] = clipmaps[i].voxelSize;
@ -1099,18 +1089,7 @@ class Inc {
kha.compute.Compute.setMatrix(voxel_cb3, m.self); kha.compute.Compute.setMatrix(voxel_cb3, m.self);
var near = camera.data.raw.near_plane; kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
var far = camera.data.raw.far_plane;
var v = new iron.math.Vec2();
v.x = far / (far - near);
v.y = (-far * near) / (far - near);
kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y);
kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
var eyeLook = camera.lookWorld().normalize();
kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z);
var width = iron.App.w(); var width = iron.App.w();
var height = iron.App.h(); var height = iron.App.h();
@ -1125,7 +1104,32 @@ class Inc {
width = Std.int(dp * Inc.getSuperSampling()); width = Std.int(dp * Inc.getSuperSampling());
} }
} }
kha.compute.Compute.setFloat2(voxel_cf3, width, height); kha.compute.Compute.setFloat2(voxel_cd3, width, height);
kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength);
#if lnx_irradiance
var irradiance = iron.Scene.active.world == null ?
iron.data.WorldData.getEmptyIrradiance() :
iron.Scene.active.world.probe.irradiance;
kha.compute.Compute.setFloats(voxel_cf3, irradiance);
#end
#if lnx_radiance
kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1);
#end
#if lnx_envcol
var x: kha.FastFloat = 0.0;
var y: kha.FastFloat = 0.0;
var z: kha.FastFloat = 0.0;
if (camera.data.raw.clear_color != null) {
x = camera.data.raw.clear_color[0];
y = camera.data.raw.clear_color[1];
z = camera.data.raw.clear_color[2];
}
kha.compute.Compute.setFloat3(voxel_ch3, x, y, z);
#end
kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1);
} }
@ -1141,12 +1145,18 @@ class Inc {
kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_ta3, rts.get("voxelsOut").image);
kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image); kha.compute.Compute.setSampledTexture(voxel_tb3, rts.get("half").image);
#if lnx_deferred
kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image); kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("gbuffer0").image);
#else
kha.compute.Compute.setSampledTexture(voxel_tc3, rts.get("lbuffer1").image);
#end
kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_td3, rts.get("voxels_diffuse").image, kha.compute.Access.Write);
kha.compute.Compute.setSampledTexture(voxel_te3, rts.get("gbuffer1").image);
#if rp_gbuffer2
kha.compute.Compute.setSampledTexture(voxel_tf3, rts.get("gbuffer2").image);
#end
#if lnx_brdf
kha.compute.Compute.setSampledTexture(voxel_tg3, iron.Scene.active.embedded.get("brdf.png"));
#end
#if lnx_radiance
kha.compute.Compute.setSampledTexture(voxel_th3, iron.Scene.active.world.probe.radiance);
#end
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
for (i in 0...Main.voxelgiClipmapCount) { for (i in 0...Main.voxelgiClipmapCount) {
@ -1174,18 +1184,7 @@ class Inc {
kha.compute.Compute.setMatrix(voxel_cb3, m.self); kha.compute.Compute.setMatrix(voxel_cb3, m.self);
var near = camera.data.raw.near_plane; kha.compute.Compute.setFloat3(voxel_cc3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
var far = camera.data.raw.far_plane;
var v = new iron.math.Vec2();
v.x = far / (far - near);
v.y = (-far * near) / (far - near);
kha.compute.Compute.setFloat2(voxel_cc3, v.x, v.y);
kha.compute.Compute.setFloat3(voxel_cd3, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
var eyeLook = camera.lookWorld().normalize();
kha.compute.Compute.setFloat3(voxel_ce3, eyeLook.x, eyeLook.y, eyeLook.z);
var width = iron.App.w(); var width = iron.App.w();
var height = iron.App.h(); var height = iron.App.h();
@ -1200,7 +1199,32 @@ class Inc {
width = Std.int(dp * Inc.getSuperSampling()); width = Std.int(dp * Inc.getSuperSampling());
} }
} }
kha.compute.Compute.setFloat2(voxel_cf3, width, height); kha.compute.Compute.setFloat2(voxel_cd3, width, height);
kha.compute.Compute.setFloat(voxel_ce3, iron.Scene.active.world == null ? 0.0 : iron.Scene.active.world.probe.raw.strength);
#if lnx_irradiance
var irradiance = iron.Scene.active.world == null ?
iron.data.WorldData.getEmptyIrradiance() :
iron.Scene.active.world.probe.irradiance;
kha.compute.Compute.setFloats(voxel_cf3, irradiance);
#end
#if lnx_radiance
kha.compute.Compute.setFloat(voxel_cg3, iron.Scene.active.world != null ? iron.Scene.active.world.probe.raw.radiance_mipmaps + 1 - 2 : 1);
#end
#if lnx_envcol
var x: kha.FastFloat = 0.0;
var y: kha.FastFloat = 0.0;
var z: kha.FastFloat = 0.0;
if (camera.data.raw.clear_color != null) {
x = camera.data.raw.clear_color[0];
y = camera.data.raw.clear_color[1];
z = camera.data.raw.clear_color[2];
}
kha.compute.Compute.setFloat3(voxel_ch3, x, y, z);
#end
kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1);
} }
@ -1216,15 +1240,12 @@ class Inc {
kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image); kha.compute.Compute.setSampledTexture(voxel_ta4, rts.get("voxelsOut").image);
kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image); kha.compute.Compute.setSampledTexture(voxel_tb4, rts.get("half").image);
#if lnx_deferred
kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image); kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("gbuffer0").image);
#else
kha.compute.Compute.setSampledTexture(voxel_tc4, rts.get("lbuffer1").image);
#end
kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image); kha.compute.Compute.setSampledTexture(voxel_td4, rts.get("voxelsSDF").image);
kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write); kha.compute.Compute.setTexture(voxel_te4, rts.get("voxels_specular").image, kha.compute.Access.Write);
#if rp_gbuffer2
//kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image); kha.compute.Compute.setSampledTexture(voxel_tf4, rts.get("gbuffer2").image);
#end
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10); var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
for (i in 0...Main.voxelgiClipmapCount) { for (i in 0...Main.voxelgiClipmapCount) {
@ -1252,18 +1273,7 @@ class Inc {
kha.compute.Compute.setMatrix(voxel_cb4, m.self); kha.compute.Compute.setMatrix(voxel_cb4, m.self);
var near = camera.data.raw.near_plane; kha.compute.Compute.setFloat3(voxel_cc4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
var far = camera.data.raw.far_plane;
var v = new iron.math.Vec2();
v.x = far / (far - near);
v.y = (-far * near) / (far - near);
kha.compute.Compute.setFloat2(voxel_cc4, v.x, v.y);
kha.compute.Compute.setFloat3(voxel_cd4, camera.transform.worldx(), camera.transform.worldy(), camera.transform.worldz());
var eyeLook = camera.lookWorld().normalize();
kha.compute.Compute.setFloat3(voxel_ce4, eyeLook.x, eyeLook.y, eyeLook.z);
var width = iron.App.w(); var width = iron.App.w();
var height = iron.App.h(); var height = iron.App.h();
@ -1278,146 +1288,10 @@ class Inc {
width = Std.int(dp * Inc.getSuperSampling()); width = Std.int(dp * Inc.getSuperSampling());
} }
} }
kha.compute.Compute.setFloat2(voxel_cf4, width, height); kha.compute.Compute.setFloat2(voxel_cd4, width, height);
kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1); kha.compute.Compute.compute(Std.int((width + 7) / 8), Std.int((height + 7) / 8), 1);
} }
public static function computeVoxelsLight() {
var rts = path.renderTargets;
var res = iron.RenderPath.getVoxelRes();
var camera = iron.Scene.active.camera;
var clipmaps = iron.RenderPath.clipmaps;
var clipmap = clipmaps[iron.RenderPath.clipmapLevel];
var lights = iron.Scene.active.lights;
pointIndex = spotIndex = 0;
for (i in 0...lights.length) {
var l = lights[i];
if (!l.visible) continue;
path.light = l;
kha.compute.Compute.setShader(voxel_sh5);
kha.compute.Compute.setTexture(voxel_ta5, rts.get("voxelsLight").image, kha.compute.Access.Write);
var fa:Float32Array = new Float32Array(Main.voxelgiClipmapCount * 10);
for (i in 0...Main.voxelgiClipmapCount) {
fa[i * 10] = clipmaps[i].voxelSize;
fa[i * 10 + 1] = clipmaps[i].extents.x;
fa[i * 10 + 2] = clipmaps[i].extents.y;
fa[i * 10 + 3] = clipmaps[i].extents.z;
fa[i * 10 + 4] = clipmaps[i].center.x;
fa[i * 10 + 5] = clipmaps[i].center.y;
fa[i * 10 + 6] = clipmaps[i].center.z;
fa[i * 10 + 7] = clipmaps[i].offset_prev.x;
fa[i * 10 + 8] = clipmaps[i].offset_prev.y;
fa[i * 10 + 9] = clipmaps[i].offset_prev.z;
}
kha.compute.Compute.setFloats(voxel_ca5, fa);
kha.compute.Compute.setInt(voxel_cb5, iron.RenderPath.clipmapLevel);
#if rp_shadowmap
if (l.data.raw.type == "sun") {
#if lnx_shadowmap_atlas
#if lnx_shadowmap_atlas_single_map
kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlas").image);
#else
kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMapAtlasSun").image);
#end
#else
kha.compute.Compute.setSampledTexture(voxel_tb5, rts.get("shadowMap").image);
#end
kha.compute.Compute.setInt(voxel_ch5, 1); // lightShadow
}
else if (l.data.raw.type == "spot" || l.data.raw.type == "area") {
#if lnx_shadowmap_atlas
#if lnx_shadowmap_atlas_single_map
kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlas").image);
#else
kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapAtlasSpot").image);
#end
#else
kha.compute.Compute.setSampledTexture(voxel_tc5, rts.get("shadowMapSpot[" + spotIndex + "]").image);
spotIndex++;
#end
kha.compute.Compute.setInt(voxel_ch5, 2);
}
else {
#if lnx_shadowmap_atlas
#if lnx_shadowmap_atlas_single_map
kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlas").image);
#else
kha.compute.Compute.setSampledTexture(voxel_td5, rts.get("shadowMapAtlasPoint").image);
kha.compute.Compute.setInt(voxel_cl5, i);
kha.compute.Compute.setFloats(voxel_cm5, iron.object.LightObject.pointLightsData);
#end
#else
kha.compute.Compute.setSampledCubeMap(voxel_td5, rts.get("shadowMapPoint[" + pointIndex + "]").cubeMap);
pointIndex++;
#end
kha.compute.Compute.setInt(voxel_ch5, 3);
}
// lightProj
var near = l.data.raw.near_plane;
var far = l.data.raw.far_plane;
var a:kha.FastFloat = far + near;
var b:kha.FastFloat = far - near;
var f2:kha.FastFloat = 2.0;
var c:kha.FastFloat = f2 * far * near;
var vx:kha.FastFloat = a / b;
var vy:kha.FastFloat = c / b;
kha.compute.Compute.setFloat2(voxel_ci5, vx, vy);
// LVP
m.setFrom(l.VP);
m.multmat(iron.object.Uniforms.biasMat);
#if lnx_shadowmap_atlas
if (l.data.raw.type == "sun")
{
// tile matrix
m.setIdentity();
// scale [0-1] coords to [0-tilescale]
m2._00 = l.tileScale[0];
m2._11 = l.tileScale[0];
// offset coordinate start from [0, 0] to [tile-start-x, tile-start-y]
m2._30 = l.tileOffsetX[0];
m2._31 = l.tileOffsetY[0];
m.multmat(m2);
#if (!kha_opengl)
m2.setIdentity();
m2._11 = -1.0;
m2._31 = 1.0;
m.multmat(m2);
#end
}
#end
kha.compute.Compute.setMatrix(voxel_cj5, m.self);
// shadowsBias
kha.compute.Compute.setFloat(voxel_ck5, l.data.raw.shadows_bias);
#end // rp_shadowmap
// lightPos
kha.compute.Compute.setFloat3(voxel_cc5, l.transform.worldx(), l.transform.worldy(), l.transform.worldz());
// lightCol
var f = l.data.raw.strength;
kha.compute.Compute.setFloat3(voxel_cd5, l.data.raw.color[0] * f, l.data.raw.color[1] * f, l.data.raw.color[2] * f);
// lightType
kha.compute.Compute.setInt(voxel_ce5, iron.data.LightData.typeToInt(l.data.raw.type));
// lightDir
var v = l.look();
kha.compute.Compute.setFloat3(voxel_cf5, v.x, v.y, v.z);
// spotData
if (l.data.raw.type == "spot") {
var vx = l.data.raw.spot_size;
var vy = vx - l.data.raw.spot_blend;
kha.compute.Compute.setFloat2(voxel_cg5, vx, vy);
}
kha.compute.Compute.compute(Std.int(res / 8), Std.int(res / 8), Std.int(res / 8));
}
}
#end // GI #end // GI
#end // Voxels #end // Voxels
} }

View File

@ -15,6 +15,11 @@ class RenderPathDeferred {
static var bloomUpsampler: Upsampler; static var bloomUpsampler: Upsampler;
#end #end
#if (rp_ssgi == "SSGI")
static var ssgitex = "singleb";
static var ssgitexb = "singleb";
#end
public static inline function setTargetMeshes() { public static inline function setTargetMeshes() {
//Always keep the order of render targets the same as defined in compiled.inc //Always keep the order of render targets the same as defined in compiled.inc
path.setTarget("gbuffer0", [ path.setTarget("gbuffer0", [
@ -57,12 +62,11 @@ class RenderPathDeferred {
Inc.initGI("voxels"); Inc.initGI("voxels");
Inc.initGI("voxelsOut"); Inc.initGI("voxelsOut");
Inc.initGI("voxelsOutB"); Inc.initGI("voxelsOutB");
#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDF");
Inc.initGI("voxelsSDFtmp"); Inc.initGI("voxelsSDFtmp");
#end #end
#if (rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
Inc.initGI("voxelsLight");
Inc.initGI("voxels_diffuse"); Inc.initGI("voxels_diffuse");
Inc.initGI("voxels_specular"); Inc.initGI("voxels_specular");
#else #else
@ -195,24 +199,94 @@ class RenderPathDeferred {
path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x"); path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x");
path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y");
} }
#elseif (rp_ssgi == "SSGI")
{
path.loadShader("shader_datas/ssgi_pass/ssgi_pass");
path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_x");
path.loadShader("shader_datas/blur_edge_pass/blur_edge_pass_y");
}
#end #end
#if ((rp_ssgi != "Off") || rp_volumetriclight) #if (rp_ssgi != "Off")
{ {
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "singlea"; t.name = "singlea";
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
#if (rp_ssgi == "SSGI")
t.format = "RGBA32";
#else
t.format = "R8";
#end
t.scale = Inc.getSuperSampling();
#if rp_ssgi_half
t.scale *= 0.5;
#end
path.createRenderTarget(t);
var t = new RenderTargetRaw();
t.name = "singleb";
t.width = 0;
t.height = 0;
t.displayp = Inc.getDisplayp();
#if (rp_ssgi == "SSGI")
t.format = "RGBA32";
#else
t.format = "R8";
#end
t.scale = Inc.getSuperSampling();
#if rp_ssgi_half
t.scale *= 0.5;
#end
path.createRenderTarget(t);
}
#end
#if rp_volumetriclight
{
var t = new RenderTargetRaw();
t.name = "volumetrica";
t.width = 0;
t.height = 0;
t.displayp = Inc.getDisplayp();
t.format = "R8";
t.scale = Inc.getSuperSampling();
#if rp_ssgi_half // Do we keep this ?
t.scale *= 0.5;
#end
path.createRenderTarget(t);
var t = new RenderTargetRaw();
t.name = "volumetricb";
t.width = 0;
t.height = 0;
t.displayp = Inc.getDisplayp();
t.format = "R8"; t.format = "R8";
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
#if rp_ssgi_half #if rp_ssgi_half
t.scale *= 0.5; t.scale *= 0.5;
#end #end
path.createRenderTarget(t); path.createRenderTarget(t);
}
#end
#if rp_volumetriclight
{
var t = new RenderTargetRaw();
t.name = "volumetrica";
t.width = 0;
t.height = 0;
t.displayp = Inc.getDisplayp();
t.format = "R8";
t.scale = Inc.getSuperSampling();
#if rp_ssgi_half // Do we keep this ?
t.scale *= 0.5;
#end
path.createRenderTarget(t);
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "singleb"; t.name = "volumetricb";
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
@ -368,7 +442,7 @@ class RenderPathDeferred {
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
path.createRenderTarget(t); path.createRenderTarget(t);
// holds background depth // holds background color
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "refr"; t.name = "refr";
t.width = 0; t.width = 0;
@ -461,7 +535,7 @@ class RenderPathDeferred {
#if (rp_ssrefr || lnx_voxelgi_refract) #if (rp_ssrefr || lnx_voxelgi_refract)
{ {
path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 path.setTarget("gbuffer_refraction");
path.clearTarget(0xffffff00); path.clearTarget(0xffffff00);
} }
#end #end
@ -517,30 +591,16 @@ class RenderPathDeferred {
path.drawShader("shader_datas/downsample_depth/downsample_depth"); path.drawShader("shader_datas/downsample_depth/downsample_depth");
#end #end
#if ((rp_ssgi == "RTGI") || (rp_ssgi == "RTAO")) #if (rp_shadowmap)
{ // atlasing is exclusive for now
if (leenkx.data.Config.raw.rp_ssgi != false) { #if lnx_shadowmap_atlas
path.setTarget("singlea"); Inc.drawShadowMapAtlas();
#if rp_ssgi_half
path.bindTarget("half", "gbufferD");
#else #else
path.bindTarget("_main", "gbufferD"); Inc.drawShadowMap();
#end
#end #end
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/ssgi_pass/ssgi_pass");
path.setTarget("singleb"); #if (rp_ssgi == "SSAO")
path.bindTarget("singlea", "tex");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x");
path.setTarget("singlea");
path.bindTarget("singleb", "tex");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y");
}
}
#elseif (rp_ssgi == "SSAO")
{ {
if (leenkx.data.Config.raw.rp_ssgi != false) { if (leenkx.data.Config.raw.rp_ssgi != false) {
path.setTarget("singlea"); path.setTarget("singlea");
@ -559,15 +619,43 @@ class RenderPathDeferred {
path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y"); path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y");
} }
} }
#elseif (rp_ssgi == "SSGI")
{
if (leenkx.data.Config.raw.rp_ssgi != false) {
path.setTarget("singlea");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("gbuffer1", "gbuffer1");
#if rp_gbuffer_emission
{
path.bindTarget("gbuffer_emission", "gbufferEmission");
}
#end
#if rp_gbuffer2
path.bindTarget("gbuffer2", "sveloc");
#end
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end #end
#if (rp_shadowmap) path.drawShader("shader_datas/ssgi_pass/ssgi_pass");
// atlasing is exclusive for now path.setTarget("singleb");
#if lnx_shadowmap_atlas path.bindTarget("singlea", "tex");
Inc.drawShadowMapAtlas(); path.bindTarget("gbuffer0", "gbuffer0");
#else path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_x");
Inc.drawShadowMap();
#end path.setTarget("singlea");
path.bindTarget("singleb", "tex");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/blur_edge_pass/blur_edge_pass_y");
}
}
#end #end
// Voxels // Voxels
@ -580,9 +668,6 @@ class RenderPathDeferred {
if (iron.RenderPath.pre_clear == true) if (iron.RenderPath.pre_clear == true)
{ {
#if (rp_voxels == "Voxel GI")
path.clearImage("voxelsLight", 0x00000000);
#end
path.clearImage("voxels", 0x00000000); path.clearImage("voxels", 0x00000000);
path.clearImage("voxelsOut", 0x00000000); path.clearImage("voxelsOut", 0x00000000);
path.clearImage("voxelsOutB", 0x00000000); path.clearImage("voxelsOutB", 0x00000000);
@ -594,26 +679,30 @@ class RenderPathDeferred {
} }
else else
{ {
#if (rp_voxels == "Voxel GI")
path.clearImage("voxelsLight", 0x00000000);
#end
path.clearImage("voxels", 0x00000000); path.clearImage("voxels", 0x00000000);
Inc.computeVoxelsOffsetPrev(); Inc.computeVoxelsOffsetPrev();
} }
path.setTarget(""); path.setTarget("");
path.bindTarget("voxels", "voxels");
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
var res = iron.RenderPath.getVoxelRes(); var res = iron.RenderPath.getVoxelRes();
path.setViewport(res, res); path.setViewport(res, res);
path.bindTarget("voxels", "voxels");
path.drawMeshes("voxel"); path.drawMeshes("voxel");
#if (rp_voxels == "Voxel GI")
Inc.computeVoxelsLight();
#end
Inc.computeVoxelsTemporal(); Inc.computeVoxelsTemporal();
#if (lnx_voxelgi_shadows || rp_voxels == "Voxel GI") #if (rp_voxels == "Voxel GI")
Inc.computeVoxelsSDF(); Inc.computeVoxelsSDF();
#end #end
@ -628,7 +717,6 @@ class RenderPathDeferred {
} }
} }
#end #end
// --- // ---
// Deferred light // Deferred light
// --- // ---
@ -760,15 +848,9 @@ class RenderPathDeferred {
} }
#end #end
#if (rp_translucency && !rp_ssrefr)
{
Inc.drawTranslucency("tex");
}
#end
#if rp_volumetriclight #if rp_volumetriclight
{ {
path.setTarget("singlea"); path.setTarget("volumetrica");
path.bindTarget("_main", "gbufferD"); path.bindTarget("_main", "gbufferD");
#if lnx_shadowmap_atlas #if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas(); Inc.bindShadowMapAtlas();
@ -777,85 +859,16 @@ class RenderPathDeferred {
#end #end
path.drawShader("shader_datas/volumetric_light/volumetric_light"); path.drawShader("shader_datas/volumetric_light/volumetric_light");
path.setTarget("singleb"); path.setTarget("volumetricb");
path.bindTarget("singlea", "tex"); path.bindTarget("volumetrica", "tex");
path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); path.drawShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x");
path.setTarget("tex"); path.setTarget("tex");
path.bindTarget("singleb", "tex"); path.bindTarget("volumetricb", "tex");
path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); path.drawShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y");
} }
#end #end
#if rp_bloom
{
inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler);
}
#end
#if rp_sss
{
#if (!kha_opengl)
path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it
#end
path.setTarget("buf");
path.bindTarget("tex", "tex");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/sss_pass/sss_pass_x");
path.setTarget("tex");
path.bindTarget("buf", "tex");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/sss_pass/sss_pass_y");
#if (!kha_opengl)
path.setDepthFrom("tex", "gbuffer0");
#end
}
#end
#if rp_ssrefr
{
if (leenkx.data.Config.raw.rp_ssrefr != false)
{
//save depth
path.setTarget("gbufferD1");
path.bindTarget("_main", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
//save background color
path.setTarget("refr");
path.bindTarget("tex", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]);
#if (rp_voxels != "Off")
{
path.bindTarget("voxelsOut", "voxels");
path.bindTarget("voxelsSDF", "voxelsSDF");
path.bindTarget("gbuffer2", "sveloc");
}
#end
path.drawMeshes("refraction");
path.setTarget("tex");
path.bindTarget("tex", "tex");
path.bindTarget("refr", "tex1");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbufferD1", "gbufferD1");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("gbuffer_refraction", "gbuffer_refraction");
path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass");
}
}
#end
#if rp_ssr #if rp_ssr
{ {
if (leenkx.data.Config.raw.rp_ssr != false) { if (leenkx.data.Config.raw.rp_ssr != false) {
@ -900,6 +913,88 @@ class RenderPathDeferred {
} }
#end #end
#if rp_sss
{
#if (!kha_opengl)
path.setDepthFrom("tex", "gbuffer1"); // Unbind depth so we can read it
#end
path.setTarget("buf");
path.bindTarget("tex", "tex");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/sss_pass/sss_pass_x");
path.setTarget("tex");
path.bindTarget("buf", "tex");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbuffer0", "gbuffer0");
path.drawShader("shader_datas/sss_pass/sss_pass_y");
#if (!kha_opengl)
path.setDepthFrom("tex", "gbuffer0");
#end
}
#end
#if (rp_translucency && !rp_ssrefr)
{
Inc.drawTranslucency("tex");
}
#end
#if rp_ssrefr
{
if (leenkx.data.Config.raw.rp_ssrefr != false)
{
//save depth
path.setTarget("gbufferD1");
path.bindTarget("_main", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
//save background color
path.setTarget("refr");
path.bindTarget("tex", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
path.setTarget("gbuffer0", ["tex", "gbuffer_refraction"]);
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
#if (rp_voxels != "Off")
path.bindTarget("voxelsOut", "voxels");
#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
path.bindTarget("voxelsSDF", "voxelsSDF");
#end
#end
#if rp_ssrs
path.bindTarget("_main", "gbufferD");
#end
path.drawMeshes("refraction");
path.setTarget("tex");
path.bindTarget("tex", "tex");
path.bindTarget("refr", "tex1");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbufferD1", "gbufferD1");
path.bindTarget("gbuffer0", "gbuffer0");
path.bindTarget("gbuffer_refraction", "gbuffer_refraction");
path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass");
}
}
#end
#if ((rp_motionblur == "Camera") || (rp_motionblur == "Object")) #if ((rp_motionblur == "Camera") || (rp_motionblur == "Object"))
{ {
if (leenkx.data.Config.raw.rp_motionblur != false) { if (leenkx.data.Config.raw.rp_motionblur != false) {
@ -964,6 +1059,12 @@ class RenderPathDeferred {
} }
#end #end
#if rp_bloom
{
inline Inc.drawBloom("tex", bloomDownsampler, bloomUpsampler);
}
#end
#if (rp_supersampling == 4) #if (rp_supersampling == 4)
var framebuffer = "buf"; var framebuffer = "buf";
#else #else

View File

@ -142,16 +142,17 @@ class RenderPathForward {
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
t.format = "R32"; t.format = "DEPTH24";
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
path.createRenderTarget(t); path.createRenderTarget(t);
//holds colors before refractive meshes are drawn
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "refr"; t.name = "refr";
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
t.format = "RGBA64"; t.format = Inc.getHdrFormat();
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
path.createRenderTarget(t); path.createRenderTarget(t);
} }
@ -200,17 +201,10 @@ class RenderPathForward {
Inc.initGI("voxels"); Inc.initGI("voxels");
Inc.initGI("voxelsOut"); Inc.initGI("voxelsOut");
Inc.initGI("voxelsOutB"); Inc.initGI("voxelsOutB");
#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) #if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
Inc.initGI("voxelsSDF"); Inc.initGI("voxelsSDF");
Inc.initGI("voxelsSDFtmp"); Inc.initGI("voxelsSDFtmp");
#end #end
#if (rp_voxels == "Voxel GI")
Inc.initGI("voxelsLight");
Inc.initGI("voxels_diffuse");
Inc.initGI("voxels_specular");
#else
Inc.initGI("voxels_ao");
#end
iron.RenderPath.clipmaps = new Array<Clipmap>(); iron.RenderPath.clipmaps = new Array<Clipmap>();
for (i in 0...Main.voxelgiClipmapCount) { for (i in 0...Main.voxelgiClipmapCount) {
var clipmap = new iron.object.Clipmap(); var clipmap = new iron.object.Clipmap();
@ -257,18 +251,25 @@ class RenderPathForward {
#end #end
#end #end
#if rp_volumetriclight #if (rp_volumetriclight || rp_ssgi != "Off")
{ {
#if (rp_volumetriclight)
path.loadShader("shader_datas/volumetric_light/volumetric_light"); path.loadShader("shader_datas/volumetric_light/volumetric_light");
path.loadShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x"); path.loadShader("shader_datas/blur_bilat_pass/blur_bilat_pass_x");
path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y"); path.loadShader("shader_datas/blur_bilat_blend_pass/blur_bilat_blend_pass_y");
#end
var t = new RenderTargetRaw(); var t = new RenderTargetRaw();
t.name = "singlea"; t.name = "singlea";
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
#if (rp_ssgi == "SSGI")
t.format = "RGBA32";
#else
t.format = "R8"; t.format = "R8";
#end
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
path.createRenderTarget(t); path.createRenderTarget(t);
@ -277,7 +278,11 @@ class RenderPathForward {
t.width = 0; t.width = 0;
t.height = 0; t.height = 0;
t.displayp = Inc.getDisplayp(); t.displayp = Inc.getDisplayp();
#if (rp_ssgi == "SSGI")
t.format = "RGBA32";
#else
t.format = "R8"; t.format = "R8";
#end
t.scale = Inc.getSuperSampling(); t.scale = Inc.getSuperSampling();
path.createRenderTarget(t); path.createRenderTarget(t);
} }
@ -374,9 +379,6 @@ class RenderPathForward {
if (iron.RenderPath.pre_clear == true) if (iron.RenderPath.pre_clear == true)
{ {
#if (rp_voxels == "Voxel GI")
path.clearImage("voxelsLight", 0x00000000);
#end
path.clearImage("voxels", 0x00000000); path.clearImage("voxels", 0x00000000);
path.clearImage("voxelsOut", 0x00000000); path.clearImage("voxelsOut", 0x00000000);
path.clearImage("voxelsOutB", 0x00000000); path.clearImage("voxelsOutB", 0x00000000);
@ -388,9 +390,6 @@ class RenderPathForward {
} }
else else
{ {
#if (rp_voxels == "Voxel GI")
path.clearImage("voxelsLight", 0x00000000);
#end
path.clearImage("voxels", 0x00000000); path.clearImage("voxels", 0x00000000);
Inc.computeVoxelsOffsetPrev(); Inc.computeVoxelsOffsetPrev();
} }
@ -400,27 +399,12 @@ class RenderPathForward {
path.setViewport(res, res); path.setViewport(res, res);
path.bindTarget("voxels", "voxels"); path.bindTarget("voxels", "voxels");
path.drawMeshes("voxel");
#if (rp_voxels == "Voxel GI")
Inc.computeVoxelsLight();
#end
Inc.computeVoxelsTemporal(); Inc.computeVoxelsTemporal();
#if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI")) #if (lnx_voxelgi_shadows || (rp_voxels == "Voxel GI"))
Inc.computeVoxelsSDF(); Inc.computeVoxelsSDF();
#end #end
if (iron.RenderPath.res_pre_clear == true)
{
iron.RenderPath.res_pre_clear = false;
#if (rp_voxels == "Voxel GI")
path.clearImage("voxels_diffuse", 0x00000000);
path.clearImage("voxels_specular", 0x00000000);
#else
path.clearImage("voxels_ao", 0x00000000);
#end
}
} }
#end #end
@ -439,7 +423,7 @@ class RenderPathForward {
#if (rp_ssrefr || lnx_voxelgi_refract) #if (rp_ssrefr || lnx_voxelgi_refract)
{ {
path.setTarget("gbuffer_refraction"); // Only clear gbuffer0 path.setTarget("gbuffer_refraction"); // Only clear gbuffer0
path.clearTarget(0xff000000); path.clearTarget(0xffffff00);
} }
#end #end
@ -449,13 +433,6 @@ class RenderPathForward {
} }
#end #end
#if rp_ssrefr
{
path.setTarget("gbuffer_refraction");
path.clearTarget(0xffffff00);
}
#end
RenderPathCreator.setTargetMeshes(); RenderPathCreator.setTargetMeshes();
#if rp_shadowmap #if rp_shadowmap
@ -472,19 +449,12 @@ class RenderPathForward {
#if (rp_voxels != "Off") #if (rp_voxels != "Off")
if (leenkx.data.Config.raw.rp_gi != false) if (leenkx.data.Config.raw.rp_gi != false)
{ {
#if (rp_voxels == "Voxel AO") #if (rp_voxels != "Off")
Inc.resolveAO();
path.bindTarget("voxels_ao", "voxels_ao");
#else
Inc.resolveDiffuse();
Inc.resolveSpecular();
path.bindTarget("voxels_diffuse", "voxels_diffuse");
path.bindTarget("voxels_specular", "voxels_specular");
#end
#if lnx_voxelgi_shadows
path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsOut", "voxels");
#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
path.bindTarget("voxelsSDF", "voxelsSDF"); path.bindTarget("voxelsSDF", "voxelsSDF");
#end #end
#end
} }
#end #end
@ -522,14 +492,31 @@ class RenderPathForward {
path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]); path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]);
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
#if (rp_voxels != "Off") #if (rp_voxels != "Off")
path.bindTarget("voxelsOut", "voxels"); path.bindTarget("voxelsOut", "voxels");
#if (rp_voxels == "Voxel GI" || lnx_voxelgi_shadows)
path.bindTarget("voxelsSDF", "voxelsSDF"); path.bindTarget("voxelsSDF", "voxelsSDF");
#end #end
#end
#if rp_ssrs
path.bindTarget("_main", "gbufferD");
#end
path.drawMeshes("refraction"); path.drawMeshes("refraction");
path.setTarget("lbuffer0"); path.setTarget("lbuffer0");
path.bindTarget("lbuffer0", "tex"); path.bindTarget("lbuffer0", "tex");
path.bindTarget("refr", "tex1"); path.bindTarget("refr", "tex1");
path.bindTarget("_main", "gbufferD"); path.bindTarget("_main", "gbufferD");
@ -577,6 +564,50 @@ class RenderPathForward {
} }
#end #end
#if rp_ssrefr
{
if (leenkx.data.Config.raw.rp_ssrefr != false)
{
path.setTarget("gbufferD1");
path.bindTarget("_main", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
path.setTarget("refr");
path.bindTarget("lbuffer0", "tex");
path.drawShader("shader_datas/copy_pass/copy_pass");
path.setTarget("lbuffer0", ["lbuffer1", "gbuffer_refraction"]);
#if rp_shadowmap
{
#if lnx_shadowmap_atlas
Inc.bindShadowMapAtlas();
#else
Inc.bindShadowMap();
#end
}
#end
#if (rp_voxels != "Off")
path.bindTarget("voxelsOut", "voxels");
path.bindTarget("voxelsSDF", "voxelsSDF");
#end
path.drawMeshes("refraction");
path.setTarget("lbuffer0");
path.bindTarget("lbuffer0", "tex");
path.bindTarget("refr", "tex1");
path.bindTarget("_main", "gbufferD");
path.bindTarget("gbufferD1", "gbufferD1");
path.bindTarget("lbuffer1", "gbuffer0");
path.bindTarget("gbuffer_refraction", "gbuffer_refraction");
path.drawShader("shader_datas/ssrefr_pass/ssrefr_pass");
}
}
#end
#if rp_bloom #if rp_bloom
{ {
inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler); inline Inc.drawBloom("lbuffer0", bloomDownsampler, bloomUpsampler);
@ -641,19 +672,17 @@ class RenderPathForward {
var framebuffer = ""; var framebuffer = "";
#end #end
RenderPathCreator.finalTarget = path.currentTarget; #if ((rp_antialiasing == "Off") || (rp_antialiasing == "FXAA"))
var target = "";
#if ((rp_antialiasing == "Off") || (rp_antialiasing == "FXAA") || (!rp_render_to_texture))
{ {
target = framebuffer; RenderPathCreator.finalTarget = path.currentTarget;
path.setTarget(framebuffer);
} }
#else #else
{ {
target = "buf"; path.setTarget("buf");
RenderPathCreator.finalTarget = path.currentTarget;
} }
#end #end
path.setTarget(target);
#if rp_compositordepth #if rp_compositordepth
{ {
@ -673,15 +702,6 @@ class RenderPathForward {
} }
#end #end
#if rp_overlays
{
path.setTarget(target);
path.clearTarget(null, 1.0);
path.drawMeshes("overlay");
}
#end
#if ((rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA")) #if ((rp_antialiasing == "SMAA") || (rp_antialiasing == "TAA"))
{ {
path.setTarget("bufa"); path.setTarget("bufa");
@ -712,6 +732,12 @@ class RenderPathForward {
} }
#end #end
#if rp_overlays
{
path.clearTarget(null, 1.0);
path.drawMeshes("overlay");
}
#end
} }
public static function setupDepthTexture() { public static function setupDepthTexture() {

View File

@ -3,35 +3,33 @@ package leenkx.system;
import haxe.Constraints.Function; import haxe.Constraints.Function;
class Signal { class Signal {
var callbacks: Array<Function> = []; var callbacks:Array<Function> = [];
public function new() { public function new() {
} }
public function connect(callback: Function) { public function connect(callback:Function) {
if (!callbacks.contains(callback)) callbacks.push(callback); if (!callbacks.contains(callback)) callbacks.push(callback);
} }
public function disconnect(callback: Function) { public function disconnect(callback:Function) {
if (callbacks.contains(callback)) callbacks.remove(callback); if (callbacks.contains(callback)) callbacks.remove(callback);
} }
public function emit(...args: Any) { public function emit(...args:Any) {
for (callback in callbacks.copy()) { for (callback in callbacks) Reflect.callMethod(this, callback, args);
if (callbacks.contains(callback)) Reflect.callMethod(null, callback, args);
}
} }
public function getConnections(): Array<Function> { public function getConnections():Array<Function> {
return callbacks; return callbacks;
} }
public function isConnected(callBack: Function):Bool { public function isConnected(callBack:Function):Bool {
return callbacks.contains(callBack); return callbacks.contains(callBack);
} }
public function isNull(): Bool { public function isNull():Bool {
return callbacks.length == 0; return callbacks.length == 0;
} }
} }

View File

@ -41,7 +41,11 @@ class Starter {
try { try {
#end #end
kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) { kha.System.start({title: Main.projectName, width: c.window_w, height: c.window_h, window: {
#if lnx_render_viewport
visible: false,
#end
mode: windowMode, windowFeatures: windowFeatures}, framebuffer: {samplesPerPixel: c.window_msaa, verticalSync: c.window_vsync}}, function(window: kha.Window) {
iron.App.init(function() { iron.App.init(function() {
#if lnx_loadscreen #if lnx_loadscreen
@ -57,7 +61,7 @@ class Starter {
iron.Scene.getRenderPath = getRenderPath; iron.Scene.getRenderPath = getRenderPath;
#end #end
#if lnx_draworder_shader #if lnx_draworder_shader
iron.RenderPath.active.drawOrder = iron.RenderPath.DrawOrder.Index; iron.RenderPath.active.drawOrder = iron.RenderPath.DrawOrder.Shader;
#end // else Distance #end // else Distance
}); });
}); });

View File

@ -1,243 +1,87 @@
package leenkx.trait; package leenkx.trait;
import iron.Trait;
import iron.math.Vec4; import iron.math.Vec4;
import iron.system.Input; import iron.system.Input;
import iron.object.Object; import iron.object.Object;
import iron.object.CameraObject; import iron.object.CameraObject;
import leenkx.trait.physics.PhysicsWorld; import leenkx.trait.physics.PhysicsWorld;
import leenkx.trait.physics.RigidBody; import leenkx.trait.internal.CameraController;
import kha.FastFloat;
class FirstPersonController extends Trait { class FirstPersonController extends CameraController {
#if (!lnx_physics) #if (!lnx_physics)
public function new() { super(); } public function new() { super(); }
#else #else
@prop public var rotationSpeed:Float = 0.15; var head: Object;
@prop public var maxPitch:Float = 2.2; static inline var rotationSpeed = 2.0;
@prop public var minPitch:Float = 0.5;
@prop public var enableJump:Bool = true;
@prop public var jumpForce:Float = 22.0;
@prop public var moveSpeed:Float = 500.0;
@prop public var forwardKey:String = "w";
@prop public var backwardKey:String = "s";
@prop public var leftKey:String = "a";
@prop public var rightKey:String = "d";
@prop public var jumpKey:String = "space";
@prop public var allowAirJump:Bool = false;
@prop public var canRun:Bool = true;
@prop public var runKey:String = "shift";
@prop public var runSpeed:Float = 1000.0;
// Sistema de estamina
@prop public var stamina:Bool = false;
@prop public var staminaBase:Float = 75.0;
@prop public var staRecoverPerSec:Float = 5.0;
@prop public var staDecreasePerSec:Float = 5.0;
@prop public var staRecoverTime:Float = 2.0;
@prop public var staDecreasePerJump:Float = 5.0;
@prop public var enableFatigue:Bool = false;
@prop public var fatigueSpeed:Float = 0.5; // the reduction of movement when fatigue is activated...
@prop public var fatigueThreshold:Float = 30.0; // Tiempo corriendo sin parar para la activacion // Time running non-stop for activation...
@prop public var fatRecoveryThreshold:Float = 7.5; // Tiempo sin correr/saltar para salir de fatiga // Time without running/jumping to get rid of fatigue...
// Var Privadas
var head:CameraObject;
var pitch:Float = 0.0;
var body:RigidBody;
var moveForward:Bool = false;
var moveBackward:Bool = false;
var moveLeft:Bool = false;
var moveRight:Bool = false;
var isRunning:Bool = false;
var canJump:Bool = true;
var staminaValue:Float = 0.0;
var timeSinceStop:Float = 0.0;
var fatigueTimer:Float = 0.0;
var fatigueCooldown:Float = 0.0;
var isFatigueActive:Bool = false;
public function new() { public function new() {
super(); super();
iron.Scene.active.notifyOnInit(init); iron.Scene.active.notifyOnInit(init);
} }
function init() { function init() {
body = object.getTrait(RigidBody);
head = object.getChildOfType(CameraObject); head = object.getChildOfType(CameraObject);
PhysicsWorld.active.notifyOnPreUpdate(preUpdate); PhysicsWorld.active.notifyOnPreUpdate(preUpdate);
notifyOnUpdate(update); notifyOnUpdate(update);
notifyOnRemove(removed); notifyOnRemove(removed);
staminaValue = staminaBase; }
var xVec = Vec4.xAxis();
var zVec = Vec4.zAxis();
function preUpdate() {
if (Input.occupied || !body.ready) return;
var mouse = Input.getMouse();
var kb = Input.getKeyboard();
if (mouse.started() && !mouse.locked) mouse.lock();
else if (kb.started("escape") && mouse.locked) mouse.unlock();
if (mouse.locked || mouse.down()) {
head.transform.rotate(xVec, -mouse.movementY / 250 * rotationSpeed);
transform.rotate(zVec, -mouse.movementX / 250 * rotationSpeed);
body.syncTransform();
}
} }
function removed() { function removed() {
PhysicsWorld.active.removePreUpdate(preUpdate); PhysicsWorld.active.removePreUpdate(preUpdate);
} }
var zVec = Vec4.zAxis(); var dir = new Vec4();
function preUpdate() {
if (Input.occupied || body == null) return;
var mouse = Input.getMouse();
var kb = Input.getKeyboard();
if (mouse.started() && !mouse.locked)
mouse.lock();
else if (kb.started("escape") && mouse.locked)
mouse.unlock();
if (mouse.locked || mouse.down()) {
var deltaTime:Float = iron.system.Time.delta;
object.transform.rotate(zVec, -mouse.movementX * rotationSpeed * deltaTime);
var deltaPitch:Float = -(mouse.movementY * rotationSpeed * deltaTime);
pitch += deltaPitch;
pitch = Math.max(minPitch, Math.min(maxPitch, pitch));
head.transform.setRotation(pitch, 0.0, 0.0);
body.syncTransform();
}
}
var dir:Vec4 = new Vec4();
function isFatigued():Bool {
return enableFatigue && isFatigueActive;
}
function update() { function update() {
if (body == null) return; if (!body.ready) return;
var deltaTime:Float = iron.system.Time.delta;
var kb = Input.getKeyboard();
moveForward = kb.down(forwardKey); if (jump) {
moveBackward = kb.down(backwardKey); body.applyImpulse(new Vec4(0, 0, 16));
moveLeft = kb.down(leftKey); jump = false;
moveRight = kb.down(rightKey);
var isMoving = moveForward || moveBackward || moveLeft || moveRight;
var isGrounded:Bool = false;
#if lnx_physics
var vel = body.getLinearVelocity();
if (Math.abs(vel.z) < 0.1) {
isGrounded = true;
}
#end
// Dejo establecido el salto para tener en cuenta la (enableFatigue) si es que es false/true....
if (isGrounded && !isFatigued()) {
canJump = true;
}
// Saltar con estamina
if (enableJump && kb.started(jumpKey) && canJump) {
var jumpPower = jumpForce;
// Disminuir el salto al 50% si la (stamina) esta por debajo o en el 20%.
if (stamina) {
if (staminaValue <= 0) {
jumpPower = 0;
} else if (staminaValue <= staminaBase * 0.2) {
jumpPower *= 0.5;
} }
staminaValue -= staDecreasePerJump; // Move
if (staminaValue < 0.0) staminaValue = 0.0;
timeSinceStop = 0.0;
}
if (jumpPower > 0) {
body.applyImpulse(new Vec4(0, 0, jumpPower));
if (!allowAirJump) canJump = false;
}
}
// Control de estamina y correr
if (canRun && kb.down(runKey) && isMoving) {
if (stamina) {
if (staminaValue > 0.0) {
isRunning = true;
staminaValue -= staDecreasePerSec * deltaTime;
if (staminaValue < 0.0) staminaValue = 0.0;
} else {
isRunning = false;
}
} else {
isRunning = true;
}
} else {
isRunning = false;
}
// (temporizadores aparte)
if (isRunning) {
timeSinceStop = 0.0;
fatigueTimer += deltaTime;
fatigueCooldown = 0.0;
} else {
timeSinceStop += deltaTime;
fatigueCooldown += deltaTime;
}
// Evitar correr y saltar al estar fatigado...
if (isFatigued()) {
isRunning = false;
canJump = false;
}
// Activar fatiga despues de correr continuamente durante cierto umbral
if (enableFatigue && fatigueTimer >= fatigueThreshold) {
isFatigueActive = true;
}
// Eliminar la fatiga despues de recuperarse
if (enableFatigue && isFatigueActive && fatigueCooldown >= fatRecoveryThreshold) {
isFatigueActive = false;
fatigueTimer = 0.0;
}
// Recuperar estamina si no esta corriendo
if (stamina && !isRunning && staminaValue < staminaBase && !isFatigued()) {
if (timeSinceStop >= staRecoverTime) {
staminaValue += staRecoverPerSec * deltaTime;
if (staminaValue > staminaBase) staminaValue = staminaBase;
}
}
// Movimiento ejes (local)
dir.set(0, 0, 0); dir.set(0, 0, 0);
if (moveForward) dir.add(object.transform.look()); if (moveForward) dir.add(transform.look());
if (moveBackward) dir.add(object.transform.look().mult(-1)); if (moveBackward) dir.add(transform.look().mult(-1));
if (moveLeft) dir.add(object.transform.right().mult(-1)); if (moveLeft) dir.add(transform.right().mult(-1));
if (moveRight) dir.add(object.transform.right()); if (moveRight) dir.add(transform.right());
// Push down
var btvec = body.getLinearVelocity(); var btvec = body.getLinearVelocity();
body.setLinearVelocity(0.0, 0.0, btvec.z - 1.0); body.setLinearVelocity(0.0, 0.0, btvec.z - 1.0);
if (isMoving) { if (moveForward || moveBackward || moveLeft || moveRight) {
var dirN = dir.normalize(); var dirN = dir.normalize();
var baseSpeed = moveSpeed; dirN.mult(6);
if (isRunning && moveForward) {
baseSpeed = runSpeed;
}
var currentSpeed = isFatigued() ? baseSpeed * fatigueSpeed : baseSpeed;
dirN.mult(currentSpeed * deltaTime);
body.activate(); body.activate();
body.setLinearVelocity(dirN.x, dirN.y, btvec.z - 1.0); body.setLinearVelocity(dirN.x, dirN.y, btvec.z - 1.0);
} }
// Keep vertical
body.setAngularFactor(0, 0, 0); body.setAngularFactor(0, 0, 0);
head.buildMatrix(); camera.buildMatrix();
} }
#end
#end
} }
// Stamina and fatigue system.....

View File

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

View File

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

View File

@ -1,98 +0,0 @@
package leenkx.trait.physics;
import iron.object.Object;
class PhysicsCache {
#if lnx_physics
static var rbCache: Map<Int, Dynamic> = new Map();
static var contactsCache: Map<Int, Array<Dynamic>> = new Map();
static var physicsFrame: Int = 0;
static var lastQueryFrame: Int = -1;
#end
public static function getCachedRigidBody(object: Object): Dynamic {
#if (!lnx_physics)
return null;
#else
if (object == null) return null;
var cached = rbCache.get(object.uid);
if (cached != null) return cached;
#if lnx_bullet
var rb = object.getTrait(leenkx.trait.physics.bullet.RigidBody);
#else
var rb = object.getTrait(leenkx.trait.physics.oimo.RigidBody);
#end
if (rb != null) rbCache.set(object.uid, rb);
return rb;
#end
}
public static function getCachedContacts(rb: Dynamic): Array<Dynamic> {
#if (!lnx_physics)
return null;
#else
if (rb == null) return null;
var rbObjectId = (rb.object != null) ? rb.object.uid : -1;
if (rbObjectId == -1) {
#if lnx_bullet
if (leenkx.trait.physics.bullet.PhysicsWorld.active == null) return null;
return leenkx.trait.physics.bullet.PhysicsWorld.active.getContacts(rb);
#else
if (leenkx.trait.physics.oimo.PhysicsWorld.active == null) return null;
return leenkx.trait.physics.oimo.PhysicsWorld.active.getContacts(rb);
#end
}
if (lastQueryFrame == physicsFrame) {
var cached = contactsCache.get(rbObjectId);
if (cached != null) return cached;
}
lastQueryFrame = physicsFrame;
var cached = contactsCache.get(rbObjectId);
if (cached != null) return cached;
#if lnx_bullet
if (leenkx.trait.physics.bullet.PhysicsWorld.active == null) return null;
var contacts = leenkx.trait.physics.bullet.PhysicsWorld.active.getContacts(rb);
#else
if (leenkx.trait.physics.oimo.PhysicsWorld.active == null) return null;
var contacts = leenkx.trait.physics.oimo.PhysicsWorld.active.getContacts(rb);
#end
if (contacts != null) {
contactsCache.set(rbObjectId, contacts);
}
return contacts;
#end
}
public static inline function hasContactWith(contacts: Array<Dynamic>, target: Dynamic): Bool {
#if (!lnx_physics)
return false;
#else
return contacts != null && target != null && contacts.indexOf(target) >= 0;
#end
}
public static function clearCache() {
#if lnx_physics
rbCache.clear();
contactsCache.clear();
#end
}
public static function clearContactsCache() {
#if lnx_physics
physicsFrame++;
contactsCache.clear();
#end
}
}

View File

@ -8,9 +8,11 @@ class PhysicsWorld extends iron.Trait { public function new() { super(); } }
#else #else
#if lnx_bullet #if lnx_bullet
typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld; typedef PhysicsWorld = leenkx.trait.physics.bullet.PhysicsWorld;
typedef Hit = leenkx.trait.physics.bullet.PhysicsWorld.Hit; typedef Hit = leenkx.trait.physics.bullet.PhysicsWorld.Hit;
#else #else
typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld; typedef PhysicsWorld = leenkx.trait.physics.oimo.PhysicsWorld;
typedef Hit = leenkx.trait.physics.oimo.PhysicsWorld.Hit; typedef Hit = leenkx.trait.physics.oimo.PhysicsWorld.Hit;
#end #end

View File

@ -7,7 +7,6 @@ import iron.system.Time;
import iron.math.Vec4; import iron.math.Vec4;
import iron.math.Quat; import iron.math.Quat;
import iron.math.RayCaster; import iron.math.RayCaster;
import leenkx.trait.physics.PhysicsCache;
class Hit { class Hit {
@ -146,7 +145,6 @@ class PhysicsWorld extends Trait {
iron.Scene.active.notifyOnRemove(function() { iron.Scene.active.notifyOnRemove(function() {
sceneRemoved = true; sceneRemoved = true;
PhysicsCache.clearCache();
}); });
} }
@ -305,8 +303,6 @@ class PhysicsWorld extends Trait {
var t = Time.fixedStep * timeScale * Time.scale; var t = Time.fixedStep * timeScale * Time.scale;
if (t == 0.0) return; // Simulation paused if (t == 0.0) return; // Simulation paused
PhysicsCache.clearContactsCache();
#if lnx_debug #if lnx_debug
var startTime = kha.Scheduler.realTime(); var startTime = kha.Scheduler.realTime();
#end #end

View File

@ -36,18 +36,6 @@ class RigidBody extends iron.Trait {
var useDeactivation: Bool; var useDeactivation: Bool;
var deactivationParams: Array<Float>; var deactivationParams: Array<Float>;
var ccd = false; // Continuous collision detection var ccd = false; // Continuous collision detection
// New velocity limiting properties
var linearVelocityMin: Float;
var linearVelocityMax: Float;
var angularVelocityMin: Float;
var angularVelocityMax: Float;
// New lock properties
var lockTranslationX: Bool;
var lockTranslationY: Bool;
var lockTranslationZ: Bool;
var lockRotationX: Bool;
var lockRotationY: Bool;
var lockRotationZ: Bool;
public var group = 1; public var group = 1;
public var mask = 1; public var mask = 1;
var trigger = false; var trigger = false;
@ -132,17 +120,7 @@ class RigidBody extends iron.Trait {
collisionMargin: 0.0, collisionMargin: 0.0,
linearDeactivationThreshold: 0.0, linearDeactivationThreshold: 0.0,
angularDeactivationThrshold: 0.0, angularDeactivationThrshold: 0.0,
deactivationTime: 0.0, deactivationTime: 0.0
linearVelocityMin: 0.0,
linearVelocityMax: 0.0,
angularVelocityMin: 0.0,
angularVelocityMax: 0.0,
lockTranslationX: false,
lockTranslationY: false,
lockTranslationZ: false,
lockRotationX: false,
lockRotationY: false,
lockRotationZ: false
}; };
if (flags == null) flags = { if (flags == null) flags = {
@ -161,18 +139,6 @@ class RigidBody extends iron.Trait {
this.angularFactors = [params.angularFactorsX, params.angularFactorsY, params.angularFactorsZ]; this.angularFactors = [params.angularFactorsX, params.angularFactorsY, params.angularFactorsZ];
this.collisionMargin = params.collisionMargin; this.collisionMargin = params.collisionMargin;
this.deactivationParams = [params.linearDeactivationThreshold, params.angularDeactivationThrshold, params.deactivationTime]; this.deactivationParams = [params.linearDeactivationThreshold, params.angularDeactivationThrshold, params.deactivationTime];
// New velocity limiting properties
this.linearVelocityMin = params.linearVelocityMin;
this.linearVelocityMax = params.linearVelocityMax;
this.angularVelocityMin = params.angularVelocityMin;
this.angularVelocityMax = params.angularVelocityMax;
// New lock properties
this.lockTranslationX = params.lockTranslationX;
this.lockTranslationY = params.lockTranslationY;
this.lockTranslationZ = params.lockTranslationZ;
this.lockRotationX = params.lockRotationX;
this.lockRotationY = params.lockRotationY;
this.lockRotationZ = params.lockRotationZ;
this.animated = flags.animated; this.animated = flags.animated;
this.trigger = flags.trigger; this.trigger = flags.trigger;
this.ccd = flags.ccd; this.ccd = flags.ccd;
@ -325,25 +291,11 @@ class RigidBody extends iron.Trait {
} }
if (linearFactors != null) { if (linearFactors != null) {
// Apply lock properties by overriding factors setLinearFactor(linearFactors[0], linearFactors[1], linearFactors[2]);
var lx = linearFactors[0];
var ly = linearFactors[1];
var lz = linearFactors[2];
if (lockTranslationX) lx = 0.0;
if (lockTranslationY) ly = 0.0;
if (lockTranslationZ) lz = 0.0;
setLinearFactor(lx, ly, lz);
} }
if (angularFactors != null) { if (angularFactors != null) {
// Apply lock properties by overriding factors setAngularFactor(angularFactors[0], angularFactors[1], angularFactors[2]);
var ax = angularFactors[0];
var ay = angularFactors[1];
var az = angularFactors[2];
if (lockRotationX) ax = 0.0;
if (lockRotationY) ay = 0.0;
if (lockRotationZ) az = 0.0;
setAngularFactor(ax, ay, az);
} }
if (trigger) bodyColl.setCollisionFlags(bodyColl.getCollisionFlags() | CF_NO_CONTACT_RESPONSE); if (trigger) bodyColl.setCollisionFlags(bodyColl.getCollisionFlags() | CF_NO_CONTACT_RESPONSE);
@ -459,55 +411,6 @@ class RigidBody extends iron.Trait {
var rbs = physics.getContacts(this); var rbs = physics.getContacts(this);
if (rbs != null) for (rb in rbs) for (f in onContact) f(rb); if (rbs != null) for (rb in rbs) for (f in onContact) f(rb);
} }
// Apply velocity limiting if enabled
if (!animated && !staticObj) {
applyVelocityLimits();
}
}
function applyVelocityLimits() {
if (!ready) return;
// Check linear velocity limits
if (linearVelocityMin > 0.0 || linearVelocityMax > 0.0) {
var velocity = getLinearVelocity();
var speed = velocity.length();
if (linearVelocityMin > 0.0 && speed < linearVelocityMin) {
// Increase velocity to minimum
if (speed > 0.0) {
velocity.normalize();
velocity.mult(linearVelocityMin);
setLinearVelocity(velocity.x, velocity.y, velocity.z);
}
} else if (linearVelocityMax > 0.0 && speed > linearVelocityMax) {
// Clamp velocity to maximum
velocity.normalize();
velocity.mult(linearVelocityMax);
setLinearVelocity(velocity.x, velocity.y, velocity.z);
}
}
// Check angular velocity limits
if (angularVelocityMin > 0.0 || angularVelocityMax > 0.0) {
var angularVel = getAngularVelocity();
var angularSpeed = angularVel.length();
if (angularVelocityMin > 0.0 && angularSpeed < angularVelocityMin) {
// Increase angular velocity to minimum
if (angularSpeed > 0.0) {
angularVel.normalize();
angularVel.mult(angularVelocityMin);
setAngularVelocity(angularVel.x, angularVel.y, angularVel.z);
}
} else if (angularVelocityMax > 0.0 && angularSpeed > angularVelocityMax) {
// Clamp angular velocity to maximum
angularVel.normalize();
angularVel.mult(angularVelocityMax);
setAngularVelocity(angularVel.x, angularVel.y, angularVel.z);
}
}
} }
public function disableCollision() { public function disableCollision() {
@ -842,16 +745,6 @@ typedef RigidBodyParams = {
var linearDeactivationThreshold: Float; var linearDeactivationThreshold: Float;
var angularDeactivationThrshold: Float; var angularDeactivationThrshold: Float;
var deactivationTime: Float; var deactivationTime: Float;
var linearVelocityMin: Float;
var linearVelocityMax: Float;
var angularVelocityMin: Float;
var angularVelocityMax: Float;
var lockTranslationX: Bool;
var lockTranslationY: Bool;
var lockTranslationZ: Bool;
var lockRotationX: Bool;
var lockRotationY: Bool;
var lockRotationZ: Bool;
} }
typedef RigidBodyFlags = { typedef RigidBodyFlags = {

Binary file not shown.

Binary file not shown.

View File

@ -1,17 +1,9 @@
import importlib import importlib
import sys import sys
import types import types
import bpy
# This gets cleared if this package/the __init__ module is reloaded # This gets cleared if this package/the __init__ module is reloaded
if bpy.app.version < (2, 92, 0): _module_cache: dict[str, types.ModuleType] = {}
from typing import Dict
ModuleCacheType = Dict[str, types.ModuleType]
else:
ModuleCacheType = dict[str, types.ModuleType]
_module_cache: ModuleCacheType = {}
def enable_reload(module_name: str): def enable_reload(module_name: str):

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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