diff --git a/Nasal/hdr.nas b/Nasal/hdr.nas index 69c2353e9..075431558 100644 --- a/Nasal/hdr.nas +++ b/Nasal/hdr.nas @@ -38,30 +38,64 @@ setprop("/sim/rendering/hdr/atmos/ground-albedo[3]", 0.4); ################################################################################ # Environment map ################################################################################ + var envmap_frame_listener = nil; var is_envmap_updating = false; + var is_prefiltering_active = false; var current_envmap_face = 0; -var envmap_update_frame = func { +var all_faces_active = false; + +var envmap_set_render_face = func(face, active) { + setprop("/sim/rendering/hdr/envmap/should-render-face-" ~ face, active); +} + +var envmap_set_render_all_faces = func(active) { + for (var i = 0; i < 6; i += 1) { + envmap_set_render_face(i, active); + } +} + +var envmap_set_prefilter = func(active) { + setprop("/sim/rendering/hdr/envmap/should-prefilter", active); +} + +# Update all the faces of the environment cubemap in a single frame +var envmap_update_all_faces_callback = func { + if (all_faces_active) { + if (envmap_frame_listener != nil) + removelistener(envmap_frame_listener); + envmap_set_render_all_faces(false); + envmap_set_prefilter(false); + is_envmap_updating = false; + all_faces_active = false; + } else { + envmap_set_render_all_faces(true); + envmap_set_prefilter(true); + all_faces_active = true; + } +} + +# Update a single cubemap face each frame. The prefiltering step is also done +# in a separate step, totalling 7 frames to update the entire environment map. +var envmap_update_frame_callback = func { if (is_prefiltering_active) { # Last frame we activated the prefiltering, which is the last step. # Now disable it and reset all variables for the next update cycle. removelistener(envmap_frame_listener); - setprop("/sim/rendering/hdr/envmap/should-prefilter", false); + envmap_set_prefilter(false); is_prefiltering_active = false; is_envmap_updating = false; return; } if (current_envmap_face < 6) { # Render the current face - setprop("/sim/rendering/hdr/envmap/should-render-face-" - ~ current_envmap_face, true); + envmap_set_render_face(current_envmap_face, true); } if (current_envmap_face > 0) { # Stop rendering the previous face - setprop("/sim/rendering/hdr/envmap/should-render-face-" - ~ (current_envmap_face - 1), false); + envmap_set_render_face(current_envmap_face - 1, false); } if (current_envmap_face < 6) { # Go to next face and update it next frame @@ -71,25 +105,38 @@ var envmap_update_frame = func { # prefilter the envmap. current_envmap_face = 0; is_prefiltering_active = true; - setprop("/sim/rendering/hdr/envmap/should-prefilter", true); + envmap_set_prefilter(true); } } -var update_envmap = func { - if (!is_envmap_updating) { +var update_envmap = func(instant = false) { + if (is_envmap_updating) { + # We are currently updating the envmap, so cancel and start over + if (envmap_frame_listener != nil) + removelistener(envmap_frame_listener); + + is_prefiltering_active = false; + all_faces_active = false; + current_envmap_face = 0; + + envmap_set_render_all_faces(false); + envmap_set_prefilter(false); + } else { is_envmap_updating = true; - # We use a listener to the frame signal because it is guaranteed to be - # fired at a defined moment, while a settimer() with interval 0 might - # not if subsystems are re-ordered. - envmap_frame_listener = setlistener("/sim/signals/frame", - envmap_update_frame); } + + var callback = instant ? envmap_update_all_faces_callback + : envmap_update_frame_callback; + # We use a listener to the frame signal because it is guaranteed to be + # fired at a defined moment, while a settimer() with interval 0 might + # not if subsystems are re-ordered. + envmap_frame_listener = setlistener("/sim/signals/frame", callback); } # Manual update setlistener("/sim/rendering/hdr/envmap/force-update", func(p) { if (p.getValue()) { - update_envmap(); + update_envmap(true); p.setValue(false); } }, 0, 0); @@ -107,6 +154,8 @@ setlistener("/sim/signals/fdm-initialized", func { settimer(update_envmap, 5); }); +# If the update rate is modified at runtime, force an envmap update and restart +# the timer with the new period. setlistener("/sim/rendering/hdr/envmap/update-rate-s", func(p) { if (envmap_timer.isRunning) { update_envmap(); @@ -115,7 +164,11 @@ setlistener("/sim/rendering/hdr/envmap/update-rate-s", func(p) { }); # Update the envmap much faster when time warp is active -var envmap_timer_warp = maketimer(1, update_envmap); +var envmap_timer_warp = maketimer(1, func() { + update_envmap(true); +}); +envmap_timer_warp.simulatedTime = true; + setlistener("/sim/time/warp-delta", func(p) { if (p.getValue() != 0) { envmap_timer_warp.start(); @@ -126,3 +179,8 @@ setlistener("/sim/time/warp-delta", func(p) { settimer(update_envmap, 1); } }); + +# Update the envmap when the view changes +setlistener("/sim/current-view/view-number", func { + update_envmap(true); +}, 0, 0);