Fix errors

This commit is contained in:
2026-04-24 00:25:29 -07:00
parent f68524a6ae
commit 01c1db41db
34 changed files with 361 additions and 210 deletions

View File

@@ -661,11 +661,87 @@ PPIScope : public Scope (abstract) — shared PPI behavior:
- Cursor range/bearing readout under scope (white text) - Cursor range/bearing readout under scope (white text)
- Bearing offset for boat mode (k/j) - Bearing offset for boat mode (k/j)
- Cursor range clamped to max range - Cursor range clamped to max range
- Range rings and labels are beam-painted per sweep sector, NOT a static overlay; - Range rings are beam-painted per sweep sector with P7 persistence and decay;
the sweep shader evaluates ring radii for the CURRENT max range at the moment however they are stored in the GAIN-INDEPENDENT G channel of the phosphor FBO
each beam angle is rendered; the phosphor buffer retains whatever was last (see PHOSPHOR FBO ARCHITECTURE below) so operator gain does not dim the rings
written, so old ring positions fade naturally as the sweep overwrites them with - renderRingLabels() — virtual method (default no-op); concrete PPI scopes that
new geometry — no special transition code required have labelled range rings override this to render mile-distance text labels in
P7 fresh-blue colour at a fixed bearing (RING_LABEL_BRG_DEG = 045°)
IMPLEMENTER CHECKLIST — required in every new PPIScope subclass:
1. computeRingRadii(): multiply each normalised ring radius by
GRAT_INNER_RING_FRAC (same as MarinePPIScope). Omitting this
places the outer ring at the scope boundary where it is clipped
and hidden behind the graticule. Target positions are scaled
automatically by PhosphorRenderer::update(); ring radii are not.
2. Override renderRingLabels() using the same pattern as
MarinePPIScope::renderRingLabels() but with the scope's own
ring-mile table. The base-class no-op produces no labels.
The p7Color() fix, two-channel FBO gain-separation, and target
position scaling are all automatic via the shared PhosphorRenderer
and shaders — no per-scope action required for those.
==================================================================
PHOSPHOR FBO ARCHITECTURE
==================================================================
The phosphor FBO is GL_RG32F (two independent float channels):
R channel — signal energy
Written by: target echoes in the sweep shader
Multiplied by: u_gain in the display shader
Effect: operator gain knob dims/brightens received echoes without
affecting the sweep beam or range rings
G channel — timing/geometry energy
Written by: range rings + sweep background glow in the sweep shader
NOT multiplied by gain in the display shader
Effect: rings always appear at a fixed brightness; the rotating
sweep-line glow is always visible even at minimum gain
Both channels decay at the same P7 rate (P7_DECAY_RATE in settings.h).
The display shader combines them: totalEnergy = max(R * gain, G).
This produces the correct visual priority: a strong target echo always
shows above the ring but a dim echo below gain threshold fades away
while the ring stays steady.
RANGE POSITION NORMALISATION
All ring radii and target range values are normalised so that
max-range maps to GRAT_INNER_RING_FRAC (0.915), NOT 1.0.
Normalised 1.0 is the outer edge of the phosphor circle (scope boundary).
The bearing graticule overlay occupies 0.915 to 0.985 of scope radius.
If max-range mapped to 1.0, the outer ring would sit at the scope
boundary — half-clipped by the sweep shader's rng > 1.0 early-exit and
visually hidden behind the graticule outer ring.
Mapping max-range → GRAT_INNER_RING_FRAC keeps all rings and targets
within the clean active display area inside the bearing scale overlay.
Scale is applied in two places:
1. PhosphorRenderer::update() — target range: × GRAT_INNER_RING_FRAC
2. computeRingRadii() in each concrete PPI scope — ring radii: × GRAT_INNER_RING_FRAC
P7 COLOUR FUNCTION
p7Color() in phosphor.frag is a piecewise linear ramp over [0, 1]:
e ≥ T_BLUE (0.82) → pure C_BLUE
[T_GREEN, T_BLUE) → mix(C_GREEN, C_BLUE, normalised within range)
[T_YGREE, T_GREEN) → mix(C_YGREE, C_GREEN, normalised within range)
[T_DARK, T_YGREE) → mix(C_YELLW, C_YGREE, normalised within range)
[0, T_DARK) → mix(C_BLACK, C_YELLW, normalised within range)
Each mix() factor is in [0, 1] and the function is continuous at every
threshold boundary. An earlier version had each branch using the formula
of the branch below it (off-by-one), which caused SWEEP_BACKGROUND_ENERGY
= 0.10 to render as saturated yellow (factor 3.33) instead of dim
yellow-green, producing an unwanted solid-yellow band behind the sweep.
==================================================================
MarinePPIScope : public PPIScope MarinePPIScope : public PPIScope
- Sweep time: 4 seconds - Sweep time: 4 seconds

View File

@@ -351,6 +351,8 @@ CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
CMAKE_DLLTOOL-ADVANCED:INTERNAL=1 CMAKE_DLLTOOL-ADVANCED:INTERNAL=1
//Path to cache edit program executable. //Path to cache edit program executable.
CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/cmake-gui CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/cmake-gui
//Whether to issue deprecation errors for macros and functions.
CMAKE_ERROR_DEPRECATED:INTERNAL=FALSE
//Executable file format //Executable file format
CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF
//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS //ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS
@@ -440,12 +442,20 @@ CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1
CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1
//ADVANCED property for variable: CMAKE_STRIP //ADVANCED property for variable: CMAKE_STRIP
CMAKE_STRIP-ADVANCED:INTERNAL=1 CMAKE_STRIP-ADVANCED:INTERNAL=1
//Suppress errors that are meant for the author of the CMakeLists.txt
// files.
CMAKE_SUPPRESS_DEVELOPER_ERRORS:INTERNAL=TRUE
//Suppress Warnings that are meant for the author of the CMakeLists.txt
// files.
CMAKE_SUPPRESS_DEVELOPER_WARNINGS:INTERNAL=TRUE
//ADVANCED property for variable: CMAKE_TAPI //ADVANCED property for variable: CMAKE_TAPI
CMAKE_TAPI-ADVANCED:INTERNAL=1 CMAKE_TAPI-ADVANCED:INTERNAL=1
//uname command //uname command
CMAKE_UNAME:INTERNAL=/usr/bin/uname CMAKE_UNAME:INTERNAL=/usr/bin/uname
//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE //ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE
CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1
//Whether to issue warnings for deprecated functionality.
CMAKE_WARN_DEPRECATED:INTERNAL=FALSE
//Details about finding Freetype //Details about finding Freetype
FIND_PACKAGE_MESSAGE_DETAILS_Freetype:INTERNAL=[/usr/lib/x86_64-linux-gnu/libfreetype.so][/usr/include/freetype2][v2.14.2()] FIND_PACKAGE_MESSAGE_DETAILS_Freetype:INTERNAL=[/usr/lib/x86_64-linux-gnu/libfreetype.so][/usr/include/freetype2][v2.14.2()]
//Details about finding OpenGL //Details about finding OpenGL

View File

