diff --git a/audio_stream_ogg_stereo.lua b/audio_stream_ogg_stereo.lua new file mode 100644 index 0000000..189ba8a --- /dev/null +++ b/audio_stream_ogg_stereo.lua @@ -0,0 +1,18 @@ +-- Stream a mono OGG file with stereo panning + +hg = require("harfang") + +hg.InputInit() +hg.AudioInit() + +src_ref = hg.StreamOGGFileStereo("resources_compiled/sounds/metro_announce.ogg", hg.StereoSourceState(1, hg.SR_Loop)) -- OGG 44.1kHz 16bit mono + +angle = 0 + +while not hg.ReadKeyboard('raw'):Key(hg.K_Escape) do + angle = angle + hg.time_to_sec_f(hg.TickClock()) * 0.5 + hg.SetSourcePanning(src_ref, math.sin(angle)) -- panning left = -1, panning right = 1 +end + +hg.AudioShutdown() +hg.InputShutdown() diff --git a/audio_stream_ogg_stereo.py b/audio_stream_ogg_stereo.py new file mode 100644 index 0000000..05891d0 --- /dev/null +++ b/audio_stream_ogg_stereo.py @@ -0,0 +1,18 @@ +# Stream a mono OGG file with stereo panning + +import harfang as hg +import math + +hg.InputInit() +hg.AudioInit() + +src_ref = hg.StreamOGGFileStereo("resources_compiled/sounds/metro_announce.ogg", hg.StereoSourceState(1, hg.SR_Loop)) # OGG 44.1kHz 16bit mono + +angle = 0 + +while not hg.ReadKeyboard('raw').Key(hg.K_Escape): + angle += hg.time_to_sec_f(hg.TickClock()) * 0.5 + hg.SetSourcePanning(src_ref, math.sin(angle)) # panning left = -1, panning right = 1 + +hg.AudioShutdown() +hg.InputShutdown() diff --git a/basic_loop.lua b/basic_loop.lua index da69a31..d96b3eb 100644 --- a/basic_loop.lua +++ b/basic_loop.lua @@ -8,7 +8,7 @@ hg.WindowSystemInit() width, height = 1280, 720 window = hg.RenderInit('Harfang - Basic Loop', width, height, hg.RF_VSync) -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(window) do hg.SetViewClear(0, hg.CF_Color | hg.CF_Depth, hg.Color.Green, 1, 0) hg.SetViewRect(0, 0, 0, width, height) diff --git a/basic_loop.py b/basic_loop.py index 9cd8ed4..a4c7ce3 100644 --- a/basic_loop.py +++ b/basic_loop.py @@ -8,7 +8,7 @@ width, height = 1280, 720 window = hg.RenderInit('Harfang - Basic Loop', width, height, hg.RF_VSync) -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(window): hg.SetViewClear(0, hg.CF_Color | hg.CF_Depth, hg.Color.Green, 1, 0) hg.SetViewRect(0, 0, 0, width, height) diff --git a/draw_lines.lua b/draw_lines.lua index 618ebfc..051d6a1 100644 --- a/draw_lines.lua +++ b/draw_lines.lua @@ -23,7 +23,7 @@ vtx = hg.Vertices(vtx_layout, line_count * 2) -- main loop angle = 0 -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do hg.SetViewClear(0, hg.CF_Color | hg.CF_Depth, hg.ColorI(64, 64, 64), 1, 0) hg.SetViewRect(0, 0, 0, res_x, res_y) diff --git a/draw_lines.py b/draw_lines.py index 56df02b..4336fab 100644 --- a/draw_lines.py +++ b/draw_lines.py @@ -24,7 +24,7 @@ # main loop angle = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): hg.SetViewClear(0, hg.CF_Color | hg.CF_Depth, hg.ColorI(64, 64, 64), 1, 0) hg.SetViewRect(0, 0, 0, res_x, res_y) diff --git a/draw_lines_starfield.lua b/draw_lines_starfield.lua index 25d5994..98b48a6 100644 --- a/draw_lines_starfield.lua +++ b/draw_lines_starfield.lua @@ -30,7 +30,7 @@ for i = 1, max_stars do end -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(window) do hg.SetViewClear(0, hg.CF_Color | hg.CF_Depth, hg.Color.Black, 1, 0) hg.SetViewRect(0, 0, 0, width, height) diff --git a/draw_lines_starfield.py b/draw_lines_starfield.py index 716d4c0..ec5a96f 100644 --- a/draw_lines_starfield.py +++ b/draw_lines_starfield.py @@ -29,7 +29,7 @@ stars.append(hg.RandomVec3(-starfield_size, starfield_size)) # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(window): hg.SetViewClear(0, hg.CF_Color | hg.CF_Depth, hg.Color.Black, 1, 0) hg.SetViewRect(0, 0, 0, width, height) diff --git a/draw_model_no_pipeline.lua b/draw_model_no_pipeline.lua index fe921e0..e44435b 100644 --- a/draw_model_no_pipeline.lua +++ b/draw_model_no_pipeline.lua @@ -19,7 +19,7 @@ shader = hg.LoadProgramFromFile('resources_compiled/shaders/mdl') -- main loop angle = 0 -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/draw_model_no_pipeline.py b/draw_model_no_pipeline.py index 34c4429..22847a3 100644 --- a/draw_model_no_pipeline.py +++ b/draw_model_no_pipeline.py @@ -19,7 +19,7 @@ # main loop angle = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/draw_text.lua b/draw_text.lua index cba7de4..debc708 100644 --- a/draw_text.lua +++ b/draw_text.lua @@ -17,7 +17,7 @@ text_uniform_values = {hg.MakeUniformSetValue('u_color', hg.Vec4(1, 1, 0))} text_render_state = hg.ComputeRenderState(hg.BM_Alpha, hg.DT_Always, hg.FC_Disabled) -- main loop -while not hg.ReadKeyboard('default'):Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do hg.SetView2D(0, 0, 0, res_x, res_y, -1, 1, hg.CF_Color | hg.CF_Depth, hg.ColorI(32, 32, 32), 0, 1) hg.DrawText(0, font, 'Hello world!', font_prg, 'u_tex', 0, hg.Mat4.Identity, hg.Vec3(res_x / 2, res_y / 2, 0), hg.DTHA_Center, hg.DTVA_Center, text_uniform_values, {}, text_render_state) diff --git a/draw_text.py b/draw_text.py index 0ee559e..e306f44 100644 --- a/draw_text.py +++ b/draw_text.py @@ -17,7 +17,7 @@ text_render_state = hg.ComputeRenderState(hg.BM_Alpha, hg.DT_Always, hg.FC_Disabled) # main loop -while not hg.ReadKeyboard('default').Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): hg.SetView2D(0, 0, 0, res_x, res_y, -1, 1, hg.CF_Color | hg.CF_Depth, hg.ColorI(32, 32, 32), 0, 1) hg.DrawText(0, font, 'Hello world!', font_prg, 'u_tex', 0, hg.Mat4.Identity, hg.Vec3(res_x / 2, res_y / 2, 0), hg.DTHA_Center, hg.DTVA_Center, text_uniform_values, [], text_render_state) diff --git a/draw_text_over_models.lua b/draw_text_over_models.lua index 7c5c053..dcc8afc 100644 --- a/draw_text_over_models.lua +++ b/draw_text_over_models.lua @@ -27,7 +27,7 @@ text_render_state = hg.ComputeRenderState(hg.BM_Alpha, hg.DT_Always, hg.FC_Disab -- main loop angle = 0 -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/draw_text_over_models.py b/draw_text_over_models.py index b4564b6..8c81205 100644 --- a/draw_text_over_models.py +++ b/draw_text_over_models.py @@ -27,7 +27,7 @@ # main loop angle = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/game_mouse_flight.lua b/game_mouse_flight.lua index 26c5252..b88a6e1 100644 --- a/game_mouse_flight.lua +++ b/game_mouse_flight.lua @@ -88,7 +88,7 @@ function update_chase_camera(target_pos) end -- game loop -while not keyboard:Down(hg.K_Escape) do +while not keyboard:Down(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() -- tick clock, retrieve elapsed clock since last call -- update mouse/keyboard devices diff --git a/game_mouse_flight.py b/game_mouse_flight.py index 965da1c..3878b02 100644 --- a/game_mouse_flight.py +++ b/game_mouse_flight.py @@ -90,7 +90,7 @@ def update_chase_camera(target_pos): # game loop -while not keyboard.Down(hg.K_Escape): +while not keyboard.Down(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() # tick clock, retrieve elapsed clock since last call # update mouse/keyboard devices diff --git a/imgui_basic.lua b/imgui_basic.lua index 973cf51..77c6a48 100644 --- a/imgui_basic.lua +++ b/imgui_basic.lua @@ -17,7 +17,7 @@ imgui_img_prg = hg.LoadProgramFromAssets('core/shader/imgui_image') hg.ImGuiInit(10, imgui_prg, imgui_img_prg) -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do hg.ImGuiBeginFrame(res_x, res_y, hg.TickClock(), hg.ReadMouse(), hg.ReadKeyboard()) if hg.ImGuiBegin('Window') then diff --git a/imgui_basic.py b/imgui_basic.py index df84a9e..0037e6a 100644 --- a/imgui_basic.py +++ b/imgui_basic.py @@ -17,7 +17,7 @@ hg.ImGuiInit(10, imgui_prg, imgui_img_prg) # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): hg.ImGuiBeginFrame(res_x, res_y, hg.TickClock(), hg.ReadMouse(), hg.ReadKeyboard()) if hg.ImGuiBegin('Window'): diff --git a/imgui_edit.lua b/imgui_edit.lua index c2533db..e0c8bf8 100644 --- a/imgui_edit.lua +++ b/imgui_edit.lua @@ -21,7 +21,7 @@ imgui_view_clear_color = hg.Color(0, 0, 0) imgui_clear_color_preset = 0 -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() -- ImGui frame diff --git a/imgui_edit.py b/imgui_edit.py index 1f94e32..3d0ad63 100644 --- a/imgui_edit.py +++ b/imgui_edit.py @@ -21,7 +21,7 @@ imgui_clear_color_preset = 0 # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() # ImGui frame diff --git a/imgui_mouse_capture.lua b/imgui_mouse_capture.lua index a0eabec..d9b9659 100644 --- a/imgui_mouse_capture.lua +++ b/imgui_mouse_capture.lua @@ -18,7 +18,7 @@ text_value = 'Clicking into this field will not clear the screen in red.' mouse = hg.Mouse() keyboard = hg.Keyboard() -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do mouse:Update() keyboard:Update() diff --git a/imgui_mouse_capture.py b/imgui_mouse_capture.py index 78450a5..cf5485f 100644 --- a/imgui_mouse_capture.py +++ b/imgui_mouse_capture.py @@ -18,7 +18,7 @@ mouse = hg.Mouse() keyboard = hg.Keyboard() -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): mouse.Update() keyboard.Update() diff --git a/input_read_gamepad.py b/input_read_gamepad.py index fae78cf..224db78 100644 --- a/input_read_gamepad.py +++ b/input_read_gamepad.py @@ -9,7 +9,7 @@ gamepad = hg.Gamepad() -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): gamepad.Update() if gamepad.Connected(): diff --git a/material_update_value.lua b/material_update_value.lua index 0b4341e..ebeaa5d 100644 --- a/material_update_value.lua +++ b/material_update_value.lua @@ -46,7 +46,7 @@ mat_update_delay = 0 texture_ref = hg.LoadTextureFromAssets('textures/squares.png', 0, res) -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() mat_update_delay = mat_update_delay - dt diff --git a/material_update_value.py b/material_update_value.py index 43265b2..8c4a88b 100644 --- a/material_update_value.py +++ b/material_update_value.py @@ -46,7 +46,7 @@ texture_ref = hg.LoadTextureFromAssets('textures/squares.png', 0, res) # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() mat_update_delay = mat_update_delay - dt diff --git a/physics_impulse.lua b/physics_impulse.lua index 69ef2b0..005e4f2 100644 --- a/physics_impulse.lua +++ b/physics_impulse.lua @@ -47,7 +47,7 @@ keyboard = hg.Keyboard() use_force = true -while not keyboard:Down(hg.K_Escape) do +while not keyboard:Down(hg.K_Escape) and hg.IsWindowOpen(win) do keyboard:Update() dt = hg.TickClock() diff --git a/physics_impulse.py b/physics_impulse.py index 5af0637..f2c3d92 100644 --- a/physics_impulse.py +++ b/physics_impulse.py @@ -47,7 +47,7 @@ use_force = True -while not keyboard.Down(hg.K_Escape): +while not keyboard.Down(hg.K_Escape) and hg.IsWindowOpen(win): keyboard.Update() dt = hg.TickClock() diff --git a/physics_kapla.lua b/physics_kapla.lua index c7e1de2..d677854 100644 --- a/physics_kapla.lua +++ b/physics_kapla.lua @@ -94,7 +94,7 @@ physics:SceneCreatePhysicsFromAssets(scene) physics_step = hg.time_from_sec_f(1 / 60) -- main loop -while not keyboard:Down(hg.K_Escape) do +while not keyboard:Down(hg.K_Escape) and hg.IsWindowOpen(win) do keyboard:Update() mouse:Update() diff --git a/physics_kapla.py b/physics_kapla.py index 2d22cb9..2888360 100644 --- a/physics_kapla.py +++ b/physics_kapla.py @@ -92,7 +92,7 @@ def fill_ring(r, ring_y, size, r_adjust, y_off): physics_step = hg.time_from_sec_f(1 / 60) # main loop -while not keyboard.Down(hg.K_Escape): +while not keyboard.Down(hg.K_Escape) and hg.IsWindowOpen(win): keyboard.Update() mouse.Update() diff --git a/physics_manual_setup.lua b/physics_manual_setup.lua index 226866b..02a1d7e 100644 --- a/physics_manual_setup.lua +++ b/physics_manual_setup.lua @@ -54,7 +54,7 @@ physics = hg.SceneBullet3Physics() physics:SceneCreatePhysicsFromAssets(scene) -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() hg.SceneUpdateSystems(scene, clocks, dt, physics, hg.time_from_sec_f(1 / 60), 1) diff --git a/physics_manual_setup.py b/physics_manual_setup.py index 9e3ca12..13d3f61 100644 --- a/physics_manual_setup.py +++ b/physics_manual_setup.py @@ -54,7 +54,7 @@ physics.SceneCreatePhysicsFromAssets(scene) # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() hg.SceneUpdateSystems(scene, clocks, dt, physics, hg.time_from_sec_f(1 / 60), 1) diff --git a/physics_overrides_matrix.lua b/physics_overrides_matrix.lua index 5a375fe..ac76b44 100644 --- a/physics_overrides_matrix.lua +++ b/physics_overrides_matrix.lua @@ -47,7 +47,7 @@ physics:SceneCreatePhysicsFromAssets(scene) -- main loop mouse, keyboard = hg.Mouse(), hg.Keyboard() -while not keyboard:Pressed(hg.K_Escape) do +while not keyboard:Pressed(hg.K_Escape) and hg.IsWindowOpen(win) do keyboard:Update() mouse:Update() diff --git a/physics_overrides_matrix.py b/physics_overrides_matrix.py index 027f392..74c0930 100644 --- a/physics_overrides_matrix.py +++ b/physics_overrides_matrix.py @@ -47,7 +47,7 @@ # main loop mouse, keyboard = hg.Mouse(), hg.Keyboard() -while not keyboard.Pressed(hg.K_Escape): +while not keyboard.Pressed(hg.K_Escape) and hg.IsWindowOpen(win): keyboard.Update() mouse.Update() diff --git a/physics_pool_of_objects.lua b/physics_pool_of_objects.lua index 3d87c34..c21c582 100644 --- a/physics_pool_of_objects.lua +++ b/physics_pool_of_objects.lua @@ -72,7 +72,7 @@ text_uniform_values = {hg.MakeUniformSetValue('u_color', hg.Vec4(1, 1, 0.5))} text_render_state = hg.ComputeRenderState(hg.BM_Alpha, hg.DT_Always, hg.FC_Disabled) -- main loop -while true do +while hg.IsWindowOpen(win) do state = hg.ReadKeyboard() if state:Key(hg.K_S) then diff --git a/physics_pool_of_objects.py b/physics_pool_of_objects.py index 3b91e81..84217c6 100644 --- a/physics_pool_of_objects.py +++ b/physics_pool_of_objects.py @@ -72,7 +72,7 @@ def create_material(diffuse, specular, self): text_render_state = hg.ComputeRenderState(hg.BM_Alpha, hg.DT_Always, hg.FC_Disabled) # main loop -while True: +while hg.IsWindowOpen(win): state = hg.ReadKeyboard() if state.Key(hg.K_S): diff --git a/render_resize_to_window.lua b/render_resize_to_window.lua index b3b51db..d1f388c 100644 --- a/render_resize_to_window.lua +++ b/render_resize_to_window.lua @@ -15,7 +15,7 @@ cube_mdl = hg.CreateCubeModel(vtx_layout, 1, 1, 1) cube_prg = hg.LoadProgramFromFile('resources_compiled/shaders/mdl') -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do render_was_reset, res_x, res_y = hg.RenderResetToWindow(win, res_x, res_y, hg.RF_VSync | hg.RF_MSAA4X | hg.RF_MaxAnisotropy) if render_was_reset then print(string.format('Render reset to %dx%d', res_x, res_y)) diff --git a/render_resize_to_window.py b/render_resize_to_window.py index dc7bb2b..8f4f791 100644 --- a/render_resize_to_window.py +++ b/render_resize_to_window.py @@ -15,7 +15,7 @@ cube_prg = hg.LoadProgramFromFile('resources_compiled/shaders/mdl') # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): render_was_reset, res_x, res_y = hg.RenderResetToWindow(win, res_x, res_y, hg.RF_VSync | hg.RF_MSAA4X | hg.RF_MaxAnisotropy) if render_was_reset: print('Render reset to %dx%d' % (res_x, res_y)) diff --git a/resources/car_engine/engine.scn b/resources/car_engine/engine.scn index b6cc136..099bc8e 100644 --- a/resources/car_engine/engine.scn +++ b/resources/car_engine/engine.scn @@ -27419,8 +27419,27 @@ ], "fog_far": 0.0, "fog_near": 0.0, - "irradiance_map": "core/pbr/blue_sky.hdr.irradiance", - "radiance_map": "core/pbr/blue_sky.hdr.radiance" + "probe": { + "irradiance_map": "core/pbr/blue_sky.hdr.irradiance", + "parallax": 0.0, + "pos": [ + 0.0, + 0.0, + 0.0 + ], + "radiance_map": "core/pbr/blue_sky.hdr.radiance", + "rot": [ + 0.0, + 0.0, + 0.0 + ], + "scl": [ + 1.0, + 1.0, + 1.0 + ], + "type": "sphere" + } }, "instances": [ { @@ -27442,6 +27461,7 @@ 2550, 255 ], + "diffuse_intensity": 1.0, "inner_angle": 9.999999747378752e-05, "outer_angle": 0.7853981852531433, "priority": 1.0, @@ -27452,7 +27472,7 @@ 500.0 ], "radius": 0.0, - "shadow_bias": 9.999999747378752e-06, + "shadow_bias": 0.0005000000237487257, "shadow_type": "map", "specular": [ 0, @@ -27460,6 +27480,7 @@ 0, 255 ], + "specular_intensity": 1.0, "type": "spot" }, { @@ -27469,6 +27490,7 @@ 255, 255 ], + "diffuse_intensity": 1.0, "inner_angle": 0.5235987901687622, "outer_angle": 0.7853981852531433, "priority": 1.0, @@ -27487,6 +27509,7 @@ 0, 255 ], + "specular_intensity": 1.0, "type": "linear" } ], @@ -35044,7 +35067,7 @@ ], "scene_anims": [ { - "anim": null, + "anim": 4294967295, "frame_duration": 50000000, "name": "Take 001", "node_anims": [ @@ -35178,7 +35201,7 @@ -0.1635737419128418 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -35196,7 +35219,7 @@ 0.16039180755615234 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -35214,7 +35237,7 @@ -0.21844716370105743 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -35232,7 +35255,7 @@ 0.1838085651397705 ], "rot": [ - 85.22080993652344, + 85.2208023071289, 180.0, 180.0 ], @@ -35844,7 +35867,7 @@ -0.004945273976773024 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -35862,7 +35885,7 @@ -5.018959045410156 ], "rot": [ - -3.12603759765625, + -3.126037359237671, 0.01269339770078659, -0.0005423406837508082 ], @@ -35899,7 +35922,7 @@ ], "rot": [ -2.4620609283447266, - 4.0438233816185443e-13, + 4.043823110568001e-13, 3.9484938756106924e-12 ], "scl": [ @@ -35972,7 +35995,7 @@ "rot": [ -42.31441116333008, 179.9835662841797, - -179.98562622070313 + -179.98561096191406 ], "scl": [ 1.0, @@ -36006,7 +36029,7 @@ 2.119384288787842 ], "rot": [ - -57.537986755371094, + -57.53798294067383, -180.0, 180.0 ], @@ -36042,7 +36065,7 @@ -0.004945273976773024 ], "rot": [ - -27.53790283203125, + -27.537900924682617, 0.0, 0.0 ], @@ -36061,8 +36084,8 @@ ], "rot": [ 45.58206558227539, - 179.9827423095703, - 179.9840087890625 + 179.98272705078125, + 179.98399353027344 ], "scl": [ 1.0, @@ -36096,7 +36119,7 @@ -2.1211297512054443 ], "rot": [ - 62.46209716796875, + 62.46208953857422, 180.0, 180.0 ], @@ -36132,7 +36155,7 @@ -0.004945273976773024 ], "rot": [ - 47.53793716430664, + 47.537933349609375, -180.0, -180.0 ], @@ -36150,8 +36173,8 @@ -5.01895809173584 ], "rot": [ - -54.93225860595703, - 0.021506860852241516, + -54.932254791259766, + 0.021506858989596367, -0.014868209138512611 ], "scl": [ @@ -36186,8 +36209,8 @@ -2.4197490215301514 ], "rot": [ - -42.46205520629883, - -1.411154700037276e-11, + -42.46205139160156, + -1.4111546133011021e-11, -4.01617142320454e-11 ], "scl": [ @@ -36241,8 +36264,8 @@ ], "rot": [ 73.44593048095703, - 0.04269658774137497, - 0.03746206685900688 + 0.04269658401608467, + 0.03746206313371658 ], "scl": [ 1.0, @@ -36276,7 +36299,7 @@ 2.194354295730591 ], "rot": [ - 57.537986755371094, + 57.53798294067383, 2.7536471366995663e-11, -1.0942671213598487e-09 ], @@ -36330,9 +36353,9 @@ -5.018959045410156 ], "rot": [ - 1.0554357767105103, - 179.9873809814453, - 179.99945068359375 + 1.0554356575012207, + 179.98736572265625, + 179.9994354248047 ], "scl": [ 1.0, @@ -36366,7 +36389,7 @@ -0.25069767236709595 ], "rot": [ - 2.4620397090911865, + 2.4620394706726074, -180.0, 180.0 ], @@ -36654,7 +36677,7 @@ -0.0050963168032467365 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -36690,7 +36713,7 @@ -0.0050963168032467365 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -36726,7 +36749,7 @@ 0.06785663962364197 ], "rot": [ - -2.13443399843527e-07, + -2.134433856326723e-07, 90.00000762939453, 2.462165117263794 ], @@ -36870,7 +36893,7 @@ -0.0050963168032467365 ], "rot": [ - 87.5377197265625, + 87.53771209716797, -180.0, -180.0 ], @@ -36888,7 +36911,7 @@ -0.07684630900621414 ], "rot": [ - -2.13443399843527e-07, + -2.134433856326723e-07, 90.00000762939453, 2.462165117263794 ], @@ -37050,7 +37073,7 @@ 0.053020551800727844 ], "rot": [ - 85.22080993652344, + 85.2208023071289, 180.0, 180.0 ], @@ -37086,7 +37109,7 @@ 2.5816879272460938 ], "rot": [ - 25.210643768310547, + 25.210641860961914, 138.3695068359375, 0.0 ], @@ -37122,7 +37145,7 @@ 2.4617958068847656 ], "rot": [ - 11.760019302368164, + 11.760018348693848, 135.82164001464844, 0.0 ], @@ -37320,9 +37343,9 @@ 0.0 ], "rot": [ - 32.325401306152344, - 2.0207064608257497e-06, - 1.0103533440997126e-06 + 32.32539749145508, + 2.0207062334520742e-06, + 1.0103532304128748e-06 ], "scl": [ 0.9999999403953552, @@ -37339,7 +37362,7 @@ ], "rot": [ -0.0, - 111.87700653076172, + 111.87699890136719, 0.0 ], "scl": [ @@ -37357,7 +37380,7 @@ ], "rot": [ 21.77312469482422, - 124.33213806152344, + 124.33212280273438, 0.0 ], "scl": [ diff --git a/resources/car_engine/engine.scn.aaa b/resources/car_engine/engine.scn.aaa new file mode 100644 index 0000000..03b674f --- /dev/null +++ b/resources/car_engine/engine.scn.aaa @@ -0,0 +1,12 @@ +{ + "bloom_bias": 0.5, + "bloom_intensity": 0.10000000149011612, + "bloom_threshold": 5.0, + "exposure": 1.0, + "gamma": 2.200000047683716, + "max_distance": 100.0, + "motion_blur": 1.0, + "sample_count": 2, + "taa_weight": 0.10000000149011612, + "z_thickness": 0.10000000149011612 +} \ No newline at end of file diff --git a/resources/car_engine/engine.scn.editor b/resources/car_engine/engine.scn.editor index 9bc52ef..6d6f792 100644 --- a/resources/car_engine/engine.scn.editor +++ b/resources/car_engine/engine.scn.editor @@ -1,5 +1,11 @@ { "editor": { + "animeditor_plugin": { + "quantize_time": true, + "show_trajectories": null, + "trajectories_tick_seconds": 1.0, + "trajectories_tick_size": 0.10000000149011612 + }, "explorer": { "node_custom_order": { "refs": [ @@ -185,6 +191,16 @@ "node_sort_method": "custom", "show_node_uid": false }, + "grid_plugin": { + "enabled": true, + "grid_color_b": 1.0, + "grid_color_g": 1.0, + "grid_color_r": 1.0, + "n_subdivs": 10, + "offset": 0.0, + "opacity": 0.5, + "subdiv_size": 1.0 + }, "navigation_plugin": { "orbit_distance": 7.836572647094727, "speed": 0.10000000149011612, @@ -192,12 +208,37 @@ }, "transform_gizmo_plugin": { "mode": "local", + "snap": "none", + "snap_rotation": 5.0, + "snap_rotation_fine": 1.0, + "snap_scale": 10.0, + "snap_scale_fine": 1.0, + "snap_translation": 1.0, + "snap_translation_fine": 0.10000000149011612, "tool": "rotation" }, "view_plugin": { - "show_node_origin": false + "show_cameras": true, + "show_collisions": false, + "show_lights": true, + "show_nodes": true, + "show_probe": true }, "views": { + "back": [ + -0.9999999403953552, + 0.0, + -8.742277657347586e-08, + 0.0, + 0.0, + 1.0, + -0.0, + 0.0, + 8.742277657347586e-08, + -0.0, + -0.9999999403953552, + 0.0 + ], "bottom": [ 1.0, -0.0, @@ -217,6 +258,20 @@ "znear": -1000.0 }, "current_camera": 7, + "front": [ + 1.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.0, + -0.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0 + ], "left": [ -8.742277657347586e-08, 0.0, diff --git a/resources/core/pbr/probe.hdr.meta b/resources/core/pbr/probe.hdr.meta index 0cfad74..0528fa0 100644 --- a/resources/core/pbr/probe.hdr.meta +++ b/resources/core/pbr/probe.hdr.meta @@ -2,7 +2,7 @@ "profiles": { "default": { "generate-probe": true, - "max-probe-size": 128, + "max-probe-size": 256, "radiance-edge-fixup": true } } diff --git a/resources/core/shader/bloom_downsample_fs.sc b/resources/core/shader/bloom_downsample_fs.sc index 8a88b93..e142d0f 100644 --- a/resources/core/shader/bloom_downsample_fs.sc +++ b/resources/core/shader/bloom_downsample_fs.sc @@ -3,29 +3,38 @@ $input v_texcoord0 #include SAMPLER2D(u_source, 0); +uniform vec4 u_source_rect; + +vec2 compute_texel(vec2 uv, vec2 center, vec4 bounds) { + vec4 w = vec4(step(bounds.xy, uv), step(uv, bounds.zw)); + return mix(center, uv, vec2(w.x*w.z, w.y*w.w)); +} void main() { vec2 uv = v_texcoord0.xy; vec4 offset = vec4(-1., 1., 1., 0.) / uResolution.xxyy; - vec4 s0 = texture2D(u_source, uv - offset.yz); - vec4 s1 = texture2D(u_source, uv - offset.wz); - vec4 s2 = texture2D(u_source, uv - offset.xz); + vec2 center = (floor(v_texcoord0.xy * uResolution.xy) + vec2_splat(0.5)) / uResolution.xy; + vec4 bounds = (floor(u_source_rect.xyzw) + vec4(1.,1.,-1.,-1.)) / uResolution.xyxy; + + vec4 s0 = texture2D(u_source, compute_texel(uv - offset.yz, center, bounds)); // -1,-1 + vec4 s1 = texture2D(u_source, compute_texel(uv - offset.wz, center, bounds)); // 0,-1 + vec4 s2 = texture2D(u_source, compute_texel(uv - offset.xz, center, bounds)); // 1,-1 - vec4 s3 = texture2D(u_source, uv + offset.xw); - vec4 s4 = texture2D(u_source, uv); - vec4 s5 = texture2D(u_source, uv + offset.yw); + vec4 s3 = texture2D(u_source, compute_texel(uv + offset.xw, center, bounds)); // -1, 0 + vec4 s4 = texture2D(u_source, compute_texel(uv, center, bounds)); // 0, 0 + vec4 s5 = texture2D(u_source, compute_texel(uv + offset.yw, center, bounds)); // 1, 0 - vec4 s6 = texture2D(u_source, uv + offset.xz); - vec4 s7 = texture2D(u_source, uv + offset.wz); - vec4 s8 = texture2D(u_source, uv + offset.yz); + vec4 s6 = texture2D(u_source, compute_texel(uv + offset.xz, center, bounds)); // -1, 1 + vec4 s7 = texture2D(u_source, compute_texel(uv + offset.wz, center, bounds)); // 0, 1 + vec4 s8 = texture2D(u_source, compute_texel(uv + offset.yz, center, bounds)); // 1, 1 offset = 0.5 * offset; - vec4 t0 = texture2D(u_source, uv - offset.yz); - vec4 t1 = texture2D(u_source, uv - offset.xz); - vec4 t2 = texture2D(u_source, uv + offset.xz); - vec4 t3 = texture2D(u_source, uv + offset.yz); + vec4 t0 = texture2D(u_source, compute_texel(uv - offset.yz, center, bounds)); // -1,-1 + vec4 t1 = texture2D(u_source, compute_texel(uv - offset.xz, center, bounds)); // 1,-1 + vec4 t2 = texture2D(u_source, compute_texel(uv + offset.xz, center, bounds)); // -1, 1 + vec4 t3 = texture2D(u_source, compute_texel(uv + offset.yz, center, bounds)); // 1, 1 vec4 v0 = s0 + s1 + s3 + s4; vec4 v1 = s1 + s2 + s4 + s5; diff --git a/resources/core/shader/bloom_upsample_fs.sc b/resources/core/shader/bloom_upsample_fs.sc index 5f7d69d..313f708 100644 --- a/resources/core/shader/bloom_upsample_fs.sc +++ b/resources/core/shader/bloom_upsample_fs.sc @@ -3,24 +3,32 @@ $input v_texcoord0 #include SAMPLER2D(u_source, 0); - +uniform vec4 u_source_rect; uniform vec4 u_params; +vec2 compute_texel(vec2 uv, vec2 center, vec4 bounds) { + vec4 w = vec4(step(bounds.xy, uv), step(uv, bounds.zw)); + return mix(center, uv, vec2(w.x*w.z, w.y*w.w)); +} + void main() { vec2 uv = v_texcoord0.xy; vec4 offset = vec4(-1., 1., 1., 0.) / uResolution.xxyy; - vec4 t0 = texture2D(u_source, uv - offset.yz); - vec4 t1 = texture2D(u_source, uv - offset.wz); - vec4 t2 = texture2D(u_source, uv - offset.xz); + vec2 center = (floor(v_texcoord0.xy * uResolution.xy) + vec2_splat(0.5)) / uResolution.xy; + vec4 bounds = (floor(u_source_rect.xyzw) + vec4(1.,1.,-1.,-1.)) / uResolution.xyxy; + + vec4 t0 = texture2D(u_source, compute_texel(uv - offset.yz, center, bounds)); // -1,-1 + vec4 t1 = texture2D(u_source, compute_texel(uv - offset.wz, center, bounds)); // 0,-1 + vec4 t2 = texture2D(u_source, compute_texel(uv - offset.xz, center, bounds)); // 1,-1 - vec4 t3 = texture2D(u_source, uv + offset.xw); - vec4 t4 = texture2D(u_source, uv); - vec4 t5 = texture2D(u_source, uv + offset.yw); + vec4 t3 = texture2D(u_source, compute_texel(uv + offset.xw, center, bounds)); // -1, 0 + vec4 t4 = texture2D(u_source, compute_texel(uv, center, bounds)); + vec4 t5 = texture2D(u_source, compute_texel(uv + offset.yw, center, bounds)); // 1, 0 - vec4 t6 = texture2D(u_source, uv + offset.xz); - vec4 t7 = texture2D(u_source, uv + offset.wz); - vec4 t8 = texture2D(u_source, uv + offset.yz); + vec4 t6 = texture2D(u_source, compute_texel(uv + offset.xz, center, bounds)); // -1, 1 + vec4 t7 = texture2D(u_source, compute_texel(uv + offset.wz, center, bounds)); // 0, 1 + vec4 t8 = texture2D(u_source, compute_texel(uv + offset.yz, center, bounds)); // 1, 1 gl_FragColor = u_params.z * (t0 + t2 + t6 + t8 + 2. * (t1 + t3 + t5 + t7) + 4. * t4) / 16.; } diff --git a/resources/core/shader/compositing_fs.sc b/resources/core/shader/compositing_fs.sc index f94b14f..d7b63fa 100644 --- a/resources/core/shader/compositing_fs.sc +++ b/resources/core/shader/compositing_fs.sc @@ -9,49 +9,42 @@ SAMPLER2D(u_copyDepth, 1); tone-mapping operators implementation taken from https://www.shadertoy.com/view/lslGzl */ -vec3 LinearToneMapping(vec3 color, float exposure) // 1. -{ +vec3 LinearToneMapping(vec3 color, float exposure) { // 1. color = clamp(exposure * color, 0., 1.); return color; } -vec3 SimpleReinhardToneMapping(vec3 color, float exposure) // 1.5 -{ +vec3 SimpleReinhardToneMapping(vec3 color, float exposure) { // 1.5 color *= exposure / (1. + color / exposure); return color; } -vec3 LumaBasedReinhardToneMapping(vec3 color) -{ +vec3 LumaBasedReinhardToneMapping(vec3 color) { float luma = dot(color, vec3(0.2126, 0.7152, 0.0722)); float toneMappedLuma = luma / (1. + luma); color *= toneMappedLuma / luma; return color; } -vec3 WhitePreservingLumaBasedReinhardToneMapping(vec3 color, float white) // 2. -{ +vec3 WhitePreservingLumaBasedReinhardToneMapping(vec3 color, float white) { // 2. float luma = dot(color, vec3(0.2126, 0.7152, 0.0722)); float toneMappedLuma = luma * (1. + luma / (white * white)) / (1. + luma); color *= toneMappedLuma / luma; return color; } -vec3 RomBinDaHouseToneMapping(vec3 color) -{ +vec3 RomBinDaHouseToneMapping(vec3 color) { color = exp(-1. / (2.72 * color + 0.15)); return color; } -vec3 FilmicToneMapping(vec3 color) -{ +vec3 FilmicToneMapping(vec3 color) { color = max(vec3(0., 0., 0.), color - vec3(0.004, 0.004, 0.004)); color = (color * (6.2 * color + .5)) / (color * (6.2 * color + 1.7) + 0.06); return color; } -vec3 Uncharted2ToneMapping(vec3 color, float exposure) -{ +vec3 Uncharted2ToneMapping(vec3 color, float exposure) { float A = 0.15; float B = 0.50; float C = 0.10; @@ -66,8 +59,31 @@ vec3 Uncharted2ToneMapping(vec3 color, float exposure) return color; } -void main() -{ +vec4 Sharpen(vec2 uv, float strength) { + vec4 up = texture2D(u_copyColor, uv + vec2(0, 1) / uResolution.xy); + vec4 left = texture2D(u_copyColor, uv + vec2(-1, 0) / uResolution.xy); + vec4 center = texture2D(u_copyColor, uv); + vec4 right = texture2D(u_copyColor, uv + vec2(1, 0) / uResolution.xy); + vec4 down = texture2D(u_copyColor, uv + vec2(0, -1) / uResolution.xy); + + float exposure = uAAAParams[1].x; + up.xyz = SimpleReinhardToneMapping(up.xyz, exposure); + left.xyz = SimpleReinhardToneMapping(left.xyz, exposure); + center.xyz = SimpleReinhardToneMapping(center.xyz, exposure); + right.xyz = SimpleReinhardToneMapping(right.xyz, exposure); + down.xyz = SimpleReinhardToneMapping(down.xyz, exposure); + + vec4 res = (1.0 + 4.0 * strength) * center - strength * (up + left + right + down); + return vec4(res.xyz, center.w); +} + +void main() { +#if 1 + vec4 in_sample = Sharpen(v_texcoord0, uAAAParams[2].y); + + vec3 color = in_sample.xyz; + float alpha = in_sample.w; +#else vec4 in_sample = texture2D(u_copyColor, v_texcoord0); vec3 color = in_sample.xyz; @@ -78,7 +94,9 @@ void main() //color = lumaBasedReinhardToneMapping(color); //color = FilmicToneMapping(color); //color = Uncharted2ToneMapping(color, exposure); +#endif + // gamma correction float inv_gamma = uAAAParams[1].y; color = pow(color, vec3_splat(inv_gamma)); diff --git a/resources/core/shader/default_fs.sc b/resources/core/shader/default_fs.sc index 0789743..1bc97ac 100644 --- a/resources/core/shader/default_fs.sc +++ b/resources/core/shader/default_fs.sc @@ -70,41 +70,54 @@ float SampleShadowPCF(sampler2DShadow map, vec4 coord, float inv_pixel_size, flo return k / 4.0; } -// Entry point of the forward pipeline default uber shader (Phong and PBR) +// Entry point of the forward pipeline default shader void main() { +#if DEPTH_ONLY != 1 #if USE_DIFFUSE_MAP +#if DIFFUSE_UV_CHANNEL == 1 + vec3 diff = texture2D(uDiffuseMap, vTexCoord1).xyz; +#else // DIFFUSE_UV_CHANNEL == 1 vec3 diff = texture2D(uDiffuseMap, vTexCoord0).xyz; -#else +#endif // DIFFUSE_UV_CHANNEL == 1 +#else // USE_DIFFUSE_MAP vec3 diff = uDiffuseColor.xyz; -#endif +#endif // USE_DIFFUSE_MAP #if USE_SPECULAR_MAP +#if SPECULAR_UV_CHANNEL == 1 + vec3 spec = texture2D(uSpecularMap, vTexCoord1).xyz; +#else // SPECULAR_UV_CHANNEL == 1 vec3 spec = texture2D(uSpecularMap, vTexCoord0).xyz; -#else +#endif // SPECULAR_UV_CHANNEL == 1 +#else // USE_SPECULAR_MAP vec3 spec = uSpecularColor.xyz; -#endif +#endif // USE_SPECULAR_MAP #if USE_SELF_MAP vec3 self = texture2D(uSelfMap, vTexCoord0).xyz; -#else +#else // USE_SELF_MAP vec3 self = uSelfColor.xyz; -#endif +#endif // USE_SELF_MAP #if USE_AMBIENT_MAP +#if AMBIENT_UV_CHANNEL == 1 vec3 ao = texture2D(uAmbientMap, vTexCoord1).xyz; -#else +#else // AMBIENT_UV_CHANNEL == 1 + vec3 ao = texture2D(uAmbientMap, vTexCoord0).xyz; +#endif // AMBIENT_UV_CHANNEL == 1 +#else // USE_AMBIENT_MAP vec3 ao = vec3_splat(1.0); -#endif +#endif // USE_AMBIENT_MAP #if USE_ADVANCED_BUFFERS ao *= texture2D(uAmbientOcclusion, gl_FragCoord.xy / uResolution.xy).x; -#endif +#endif // USE_ADVANCED_BUFFERS #if USE_LIGHT_MAP vec3 light = texture2D(uLightMap, vTexCoord1).xyz; -#else +#else // USE_LIGHT_MAP vec3 light = vec3_splat(0.0); -#endif +#endif // USE_LIGHT_MAP // vec3 view = mul(u_view, vec4(vWorldPos,1.0)).xyz; // fragment view space pos @@ -121,7 +134,7 @@ void main() { N.xy = texture2D(uNormalMap, vTexCoord0).xy * 2.0 - 1.0; N.z = sqrt(1.0 - dot(N.xy, N.xy)); N = normalize(mul(N, TBN)); -#endif +#endif // USE_NORMAL_MAP vec3 R = reflect(-V, N); // view reflection vector around normal @@ -150,7 +163,7 @@ void main() { float ramp_k = clamp((view.z - (uLinearShadowSlice.w - ramp_len)) / ramp_len, 0.0, 1.0); k *= pcf * (1.0 - ramp_k) + ramp_k; } -#endif +#endif // SLOT0_SHADOWS c_diff = uLightDiffuse[0].xyz * m.i_diff * k; c_spec = uLightSpecular[0].xyz * m.i_spec * k; } @@ -167,7 +180,7 @@ void main() { #if SLOT1_SHADOWS k *= SampleShadowPCF(uSpotShadowMap, vSpotShadowCoord, uShadowState.y, uShadowState.w); -#endif +#endif // SLOT1_SHADOWS c_diff += uLightDiffuse[1].xyz * m.i_diff * k; c_spec += uLightSpecular[1].xyz * m.i_spec * k; @@ -194,28 +207,38 @@ void main() { #if USE_REFLECTION_MAP vec4 reflection = texture2D(uReflectionMap, R.xy); color += reflection.xyz; -#endif +#endif // USE_REFLECTION_MAP color = DistanceFog(view, color); +#endif // DEPTH_ONLY != 1 #if USE_OPACITY_MAP float opacity = texture2D(uOpacityMap, vTexCoord0).x; -#else + +#if ENABLE_ALPHA_CUT + if (opacity < 0.8) + discard; +#endif // ENABLE_ALPHA_CUT +#else // USE_OPACITY_MAP float opacity = 1.0; -#endif +#endif // USE_OPACITY_MAP +#if DEPTH_ONLY + ; +#else // DEPTH_ONLY #if FORWARD_PIPELINE_AAA_PREPASS vec3 N_view = mul(u_view, vec4(N, 0)).xyz; vec2 velocity = vec2(vProjPos.xy / vProjPos.w - vPrevProjPos.xy / vPrevProjPos.w); gl_FragData[0] = vec4(N_view.xyz, vProjPos.z); gl_FragData[1] = vec4(velocity.xy, gloss, 0.); // -#else +#else // FORWARD_PIPELINE_AAA_PREPASS // incorrectly apply gamma correction at fragment shader level in the non-AAA pipeline -# if FORWARD_PIPELINE_AAA == 0 +#if FORWARD_PIPELINE_AAA != 1 float gamma = 2.2; color = pow(color, vec3_splat(1. / gamma)); -# endif +#endif // FORWARD_PIPELINE_AAA != 1 gl_FragColor = vec4(color, opacity); -#endif +#endif // FORWARD_PIPELINE_AAA_PREPASS +#endif // DEPTH_ONLY } diff --git a/resources/core/shader/default_vs.sc b/resources/core/shader/default_vs.sc index 7a46352..b509d2b 100644 --- a/resources/core/shader/default_vs.sc +++ b/resources/core/shader/default_vs.sc @@ -24,15 +24,16 @@ void main() { mul(uPreviousModel[int(a_indices.y * 256.0)], vtx) * a_weight.y + mul(uPreviousModel[int(a_indices.z * 256.0)], vtx) * a_weight.z + mul(uPreviousModel[int(a_indices.w * 256.0)], vtx) * a_weight.w; -#endif -#else +#endif // FORWARD_PIPELINE_AAA_PREPASS +#else // ENABLE_SKINNING vec4 world_pos = mul(u_model[0], vtx); #if FORWARD_PIPELINE_AAA_PREPASS vec4 prv_world_pos = mul(uPreviousModel[0], vtx); -#endif -#endif +#endif // FORWARD_PIPELINE_AAA_PREPASS +#endif // ENABLE_SKINNING +#if DEPTH_ONLY != 1 // normal vec4 normal = vec4(a_normal * 2. - 1., 0.); @@ -46,12 +47,12 @@ void main() { skinned_normal = normalize(skinned_normal); vNormal = skinned_normal.xyz; -#else +#else // ENABLE_SKINNING vNormal = mul(normal_mat(u_model[0]), normal.xyz); -#endif +#endif // ENABLE_SKINNING // tangent frame -#if (USE_NORMAL_MAP) // [EJ] FIXME this probably won't be the only condition to compute the tangent frame for long +#if USE_NORMAL_MAP vec4 tangent = vec4(a_tangent * 2.0 - 1.0, 0.0); vec4 binormal = vec4(a_bitangent * 2.0 - 1.0, 0.0); @@ -70,47 +71,40 @@ void main() { vTangent = skinned_tangent.xyz; vBinormal = skinned_binormal.xyz; -#else +#else // ENABLE_SKINNING vTangent = mul(u_model[0], tangent).xyz; vBinormal = mul(u_model[0], binormal).xyz; -#endif -#endif +#endif // ENABLE_SKINNING +#endif // USE_NORMAL_MAP // shadow data -#if (SLOT0_SHADOWS || SLOT1_SHADOWS) +#if SLOT0_SHADOWS || SLOT1_SHADOWS float shadowMapShrinkOffset = 0.01; vec3 shadowVertexShrinkOffset = vNormal * shadowMapShrinkOffset; -#endif +#endif // SLOT0_SHADOWS || SLOT1_SHADOWS -#if (SLOT0_SHADOWS) +#if SLOT0_SHADOWS vLinearShadowCoord0 = mul(uLinearShadowMatrix[0], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); vLinearShadowCoord1 = mul(uLinearShadowMatrix[1], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); vLinearShadowCoord2 = mul(uLinearShadowMatrix[2], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); vLinearShadowCoord3 = mul(uLinearShadowMatrix[3], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); -#endif +#endif // SLOT0_SHADOWS -#if (SLOT1_SHADOWS) +#if SLOT1_SHADOWS vSpotShadowCoord = mul(uSpotShadowMatrix, vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); -#endif +#endif // SLOT1_SHADOWS +#endif // DEPTH_ONLY != 1 - // vWorldPos = world_pos.xyz; -#if (USE_DIFFUSE_MAP || USE_SPECULAR_MAP|| USE_NORMAL_MAP || USE_SELF_MAP || USE_OPACITY_MAP) vTexCoord0 = a_texcoord0; -#endif - -#if (USE_LIGHT_MAP || USE_AMBIENT_MAP) vTexCoord1 = a_texcoord1; -#endif - // vec4 proj_pos = mul(uViewProjUnjittered, world_pos); #if FORWARD_PIPELINE_AAA_PREPASS vProjPos = proj_pos; vPrevProjPos = mul(uPreviousViewProjection, prv_world_pos); -#endif +#endif // FORWARD_PIPELINE_AAA_PREPASS - // gl_Position = mul(u_viewProj, world_pos); } diff --git a/resources/core/shader/forward_pipeline.sh b/resources/core/shader/forward_pipeline.sh index 4344696..e4bda47 100644 --- a/resources/core/shader/forward_pipeline.sh +++ b/resources/core/shader/forward_pipeline.sh @@ -29,19 +29,21 @@ uniform mat4 uMainInvProjection; // inverse projection for the main render (used uniform mat4 uPreviousViewProjection; uniform mat4 uPreviousModel[BGFX_CONFIG_MAX_BONES]; uniform mat4 uViewProjUnjittered; -uniform vec4 uAAAParams[2]; // [0].x: ssgi ratio, [0].y: ssr ratio, [0].z: temporal AA weight, [0].w: motion blur strength, [1].x: exposure, [1].y: 1/gamma, [1].z: sample count, [1].w: max radius +uniform vec4 uAAAParams[3]; // [0].x: ssgi ratio, [0].y: ssr ratio, [0].z: temporal AA weight, [0].w: motion blur strength, + // [1].x: exposure, [1].y: 1/gamma, [1].z: sample count, [1].w: screenspace ray max length + // [2].x: specular weight, [2].y: sharpen uniform mat4 uMainInvView; // inversion view matrix - -#if FORWARD_PIPELINE_AAA -SAMPLER2D(uIrradianceMap, 8); -SAMPLER2D(uRadianceMap, 9); -#else -SAMPLERCUBE(uIrradianceMap, 8); -SAMPLERCUBE(uRadianceMap, 9); -#endif -SAMPLER2D(uBrdfMap, 10); -SAMPLER2D(uNoiseMap, 11); +uniform mat4 uProbeMatrix; +uniform mat4 uInvProbeMatrix; +uniform vec4 uProbeData; + +SAMPLERCUBE(uIrradianceMap, 7); +SAMPLERCUBE(uRadianceMap, 8); +SAMPLER2D(uSSIrradianceMap, 9); +SAMPLER2D(uSSRadianceMap, 10); +SAMPLER2D(uBrdfMap, 11); +SAMPLER2D(uNoiseMap, 12); SAMPLER2D(uAmbientOcclusion, 13); SAMPLER2DSHADOW(uLinearShadowMap, 14); SAMPLER2DSHADOW(uSpotShadowMap, 15); @@ -79,8 +81,7 @@ vec3 Unproject(vec3 frag_coord) { return ndc.xyz / ndc.w; } -vec3 ComputeFragCoordViewRay(vec2 frag_coord) -{ +vec3 ComputeFragCoordViewRay(vec2 frag_coord) { vec2 sp = ((frag_coord - u_viewRect.xy) / u_viewRect.zw) * 2. - 1.; sp.y *= -1.; @@ -92,3 +93,65 @@ vec3 ComputeFragCoordViewRay(vec2 frag_coord) } bool isNan(float val) { return (val <= 0.0 || 0.0 <= val) ? false : true; } + +// +vec2 RaySphere(vec3 r0, vec3 rd, vec3 s0, float sr) { + float a = dot(rd, rd); + vec3 s0_r0 = r0 - s0; + + float b = 2.0 * dot(rd, s0_r0); + float c = dot(s0_r0, s0_r0) - (sr * sr); + float disc = b * b - 4.0 * a* c; + + if (disc < 0.0) + return vec2(-1.0, -1.0); + + return vec2(-b - sqrt(disc), -b + sqrt(disc)) / (2.0 * a); +} + +vec3 RayBox(vec3 ray_origin, vec3 ray_dir, vec3 minpos, vec3 maxpos) { + vec3 inverse_dir = 1.0 / ray_dir; + vec3 tbot = inverse_dir * (minpos - ray_origin); + vec3 ttop = inverse_dir * (maxpos - ray_origin); + vec3 tmin = min(ttop, tbot); + vec3 tmax = max(ttop, tbot); + vec2 traverse = max(tmin.xx, tmin.yz); + float traverselow = max(traverse.x, traverse.y); + traverse = min(tmax.xx, tmax.yz); + float traversehi = min(traverse.x, traverse.y); + return vec3(float(traversehi > max(traverselow, 0.0)), traversehi, traverselow); +} + +vec3 ReprojectProbe(vec3 O, vec3 V) { + vec3 W; + + if (uProbeData.x == 0.0) { + vec3 local_O = mul(uInvProbeMatrix, vec4(O, 1.0)).xyz; // move ray to probe volume space + vec3 local_V = mul(uInvProbeMatrix, vec4(V, 0.0)).xyz; + local_V = normalize(local_V); + + vec2 T = RaySphere(local_O, local_V, vec3(0.0, 0.0, 0.0), 0.5); + + if (T.y > -1.0) { + vec3 local_I = local_O + local_V * T.y; + W = normalize(mul(uProbeMatrix, vec4(local_I, 0.0)).xyz); + } else { + return V; + } + } else if (uProbeData.x == 1.0) { + vec3 local_O = mul(uInvProbeMatrix, vec4(O, 1.0)).xyz; // move ray to probe volume space + vec3 local_V = mul(uInvProbeMatrix, vec4(V, 0.0)).xyz; + local_V = normalize(local_V); + + vec3 T = RayBox(local_O, local_V, vec3(-0.5, -0.5, -0.5), vec3(0.5, 0.5, 0.5)); // intersect with volume + + if (T.x == 0.0) { + return V; + } else { + vec3 local_I = local_O + local_V * T.y; + W = normalize(mul(uProbeMatrix, vec4(local_I, 0.0)).xyz); // move intersection back to world space + } + } + + return normalize(mix(V, W, uProbeData.y)); +} diff --git a/resources/core/shader/hiz_compute_cs.sc b/resources/core/shader/hiz_compute_cs.sc index e9bf7fe..184e56c 100644 --- a/resources/core/shader/hiz_compute_cs.sc +++ b/resources/core/shader/hiz_compute_cs.sc @@ -5,51 +5,49 @@ IMAGE2D_RO(u_depthTexIn, rg32f, 0); // input: level i of the min depth pyramid IMAGE2D_WR(u_depthTexOut, rg32f, 1); // output: level i+1 of the min depth pyramid -uniform vec4 u_zBounds; // near(x) far(y) unused(z,w) - NUM_THREADS(16, 16, 1) void main() { - ivec2 sizeOut = imageSize(u_depthTexOut); - ivec2 coordOut = ivec2(gl_GlobalInvocationID.xy); + ivec2 sizeOut = imageSize(u_depthTexOut); + ivec2 coordOut = ivec2(gl_GlobalInvocationID.xy); - ivec2 sizeIn = imageSize(u_depthTexIn); - ivec2 coordIn = coordOut * 2; + ivec2 sizeIn = imageSize(u_depthTexIn); + ivec2 coordIn = coordOut * 2; - vec2 z = vec2(1.0, 0.0); + vec2 z = vec2(1.0, 0.0); - // The computation is applied on all the texture area. - // It's not restricted to the actual viewport so we don't need to perform any extra check. - vec2 z0 = imageLoad(u_depthTexIn, coordIn).xy; + // The computation is applied on all the texture area. + // It's not restricted to the actual viewport so we don't need to perform any extra check. + vec2 z0 = imageLoad(u_depthTexIn, coordIn).xy; vec2 z2 = imageLoad(u_depthTexIn, coordIn + ivec2(0, 1)).xy; vec2 z1 = imageLoad(u_depthTexIn, coordIn + ivec2(1, 0)).xy; - vec2 z3 = imageLoad(u_depthTexIn, coordIn + ivec2(1, 1)).xy; - - z.x = min(min(z0.x, z1.x), min(z2.x, z3.x)); - z.y = max(max(z0.y, z1.y), max(z2.y, z3.y)); - - // Here we handle the case where the size of the previous level is odd and we are on the boundaries - // of the output texture. - // In this case, we will need to sample an extra row or column. - bvec4 odd_last = bvec4(greaterThan(sizeIn.xy, 2*sizeOut.xy), equal(coordOut, sizeOut-ivec2(1,1))); - bvec2 extra_fetch = bvec2(all(odd_last.xz), all(odd_last.yw)); - if(extra_fetch.x) { - vec2 z4 = imageLoad(u_depthTexIn, coordIn + ivec2(2,0)).xy; - vec2 z5 = imageLoad(u_depthTexIn, coordIn + ivec2(2,1)).xy; + vec2 z3 = imageLoad(u_depthTexIn, coordIn + ivec2(1, 1)).xy; + + z.x = min(min(z0.x, z1.x), min(z2.x, z3.x)); + z.y = max(max(z0.y, z1.y), max(z2.y, z3.y)); + + // Here we handle the case where the size of the previous level is odd and we are on the boundaries + // of the output texture. + // In this case, we will need to sample an extra row or column. + bvec4 odd_last = bvec4(greaterThan(sizeIn.xy, 2*sizeOut.xy), equal(coordOut, sizeOut-ivec2(1,1))); + bvec2 extra_fetch = bvec2(all(odd_last.xz), all(odd_last.yw)); + if(extra_fetch.x) { + vec2 z4 = imageLoad(u_depthTexIn, coordIn + ivec2(2,0)).xy; + vec2 z5 = imageLoad(u_depthTexIn, coordIn + ivec2(2,1)).xy; z.x = min(z.x, min(z4.x, z5.x)); z.y = max(z.y, max(z4.y, z5.y)); - } - if(extra_fetch.y) { - vec2 z6 = imageLoad(u_depthTexIn, coordIn + ivec2(0,2)).xy; - vec2 z7 = imageLoad(u_depthTexIn, coordIn + ivec2(1,2)).xy; + } + if(extra_fetch.y) { + vec2 z6 = imageLoad(u_depthTexIn, coordIn + ivec2(0,2)).xy; + vec2 z7 = imageLoad(u_depthTexIn, coordIn + ivec2(1,2)).xy; z.x = min(z.x, min(z6.x, z7.x)); z.y = max(z.y, max(z6.y, z7.y)); - - if(extra_fetch.x) { - vec2 z8 = imageLoad(u_depthTexIn, coordIn + ivec2(2,2)).xy; - z.x = min(z.x, z8.x); + + if(extra_fetch.x) { + vec2 z8 = imageLoad(u_depthTexIn, coordIn + ivec2(2,2)).xy; + z.x = min(z.x, z8.x); z.y = max(z.y, z8.y); } - } + } - imageStore(u_depthTexOut, coordOut, vec4(z.x, z.y,0,1) ); + imageStore(u_depthTexOut, coordOut, vec4(z.x, z.y, 0, 1)); } \ No newline at end of file diff --git a/resources/core/shader/hiz_copy_cs.sc b/resources/core/shader/hiz_copy_cs.sc index 3083f58..4a64ae8 100644 --- a/resources/core/shader/hiz_copy_cs.sc +++ b/resources/core/shader/hiz_copy_cs.sc @@ -6,6 +6,7 @@ SAMPLER2D(u_depth, 0); IMAGE2D_WR(u_depthTexOut, rg32f, 1); // output: level 0 of the min/max depth pyramid uniform mat4 u_projection; +uniform vec4 u_zThickness; NUM_THREADS(16, 16, 1) void main() { @@ -13,13 +14,13 @@ void main() { ivec2 coord = ivec2(gl_GlobalInvocationID.xy) + ivec2(u_viewRect.xy); #if BGFX_SHADER_LANGUAGE_GLSL - ivec2 tex_coord = ivec2(coord.x, textureSize(u_depth, 0).y - 1 - coord.y); + ivec2 tex_coord = ivec2(coord.x, textureSize(u_depth, 0).y - 1 - coord.y); #else - ivec2 tex_coord = coord; + ivec2 tex_coord = coord; #endif vec2 z; - if(all(bvec4(greaterThanEqual(coord, viewport.xy), lessThan(coord, viewport.xy + viewport.zw)))) { + if (all(bvec4(greaterThanEqual(coord, viewport.xy), lessThan(coord, viewport.xy + viewport.zw)))) { z = texelFetch(u_depth, tex_coord, 0).ww; #if BGFX_SHADER_LANGUAGE_GLSL @@ -27,7 +28,7 @@ void main() { #else vec2 q = u_projection[2].zw; #endif - z.y += 0.1 * q.x; + z.y += u_zThickness.x * q.x; // Store logarithmic depth z.xy = q.x * z.xy / (z.xy - q.yy); diff --git a/resources/core/shader/hiz_trace.sh b/resources/core/shader/hiz_trace.sh index 791d45f..c96f915 100644 --- a/resources/core/shader/hiz_trace.sh +++ b/resources/core/shader/hiz_trace.sh @@ -5,44 +5,37 @@ uniform vec4 u_depthTexInfos; // width(x) heigh(y) start mipmap level(z) max mipmap level(w) -vec3 intersect_cell_boundary(vec3 pos, vec3 dir, vec2 cell, vec2 cell_count, vec4 cross_step) { - vec2 planes = (cell + cross_step.xy) / cell_count; - vec3 intersection; - if(dir.x == 0.0) { - float delta = (planes.y - pos.y) / dir.y; - intersection = pos + dir * delta; - intersection.y += cross_step.w; +// +vec3 ray_step_cell(vec3 ray, vec3 dir, float step, vec2 z_range) { + float t_ = 100000000.0; // [EJ] any large value is ok + + if (dir.x > 0.0) + t_ = min(t_, (floor(ray.x / step + 1.0) * step - ray.x) / dir.x); + else if (dir.x < 0.0) + t_ = min(t_, (ceil(ray.x / step - 1.0) * step - ray.x) / dir.x); + + if (dir.y > 0.0) + t_ = min(t_, (floor(ray.y / step + 1.0) * step - ray.y) / dir.y); + else if (dir.y < 0.0) + t_ = min(t_, (ceil(ray.y / step - 1.0) * step - ray.y) / dir.y); + + if (dir.z > 0.0) { + if (ray.z < z_range.x) + t_ = min(t_, (z_range.x - ray.z) / dir.z); + } else if (dir.z < 0.0) { + if (ray.z > z_range.y) + t_ = min(t_, (z_range.y - ray.z) / dir.z); } - else if(dir.y == 0.0) { - float delta = (planes.x - pos.x) / dir.x; - intersection = pos + dir * delta; - intersection.x += cross_step.z; - } - else { - vec2 delta = (planes - pos.xy) / dir.xy; - intersection = pos + dir * min(delta.x, delta.y); - intersection.xy += (delta.x < delta.y) ? vec2(cross_step.z, 0.0) : vec2(0.0, cross_step.w); - } - return intersection; -} -// returns the texture size in pixels for a given pyramid level. -// textureSize(sampler, level) should be used. -// Unfortunately bgfx directx implementation always returns the size of level 0. -vec2 mip_size(int level) { - return floor(u_depthTexInfos.xy / ((level != 0) ? exp2(level) : 1.0)); + return ray + dir * t_; } -bool hiz_trace(vec3 ray_o, vec3 ray_d, mat4 proj, float z_near, int max_iterations, out vec3 ray) { - vec2 viewport_scale = uv_ratio.xy / u_depthTexInfos.xy; - vec3 viewport_min = vec3(u_viewRect.xy * viewport_scale, 0.); - vec3 viewport_max = vec3((u_viewRect.xy + u_viewRect.zw) * viewport_scale, 1.); +float hiz_trace(vec3 ray_o, vec3 ray_d, mat4 proj, float z_near, int max_iterations, out vec3 ray) { + vec3 viewport_min = vec3(u_viewRect.xy, 0.); + vec3 viewport_max = vec3(u_viewRect.xy + u_viewRect.zw, 1.); - int level_max = int(u_depthTexInfos.w); int level_min = int(u_depthTexInfos.z); - ivec2 iterations = ivec2(0, level_min); - - vec2 cell_count = mip_size(level_min); + int level_max = int(u_depthTexInfos.w); // clip to the near plane float ray_len = ((ray_o.z + ray_d.z * 1000.0) < z_near) ? (z_near - ray_o.z) / ray_d.z : 1000.0; @@ -52,97 +45,108 @@ bool hiz_trace(vec3 ray_o, vec3 ray_d, mat4 proj, float z_near, int max_iteratio vec4 h0 = mul(proj, vec4(ray_o, 1.)); vec4 h1 = mul(proj, vec4(end_point, 1.)); - // screen-space endpoints + // endpoints in screen space vec3 p0 = h0.xyz / h0.w; - p0.y *= -1.; - p0.xy = NDCToViewRect(p0.xy) / cell_count.xy; + p0.y *= -1.0; + p0.xy = NDCToViewRect(p0.xy); vec3 p1 = h1.xyz / h1.w; - p1.y *= -1.; - p1.xy = NDCToViewRect(p1.xy) / cell_count.xy; + p1.y *= -1.0; + p1.xy = NDCToViewRect(p1.xy); - // compute ray start position and direction in screen space - vec3 pos = p0; + // + ray = p0; vec3 dir = normalize(p1 - p0); - if(dir.z == 0) { - ray = vec3(-1., -1., 0.); - return false; - } + vec2 uv_offset = sign(dir.xy) * 0.0001; // slight nudge to sample the correct cell - vec4 cross_step; - cross_step.xy = step(vec2_splat(0.0), dir.xy); - cross_step.zw = (2.0 * cross_step.xy - vec2_splat(1.0)) * vec2_splat(0.5) / cell_count.xy; - - vec2 cell = floor(pos.xy * cell_count); - pos.xy = cell / cell_count + vec2_splat(0.25) / cell_count.xy; - - ray = intersect_cell_boundary(pos, dir, cell, cell_count, cross_step); - - for(iterations.x = 0; (iterations.x < max_iterations) && (iterations.y >= 0); ++iterations.x, --iterations.y) { - // check if the ray goes out of the viewport. - if(any(lessThan(ray, viewport_min))) { - return false; - } - if(any(greaterThanEqual(ray, viewport_max))) { - return false; - } - cell_count = mip_size(iterations.y); - cell = floor(ray.xy * cell_count); - - vec2 z_interval = texelFetch(u_depthTex, ivec2(cell), iterations.y).xy; - - vec3 tmp = ray; - float dz = z_interval.x - ray.z; - if (dz > 0) { - tmp = ray + dz * sign(dir.z) * dir / dir.z; - } - else { - dz = ray.z - z_interval.y; - if (dz > 0) { - tmp = ray + dz * sign(dir.z) * dir / dir.z; - } - } - vec2 new_cell = floor(tmp.xy * cell_count); - if (any(notEqual(new_cell, cell))) { - tmp = intersect_cell_boundary(ray, dir, cell, cell_count, cross_step); - iterations.y = min(level_max, iterations.y + 2); +#if 1 + int level = level_min; + + int iterations = 0; + + while (level > -1) { + if (++iterations == max_iterations) + return -1.0; + + if (any(lessThan(ray, viewport_min))) + return 0.0; // TODO ramp out + if (any(greaterThanEqual(ray, viewport_max))) + return 0.0; // TODO ramp out + + float step = pow(2.0, level); + vec2 z_range = texelFetch(u_depthTex, ivec2(ray.xy / step + uv_offset), level).xy; + + if (ray.z >= z_range.x && ray.z <= z_range.y) { + --level; + } else { + ray = ray_step_cell(ray, dir, step, z_range); + if (level < level_max - 2) + ++level; } - else if ((iterations.y == (level_min+1)) && (dz > 0.00001)) { - tmp = intersect_cell_boundary(ray, dir, cell, cell_count, cross_step); - iterations.y = 2; + } + + vec2 k_fade = saturate((ray.xy - viewport_min) / (u_viewRect.zw * 0.1)); + k_fade *= saturate(vec2(1.0, 1.0) - (ray.xy - viewport_max * 0.9) / (u_viewRect.zw * 0.1)); + + ray.xy /= u_depthTexInfos.xy; + + return k_fade.x * k_fade.y; // hit +#else + int level = 0; // reference implementation (works on any mip level) + + for (int i = 0; i < 4096; ++i) { + if (any(lessThan(ray, viewport_min))) + return false; + if (any(greaterThanEqual(ray, viewport_max))) + return false; + + float step = pow(2.0, level); + vec2 z_range = texelFetch(u_depthTex, ivec2(ray.xy / step), level).xy; + + if (ray.z >= z_range.x && ray.z <= z_range.y) { + ray.xy = ray.xy / u_depthTexInfos.xy; + return true; } - ray = tmp; + ray = ray_step_cell(ray, dir, step, z_range); } - return iterations.y < 0 && iterations.x < max_iterations; + return 0.0; +#endif } -bool TraceScreenRay(vec3 ray_o, vec3 ray_d, mat4 proj, float z_near, int max_iterations, out vec2 hit_pixel, out vec3 hit_point) { +float TraceScreenRay(vec3 ray_o, vec3 ray_d, mat4 proj, float z_near, int max_iterations, out vec2 hit_pixel, out vec3 hit_point) { vec3 ray; - if (hiz_trace(ray_o, ray_d, proj, z_near, max_iterations, ray)) { + float hit = hiz_trace(ray_o, ray_d, proj, z_near, max_iterations, ray); + + if (hit > 0.0) { // compute screen position of the hit pixel #if BGFX_SHADER_LANGUAGE_GLSL hit_pixel = vec2(ray.x, 1.0 - ray.y) * floor(uResolution.xy / uv_ratio); #else hit_pixel = ray.xy * floor(uResolution.xy / uv_ratio); #endif - - // and its world space coordinates hit_point = ray; - hit_point.xy = 2. * hit_point.xy - 1.; - hit_point.y *= -1.; - - vec4 p = mul(uMainInvProjection, vec4(hit_point, 1.)); - hit_point.xyz = p.xyz / p.w; - return true; } else { hit_pixel = vec2_splat(0.); hit_point = vec3_splat(0.); - return false; } + + return hit; +} + +float ComputeRayLogDepth(in mat4 projection, in vec3 ray) { + const float z_epsilon = 0.1; // [todo] parameter? + + float za = texelFetch(u_depthTex, ivec2(floor(ray.xy * u_depthTexInfos.xy)), 0).x; + float zb = z_epsilon * (za - projection[2].z); +#if BGFX_SHADER_LANGUAGE_GLSL + return (zb + projection[3].z * za) / (zb + projection[3].z); +#else + return (zb + projection[2].w * za) / (zb + projection[2].w); +#endif } #endif // HIZ_TRACE_SH_HEADER_GUARD diff --git a/resources/core/shader/pbr_fs.sc b/resources/core/shader/pbr_fs.sc index e337cd3..50c0549 100644 --- a/resources/core/shader/pbr_fs.sc +++ b/resources/core/shader/pbr_fs.sc @@ -39,16 +39,17 @@ float SampleShadowPCF(sampler2DShadow map, vec4 coord, float inv_pixel_size, flo #if FORWARD_PIPELINE_AAA #define PCF_SAMPLE_COUNT 2.0 // 3x3 +// float weights[9] = {0.024879, 0.107973, 0.024879, 0.107973, 0.468592, 0.107973, 0.024879, 0.107973, 0.024879}; + float weights[9] = {0.011147, 0.083286, 0.011147, 0.083286, 0.622269, 0.083286, 0.011147, 0.083286, 0.011147}; + for (float j = 0.0; j <= PCF_SAMPLE_COUNT; ++j) { - float v = (j + jitter.y) / PCF_SAMPLE_COUNT * 2.0 - 1.0; + float v = 6.0 * (j + jitter.y) / PCF_SAMPLE_COUNT - 1.0; for (float i = 0.0; i <= PCF_SAMPLE_COUNT; ++i) { - float u = (i + jitter.x) / PCF_SAMPLE_COUNT * 2.0 - 1.0; - k += SampleHardShadow(map, coord + vec4(vec2(u, v) * k_pixel_size, 0.0, 0.0), bias); + float u = 6.0 * (i + jitter.x) / PCF_SAMPLE_COUNT - 1.0; + k += SampleHardShadow(map, coord + vec4(vec2(u, v) * k_pixel_size, 0.0, 0.0), bias) * weights[j * 3 + i]; } } - - k /= (PCF_SAMPLE_COUNT + 1) * (PCF_SAMPLE_COUNT + 1); -#else +#else // FORWARD_PIPELINE_AAA // 2x2 k += SampleHardShadow(map, coord + vec4(vec2(-0.5, -0.5) * k_pixel_size, 0.0, 0.0), bias); k += SampleHardShadow(map, coord + vec4(vec2( 0.5, -0.5) * k_pixel_size, 0.0, 0.0), bias); @@ -56,7 +57,7 @@ float SampleShadowPCF(sampler2DShadow map, vec4 coord, float inv_pixel_size, flo k += SampleHardShadow(map, coord + vec4(vec2( 0.5, 0.5) * k_pixel_size, 0.0, 0.0), bias); k /= 4.0; -#endif +#endif // FORWARD_PIPELINE_AAA return k; } @@ -121,39 +122,33 @@ vec3 DistanceFog(vec3 pos, vec3 color) { // Entry point of the forward pipeline default uber shader (Phong and PBR) void main() { -#if FORWARD_PIPELINE_AAA - vec4 jitter = texture2D(uNoiseMap, mod(gl_FragCoord.xy, vec2(64, 64)) / vec2(64, 64)); -#else - vec4 jitter = vec4_splat(0.); -#endif - // #if USE_BASE_COLOR_OPACITY_MAP vec4 base_opacity = texture2D(uBaseOpacityMap, vTexCoord0); base_opacity.xyz = sRGB2linear(base_opacity.xyz); -#else +#else // USE_BASE_COLOR_OPACITY_MAP vec4 base_opacity = uBaseOpacityColor; -#endif +#endif // USE_BASE_COLOR_OPACITY_MAP - // +#if DEPTH_ONLY != 1 #if USE_OCCLUSION_ROUGHNESS_METALNESS_MAP vec4 occ_rough_metal = texture2D(uOcclusionRoughnessMetalnessMap, vTexCoord0); -#else +#else // USE_OCCLUSION_ROUGHNESS_METALNESS_MAP vec4 occ_rough_metal = uOcclusionRoughnessMetalnessColor; -#endif +#endif // USE_OCCLUSION_ROUGHNESS_METALNESS_MAP // #if USE_SELF_MAP vec4 self = texture2D(uSelfMap, vTexCoord0); -#else +#else // USE_SELF_MAP vec4 self = uSelfColor; -#endif +#endif // USE_SELF_MAP // vec3 view = mul(u_view, vec4(vWorldPos, 1.0)).xyz; vec3 P = vWorldPos; // fragment world pos - vec3 V = normalize(GetT(u_invView) - P); // view vector - vec3 N = normalize(vNormal); // geometry normal + vec3 V = normalize(GetT(u_invView) - P); // world space view vector + vec3 N = sign(dot(V, vNormal)) * normalize(vNormal); // geometry normal #if USE_NORMAL_MAP vec3 T = normalize(vTangent); @@ -164,7 +159,7 @@ void main() { N.xy = texture2D(uNormalMap, vTexCoord0).xy * 2.0 - 1.0; N.z = sqrt(1.0 - dot(N.xy, N.xy)); N = normalize(mul(N, TBN)); -#endif +#endif // USE_NORMAL_MAP vec3 R = reflect(-V, N); // view reflection vector around normal @@ -175,6 +170,13 @@ void main() { vec3 color = vec3(0.0, 0.0, 0.0); + // jitter +#if FORWARD_PIPELINE_AAA + vec4 jitter = texture2D(uNoiseMap, mod(gl_FragCoord.xy, vec2(64, 64)) / vec2(64, 64)); +#else // FORWARD_PIPELINE_AAA + vec4 jitter = vec4_splat(0.); +#endif // FORWARD_PIPELINE_AAA + // SLOT 0: linear light { float k_shadow = 1.0; @@ -188,16 +190,16 @@ void main() { } else if(view.z < uLinearShadowSlice.z * k_fade_split) { k_shadow *= SampleShadowPCF(uLinearShadowMap, vLinearShadowCoord2, uShadowState.y * 0.5, uShadowState.z, jitter); } else if(view.z < uLinearShadowSlice.w * k_fade_split) { -# if FORWARD_PIPELINE_AAA +#if FORWARD_PIPELINE_AAA k_shadow *= SampleShadowPCF(uLinearShadowMap, vLinearShadowCoord3, uShadowState.y * 0.5, uShadowState.z, jitter); -# else +#else // FORWARD_PIPELINE_AAA float pcf = SampleShadowPCF(uLinearShadowMap, vLinearShadowCoord3, uShadowState.y * 0.5, uShadowState.z, jitter); float ramp_len = (uLinearShadowSlice.w - uLinearShadowSlice.z) * 0.25; float ramp_k = clamp((view.z - (uLinearShadowSlice.w - ramp_len)) / max(ramp_len, 1e-8), 0.0, 1.0); k_shadow *= pcf * (1.0 - ramp_k) + ramp_k; -# endif +#endif // FORWARD_PIPELINE_AAA } -#endif +#endif // SLOT0_SHADOWS color += GGX(V, N, NdotV, uLightDir[0].xyz, base_opacity.xyz, occ_rough_metal.g, occ_rough_metal.b, F0, uLightDiffuse[0].xyz * k_shadow, uLightSpecular[0].xyz * k_shadow); } // SLOT 1: point/spot light (with optional shadows) @@ -209,7 +211,7 @@ void main() { #if SLOT1_SHADOWS attenuation *=SampleShadowPCF(uSpotShadowMap, vSpotShadowCoord, uShadowState.y, uShadowState.w, jitter); -#endif +#endif // SLOT1_SHADOWS color += GGX(V, N, NdotV, L, base_opacity.xyz, occ_rough_metal.g, occ_rough_metal.b, F0, uLightDiffuse[1].xyz * attenuation, uLightSpecular[1].xyz * attenuation); } // SLOT 2-N: point/spot light (no shadows) [todo] @@ -225,13 +227,7 @@ void main() { } // IBL -#if FORWARD_PIPELINE_AAA - vec4 irradiance_occlusion = texture2D(uIrradianceMap, gl_FragCoord.xy / uResolution.xy); - - vec3 irradiance = irradiance_occlusion.xyz; - vec3 radiance = texture2D(uRadianceMap, gl_FragCoord.xy / uResolution.xy).xyz; -#else - float MAX_REFLECTION_LOD = 6.; + float MAX_REFLECTION_LOD = 10.; #if 0 // LOD selection vec3 Ndx = normalize(N + ddx(N)); float dx = length(Ndx.xy / Ndx.z - N.xy / N.z) * 256.0; @@ -241,14 +237,25 @@ void main() { float dd = max(dx, dy); float lod_level = log2(dd); #endif - vec3 irradiance = textureCube(uIrradianceMap, N).xyz; - vec3 radiance = textureCubeLod(uRadianceMap, R, occ_rough_metal.y * MAX_REFLECTION_LOD).xyz; + + vec3 irradiance = textureCube(uIrradianceMap, ReprojectProbe(P, N)).xyz; + vec3 radiance = textureCubeLod(uRadianceMap, ReprojectProbe(P, R), occ_rough_metal.y * MAX_REFLECTION_LOD).xyz; + +#if FORWARD_PIPELINE_AAA + vec4 ss_irradiance = texture2D(uSSIrradianceMap, gl_FragCoord.xy / uResolution.xy); + vec4 ss_radiance = texture2D(uSSRadianceMap, gl_FragCoord.xy / uResolution.xy); + + irradiance = ss_irradiance.xyz; // mix(irradiance, ss_irradiance, ss_irradiance.w); + radiance = mix(radiance, ss_radiance, ss_radiance.w); #endif vec3 diffuse = irradiance * base_opacity.xyz; vec3 F = FresnelSchlickRoughness(NdotV, F0, occ_rough_metal.y); vec2 brdf = texture2D(uBrdfMap, vec2(NdotV, occ_rough_metal.y)).xy; vec3 specular = radiance * (F * brdf.x + brdf.y); +#if FORWARD_PIPELINE_AAA + specular *= uAAAParams[2].x; // * specular weight +#endif vec3 kS = specular; vec3 kD = vec3_splat(1.) - kS; @@ -261,21 +268,29 @@ void main() { color += self.xyz; color = DistanceFog(view, color); +#endif // DEPTH_ONLY != 1 float opacity = base_opacity.w; +#if ENABLE_ALPHA_CUT + if (opacity < 0.8) + discard; +#endif // ENABLE_ALPHA_CUT + +#if DEPTH_ONLY != 1 #if FORWARD_PIPELINE_AAA_PREPASS vec3 N_view = mul(u_view, vec4(N, 0)).xyz; vec2 velocity = vec2(vProjPos.xy / vProjPos.w - vPrevProjPos.xy / vPrevProjPos.w); gl_FragData[0] = vec4(N_view.xyz, vProjPos.z); gl_FragData[1] = vec4(velocity.xy, occ_rough_metal.y, 0.); -#else +#else // FORWARD_PIPELINE_AAA_PREPASS // incorrectly apply gamma correction at fragment shader level in the non-AAA pipeline -# if FORWARD_PIPELINE_AAA == 0 +#if FORWARD_PIPELINE_AAA != 1 float gamma = 2.2; color = pow(color, vec3_splat(1. / gamma)); -# endif +#endif // FORWARD_PIPELINE_AAA != 1 gl_FragColor = vec4(color, opacity); -#endif +#endif // FORWARD_PIPELINE_AAA_PREPASS +#endif // DEPTH_ONLY } diff --git a/resources/core/shader/pbr_vs.sc b/resources/core/shader/pbr_vs.sc index 8b9ecc9..f1b2ab9 100644 --- a/resources/core/shader/pbr_vs.sc +++ b/resources/core/shader/pbr_vs.sc @@ -34,15 +34,16 @@ void main() { mul(uPreviousModel[int(a_indices.y * 256.0)], vtx) * a_weight.y + mul(uPreviousModel[int(a_indices.z * 256.0)], vtx) * a_weight.z + mul(uPreviousModel[int(a_indices.w * 256.0)], vtx) * a_weight.w; -#endif -#else +#endif // FORWARD_PIPELINE_AAA_PREPASS +#else // ENABLE_SKINNING vec4 world_pos = mul(u_model[0], vtx); #if FORWARD_PIPELINE_AAA_PREPASS vec4 prv_world_pos = mul(uPreviousModel[0], vtx); -#endif -#endif +#endif // FORWARD_PIPELINE_AAA_PREPASS +#endif // ENABLE_SKINNING +#if DEPTH_ONLY != 1 // normal vec4 normal = vec4(a_normal * 2. - 1., 0.); @@ -56,12 +57,12 @@ void main() { skinned_normal = normalize(skinned_normal); vNormal = skinned_normal.xyz; -#else +#else // ENABLE_SKINNING vNormal = mul(normal_mat(u_model[0]), normal.xyz); -#endif +#endif // ENABLE_SKINNING // tangent frame -#if (USE_NORMAL_MAP) // [EJ] FIXME this probably won't be the only condition to compute the tangent frame for long +#if USE_NORMAL_MAP // [EJ] FIXME this probably won't be the only condition to compute the tangent frame for long vec4 tangent = vec4(a_tangent * 2.0 - 1.0, 0.0); vec4 binormal = vec4(a_bitangent * 2.0 - 1.0, 0.0); @@ -80,39 +81,42 @@ void main() { vTangent = skinned_tangent.xyz; vBinormal = skinned_binormal.xyz; -#else +#else // ENABLE_SKINNING vTangent = mul(u_model[0], tangent).xyz; vBinormal = mul(u_model[0], binormal).xyz; -#endif -#endif +#endif // ENABLE_SKINNING +#endif // USE_NORMAL_MAP // shadow data -#if (SLOT0_SHADOWS || SLOT1_SHADOWS) +#if SLOT0_SHADOWS || SLOT1_SHADOWS float shadowMapShrinkOffset = 0.01; vec3 shadowVertexShrinkOffset = vNormal * shadowMapShrinkOffset; #endif -#if (SLOT0_SHADOWS) +#if SLOT0_SHADOWS vLinearShadowCoord0 = mul(uLinearShadowMatrix[0], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); vLinearShadowCoord1 = mul(uLinearShadowMatrix[1], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); vLinearShadowCoord2 = mul(uLinearShadowMatrix[2], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); vLinearShadowCoord3 = mul(uLinearShadowMatrix[3], vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); #endif -#if (SLOT1_SHADOWS) +#if SLOT1_SHADOWS vSpotShadowCoord = mul(uSpotShadowMatrix, vec4(world_pos.xyz + shadowVertexShrinkOffset, 1.0)); #endif +#endif // DEPTH_ONLY // vWorldPos = world_pos.xyz; -#if (USE_BASE_COLOR_OPACITY_MAP || USE_OCCLUSION_ROUGHNESS_METALNESS_MAP || USE_DIFFUSE_MAP || USE_SPECULAR_MAP|| USE_NORMAL_MAP || USE_SELF_MAP || USE_OPACITY_MAP) +#if USE_BASE_COLOR_OPACITY_MAP || USE_OCCLUSION_ROUGHNESS_METALNESS_MAP || USE_DIFFUSE_MAP || USE_SPECULAR_MAP|| USE_NORMAL_MAP || USE_SELF_MAP || USE_OPACITY_MAP vTexCoord0 = a_texcoord0; #endif -#if (USE_LIGHT_MAP || USE_AMBIENT_MAP) +#if DEPTH_ONLY != 1 +#if USE_LIGHT_MAP || USE_AMBIENT_MAP vTexCoord1 = a_texcoord1; #endif +#endif // DEPTH_ONLY != 1 // vec4 proj_pos = mul(uViewProjUnjittered, world_pos); diff --git a/resources/core/shader/ssgi_fs.sc b/resources/core/shader/ssgi_fs.sc index 48d4e12..f8294fb 100644 --- a/resources/core/shader/ssgi_fs.sc +++ b/resources/core/shader/ssgi_fs.sc @@ -16,15 +16,17 @@ SAMPLER2D(u_depthTex, 5); // input: minimum depth pyramid #include #include - void main() { + vec4 color = vec4(0.0, 0.0, 0.0, 0.0); vec4 jitter = texture2D(u_noise, mod(gl_FragCoord.xy, vec2(64, 64)) / vec2(64, 64)); // sample normal/depth vec2 uv = GetAttributeTexCoord(vTexCoord0, textureSize(u_attr0, 0).xy); vec4 attr0 = texture2D(u_attr0, uv); - vec3 n = attr0.xyz; + vec3 n = normalize(attr0.xyz); + if (isNan(n.x) || isNan(n.y) |isNan(n.z)) + n = vec3(0, 1, 0); // compute ray origin & direction vec3 ray_o = GetRayOrigin(uMainProjection, v_viewRay, attr0.w); @@ -34,7 +36,6 @@ void main() { vec3 up = cross(n, right); // - vec4 color = vec4_splat(0.); const float z_min = 0.1; for (int i = 0; i < int(sample_count); ++i) { @@ -49,30 +50,33 @@ void main() { vec2 hit_pixel; vec3 hit_point; - if (TraceScreenRay(ray_o - v_viewRay * 0.05, ray_d_spread, uMainProjection, z_min, /*jitter.z,*/ 64, hit_pixel, hit_point)) { + float k = TraceScreenRay(ray_o - v_viewRay * 0.05, ray_d_spread, uMainProjection, z_min, 192, hit_pixel, hit_point); + + if (k > 0.0) { // use hit pixel velocity to compensate the fact that we are sampling the previous frame - vec2 uv = hit_pixel * uv_ratio / uResolution.xy; + uv = hit_pixel * uv_ratio / uResolution.xy; vec2 vel = GetVelocityVector(uv); - vec4 attr0 = texelFetch(u_attr0, ivec2(hit_pixel), 0); + attr0 = texelFetch(u_attr0, ivec2(hit_pixel), 0); + + float log_depth = ComputeRayLogDepth(uMainProjection, hit_point); - if (dot(attr0.xyz, ray_d_spread) < 0.0) { // ray facing the collision + if ((dot(attr0.xyz, ray_d_spread) < 0.0) && (hit_point.z <= log_depth)) { // ray facing the collision vec3 irradiance = texture2D(u_color, uv - vel * uv_ratio).xyz; - color += vec4(irradiance * 1.0, 0.0); + color += vec4(irradiance, 1.0); } else { color += vec4(0.0, 0.0, 0.0, 0.0); // backface hit } } else { vec3 world_ray_d_spread = mul(uMainInvView, vec4(ray_d_spread, 0.0)).xyz; - color += vec4(textureCubeLod(u_probe, world_ray_d_spread, 0).xyz, 1.); + vec3 world_ray_o = mul(uMainInvView, vec4(ray_o, 1.0)).xyz; + color += vec4(textureCubeLod(u_probe, ReprojectProbe(world_ray_o, world_ray_d_spread), 0).xyz, 0.); } } } -#if 1 - if (isNan(color.x) || isNan(color.y) || isNan(color.z)) - color = vec4(1., 0., 0., 1.); -#endif + color /= sample_count * sample_count; + color = (saturate(color) / 32.0) * 32.0; - gl_FragColor = color / (sample_count * sample_count); + gl_FragColor = color; } diff --git a/resources/core/shader/ssr_fs.sc b/resources/core/shader/ssr_fs.sc index b8b0808..6c693e7 100644 --- a/resources/core/shader/ssr_fs.sc +++ b/resources/core/shader/ssr_fs.sc @@ -16,30 +16,49 @@ SAMPLER2D(u_depthTex, 5); // input: minimum depth pyramid #include #include - void main() { + vec4 color = vec4(0.0, 0.0, 0.0, 0.0); vec4 jitter = texture2D(u_noise, mod(gl_FragCoord.xy, vec2(64, 64)) / vec2(64, 64)); // sample normal/depth vec2 uv = GetAttributeTexCoord(vTexCoord0, textureSize(u_attr0, 0).xy); vec4 attr0 = texture2D(u_attr0, uv); - vec3 n = attr0.xyz; + vec3 n = normalize(attr0.xyz); + if (isNan(n.x) || isNan(n.y) |isNan(n.z)) + n = vec3(0, 1, 0); // compute ray origin & direction vec3 ray_o = GetRayOrigin(uMainProjection, v_viewRay, attr0.w); vec3 ray_d = reflect(normalize(ray_o), n); - // roughness + const float z_min = 0.1; + +#if 0 + vec2 hit_pixel; + vec3 hit_point; + + float k = TraceScreenRay(ray_o - v_viewRay * 0.05, ray_d, uMainProjection, z_min, 4096, hit_pixel, hit_point); + + if (k > 0.0) { + uv = hit_pixel * uv_ratio / uResolution.xy; + vec2 vel = GetVelocityVector(uv); + color = mix(color, vec4(texture2D(u_color, uv - vel * uv_ratio).xyz, 1.0), k); + } else if (k == 0.0) { + color = vec4(1.0, 0.0, 0.0, 0.0); + } else if (k == -1) { + color = vec4(0.0, 1.0, 0.0, 0.0); // max iteration reached (most likely due to a bug) + } +#else float roughness = texture2D(u_attr1, uv).z; + roughness = pow(roughness, 2.5); vec3 right = cross(ray_d, vec3(0, 0, 1)); vec3 up = cross(ray_d, right); - - const float z_min = 0.1; // - vec4 color = vec4_splat(0.); + vec3 world_ray_o = mul(uMainInvView, vec4(ray_o, 1.0)).xyz; + for (int i = 0; i < int(sample_count); ++i) { float r = roughness * (float(i) + jitter.y) / sample_count; float spread = r * 3.141592 * 0.5 * 0.99; @@ -49,31 +68,35 @@ void main() { float angle = float(j + jitter.w) / sample_count * 2. * 3.141592; vec3 ray_d_spread = (right * cos(angle) + up * sin(angle)) * sin_spread + ray_d * cos_spread; + vec3 world_ray_d = mul(uMainInvView, vec4(ray_d_spread, 0.0)).xyz; + vec4 fallback = vec4(textureCubeLod(u_probe, ReprojectProbe(world_ray_o, world_ray_d), 0).xyz, 0.); + vec2 hit_pixel; vec3 hit_point; - if (TraceScreenRay(ray_o - v_viewRay * 0.05, ray_d_spread, uMainProjection, z_min, /*jitter.z,*/ 64, hit_pixel, hit_point)) { + float k = TraceScreenRay(ray_o - v_viewRay * 0.05, ray_d_spread, uMainProjection, z_min, 192, hit_pixel, hit_point); + + if (k > 0.0) { // use hit pixel velocity to compensate the fact that we are sampling the previous frame uv = hit_pixel * uv_ratio / uResolution.xy; vec2 vel = GetVelocityVector(uv); - - vec4 attr0 = texelFetch(u_attr0, ivec2(hit_pixel), 0); - - if (dot(attr0.xyz, ray_d_spread) < 0.0) { - color += vec4(texture2D(u_color, uv - vel * uv_ratio).xyz, 0.); - } else { - color += vec4(0.0, 0.0, 0.0, 0.0); // backface hit - } + + attr0 = texelFetch(u_attr0, ivec2(hit_pixel), 0); + + float log_depth = ComputeRayLogDepth(uMainProjection, hit_point); + + vec4 output = vec4(0.0, 0.0, 0.0, 1.0); // assume backface hit + if (dot(attr0.xyz, ray_d_spread) < 0.0 && hit_point.z <= log_depth) + output = vec4(texture2D(u_color, uv - vel * uv_ratio).xyz, 1.0); // front face hit + + color += mix(fallback, output, k); } else { - vec3 world_ray_d_spread = mul(uMainInvView, vec4(ray_d_spread, 0.0)).xyz; - color += vec4(textureCubeLod(u_probe, world_ray_d_spread, 0).xyz, 1.); + color += fallback; } } } -#if 1 - if (isNan(color.x) || isNan(color.y) || isNan(color.z)) - color = vec4(1., 0., 0., 1.); + color /= sample_count * sample_count; #endif - gl_FragColor = color / (sample_count * sample_count); + gl_FragColor = color; } diff --git a/resources/core/shader/taa_fs.sc b/resources/core/shader/taa_fs.sc index 4836804..8237b94 100644 --- a/resources/core/shader/taa_fs.sc +++ b/resources/core/shader/taa_fs.sc @@ -10,6 +10,7 @@ SAMPLER2D(u_attr1, 3); #define AABB_CLAMPING 0 #define AABB_CLAMPING_FAST 1 #define VARIANCE_CLIPPING_GAMMA 0 // https://community.arm.com/developer/tools-software/graphics/b/blog/posts/temporal-anti-aliasing +#define LUMINANCE_AJDUST 1 void main() { vec2 uv = gl_FragCoord.xy / uResolution.xy; @@ -81,7 +82,20 @@ void main() { prv_color = clamp(prv_color, box_min, box_max); #endif +#if LUMINANCE_AJDUST + const vec3 luminance = vec3(0.2127, 0.7152, 0.0722); + + float l0 = dot(luminance, prv_color); + float l1 = dot(luminance, color); + + float w1 = (uAAAParams[0].z) / (1.0 + l1); + float w0 = (1.0 - uAAAParams[0].z) / (1.0 + l0); + + vec3 taa_out = (w1 * color + w0 * prv_color) / max(w0 + w1, 0.00001); + gl_FragColor = vec4(taa_out, 1.); +#else // TAA vec3 taa_out = color * uAAAParams[0].z + prv_color * (1. - uAAAParams[0].z); gl_FragColor = vec4(taa_out, 1.); +#endif } diff --git a/resources/sounds/metro_announce.ogg b/resources/sounds/metro_announce.ogg new file mode 100644 index 0000000..5edb891 Binary files /dev/null and b/resources/sounds/metro_announce.ogg differ diff --git a/scene_aaa.lua b/scene_aaa.lua index 93c8745..5dff4f8 100644 --- a/scene_aaa.lua +++ b/scene_aaa.lua @@ -28,7 +28,7 @@ pipeline_aaa_config.sample_count = 1 -- main loop frame = 0 -while not hg.Keyboard():Down(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() trs = scene:GetNode('engine_master'):GetTransform() diff --git a/scene_aaa.py b/scene_aaa.py index 192713f..6481cec 100644 --- a/scene_aaa.py +++ b/scene_aaa.py @@ -27,7 +27,7 @@ # main loop frame = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() trs = scene.GetNode('engine_master').GetTransform() diff --git a/scene_draw_to_multiple_viewports.lua b/scene_draw_to_multiple_viewports.lua index 296b8b0..8b0e664 100644 --- a/scene_draw_to_multiple_viewports.lua +++ b/scene_draw_to_multiple_viewports.lua @@ -40,14 +40,14 @@ hg.CreateObject(scene, hg.TranslationMat4(hg.Vec3(0, 0, 0)), ground_ref, {mat_gr -- define viewports viewports = { - {rect = hg.IntRect(0, 0, res_x / 2, res_y / 2), cam_pos = hg.Vec3(-4.015, 2.368, -3.484), cam_rot = hg.Vec3(0.35, 0.87, 0.0)}, - {rect = hg.IntRect(res_x / 2, 0, res_x, res_y / 2), cam_pos = hg.Vec3(-4.143, 2.976, 4.127), cam_rot = hg.Vec3(0.423, 2.365, 0.0)}, - {rect = hg.IntRect(0, res_y / 2, res_x / 2, res_y), cam_pos = hg.Vec3(4.020, 2.374, 3.469), cam_rot = hg.Vec3(0.353, 4.016, 0.0)}, - {rect = hg.IntRect(res_x / 2, res_y / 2, res_x, res_y), cam_pos = hg.Vec3(3.469, 2.374, -4.020), cam_rot = hg.Vec3(0.353, -0.695, 0.0)} + {rect = hg.IntRect(0, 0, res_x // 2, res_y // 2), cam_pos = hg.Vec3(-4.015, 2.368, -3.484), cam_rot = hg.Vec3(0.35, 0.87, 0.0)}, + {rect = hg.IntRect(res_x // 2, 0, res_x, res_y // 2), cam_pos = hg.Vec3(-4.143, 2.976, 4.127), cam_rot = hg.Vec3(0.423, 2.365, 0.0)}, + {rect = hg.IntRect(0, res_y // 2, res_x // 2, res_y), cam_pos = hg.Vec3(4.020, 2.374, 3.469), cam_rot = hg.Vec3(0.353, 4.016, 0.0)}, + {rect = hg.IntRect(res_x // 2, res_y // 2, res_x, res_y), cam_pos = hg.Vec3(3.469, 2.374, -4.020), cam_rot = hg.Vec3(0.353, -0.695, 0.0)} } -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() -- animate yellow cube & update scene once for all viewports diff --git a/scene_draw_to_multiple_viewports.py b/scene_draw_to_multiple_viewports.py index 5369299..6098514 100644 --- a/scene_draw_to_multiple_viewports.py +++ b/scene_draw_to_multiple_viewports.py @@ -47,7 +47,7 @@ ] # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() # animate yellow cube & update scene once for all viewports diff --git a/scene_draw_to_texture.lua b/scene_draw_to_texture.lua index 1ce3bcb..d63e550 100644 --- a/scene_draw_to_texture.lua +++ b/scene_draw_to_texture.lua @@ -34,7 +34,7 @@ cube_prg = hg.LoadProgramFromAssets('shaders/texture') -- main loop angle = 0 -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/scene_draw_to_texture.py b/scene_draw_to_texture.py index a466cc0..05e1bf8 100644 --- a/scene_draw_to_texture.py +++ b/scene_draw_to_texture.py @@ -35,7 +35,7 @@ # main loop angle = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/scene_instances.lua b/scene_instances.lua index ebfe8ef..e44e91c 100644 --- a/scene_instances.lua +++ b/scene_instances.lua @@ -95,7 +95,7 @@ print(string.format('%d nodes in scene', scene:GetAllNodeCount())) -- main loop keyboard = hg.Keyboard() -while not keyboard:Pressed(hg.K_Escape) do +while not keyboard:Down(hg.K_Escape) and hg.IsWindowOpen(win) do _, res_x, res_y = hg.RenderResetToWindow(win, res_x, res_y, hg.RF_VSync | hg.RF_MSAA4X | hg.RF_MaxAnisotropy) keyboard:Update() diff --git a/scene_instances.py b/scene_instances.py index 44905d9..d0fe4dd 100644 --- a/scene_instances.py +++ b/scene_instances.py @@ -77,7 +77,7 @@ def destroy(self): # main loop keyboard = hg.Keyboard() -while not keyboard.Pressed(hg.K_Escape): +while not keyboard.Down(hg.K_Escape) and hg.IsWindowOpen(win): _, res_x, res_y = hg.RenderResetToWindow(win, res_x, res_y, hg.RF_VSync | hg.RF_MSAA4X | hg.RF_MaxAnisotropy) keyboard.Update() diff --git a/scene_light_priority.lua b/scene_light_priority.lua index c5fbf42..6f2ade0 100644 --- a/scene_light_priority.lua +++ b/scene_light_priority.lua @@ -55,7 +55,7 @@ end -- main loop angle = 0 -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() -- animate lights diff --git a/scene_light_priority.py b/scene_light_priority.py index c39cd64..14f99fb 100644 --- a/scene_light_priority.py +++ b/scene_light_priority.py @@ -55,7 +55,7 @@ # main loop angle = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() # animate lights diff --git a/scene_many_nodes.lua b/scene_many_nodes.lua index 3202f56..82474a6 100644 --- a/scene_many_nodes.lua +++ b/scene_many_nodes.lua @@ -50,7 +50,7 @@ end -- main loop angle = 0 -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() angle = angle + hg.time_to_sec_f(dt) diff --git a/scene_many_nodes.py b/scene_many_nodes.py index 5865e6f..20405f2 100644 --- a/scene_many_nodes.py +++ b/scene_many_nodes.py @@ -49,7 +49,7 @@ # main loop angle = 0 -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() angle += hg.time_to_sec_f(dt) diff --git a/scene_pbr.lua b/scene_pbr.lua index 5241ef9..3540eaa 100644 --- a/scene_pbr.lua +++ b/scene_pbr.lua @@ -19,7 +19,7 @@ scene = hg.Scene() hg.LoadSceneFromAssets("materials/materials.scn", scene, res, hg.GetForwardPipelineInfo()) -- main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() scene:Update(dt) diff --git a/scene_pbr.py b/scene_pbr.py index c645e36..0ad2cb9 100644 --- a/scene_pbr.py +++ b/scene_pbr.py @@ -19,7 +19,7 @@ hg.LoadSceneFromAssets("materials/materials.scn", scene, res, hg.GetForwardPipelineInfo()) # main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() scene.Update(dt) diff --git a/scene_vr.lua b/scene_vr.lua index 2b3de54..97437d6 100644 --- a/scene_vr.lua +++ b/scene_vr.lua @@ -77,7 +77,7 @@ quad_uniform_set_value_list:push_back(hg.MakeUniformSetValue("color", hg.Vec4(1, quad_uniform_set_texture_list = hg.UniformSetTextureList() -- Main loop -while not hg.ReadKeyboard():Key(hg.K_Escape) do +while not hg.ReadKeyboard():Key(hg.K_Escape) and hg.IsWindowOpen(win) do dt = hg.TickClock() scene:Update(dt) diff --git a/scene_vr.py b/scene_vr.py index db3a210..393d636 100644 --- a/scene_vr.py +++ b/scene_vr.py @@ -77,7 +77,7 @@ def create_material(ubc, orm): quad_uniform_set_texture_list = hg.UniformSetTextureList() # Main loop -while not hg.ReadKeyboard().Key(hg.K_Escape): +while not hg.ReadKeyboard().Key(hg.K_Escape) and hg.IsWindowOpen(win): dt = hg.TickClock() scene.Update(dt)