@@ -11,98 +11,21 @@ set(CMAKE_MAKEFILE_DEPENDS
"CMakeFiles/4.2.3/CMakeCCompiler.cmake" "CMakeFiles/4.2.3/CMakeCCompiler.cmake"
"CMakeFiles/4.2.3/CMakeCXXCompiler.cmake" "CMakeFiles/4.2.3/CMakeCXXCompiler.cmake"
"CMakeFiles/4.2.3/CMakeSystem.cmake" "CMakeFiles/4.2.3/CMakeSystem.cmake"
"/usr/share/cmake-4.2/Modules/CMakeCCompiler.cmake.in"
"/usr/share/cmake-4.2/Modules/CMakeCCompilerABI.c"
"/usr/share/cmake-4.2/Modules/CMakeCInformation.cmake" "/usr/share/cmake-4.2/Modules/CMakeCInformation.cmake"
"/usr/share/cmake-4.2/Modules/CMakeCXXCompiler.cmake.in"
"/usr/share/cmake-4.2/Modules/CMakeCXXCompilerABI.cpp"
"/usr/share/cmake-4.2/Modules/CMakeCXXInformation.cmake" "/usr/share/cmake-4.2/Modules/CMakeCXXInformation.cmake"
"/usr/share/cmake-4.2/Modules/CMakeCommonLanguageInclude.cmake" "/usr/share/cmake-4.2/Modules/CMakeCommonLanguageInclude.cmake"
"/usr/share/cmake-4.2/Modules/CMakeCompilerIdDetection.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineCCompiler.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineCXXCompiler.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineCompilerABI.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineCompilerId.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineCompilerSupport.cmake"
"/usr/share/cmake-4.2/Modules/CMakeDetermineSystem.cmake"
"/usr/share/cmake-4.2/Modules/CMakeFindBinUtils.cmake"
"/usr/share/cmake-4.2/Modules/CMakeGenericSystem.cmake" "/usr/share/cmake-4.2/Modules/CMakeGenericSystem.cmake"
"/usr/share/cmake-4.2/Modules/CMakeInitializeConfigs.cmake" "/usr/share/cmake-4.2/Modules/CMakeInitializeConfigs.cmake"
"/usr/share/cmake-4.2/Modules/CMakeLanguageInformation.cmake" "/usr/share/cmake-4.2/Modules/CMakeLanguageInformation.cmake"
"/usr/share/cmake-4.2/Modules/CMakeParseImplicitIncludeInfo.cmake"
"/usr/share/cmake-4.2/Modules/CMakeParseImplicitLinkInfo.cmake"
"/usr/share/cmake-4.2/Modules/CMakeParseLibraryArchitecture.cmake"
"/usr/share/cmake-4.2/Modules/CMakeSystem.cmake.in"
"/usr/share/cmake-4.2/Modules/CMakeSystemSpecificInformation.cmake" "/usr/share/cmake-4.2/Modules/CMakeSystemSpecificInformation.cmake"
"/usr/share/cmake-4.2/Modules/CMakeSystemSpecificInitialize.cmake" "/usr/share/cmake-4.2/Modules/CMakeSystemSpecificInitialize.cmake"
"/usr/share/cmake-4.2/Modules/CMakeTestCCompiler.cmake"
"/usr/share/cmake-4.2/Modules/CMakeTestCXXCompiler.cmake"
"/usr/share/cmake-4.2/Modules/CMakeTestCompilerCommon.cmake"
"/usr/share/cmake-4.2/Modules/CMakeUnixFindMake.cmake"
"/usr/share/cmake-4.2/Modules/CheckCSourceCompiles.cmake" "/usr/share/cmake-4.2/Modules/CheckCSourceCompiles.cmake"
"/usr/share/cmake-4.2/Modules/CheckIncludeFile.cmake" "/usr/share/cmake-4.2/Modules/CheckIncludeFile.cmake"
"/usr/share/cmake-4.2/Modules/CheckLibraryExists.cmake" "/usr/share/cmake-4.2/Modules/CheckLibraryExists.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/ADSP-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/ARMCC-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/ARMClang-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/AppleClang-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Borland-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Bruce-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/CMakeCommonCompilerMacros.cmake" "/usr/share/cmake-4.2/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Clang-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Clang-DetermineCompilerInternal.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Compaq-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Compaq-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Cray-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/CrayClang-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Diab-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Embarcadero-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Fujitsu-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GHS-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GNU-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GNU-C.cmake" "/usr/share/cmake-4.2/Modules/Compiler/GNU-C.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GNU-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GNU-CXX.cmake" "/usr/share/cmake-4.2/Modules/Compiler/GNU-CXX.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GNU-FindBinUtils.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/GNU.cmake" "/usr/share/cmake-4.2/Modules/Compiler/GNU.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/HP-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/HP-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/IAR-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/IBMCPP-CXX-DetermineVersionInternal.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/IBMClang-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Intel-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/LCC-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/LCC-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/MSVC-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/NVHPC-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/NVIDIA-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/OrangeC-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/PGI-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/PathScale-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Renesas-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/SCO-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/SDCC-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/SunPro-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/SunPro-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/TI-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/TIClang-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Tasking-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/VisualAge-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/Watcom-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/XL-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/XL-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/XLClang-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/XLClang-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/zOS-C-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/Compiler/zOS-CXX-DetermineCompiler.cmake"
"/usr/share/cmake-4.2/Modules/FindFreetype.cmake" "/usr/share/cmake-4.2/Modules/FindFreetype.cmake"
"/usr/share/cmake-4.2/Modules/FindOpenGL.cmake" "/usr/share/cmake-4.2/Modules/FindOpenGL.cmake"
"/usr/share/cmake-4.2/Modules/FindPackageHandleStandardArgs.cmake" "/usr/share/cmake-4.2/Modules/FindPackageHandleStandardArgs.cmake"
@@ -112,11 +35,7 @@ set(CMAKE_MAKEFILE_DEPENDS
"/usr/share/cmake-4.2/Modules/Internal/CMakeCLinkerInformation.cmake" "/usr/share/cmake-4.2/Modules/Internal/CMakeCLinkerInformation.cmake"
"/usr/share/cmake-4.2/Modules/Internal/CMakeCXXLinkerInformation.cmake" "/usr/share/cmake-4.2/Modules/Internal/CMakeCXXLinkerInformation.cmake"
"/usr/share/cmake-4.2/Modules/Internal/CMakeCommonLinkerInformation.cmake" "/usr/share/cmake-4.2/Modules/Internal/CMakeCommonLinkerInformation.cmake"
"/usr/share/cmake-4.2/Modules/Internal/CMakeDetermineLinkerId.cmake"
"/usr/share/cmake-4.2/Modules/Internal/CMakeInspectCLinker.cmake"
"/usr/share/cmake-4.2/Modules/Internal/CMakeInspectCXXLinker.cmake"
"/usr/share/cmake-4.2/Modules/Internal/CheckSourceCompiles.cmake" "/usr/share/cmake-4.2/Modules/Internal/CheckSourceCompiles.cmake"
"/usr/share/cmake-4.2/Modules/Internal/FeatureTesting.cmake"
"/usr/share/cmake-4.2/Modules/Linker/GNU-C.cmake" "/usr/share/cmake-4.2/Modules/Linker/GNU-C.cmake"
"/usr/share/cmake-4.2/Modules/Linker/GNU-CXX.cmake" "/usr/share/cmake-4.2/Modules/Linker/GNU-CXX.cmake"
"/usr/share/cmake-4.2/Modules/Linker/GNU.cmake" "/usr/share/cmake-4.2/Modules/Linker/GNU.cmake"
@@ -124,7 +43,6 @@ set(CMAKE_MAKEFILE_DEPENDS
"/usr/share/cmake-4.2/Modules/Platform/Linker/Linux-GNU-C.cmake" "/usr/share/cmake-4.2/Modules/Platform/Linker/Linux-GNU-C.cmake"
"/usr/share/cmake-4.2/Modules/Platform/Linker/Linux-GNU-CXX.cmake" "/usr/share/cmake-4.2/Modules/Platform/Linker/Linux-GNU-CXX.cmake"
"/usr/share/cmake-4.2/Modules/Platform/Linker/Linux-GNU.cmake" "/usr/share/cmake-4.2/Modules/Platform/Linker/Linux-GNU.cmake"
"/usr/share/cmake-4.2/Modules/Platform/Linux-Determine-CXX.cmake"
"/usr/share/cmake-4.2/Modules/Platform/Linux-GNU-C.cmake" "/usr/share/cmake-4.2/Modules/Platform/Linux-GNU-C.cmake"
"/usr/share/cmake-4.2/Modules/Platform/Linux-GNU-CXX.cmake" "/usr/share/cmake-4.2/Modules/Platform/Linux-GNU-CXX.cmake"
"/usr/share/cmake-4.2/Modules/Platform/Linux-GNU.cmake" "/usr/share/cmake-4.2/Modules/Platform/Linux-GNU.cmake"
@@ -142,13 +60,6 @@ set(CMAKE_MAKEFILE_OUTPUTS
# Byproducts of CMake generate step: # Byproducts of CMake generate step:
set(CMAKE_MAKEFILE_PRODUCTS set(CMAKE_MAKEFILE_PRODUCTS
"CMakeFiles/4.2.3/CMakeSystem.cmake"
"CMakeFiles/4.2.3/CMakeCCompiler.cmake"
"CMakeFiles/4.2.3/CMakeCXXCompiler.cmake"
"CMakeFiles/4.2.3/CMakeCCompiler.cmake"
"CMakeFiles/4.2.3/CMakeCCompiler.cmake"
"CMakeFiles/4.2.3/CMakeCXXCompiler.cmake"
"CMakeFiles/4.2.3/CMakeCXXCompiler.cmake"
"CMakeFiles/CMakeDirectoryInformation.cmake" "CMakeFiles/CMakeDirectoryInformation.cmake"
) )

View File

@@ -2432,6 +2432,7 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o
/usr/include/c++/15/bits/ranges_util.h /usr/include/c++/15/bits/ranges_util.h
/usr/include/c++/15/bits/refwrap.h /usr/include/c++/15/bits/refwrap.h
/usr/include/c++/15/bits/requires_hosted.h /usr/include/c++/15/bits/requires_hosted.h
/usr/include/c++/15/bits/specfun.h
/usr/include/c++/15/bits/std_abs.h /usr/include/c++/15/bits/std_abs.h
/usr/include/c++/15/bits/std_mutex.h /usr/include/c++/15/bits/std_mutex.h
/usr/include/c++/15/bits/stl_algobase.h /usr/include/c++/15/bits/stl_algobase.h
@@ -2457,13 +2458,13 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o
/usr/include/c++/15/cerrno /usr/include/c++/15/cerrno
/usr/include/c++/15/climits /usr/include/c++/15/climits
/usr/include/c++/15/clocale /usr/include/c++/15/clocale
/usr/include/c++/15/cmath
/usr/include/c++/15/compare /usr/include/c++/15/compare
/usr/include/c++/15/concepts /usr/include/c++/15/concepts
/usr/include/c++/15/cstddef /usr/include/c++/15/cstddef
/usr/include/c++/15/cstdint /usr/include/c++/15/cstdint
/usr/include/c++/15/cstdio /usr/include/c++/15/cstdio
/usr/include/c++/15/cstdlib /usr/include/c++/15/cstdlib
/usr/include/c++/15/cstring
/usr/include/c++/15/ctime /usr/include/c++/15/ctime
/usr/include/c++/15/cwchar /usr/include/c++/15/cwchar
/usr/include/c++/15/debug/assertions.h /usr/include/c++/15/debug/assertions.h
@@ -2484,6 +2485,18 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o
/usr/include/c++/15/ratio /usr/include/c++/15/ratio
/usr/include/c++/15/string /usr/include/c++/15/string
/usr/include/c++/15/string_view /usr/include/c++/15/string_view
/usr/include/c++/15/tr1/bessel_function.tcc
/usr/include/c++/15/tr1/beta_function.tcc
/usr/include/c++/15/tr1/ell_integral.tcc
/usr/include/c++/15/tr1/exp_integral.tcc
/usr/include/c++/15/tr1/gamma.tcc
/usr/include/c++/15/tr1/hypergeometric.tcc
/usr/include/c++/15/tr1/legendre_function.tcc
/usr/include/c++/15/tr1/modified_bessel_func.tcc
/usr/include/c++/15/tr1/poly_hermite.tcc
/usr/include/c++/15/tr1/poly_laguerre.tcc
/usr/include/c++/15/tr1/riemann_zeta.tcc
/usr/include/c++/15/tr1/special_function_util.h
/usr/include/c++/15/tuple /usr/include/c++/15/tuple
/usr/include/c++/15/type_traits /usr/include/c++/15/type_traits
/usr/include/c++/15/unordered_map /usr/include/c++/15/unordered_map
@@ -2502,14 +2515,13 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o
/usr/include/linux/stddef.h /usr/include/linux/stddef.h
/usr/include/linux/types.h /usr/include/linux/types.h
/usr/include/locale.h /usr/include/locale.h
/usr/include/math.h
/usr/include/pthread.h /usr/include/pthread.h
/usr/include/sched.h /usr/include/sched.h
/usr/include/stdc-predef.h /usr/include/stdc-predef.h
/usr/include/stdint.h /usr/include/stdint.h
/usr/include/stdio.h /usr/include/stdio.h
/usr/include/stdlib.h /usr/include/stdlib.h
/usr/include/string.h
/usr/include/strings.h
/usr/include/syscall.h /usr/include/syscall.h
/usr/include/time.h /usr/include/time.h
/usr/include/unistd.h /usr/include/unistd.h
@@ -2531,12 +2543,22 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o
/usr/include/x86_64-linux-gnu/bits/errno.h /usr/include/x86_64-linux-gnu/bits/errno.h
/usr/include/x86_64-linux-gnu/bits/floatn-common.h /usr/include/x86_64-linux-gnu/bits/floatn-common.h
/usr/include/x86_64-linux-gnu/bits/floatn.h /usr/include/x86_64-linux-gnu/bits/floatn.h
/usr/include/x86_64-linux-gnu/bits/flt-eval-method.h
/usr/include/x86_64-linux-gnu/bits/fp-fast.h
/usr/include/x86_64-linux-gnu/bits/fp-logb.h
/usr/include/x86_64-linux-gnu/bits/getopt_core.h /usr/include/x86_64-linux-gnu/bits/getopt_core.h
/usr/include/x86_64-linux-gnu/bits/getopt_posix.h /usr/include/x86_64-linux-gnu/bits/getopt_posix.h
/usr/include/x86_64-linux-gnu/bits/iscanonical.h
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h /usr/include/x86_64-linux-gnu/bits/libc-header-start.h
/usr/include/x86_64-linux-gnu/bits/libm-simd-decl-stubs.h
/usr/include/x86_64-linux-gnu/bits/local_lim.h /usr/include/x86_64-linux-gnu/bits/local_lim.h
/usr/include/x86_64-linux-gnu/bits/locale.h /usr/include/x86_64-linux-gnu/bits/locale.h
/usr/include/x86_64-linux-gnu/bits/long-double.h /usr/include/x86_64-linux-gnu/bits/long-double.h
/usr/include/x86_64-linux-gnu/bits/math-vector.h
/usr/include/x86_64-linux-gnu/bits/mathcalls-helper-functions.h
/usr/include/x86_64-linux-gnu/bits/mathcalls-macros.h
/usr/include/x86_64-linux-gnu/bits/mathcalls-narrow.h
/usr/include/x86_64-linux-gnu/bits/mathcalls.h
/usr/include/x86_64-linux-gnu/bits/posix1_lim.h /usr/include/x86_64-linux-gnu/bits/posix1_lim.h
/usr/include/x86_64-linux-gnu/bits/posix2_lim.h /usr/include/x86_64-linux-gnu/bits/posix2_lim.h
/usr/include/x86_64-linux-gnu/bits/posix_opt.h /usr/include/x86_64-linux-gnu/bits/posix_opt.h

View File

@@ -2421,6 +2421,7 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o: /home/maallyn/new-radar/src/sco
/usr/include/c++/15/bits/ranges_util.h \ /usr/include/c++/15/bits/ranges_util.h \
/usr/include/c++/15/bits/refwrap.h \ /usr/include/c++/15/bits/refwrap.h \
/usr/include/c++/15/bits/requires_hosted.h \ /usr/include/c++/15/bits/requires_hosted.h \
/usr/include/c++/15/bits/specfun.h \
/usr/include/c++/15/bits/std_abs.h \ /usr/include/c++/15/bits/std_abs.h \
/usr/include/c++/15/bits/std_mutex.h \ /usr/include/c++/15/bits/std_mutex.h \
/usr/include/c++/15/bits/stl_algobase.h \ /usr/include/c++/15/bits/stl_algobase.h \
@@ -2446,13 +2447,13 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o: /home/maallyn/new-radar/src/sco
/usr/include/c++/15/cerrno \ /usr/include/c++/15/cerrno \
/usr/include/c++/15/climits \ /usr/include/c++/15/climits \
/usr/include/c++/15/clocale \ /usr/include/c++/15/clocale \
/usr/include/c++/15/cmath \
/usr/include/c++/15/compare \ /usr/include/c++/15/compare \
/usr/include/c++/15/concepts \ /usr/include/c++/15/concepts \
/usr/include/c++/15/cstddef \ /usr/include/c++/15/cstddef \
/usr/include/c++/15/cstdint \ /usr/include/c++/15/cstdint \
/usr/include/c++/15/cstdio \ /usr/include/c++/15/cstdio \
/usr/include/c++/15/cstdlib \ /usr/include/c++/15/cstdlib \
/usr/include/c++/15/cstring \
/usr/include/c++/15/ctime \ /usr/include/c++/15/ctime \
/usr/include/c++/15/cwchar \ /usr/include/c++/15/cwchar \
/usr/include/c++/15/debug/assertions.h \ /usr/include/c++/15/debug/assertions.h \
@@ -2473,6 +2474,18 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o: /home/maallyn/new-radar/src/sco
/usr/include/c++/15/ratio \ /usr/include/c++/15/ratio \
/usr/include/c++/15/string \ /usr/include/c++/15/string \
/usr/include/c++/15/string_view \ /usr/include/c++/15/string_view \
/usr/include/c++/15/tr1/bessel_function.tcc \
/usr/include/c++/15/tr1/beta_function.tcc \
/usr/include/c++/15/tr1/ell_integral.tcc \
/usr/include/c++/15/tr1/exp_integral.tcc \
/usr/include/c++/15/tr1/gamma.tcc \
/usr/include/c++/15/tr1/hypergeometric.tcc \
/usr/include/c++/15/tr1/legendre_function.tcc \
/usr/include/c++/15/tr1/modified_bessel_func.tcc \
/usr/include/c++/15/tr1/poly_hermite.tcc \
/usr/include/c++/15/tr1/poly_laguerre.tcc \
/usr/include/c++/15/tr1/riemann_zeta.tcc \
/usr/include/c++/15/tr1/special_function_util.h \
/usr/include/c++/15/tuple \ /usr/include/c++/15/tuple \
/usr/include/c++/15/type_traits \ /usr/include/c++/15/type_traits \
/usr/include/c++/15/unordered_map \ /usr/include/c++/15/unordered_map \
@@ -2491,14 +2504,13 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o: /home/maallyn/new-radar/src/sco
/usr/include/linux/stddef.h \ /usr/include/linux/stddef.h \
/usr/include/linux/types.h \ /usr/include/linux/types.h \
/usr/include/locale.h \ /usr/include/locale.h \
/usr/include/math.h \
/usr/include/pthread.h \ /usr/include/pthread.h \
/usr/include/sched.h \ /usr/include/sched.h \
/usr/include/stdc-predef.h \ /usr/include/stdc-predef.h \
/usr/include/stdint.h \ /usr/include/stdint.h \
/usr/include/stdio.h \ /usr/include/stdio.h \
/usr/include/stdlib.h \ /usr/include/stdlib.h \
/usr/include/string.h \
/usr/include/strings.h \
/usr/include/syscall.h \ /usr/include/syscall.h \
/usr/include/time.h \ /usr/include/time.h \
/usr/include/unistd.h \ /usr/include/unistd.h \
@@ -2520,12 +2532,22 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o: /home/maallyn/new-radar/src/sco
/usr/include/x86_64-linux-gnu/bits/errno.h \ /usr/include/x86_64-linux-gnu/bits/errno.h \
/usr/include/x86_64-linux-gnu/bits/floatn-common.h \ /usr/include/x86_64-linux-gnu/bits/floatn-common.h \
/usr/include/x86_64-linux-gnu/bits/floatn.h \ /usr/include/x86_64-linux-gnu/bits/floatn.h \
/usr/include/x86_64-linux-gnu/bits/flt-eval-method.h \
/usr/include/x86_64-linux-gnu/bits/fp-fast.h \
/usr/include/x86_64-linux-gnu/bits/fp-logb.h \
/usr/include/x86_64-linux-gnu/bits/getopt_core.h \ /usr/include/x86_64-linux-gnu/bits/getopt_core.h \
/usr/include/x86_64-linux-gnu/bits/getopt_posix.h \ /usr/include/x86_64-linux-gnu/bits/getopt_posix.h \
/usr/include/x86_64-linux-gnu/bits/iscanonical.h \
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h \ /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
/usr/include/x86_64-linux-gnu/bits/libm-simd-decl-stubs.h \
/usr/include/x86_64-linux-gnu/bits/local_lim.h \ /usr/include/x86_64-linux-gnu/bits/local_lim.h \
/usr/include/x86_64-linux-gnu/bits/locale.h \ /usr/include/x86_64-linux-gnu/bits/locale.h \
/usr/include/x86_64-linux-gnu/bits/long-double.h \ /usr/include/x86_64-linux-gnu/bits/long-double.h \
/usr/include/x86_64-linux-gnu/bits/math-vector.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls-helper-functions.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls-macros.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls-narrow.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls.h \
/usr/include/x86_64-linux-gnu/bits/posix1_lim.h \ /usr/include/x86_64-linux-gnu/bits/posix1_lim.h \
/usr/include/x86_64-linux-gnu/bits/posix2_lim.h \ /usr/include/x86_64-linux-gnu/bits/posix2_lim.h \
/usr/include/x86_64-linux-gnu/bits/posix_opt.h \ /usr/include/x86_64-linux-gnu/bits/posix_opt.h \

View File

@@ -199,4 +199,26 @@ CMakeFiles/radar.dir/src/scope_marine_ppi.cpp.o: \
/home/maallyn/new-radar/include/KHR/khrplatform.h \ /home/maallyn/new-radar/include/KHR/khrplatform.h \
/home/maallyn/new-radar/src/phosphor.h \ /home/maallyn/new-radar/src/phosphor.h \
/home/maallyn/new-radar/src/graticule.h /usr/include/GLFW/glfw3.h \ /home/maallyn/new-radar/src/graticule.h /usr/include/GLFW/glfw3.h \
/usr/include/c++/15/cstring /usr/include/string.h /usr/include/strings.h /usr/include/c++/15/cmath /usr/include/math.h \
/usr/include/x86_64-linux-gnu/bits/math-vector.h \
/usr/include/x86_64-linux-gnu/bits/libm-simd-decl-stubs.h \
/usr/include/x86_64-linux-gnu/bits/flt-eval-method.h \
/usr/include/x86_64-linux-gnu/bits/fp-logb.h \
/usr/include/x86_64-linux-gnu/bits/fp-fast.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls-macros.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls-helper-functions.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls.h \
/usr/include/x86_64-linux-gnu/bits/mathcalls-narrow.h \
/usr/include/x86_64-linux-gnu/bits/iscanonical.h \
/usr/include/c++/15/bits/specfun.h /usr/include/c++/15/tr1/gamma.tcc \
/usr/include/c++/15/tr1/special_function_util.h \
/usr/include/c++/15/tr1/bessel_function.tcc \
/usr/include/c++/15/tr1/beta_function.tcc \
/usr/include/c++/15/tr1/ell_integral.tcc \
/usr/include/c++/15/tr1/exp_integral.tcc \
/usr/include/c++/15/tr1/hypergeometric.tcc \
/usr/include/c++/15/tr1/legendre_function.tcc \
/usr/include/c++/15/tr1/modified_bessel_func.tcc \
/usr/include/c++/15/tr1/poly_hermite.tcc \
/usr/include/c++/15/tr1/poly_laguerre.tcc \
/usr/include/c++/15/tr1/riemann_zeta.tcc

Binary file not shown.

View File

@@ -2,9 +2,15 @@
* MIT License * MIT License
* Author: Mark Allyn * Author: Mark Allyn
* *
* phosphor.frag — maps the single-channel phosphor energy texture to * phosphor.frag — maps the two-channel phosphor energy texture to the
* the P7 colour sequence (blue → green → yellow-green → dark) and * P7 colour sequence (blue → green → yellow-green → dark) and applies
* applies a simple inline bloom (box-filter glow) to bright pixels. * a simple inline bloom (box-filter glow) to bright pixels.
*
* The phosphor FBO is GL_RG32F:
* R channel — signal energy (target echoes, sweep background)
* multiplied by u_gain before display
* G channel — range ring energy, gain-independent; mixed with signal
* after gain is applied so rings never dim with gain
* *
* Coordinate system: gl_FragCoord.xy in GL viewport pixels (origin * Coordinate system: gl_FragCoord.xy in GL viewport pixels (origin
* bottom-left). Scope centre is passed as u_scopeCenter in the same * bottom-left). Scope centre is passed as u_scopeCenter in the same
@@ -14,17 +20,19 @@
out vec4 fragColor; out vec4 fragColor;
uniform sampler2D u_phosphor; // GL_R32F phosphor energy FBO uniform sampler2D u_phosphor; // GL_RG32F phosphor energy FBO
uniform vec2 u_scopeCenter; // scope centre in GL viewport pixels (bottom-left origin) uniform vec2 u_scopeCenter; // scope centre in GL viewport pixels (bottom-left origin)
uniform float u_scopeRadius; // scope radius in pixels uniform float u_scopeRadius; // scope radius in pixels
uniform float u_gain; // receiver gain [0,1] — scales brightness uniform float u_gain; // receiver gain [0,1] — scales signal (R) channel only
uniform float u_bloomStep; // UV step for bloom sample (≈ 2.5 / FBO_SIZE) uniform float u_bloomStep; // UV step for bloom sample (≈ 2.5 / FBO_SIZE)
uniform float u_bloomStrength; // additive blend weight for bloom uniform float u_bloomStrength; // additive blend weight for bloom
// P7 energy thresholds (match settings.h) // P7 energy thresholds — MUST match settings.h P7_THRESH_* constants.
// T_YGREE is intentionally low (0.05) to keep most of the decay in the
// GREEN zone; see the comment in settings.h for the full rationale.
const float T_BLUE = 0.82; const float T_BLUE = 0.82;
const float T_GREEN = 0.55; const float T_GREEN = 0.55;
const float T_YGREE = 0.22; const float T_YGREE = 0.05;
const float T_DARK = 0.03; const float T_DARK = 0.03;
// P7 colour anchors // P7 colour anchors
@@ -34,16 +42,22 @@ const vec3 C_YGREE = vec3(0.50, 1.00, 0.05);
const vec3 C_YELLW = vec3(0.70, 0.70, 0.00); const vec3 C_YELLW = vec3(0.70, 0.70, 0.00);
const vec3 C_BLACK = vec3(0.00, 0.00, 0.00); const vec3 C_BLACK = vec3(0.00, 0.00, 0.00);
// P7 colour ramp: hue selected by energy level, then scaled by energy so
// brightness decreases monotonically from fresh strike (peak) to dark.
// This prevents intermediate decay colours (yellow-green) from appearing
// brighter than the initial blue flash.
vec3 p7Color(float e) { vec3 p7Color(float e) {
if (e < T_DARK) return C_BLACK;
vec3 hue;
if (e >= T_BLUE) if (e >= T_BLUE)
return mix(C_GREEN, C_BLUE, (e - T_GREEN) / (T_BLUE - T_GREEN)); hue = C_BLUE;
if (e >= T_GREEN) else if (e >= T_GREEN)
return mix(C_YGREE, C_GREEN, (e - T_YGREE) / (T_GREEN - T_YGREE)); hue = mix(C_GREEN, C_BLUE, (e - T_GREEN) / (T_BLUE - T_GREEN));
if (e >= T_YGREE) else if (e >= T_YGREE)
return mix(C_YELLW, C_YGREE, (e - T_DARK ) / (T_YGREE - T_DARK )); hue = mix(C_YGREE, C_GREEN, (e - T_YGREE) / (T_GREEN - T_YGREE));
if (e >= T_DARK) else
return mix(C_BLACK, C_YELLW, e / T_DARK); hue = mix(C_YELLW, C_YGREE, (e - T_DARK) / (T_YGREE - T_DARK));
return C_BLACK; return hue * e;
} }
void main() { void main() {
@@ -57,10 +71,12 @@ void main() {
} }
// Map from PPI delta [-1,+1] to phosphor texture UV [0,1] // Map from PPI delta [-1,+1] to phosphor texture UV [0,1]
// delta.x = east, delta.y = north (both y directions already match)
vec2 uv = delta * 0.5 + 0.5; vec2 uv = delta * 0.5 + 0.5;
float energy = texture(u_phosphor, uv).r * u_gain; vec2 rg = texture(u_phosphor, uv).rg;
// Signal (R): gain-scaled received echoes.
// Ring (G): gain-independent timing reference; always at full brightness.
float energy = max(rg.r * u_gain, rg.g);
// Inline bloom: weighted box-filter over a 5×5 neighbourhood // Inline bloom: weighted box-filter over a 5×5 neighbourhood
float bloom = 0.0; float bloom = 0.0;
@@ -68,7 +84,8 @@ void main() {
for (int dx = -2; dx <= 2; dx++) { for (int dx = -2; dx <= 2; dx++) {
for (int dy = -2; dy <= 2; dy++) { for (int dy = -2; dy <= 2; dy++) {
float w = exp(-float(dx*dx + dy*dy) * 0.45); float w = exp(-float(dx*dx + dy*dy) * 0.45);
float e = texture(u_phosphor, uv + vec2(dx, dy) * u_bloomStep).r; vec2 srg = texture(u_phosphor, uv + vec2(dx, dy) * u_bloomStep).rg;
float e = max(srg.r * u_gain, srg.g);
bloom += e * w; bloom += e * w;
wsum += w; wsum += w;
} }

View File

@@ -4,13 +4,16 @@
* *
* sweep.frag — phosphor accumulation update shader. * sweep.frag — phosphor accumulation update shader.
* *
* For each texel in the 1024×1024 phosphor FBO: * The FBO is GL_RG32F (two independent energy channels):
* 1. Decay the previous frame's energy by u_decayFactor. * R — signal energy: target echoes + sweep-background glow.
* 2. If the texel's PPI bearing falls within the current sweep arc * Multiplied by u_gain in the display pass so operators can
* [u_beamAnglePrev, u_beamAngle], add contributions from: * adjust received-signal brightness without touching rings.
* - range rings (beam-painted per the P7 spec) * G — range-ring energy: written at u_ringBrightness; NOT scaled
* - target echoes * by gain. Rings are a precision timing reference, not a
* 3. Output the updated single-channel energy value. * received echo. Both channels decay at the same P7 rate.
*
* The sweep background (u_sweepBg) goes into the G channel so the
* rotating beam is always visible regardless of the gain setting.
* *
* PPI convention: north = +y, east = +x; bearing = atan2(x, y) * PPI convention: north = +y, east = +x; bearing = atan2(x, y)
* in degrees, clockwise from north. * in degrees, clockwise from north.
@@ -19,13 +22,13 @@
in vec2 vTexCoord; in vec2 vTexCoord;
layout(location = 0) out vec4 fragOut; // .r = energy; .gba unused layout(location = 0) out vec4 fragOut; // .r = signal; .g = ring+sweep; .ba unused
uniform sampler2D u_prevPhosphor; // previous frame's energy texture (GL_R32F) uniform sampler2D u_prevPhosphor; // previous frame's energy texture (GL_RG32F)
uniform float u_decayFactor; // exp(-decay_rate * dt) uniform float u_decayFactor; // exp(-decay_rate * dt)
uniform float u_beamAngle; // current beam angle, degrees CW from north uniform float u_beamAngle; // current beam angle, degrees CW from north
uniform float u_beamAnglePrev; // beam angle at previous frame uniform float u_beamAnglePrev; // beam angle at previous frame
uniform float u_sweepBg; // ambient sweep-line energy (makes beam visible) uniform float u_sweepBg; // ambient sweep-line energy (gain-independent)
uniform float u_halfBeamDeg; // half-beamwidth for target blobs (display widening) uniform float u_halfBeamDeg; // half-beamwidth for target blobs (display widening)
// Targets: .x = range_norm (0-1), .y = bearing_deg, .z = brightness, .w = size_norm // Targets: .x = range_norm (0-1), .y = bearing_deg, .z = brightness, .w = size_norm
@@ -59,8 +62,8 @@ bool inSweep(float b, float prev, float curr) {
// ---------------------------------------------------------------- // ----------------------------------------------------------------
void main() { void main() {
vec2 pos = vTexCoord * 2.0 - 1.0; // PPI coords: (-1,-1) SW … (+1,+1) NE vec2 pos = vTexCoord * 2.0 - 1.0; // PPI coords: (-1,-1) SW … (+1,+1) NE
float rng = length(pos); float rng = length(pos);
if (rng > 1.0) { if (rng > 1.0) {
fragOut = vec4(0.0); fragOut = vec4(0.0);
@@ -71,23 +74,25 @@ void main() {
float brg = degrees(atan(pos.x, pos.y)); float brg = degrees(atan(pos.x, pos.y));
if (brg < 0.0) brg += 360.0; if (brg < 0.0) brg += 360.0;
// Decay previous value vec2 prev = texture(u_prevPhosphor, vTexCoord).rg;
float energy = texture(u_prevPhosphor, vTexCoord).r * u_decayFactor; float signal = prev.r * u_decayFactor;
float ring = prev.g * u_decayFactor;
if (inSweep(brg, u_beamAnglePrev, u_beamAngle)) { if (inSweep(brg, u_beamAnglePrev, u_beamAngle)) {
float contrib = u_sweepBg; // beam passage gives a faint ambient glow // ---- Range rings → G channel (gain-independent) ----
float ringContrib = u_sweepBg; // sweep-background glow also in G channel
// ---- Range rings (painted at every bearing as beam sweeps) ----
for (int i = 0; i < u_ringCount; i++) { for (int i = 0; i < u_ringCount; i++) {
float d = abs(rng - u_ringRadii[i]); float d = abs(rng - u_ringRadii[i]);
if (d < u_ringWidth) { if (d < u_ringWidth) {
float w = 1.0 - d / u_ringWidth; float w = 1.0 - d / u_ringWidth;
contrib = max(contrib, u_ringBrightness * w * w); ringContrib = max(ringContrib, u_ringBrightness * w * w);
} }
} }
ring = max(ring, ringContrib);
// ---- Target echoes ---- // ---- Target echoes → R channel (gain-scaled in display pass) ----
float sigContrib = 0.0;
for (int i = 0; i < u_targetCount; i++) { for (int i = 0; i < u_targetCount; i++) {
float tRng = u_targets[i].x; float tRng = u_targets[i].x;
float tBrg = u_targets[i].y; float tBrg = u_targets[i].y;
@@ -96,21 +101,18 @@ void main() {
if (tRng <= 0.0 || tBrt <= 0.0) continue; if (tRng <= 0.0 || tBrt <= 0.0) continue;
// Angular proximity: beam must be sweeping over the target's bearing
float dBrg = angleDiff(brg, tBrg); float dBrg = angleDiff(brg, tBrg);
if (dBrg >= u_halfBeamDeg) continue; if (dBrg >= u_halfBeamDeg) continue;
// Range proximity: pixel must be within the target blob
float dRng = abs(rng - tRng); float dRng = abs(rng - tRng);
if (dRng >= tSize) continue; if (dRng >= tSize) continue;
float bw = 1.0 - dBrg / u_halfBeamDeg; // angular taper float bw = 1.0 - dBrg / u_halfBeamDeg;
float rw = 1.0 - dRng / tSize; // range taper float rw = 1.0 - dRng / tSize;
contrib = max(contrib, tBrt * bw * rw); sigContrib = max(sigContrib, tBrt * bw * rw);
} }
signal = max(signal, sigContrib);
energy = max(energy, contrib);
} }
fragOut = vec4(clamp(energy, 0.0, 1.0), 0.0, 0.0, 1.0); fragOut = vec4(clamp(signal, 0.0, 1.0), clamp(ring, 0.0, 1.0), 0.0, 1.0);
} }

8
issues Normal file
View File

@@ -0,0 +1,8 @@
Only one range ring no matter the max range. Range ring has no number indicating ring (I forgot if I mentioned that)
It seems that the empty scan line is excessively strong, along with the range rings. The gain does affect the range rings. I wonder
if this is how things are normal of a period radar. I thought that the gain would be only for targets and noise and land. Not the scan beam
itself and the range rings. Also the cursor seems to be the same color as the p7 fading. It should be more white, like an incandescent light.
At 1/2 on the gain control, the sweeping beams leave a solid yellow for about 1/3 of a sweep. It is solid, not varying due to noise.

View File

@@ -2,9 +2,15 @@
* MIT License * MIT License
* Author: Mark Allyn * Author: Mark Allyn
* *
* phosphor.frag — maps the single-channel phosphor energy texture to * phosphor.frag — maps the two-channel phosphor energy texture to the
* the P7 colour sequence (blue → green → yellow-green → dark) and * P7 colour sequence (blue → green → yellow-green → dark) and applies
* applies a simple inline bloom (box-filter glow) to bright pixels. * a simple inline bloom (box-filter glow) to bright pixels.
*
* The phosphor FBO is GL_RG32F:
* R channel — signal energy (target echoes, sweep background)
* multiplied by u_gain before display
* G channel — range ring energy, gain-independent; mixed with signal
* after gain is applied so rings never dim with gain
* *
* Coordinate system: gl_FragCoord.xy in GL viewport pixels (origin * Coordinate system: gl_FragCoord.xy in GL viewport pixels (origin
* bottom-left). Scope centre is passed as u_scopeCenter in the same * bottom-left). Scope centre is passed as u_scopeCenter in the same
@@ -14,17 +20,19 @@
out vec4 fragColor; out vec4 fragColor;
uniform sampler2D u_phosphor; // GL_R32F phosphor energy FBO uniform sampler2D u_phosphor; // GL_RG32F phosphor energy FBO
uniform vec2 u_scopeCenter; // scope centre in GL viewport pixels (bottom-left origin) uniform vec2 u_scopeCenter; // scope centre in GL viewport pixels (bottom-left origin)
uniform float u_scopeRadius; // scope radius in pixels uniform float u_scopeRadius; // scope radius in pixels
uniform float u_gain; // receiver gain [0,1] — scales brightness uniform float u_gain; // receiver gain [0,1] — scales signal (R) channel only
uniform float u_bloomStep; // UV step for bloom sample (≈ 2.5 / FBO_SIZE) uniform float u_bloomStep; // UV step for bloom sample (≈ 2.5 / FBO_SIZE)
uniform float u_bloomStrength; // additive blend weight for bloom uniform float u_bloomStrength; // additive blend weight for bloom
// P7 energy thresholds (match settings.h) // P7 energy thresholds — MUST match settings.h P7_THRESH_* constants.
// T_YGREE is intentionally low (0.05) to keep most of the decay in the
// GREEN zone; see the comment in settings.h for the full rationale.
const float T_BLUE = 0.82; const float T_BLUE = 0.82;
const float T_GREEN = 0.55; const float T_GREEN = 0.55;
const float T_YGREE = 0.22; const float T_YGREE = 0.05;
const float T_DARK = 0.03; const float T_DARK = 0.03;
// P7 colour anchors // P7 colour anchors
@@ -34,16 +42,22 @@ const vec3 C_YGREE = vec3(0.50, 1.00, 0.05);
const vec3 C_YELLW = vec3(0.70, 0.70, 0.00); const vec3 C_YELLW = vec3(0.70, 0.70, 0.00);
const vec3 C_BLACK = vec3(0.00, 0.00, 0.00); const vec3 C_BLACK = vec3(0.00, 0.00, 0.00);
// P7 colour ramp: hue selected by energy level, then scaled by energy so
// brightness decreases monotonically from fresh strike (peak) to dark.
// This prevents intermediate decay colours (yellow-green) from appearing
// brighter than the initial blue flash.
vec3 p7Color(float e) { vec3 p7Color(float e) {
if (e < T_DARK) return C_BLACK;
vec3 hue;
if (e >= T_BLUE) if (e >= T_BLUE)
return mix(C_GREEN, C_BLUE, (e - T_GREEN) / (T_BLUE - T_GREEN)); hue = C_BLUE;
if (e >= T_GREEN) else if (e >= T_GREEN)
return mix(C_YGREE, C_GREEN, (e - T_YGREE) / (T_GREEN - T_YGREE)); hue = mix(C_GREEN, C_BLUE, (e - T_GREEN) / (T_BLUE - T_GREEN));
if (e >= T_YGREE) else if (e >= T_YGREE)
return mix(C_YELLW, C_YGREE, (e - T_DARK ) / (T_YGREE - T_DARK )); hue = mix(C_YGREE, C_GREEN, (e - T_YGREE) / (T_GREEN - T_YGREE));
if (e >= T_DARK) else
return mix(C_BLACK, C_YELLW, e / T_DARK); hue = mix(C_YELLW, C_YGREE, (e - T_DARK) / (T_YGREE - T_DARK));
return C_BLACK; return hue * e;
} }
void main() { void main() {
@@ -57,10 +71,12 @@ void main() {
} }
// Map from PPI delta [-1,+1] to phosphor texture UV [0,1] // Map from PPI delta [-1,+1] to phosphor texture UV [0,1]
// delta.x = east, delta.y = north (both y directions already match)
vec2 uv = delta * 0.5 + 0.5; vec2 uv = delta * 0.5 + 0.5;
float energy = texture(u_phosphor, uv).r * u_gain; vec2 rg = texture(u_phosphor, uv).rg;
// Signal (R): gain-scaled received echoes.
// Ring (G): gain-independent timing reference; always at full brightness.
float energy = max(rg.r * u_gain, rg.g);
// Inline bloom: weighted box-filter over a 5×5 neighbourhood // Inline bloom: weighted box-filter over a 5×5 neighbourhood
float bloom = 0.0; float bloom = 0.0;
@@ -68,7 +84,8 @@ void main() {
for (int dx = -2; dx <= 2; dx++) { for (int dx = -2; dx <= 2; dx++) {
for (int dy = -2; dy <= 2; dy++) { for (int dy = -2; dy <= 2; dy++) {
float w = exp(-float(dx*dx + dy*dy) * 0.45); float w = exp(-float(dx*dx + dy*dy) * 0.45);
float e = texture(u_phosphor, uv + vec2(dx, dy) * u_bloomStep).r; vec2 srg = texture(u_phosphor, uv + vec2(dx, dy) * u_bloomStep).rg;
float e = max(srg.r * u_gain, srg.g);
bloom += e * w; bloom += e * w;
wsum += w; wsum += w;
} }

View File

@@ -4,13 +4,16 @@
* *
* sweep.frag — phosphor accumulation update shader. * sweep.frag — phosphor accumulation update shader.
* *
* For each texel in the 1024×1024 phosphor FBO: * The FBO is GL_RG32F (two independent energy channels):
* 1. Decay the previous frame's energy by u_decayFactor. * R — signal energy: target echoes + sweep-background glow.
* 2. If the texel's PPI bearing falls within the current sweep arc * Multiplied by u_gain in the display pass so operators can
* [u_beamAnglePrev, u_beamAngle], add contributions from: * adjust received-signal brightness without touching rings.
* - range rings (beam-painted per the P7 spec) * G — range-ring energy: written at u_ringBrightness; NOT scaled
* - target echoes * by gain. Rings are a precision timing reference, not a
* 3. Output the updated single-channel energy value. * received echo. Both channels decay at the same P7 rate.
*
* The sweep background (u_sweepBg) goes into the G channel so the
* rotating beam is always visible regardless of the gain setting.
* *
* PPI convention: north = +y, east = +x; bearing = atan2(x, y) * PPI convention: north = +y, east = +x; bearing = atan2(x, y)
* in degrees, clockwise from north. * in degrees, clockwise from north.
@@ -19,17 +22,18 @@
in vec2 vTexCoord; in vec2 vTexCoord;
layout(location = 0) out vec4 fragOut; // .r = energy; .gba unused layout(location = 0) out vec4 fragOut; // .r = signal; .g = ring+sweep; .ba unused
uniform sampler2D u_prevPhosphor; // previous frame's energy texture (GL_R32F) uniform sampler2D u_prevPhosphor; // previous frame's energy texture (GL_RG32F)
uniform float u_decayFactor; // exp(-decay_rate * dt) uniform float u_decayFactor; // exp(-decay_rate * dt)
uniform float u_beamAngle; // current beam angle, degrees CW from north uniform float u_beamAngle; // current beam angle, degrees CW from north
uniform float u_beamAnglePrev; // beam angle at previous frame uniform float u_beamAnglePrev; // beam angle at previous frame
uniform float u_sweepBg; // ambient sweep-line energy (makes beam visible) uniform float u_sweepBg; // ambient sweep-line energy (gain-independent)
uniform float u_halfBeamDeg; // half-beamwidth for target blobs (display widening) uniform float u_halfBeamDeg; // half-beamwidth for target blobs (display widening)
// Targets: .x = range_norm (0-1), .y = bearing_deg, .z = brightness, .w = size_norm // Targets: .x = range_norm (0-1), .y = bearing_deg, .z = brightness, .w = radial_size_norm
uniform vec4 u_targets[32]; uniform vec4 u_targets[32];
uniform float u_targetAngHalfDeg[32]; // per-target azimuthal half-width (degrees)
uniform int u_targetCount; uniform int u_targetCount;
// Range rings: up to 4 normalised radii // Range rings: up to 4 normalised radii
@@ -59,8 +63,8 @@ bool inSweep(float b, float prev, float curr) {
// ---------------------------------------------------------------- // ----------------------------------------------------------------
void main() { void main() {
vec2 pos = vTexCoord * 2.0 - 1.0; // PPI coords: (-1,-1) SW … (+1,+1) NE vec2 pos = vTexCoord * 2.0 - 1.0; // PPI coords: (-1,-1) SW … (+1,+1) NE
float rng = length(pos); float rng = length(pos);
if (rng > 1.0) { if (rng > 1.0) {
fragOut = vec4(0.0); fragOut = vec4(0.0);
@@ -71,23 +75,25 @@ void main() {
float brg = degrees(atan(pos.x, pos.y)); float brg = degrees(atan(pos.x, pos.y));
if (brg < 0.0) brg += 360.0; if (brg < 0.0) brg += 360.0;
// Decay previous value vec2 prev = texture(u_prevPhosphor, vTexCoord).rg;
float energy = texture(u_prevPhosphor, vTexCoord).r * u_decayFactor; float signal = prev.r * u_decayFactor;
float ring = prev.g * u_decayFactor;
if (inSweep(brg, u_beamAnglePrev, u_beamAngle)) { if (inSweep(brg, u_beamAnglePrev, u_beamAngle)) {
float contrib = u_sweepBg; // beam passage gives a faint ambient glow // ---- Range rings → G channel (gain-independent) ----
float ringContrib = u_sweepBg; // sweep-background glow also in G channel
// ---- Range rings (painted at every bearing as beam sweeps) ----
for (int i = 0; i < u_ringCount; i++) { for (int i = 0; i < u_ringCount; i++) {
float d = abs(rng - u_ringRadii[i]); float d = abs(rng - u_ringRadii[i]);
if (d < u_ringWidth) { if (d < u_ringWidth) {
float w = 1.0 - d / u_ringWidth; float w = 1.0 - d / u_ringWidth;
contrib = max(contrib, u_ringBrightness * w * w); ringContrib = max(ringContrib, u_ringBrightness * w * w);
} }
} }
ring = max(ring, ringContrib);
// ---- Target echoes ---- // ---- Target echoes → R channel (gain-scaled in display pass) ----
float sigContrib = 0.0;
for (int i = 0; i < u_targetCount; i++) { for (int i = 0; i < u_targetCount; i++) {
float tRng = u_targets[i].x; float tRng = u_targets[i].x;
float tBrg = u_targets[i].y; float tBrg = u_targets[i].y;
@@ -96,21 +102,19 @@ void main() {
if (tRng <= 0.0 || tBrt <= 0.0) continue; if (tRng <= 0.0 || tBrt <= 0.0) continue;
// Angular proximity: beam must be sweeping over the target's bearing float tAngHalf = u_targetAngHalfDeg[i];
float dBrg = angleDiff(brg, tBrg); float dBrg = angleDiff(brg, tBrg);
if (dBrg >= u_halfBeamDeg) continue; if (dBrg >= tAngHalf) continue;
// Range proximity: pixel must be within the target blob
float dRng = abs(rng - tRng); float dRng = abs(rng - tRng);
if (dRng >= tSize) continue; if (dRng >= tSize) continue;
float bw = 1.0 - dBrg / u_halfBeamDeg; // angular taper float bw = 1.0 - dBrg / tAngHalf;
float rw = 1.0 - dRng / tSize; // range taper float rw = 1.0 - dRng / tSize;
contrib = max(contrib, tBrt * bw * rw); sigContrib = max(sigContrib, tBrt * bw * rw);
} }
signal = max(signal, sigContrib);
energy = max(energy, contrib);
} }
fragOut = vec4(clamp(energy, 0.0, 1.0), 0.0, 0.0, 1.0); fragOut = vec4(clamp(signal, 0.0, 1.0), clamp(ring, 0.0, 1.0), 0.0, 1.0);
} }

View File

@@ -102,9 +102,9 @@ bool PhosphorRenderer::init(const std::string& shaderDir) {
glGenTextures(1, &tex_[i]); glGenTextures(1, &tex_[i]);
glBindTexture(GL_TEXTURE_2D, tex_[i]); glBindTexture(GL_TEXTURE_2D, tex_[i]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, glTexImage2D(GL_TEXTURE_2D, 0, GL_RG32F,
fboSize_, fboSize_, 0, fboSize_, fboSize_, 0,
GL_RED, GL_FLOAT, nullptr); GL_RG, GL_FLOAT, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -193,16 +193,19 @@ void PhosphorRenderer::update(
// Target array: pack into vec4 array // Target array: pack into vec4 array
float tdata[MAX_TARGETS * 4] = {}; float tdata[MAX_TARGETS * 4] = {};
float angData[MAX_TARGETS] = {};
int tCount = (targetCount < MAX_TARGETS) ? targetCount : MAX_TARGETS; int tCount = (targetCount < MAX_TARGETS) ? targetCount : MAX_TARGETS;
float invRange = (maxRangeM > 0.f) ? 1.0f / maxRangeM : 0.f; float invRange = (maxRangeM > 0.f) ? 1.0f / maxRangeM : 0.f;
for (int i = 0; i < tCount; ++i) { for (int i = 0; i < tCount; ++i) {
tdata[i*4+0] = targets[i].range_m * invRange; // normalised 0-1 tdata[i*4+0] = targets[i].range_m * invRange * GRAT_INNER_RING_FRAC;
tdata[i*4+1] = targets[i].bearing_deg; tdata[i*4+1] = targets[i].bearing_deg;
tdata[i*4+2] = targets[i].brightness; tdata[i*4+2] = targets[i].brightness;
tdata[i*4+3] = targets[i].size_m * invRange; // normalised blob half-radius tdata[i*4+3] = targets[i].size_m * invRange * GRAT_INNER_RING_FRAC;
angData[i] = targets[i].ang_half_deg;
} }
glUniform4fv(glGetUniformLocation(sweepProg_, "u_targets"), tCount, tdata); glUniform4fv(glGetUniformLocation(sweepProg_, "u_targets"), tCount, tdata);
glUniform1i (glGetUniformLocation(sweepProg_, "u_targetCount"), tCount); glUniform1fv(glGetUniformLocation(sweepProg_, "u_targetAngHalfDeg"), tCount, angData);
glUniform1i (glGetUniformLocation(sweepProg_, "u_targetCount"), tCount);
glBindVertexArray(quadVAO_); glBindVertexArray(quadVAO_);
glDrawArrays(GL_TRIANGLES, 0, 6); glDrawArrays(GL_TRIANGLES, 0, 6);

View File

@@ -7,7 +7,7 @@
#include "scope_marine_ppi.h" #include "scope_marine_ppi.h"
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <cstring> #include <cmath>
// ---------------------------------------------------------------- // ----------------------------------------------------------------
@@ -18,8 +18,14 @@ float MarinePPIScope::maxRangeM() const {
void MarinePPIScope::computeRingRadii() { void MarinePPIScope::computeRingRadii() {
int n = MARINE_RING_COUNT[maxRangeIdx_]; int n = MARINE_RING_COUNT[maxRangeIdx_];
float maxMi = MARINE_RANGE_STEPS[maxRangeIdx_]; float maxMi = MARINE_RANGE_STEPS[maxRangeIdx_];
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i) {
ringRadiiNorm_[i] = MARINE_RING_MILES[maxRangeIdx_][i] / maxMi; // Scale by GRAT_INNER_RING_FRAC so max-range maps to the inner
// graticule ring boundary. Targets use the same scale factor
// (applied in PhosphorRenderer::update), so rings and targets
// remain co-registered in the display.
ringRadiiNorm_[i] = (MARINE_RING_MILES[maxRangeIdx_][i] / maxMi)
* GRAT_INNER_RING_FRAC;
}
} }
void MarinePPIScope::handleKeyRange(int key, int /*action*/) { void MarinePPIScope::handleKeyRange(int key, int /*action*/) {

View File

@@ -185,9 +185,16 @@ void PPIScope::render(float dt, float viewportW, float viewportH) {
} }
graticule_.render(viewportW, viewportH, gratI, brgOffsetDeg_); graticule_.render(viewportW, viewportH, gratI, brgOffsetDeg_);
// 3. Yellow cursor overlay // 3. Yellow cursor overlay — clamp cursor to max range each frame so it
// never escapes the active display area regardless of how it was set.
{
float maxMi = maxM / MILES_TO_METERS;
if (cursorRngMi_ > maxMi) cursorRngMi_ = maxMi;
}
// Map cursor range [0, maxM] → normalised radius [0, GRAT_INNER_RING_FRAC]
// so the cursor at max range sits on the outer ring, not on the bezel.
float cursorNorm = (maxM > 0.f) float cursorNorm = (maxM > 0.f)
? std::min((cursorRngMi_ * MILES_TO_METERS) / maxM, 1.0f) ? (cursorRngMi_ * MILES_TO_METERS / maxM) * GRAT_INNER_RING_FRAC
: 0.f; : 0.f;
// Cursor bearing in display coordinates (subtract offset so it tracks the display) // Cursor bearing in display coordinates (subtract offset so it tracks the display)
float dispBrg = std::fmod(cursorBrgDeg_ - brgOffsetDeg_ + 360.f, 360.f); float dispBrg = std::fmod(cursorBrgDeg_ - brgOffsetDeg_ + 360.f, 360.f);

View File

@@ -31,9 +31,16 @@ constexpr int PHOSPHOR_FBO_SIZE = 1024; // texels per side for phospho
constexpr float P7_DECAY_RATE = 1.1513f; // s^-1; <1% remains after 4 s constexpr float P7_DECAY_RATE = 1.1513f; // s^-1; <1% remains after 4 s
// Energy thresholds that define colour transitions in the display shader // Energy thresholds that define colour transitions in the display shader
// T_YGREE is deliberately low (0.05) so that the ring spends the vast
// majority of the 4-second sweep period in the GREEN zone rather than
// in the yellow-green/yellow zone. With exponential decay (rate 1.15),
// a ring painted at 0.72 stays green for ~2.5 s, dips through a faint
// yellow-green for ~0.45 s (≈ 40° of arc), then goes black. Setting
// T_YGREE = 0.22 (old value) extended the yellow zone to ~1.75 s (44%
// of the scope arc), which is the source of the "solid yellow" report.
constexpr float P7_THRESH_BLUE = 0.82f; // above this: blue strike constexpr float P7_THRESH_BLUE = 0.82f; // above this: blue strike
constexpr float P7_THRESH_GREEN = 0.55f; // above this: green persistence constexpr float P7_THRESH_GREEN = 0.55f; // above this: green persistence
constexpr float P7_THRESH_YELLOW_GR = 0.22f; // above this: yellow-green fade constexpr float P7_THRESH_YELLOW_GR = 0.05f; // above this: yellow-green fade
constexpr float P7_THRESH_DARK = 0.03f; // below this: essentially black constexpr float P7_THRESH_DARK = 0.03f; // below this: essentially black
// Colour anchors (RGB) // Colour anchors (RGB)
@@ -42,8 +49,12 @@ constexpr float P7_GREEN_R = 0.05f, P7_GREEN_G = 1.00f, P7_GREEN_B = 0.30f;
constexpr float P7_YGREE_R = 0.50f, P7_YGREE_G = 1.00f, P7_YGREE_B = 0.05f; constexpr float P7_YGREE_R = 0.50f, P7_YGREE_G = 1.00f, P7_YGREE_B = 0.05f;
constexpr float P7_YELLW_R = 0.70f, P7_YELLW_G = 0.70f, P7_YELLW_B = 0.00f; constexpr float P7_YELLW_R = 0.70f, P7_YELLW_G = 0.70f, P7_YELLW_B = 0.00f;
// Sweep background energy — gives the rotating beam its visible glow // Sweep background energy written to the G channel each frame the beam
constexpr float SWEEP_BACKGROUND_ENERGY = 0.10f; // sweeps over a texel. Kept just above T_DARK so the rotating beam is
// barely visible as a dim trace; it decays to black in ~0.3 s (7% of
// the 4-second sweep arc). 0.10 (old value) left a visible glow for
// ~1.3 s (33% of arc) — major contributor to the "solid yellow" report.
constexpr float SWEEP_BACKGROUND_ENERGY = 0.04f;
// Half-beamwidth used by sweep shader for target blob display (degrees) // Half-beamwidth used by sweep shader for target blob display (degrees)
constexpr float SWEEP_HALF_BEAM_DEG = 1.0f; constexpr float SWEEP_HALF_BEAM_DEG = 1.0f;
@@ -83,7 +94,13 @@ constexpr int GRAT_SEGMENTS = 360; // circle tessellation segm
// RANGE RINGS (beam-painted; widths in normalised 0-1 scope space) // RANGE RINGS (beam-painted; widths in normalised 0-1 scope space)
// ================================================================ // ================================================================
constexpr float RING_WIDTH_NORM = 0.005f; constexpr float RING_WIDTH_NORM = 0.005f;
constexpr float RING_BRIGHTNESS = 0.72f; constexpr float RING_BRIGHTNESS = 1.0f;
// Range-ring distance labels
// Labels appear at a fixed bearing so they don't clutter the display.
// Colour uses the P7 fresh-blue constants (P7_BLUE_R/G/B) already above.
constexpr float RING_LABEL_BRG_DEG = 45.0f; // NE: clear of bearing-mark clusters
constexpr int RING_LABEL_FONT_SIZE = 14; // pixels (matches graticule labels)
// Marine PPI range steps (miles) and ring definitions // Marine PPI range steps (miles) and ring definitions
// Index: 0 (max 2 mi) 1 (max 4 mi) 2 (max 6 mi) // Index: 0 (max 2 mi) 1 (max 4 mi) 2 (max 6 mi)

View File

@@ -67,6 +67,11 @@ Simulator::Simulator() {
// 7. Large barge under tow N — bearing 355°, 4.8 mi // 7. Large barge under tow N — bearing 355°, 4.8 mi
targets_[n++] = { 7, 48.8127f, -122.5739f, 3.08f, 175.0f, 1000.0f, 30.0f }; targets_[n++] = { 7, 48.8127f, -122.5739f, 3.08f, 175.0f, 1000.0f, 30.0f };
// 8. DEBUG: large broadside cargo ship NE — bearing 045°, 1.0 mi
// Stationary (speed=0). RCS 500,000 m² (big steel hull broadside).
// sizeM=150 so the blob is clearly visible even in no-persistence mode.
targets_[n++] = { 8, 48.7538f, -122.5492f, 0.0f, 0.0f, 500000.0f, 150.0f };
targetCount_ = n; targetCount_ = n;
} }

View File

@@ -27,7 +27,8 @@ struct SimTarget {
float speedMps; // metres per second float speedMps; // metres per second
float headingDeg; // true heading, CW from north float headingDeg; // true heading, CW from north
float sigmaM2; // RCS in m² float sigmaM2; // RCS in m²
float sizeM; // physical blob half-radius in metres float sizeM; // radial blob half-width in metres (range direction)
float angHalfDeg; // azimuthal half-width in degrees (bearing direction)
}; };
class Simulator { class Simulator {

View File

@@ -23,7 +23,8 @@ struct TargetState {
float range_m = 0.0f; // metres from radar origin float range_m = 0.0f; // metres from radar origin
float bearing_deg = 0.0f; // degrees true, CW from north float bearing_deg = 0.0f; // degrees true, CW from north
float brightness = 0.0f; // 0-1, from radar equation float brightness = 0.0f; // 0-1, from radar equation
float size_m = 50.0f; // physical blob half-radius in metres; scope normalises to [0,1] float size_m = 50.0f; // radial blob half-width in metres (range direction)
float ang_half_deg = SWEEP_HALF_BEAM_DEG; // azimuthal half-width in degrees
bool valid = false; bool valid = false;
}; };