Skip to content

add Weather effects#478

Merged
nschimme merged 2 commits intoMUME:masterfrom
nschimme:weather
Mar 26, 2026
Merged

add Weather effects#478
nschimme merged 2 commits intoMUME:masterfrom
nschimme:weather

Conversation

@nschimme
Copy link
Copy Markdown
Contributor

@nschimme nschimme commented Mar 26, 2026

Summary by Sourcery

Add a GPU-accelerated, UBO-driven weather and time-of-day system with configurable intensities and integrate it into the rendering pipeline.

New Features:

  • Introduce a unified UBO block system for camera, time, weather, and named colors, with type-safe CPU shadow storage and updates.
  • Implement a GLWeather manager with particle simulation and rendering, atmospheric effects, and time-of-day overlays driven by game state and configuration.
  • Add configurable weather atmosphere, precipitation, and time-of-day intensity settings, including UI controls and persistence in configuration.

Bug Fixes:

  • Replace fragile string conversion for shader sources with a UTF-8 safe helper to avoid encoding issues when loading shaders.

Enhancements:

  • Extend UBO manager with typed accessors, partial field syncing, and stricter error handling for rebuild functions to improve robustness.
  • Augment OpenGL legacy wrappers to support transform feedback, buffer sub-data updates, and new blend modes needed by the weather shaders.
  • Optimize view-projection handling and invalidation so UBO updates are triggered only when viewport or camera state actually changes.
  • Refine FrameManager to track elapsed time and feed a time UBO used for smooth GPU-side animations across the app.

Build:

  • Register new weather-related sources, meshes, and shaders in the build configuration so they are compiled and packaged.

Adds UboBlocks.h with NamedColorsBlock definition and UboManager with
lazy UBO rebuild pattern. Uses glBufferSubData on a buffer to update
the block.
@sourcery-ai
Copy link
Copy Markdown

sourcery-ai bot commented Mar 26, 2026

Reviewer's Guide

Introduce a GPU-driven weather system (atmosphere, precipitation, time-of-day) with new UBO blocks, shaders, meshes, and configuration controls, refactoring UBO management and render pipeline to support time-based transitions and per-frame updates.

Sequence diagram for frame update and weather rendering pipeline

sequenceDiagram
    participant User
    participant FrameManager
    participant MapCanvas
    participant OpenGL
    participant Functions as Legacy_Functions
    participant UboManager as Legacy_UboManager
    participant GLWeather
    participant GPU as Shaders_And_Pipeline

    User->>FrameManager: requestFrame()
    activate FrameManager
    FrameManager->>FrameManager: beginFrame()
    Note over FrameManager: Compute deltaTime and m_elapsedTime
    FrameManager->>UboManager: get<TimeBlock>()
    FrameManager->>UboManager: invalidate(TimeBlock)
    deactivate FrameManager

    User->>MapCanvas: paintGL()
    activate MapCanvas
    MapCanvas->>OpenGL: getOpenGL()
    MapCanvas->>GLWeather: update()
    activate GLWeather
    GLWeather->>FrameManager: getElapsedTime()
    GLWeather->>UboManager: get<WeatherBlock>()
    Note over GLWeather: applyTransition for intensities and timeOfDay
    deactivate GLWeather

    MapCanvas->>GLWeather: prepare()
    activate GLWeather
    GLWeather->>OpenGL: getSharedFunctions(Badge_GLWeather)
    GLWeather->>Functions: getUboManager()
    GLWeather->>UboManager: bind(Functions, CameraBlock)
    GLWeather->>UboManager: bind(Functions, WeatherBlock)
    deactivate GLWeather

    MapCanvas->>UboManager: bind(Functions, TimeBlock)

    MapCanvas->>GLWeather: render(renderState)
    activate GLWeather
    alt precipitation active
        GLWeather->>Shaders_And_Pipeline: ParticleSimulationShader + ParticleRenderShader
    end
    alt atmosphere or fog active
        GLWeather->>Shaders_And_Pipeline: AtmosphereShader
    end
    alt time-of-day overlay active
        GLWeather->>Shaders_And_Pipeline: TimeOfDayShader
    end
    deactivate GLWeather

    Shaders_And_Pipeline-->>User: updated weather visuals on screen
    deactivate MapCanvas
Loading

Class diagram for updated UBO management and weather UBO blocks

classDiagram
    direction LR

    namespace Legacy {
        class UboManager {
            -EnumIndexedArray~RebuildFunction,SharedVboEnum~ m_rebuildFunctions
            -EnumIndexedArray~optional~GLuint~~ m_boundBuffers
            -SharedVboBlocks m_shadowBlocks
            +template~SharedVboEnum Block~ BlockType~Block~::type &get()
            +template~SharedVboEnum Block~ const BlockType~Block~::type &get() const
            +void invalidate(SharedVboEnum block)
            +void registerRebuildFunction(SharedVboEnum block, RebuildFunction func, bool allowOverwrite=false)
            +void unregisterRebuildFunction(SharedVboEnum block)
            +bool isInvalid(SharedVboEnum block) const
            +GLuint update(Functions &gl, SharedVboEnum block, const void *data, size_t size)
            +template~SharedVboEnum Block~ GLuint update(Functions &gl, const BlockType~Block~::type &data)
            +template~SharedVboEnum Block~ GLuint sync(Functions &gl)
            +template~SharedVboEnum Block, typename T, typename... Us~ void syncFields(Functions &gl, Us T::*...members)
            +template~SharedVboEnum Block, typename T, typename U~ void syncField(Functions &gl, U T::*member)
            +GLuint bind(Functions &gl, SharedVboEnum block)
        }

        class SharedVboEnum {
            <<enum>>
            NamedColorsBlock
            CameraBlock
            TimeBlock
            WeatherBlock
            NUM_BLOCKS
        }

        class CameraBlock {
            +mat4 viewProj
            +vec4 playerPos
        }

        class TimeBlock {
            +vec4 time
        }

        class WeatherBlock {
            +vec4 intensities
            +vec4 targets
            +vec4 timeOfDay
            +vec4 config
        }

        class NamedColorsBlock {
            +array~vec4,MAX_NAMED_COLORS~ colors
        }

        class BlockType~Block~ {
            <<template specialization>>
        }

        class SharedVboBlocks {
            <<typedef>>
            %% tuple<NamedColorsBlock,CameraBlock,TimeBlock,WeatherBlock>
        }

        class Functions {
            +void glBindBuffer(GLenum target, GLuint buffer)
            +void glBufferData(GLenum target, GLsizeiptr size, const void *data, GLenum usage)
            +void glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const void *data)
            +void glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
            +void glUniformBlockBinding(GLuint program, SharedVboEnum block)
            +const char *getShaderVersion() const
            +static const char *getUniformBlockName(SharedVboEnum block)
            +void applyDefaultUniformBlockBindings(GLuint program)
            +UboManager &getUboManager()
        }
    }

    class FrameManager {
        -QOpenGLWindow &m_window
        -Legacy::UboManager &m_uboManager
        -float m_elapsedTime
        +FrameManager(QOpenGLWindow &window, Legacy::UboManager &uboManager, QObject *parent)
        +~FrameManager()
        +optional~Frame~ beginFrame()
        +float getElapsedTime() const
    }

    class MapCanvas {
        -OpenGL m_opengl
        -FrameManager m_frameManager
        +void initializeGL()
        +void actuallyPaintGL()
        +void onViewProjDirty() const
    }

    class GLWeather {
        -OpenGL &m_gl
        -FrameManager &m_animationManager
        -float m_currentRainIntensity
        -float m_currentSnowIntensity
        -float m_currentCloudsIntensity
        -float m_currentFogIntensity
        -float m_currentTimeOfDayIntensity
        -float m_gameRainIntensity
        -float m_gameSnowIntensity
        -float m_gameCloudsIntensity
        -float m_gameFogIntensity
        -float m_gameTimeOfDayIntensity
        +GLWeather(OpenGL &gl, MapData &mapData, const MapCanvasTextures &textures, GameObserver &observer, FrameManager &frameManager)
        +~GLWeather()
        +void update()
        +void prepare()
        +void render(const GLRenderState &rs)
        +bool isAnimating() const
        +bool isTransitioning() const
    }

    %% Relationships
    UboManager --> SharedVboEnum
    UboManager --> SharedVboBlocks
    SharedVboBlocks --> NamedColorsBlock
    SharedVboBlocks --> CameraBlock
    SharedVboBlocks --> TimeBlock
    SharedVboBlocks --> WeatherBlock

    BlockType~Block~ <.. SharedVboEnum
    Functions --> UboManager

    FrameManager --> UboManager : holds reference
    FrameManager --> TimeBlock : updates via get<TimeBlock>()

    MapCanvas --> OpenGL : m_opengl
    MapCanvas --> FrameManager : m_frameManager
    MapCanvas --> CameraBlock : rebuild function updates

    GLWeather --> OpenGL
    GLWeather --> FrameManager
    GLWeather --> WeatherBlock : uses via UboManager.get<WeatherBlock>()
    GLWeather --> NamedColorsBlock : uses in shaders via UBO
Loading

Class diagram for new weather rendering subsystem (GLWeather, meshes, shaders)

classDiagram
    direction LR

    class GLWeather {
        -OpenGL &m_gl
        -MapData &m_data
        -const MapCanvasTextures &m_textures
        -FrameManager &m_animationManager
        -GameObserver &m_observer
        -ChangeMonitor::Lifetime m_lifetime
        -float m_currentRainIntensity
        -float m_currentSnowIntensity
        -float m_currentCloudsIntensity
        -float m_currentFogIntensity
        -float m_currentTimeOfDayIntensity
        -float m_gameRainIntensity
        -float m_gameSnowIntensity
        -float m_gameCloudsIntensity
        -float m_gameFogIntensity
        -float m_gameTimeOfDayIntensity
        -MumeTimeEnum m_currentTimeOfDay
        -MumeMoonVisibilityEnum m_moonVisibility
        -unique_ptr~Legacy::ParticleSimulationMesh~ m_simulation
        -unique_ptr~Legacy::ParticleRenderMesh~ m_particles
        -UniqueMesh m_atmosphere
        -UniqueMesh m_timeOfDay
        +GLWeather(OpenGL &gl, MapData &mapData, const MapCanvasTextures &textures, GameObserver &observer, FrameManager &frameManager)
        +~GLWeather()
        +void update()
        +void prepare()
        +void render(const GLRenderState &rs)
        +bool isAnimating() const
        +bool isTransitioning() const
        -void updateTargets()
        -void updateFromGame()
        -void initMeshes()
        -void syncWeatherAtmosphere()
        -void syncWeatherTimeOfDay()
        -float applyTransition(float startTime, float startVal, float targetVal) const
        -template~T~ T applyTransition(float startTime, T startVal, T targetVal) const
        -template~T~ struct TransitionPair
        -template~Pairs...~ void startTransitions(float &startTime, Pairs... pairs)
        -NamedColorEnum getCurrentColorIdx() const
    }

    class MapCanvas {
        -GLWeather m_weather
        +MapCanvas(MapData &mapData, GameObserver &observer, PrespammedPath &prespammedPath, Mmapper2Group &groupManager, QWindow *parent)
        +void initializeGL()
        +void actuallyPaintGL()
        +void onMovement()
        +void onViewProjDirty() const
    }

    class FrameManager {
        -Legacy::UboManager &m_uboManager
        -float m_elapsedTime
        +FrameManager(QOpenGLWindow &window, Legacy::UboManager &uboManager, QObject *parent)
        +~FrameManager()
        +optional~Frame~ beginFrame()
        +float getElapsedTime() const
    }

    class GameObserver {
        +MumeTimeEnum getTimeOfDay() const
        +MumeMoonVisibilityEnum getMoonVisibility() const
        +PromptWeatherEnum getWeather() const
        +PromptFogEnum getFog() const
        +Signal2~PromptWeatherEnum~ sig2_weatherChanged
        +Signal2~PromptFogEnum~ sig2_fogChanged
        +Signal2~MumeTimeEnum~ sig2_timeOfDayChanged
        +Signal2~MumeMoonVisibilityEnum~ sig2_moonVisibilityChanged
    }

    class MapCanvasTextures {
        +SharedMMTexture noise
    }

    namespace Legacy {
        class AtmosphereMesh {
            +AtmosphereMesh(SharedFunctions sharedFunctions, shared_ptr~AtmosphereShader~ program)
            +~AtmosphereMesh()
            +void virt_render(const GLRenderState &renderState)
        }

        class TimeOfDayMesh {
            +TimeOfDayMesh(SharedFunctions sharedFunctions, shared_ptr~TimeOfDayShader~ program)
            +~TimeOfDayMesh()
            +void virt_render(const GLRenderState &renderState)
        }

        class ParticleSimulationMesh {
            -SharedFunctions m_shared_functions
            -Functions &m_functions
            -shared_ptr~ParticleSimulationShader~ m_program
            -TFO m_tfo
            -VBO m_vbos[2]
            -VAO m_vaos[2]
            -uint32_t m_currentBuffer
            -uint32_t m_numParticles
            -bool m_initialized
            +ParticleSimulationMesh(SharedFunctions shared_functions, shared_ptr~ParticleSimulationShader~ program)
            +~ParticleSimulationMesh()
            +bool virt_isEmpty() const
            +uint32_t getCurrentBuffer() const
            +uint32_t getNumParticles() const
            +const VBO &getParticleVbo(uint32_t index) const
            -void init()
            -void virt_reset()
            -void virt_render(const GLRenderState &renderState)
        }

        class ParticleRenderMesh {
            -SharedFunctions m_shared_functions
            -Functions &m_functions
            -shared_ptr~ParticleRenderShader~ m_program
            -const ParticleSimulationMesh &m_simulation
            -VAO m_vaos[2]
            -float m_intensity
            -bool m_initialized
            +ParticleRenderMesh(SharedFunctions shared_functions, shared_ptr~ParticleRenderShader~ program, const ParticleSimulationMesh &simulation)
            +~ParticleRenderMesh()
            +void setIntensity(float intensity)
            -void init()
            -void virt_reset()
            -bool virt_isEmpty() const
            -void virt_render(const GLRenderState &renderState)
        }

        class TFO {
            -WeakFunctions m_weakFunctions
            -GLuint m_tfo
            +TFO()
            +~TFO()
            +void emplace(const SharedFunctions &sharedFunctions)
            +void reset()
            +GLuint get() const
        }

        class AtmosphereShader {
            +~AtmosphereShader()
            -void virt_setUniforms(const mat4 &mvp, const GLRenderState::Uniforms &uniforms)
        }

        class TimeOfDayShader {
            +~TimeOfDayShader()
            -void virt_setUniforms(const mat4 &mvp, const GLRenderState::Uniforms &uniforms)
        }

        class ParticleSimulationShader {
            +~ParticleSimulationShader()
            -void virt_setUniforms(const mat4 &mvp, const GLRenderState::Uniforms &uniforms)
        }

        class ParticleRenderShader {
            +~ParticleRenderShader()
            -void virt_setUniforms(const mat4 &mvp, const GLRenderState::Uniforms &uniforms)
        }

        class ShaderPrograms {
            -shared_ptr~AtmosphereShader~ m_atmosphere
            -shared_ptr~TimeOfDayShader~ m_timeOfDay
            -shared_ptr~ParticleSimulationShader~ m_particleSimulation
            -shared_ptr~ParticleRenderShader~ m_particleRender
            +const shared_ptr~AtmosphereShader~ &getAtmosphereShader()
            +const shared_ptr~TimeOfDayShader~ &getTimeOfDayShader()
            +const shared_ptr~ParticleSimulationShader~ &getParticleSimulationShader()
            +const shared_ptr~ParticleRenderShader~ &getParticleRenderShader()
        }
    }

    %% Relationships
    MapCanvas --> GLWeather : "m_weather"
    MapCanvas --> FrameManager : "m_frameManager"

    GLWeather --> MapData
    GLWeather --> MapCanvasTextures
    GLWeather --> GameObserver
    GLWeather --> FrameManager
    GLWeather --> Legacy.ParticleSimulationMesh
    GLWeather --> Legacy.ParticleRenderMesh
    GLWeather --> Legacy.AtmosphereMesh
    GLWeather --> Legacy.TimeOfDayMesh
    GLWeather --> Legacy.ShaderPrograms

    Legacy.ParticleSimulationMesh --> Legacy.TFO
    Legacy.ParticleSimulationMesh --> Legacy.VBO
    Legacy.ParticleSimulationMesh --> Legacy.VAO
    Legacy.ParticleSimulationMesh --> Legacy.ParticleSimulationShader

    Legacy.ParticleRenderMesh --> Legacy.ParticleRenderShader
    Legacy.ParticleRenderMesh --> Legacy.ParticleSimulationMesh
    Legacy.ParticleRenderMesh --> Legacy.VAO

    Legacy.ShaderPrograms --> Legacy.AtmosphereShader
    Legacy.ShaderPrograms --> Legacy.TimeOfDayShader
    Legacy.ShaderPrograms --> Legacy.ParticleSimulationShader
    Legacy.ShaderPrograms --> Legacy.ParticleRenderShader
Loading

File-Level Changes

Change Details Files
Refactor UBO infrastructure to support typed blocks, shadow copies, partial updates, and weather/camera/time data.
  • Introduce Legacy::SharedVboEnum and UBO block structures (CameraBlock, TimeBlock, WeatherBlock, NamedColorsBlock) in UboBlocks.h, replacing the old enum definition in Legacy.h.
  • Extend UboManager with a tuple-backed CPU shadow store and type-safe get/update/sync/syncField(s) APIs, plus safer rebuild function registration/unregistration and error handling.
  • Expose new gl* APIs in Legacy::Functions (buffer sub-data, transform feedback, uniform block binding by Program) and adjust uniform block naming and assertions to use Legacy::SharedVboEnum from UboBlocks.
src/opengl/UboManager.h
src/opengl/UboBlocks.h
src/opengl/legacy/Legacy.h
src/opengl/legacy/Legacy.cpp
Add a time and weather pipeline (UBOs, frame timing, uniforms) driving shaders and animations.
  • Extend FrameManager to track elapsed time, compute per-frame delta, maintain a TimeBlock UBO shadow, and mark it invalid each frame so the UBO rebuild function can sync it.
  • Wire FrameManager to UboManager (constructor takes UboManager, registers/unregisters TimeBlock rebuild) and expose getElapsedTime.
  • Initialize and update CameraBlock and TimeBlock in MapCanvas/MapCanvasViewport (invalidate camera UBO on view/projection changes and player movement, register CameraBlock rebuild).
src/display/FrameManager.h
src/display/FrameManager.cpp
src/display/MapCanvasData.h
src/display/MapCanvasData.cpp
src/display/mapcanvas_gl.cpp
Implement the GLWeather system: CPU-side weather state, transitions, and GPU rendering for particles, atmosphere, and time-of-day overlays.
  • Add GLWeather class that listens to GameObserver weather/fog/time-of-day/moon signals and configuration changes, computes target intensities, manages transition timing, and updates the WeatherBlock UBO.
  • Integrate GLWeather into MapCanvas: construct with OpenGL, MapData, textures, GameObserver, and FrameManager; hook into paint loop via update/prepare/render; ensure UBO bindings for CameraBlock, WeatherBlock, and TimeBlock before weather rendering.
  • Define WeatherConstants (radius, extents, transition duration) and use them in shaders and CPU code for consistent spatial behavior.
src/opengl/Weather.h
src/opengl/Weather.cpp
src/display/mapcanvas.h
src/display/mapcanvas.cpp
src/opengl/Weather.h
Introduce GLSL shader suite and legacy meshes for weather atmosphere, time-of-day overlay, and particle simulation/rendering using transform feedback.
  • Add AtmosphereShader, TimeOfDayShader, ParticleSimulationShader, and ParticleRenderShader types, register them in ShaderPrograms (creation, early_init, resetAll, getters).
  • Implement WeatherMeshes: AtmosphereMesh and TimeOfDayMesh as fullscreen meshes; ParticleSimulationMesh (transform feedback pipeline with double-buffered VBO/VAO) and ParticleRenderMesh (instanced quad rendering driven by simulation).
  • Add GLSL shaders for atmosphere, time-of-day, particle simulation, and particle rendering, wired to NamedColorsBlock, CameraBlock, TimeBlock, and WeatherBlock; use noise-based fog/clouds and precipitation visuals and support defines from WeatherConstants.
  • Extend ShaderUtils with loadTransformFeedbackShaders and inject weather-related #defines (radius, extent, mask radii) into shader sources; improve shader text loading to use UTF-8-safe conversion.
src/opengl/legacy/Shaders.h
src/opengl/legacy/Shaders.cpp
src/opengl/legacy/WeatherMeshes.h
src/opengl/legacy/WeatherMeshes.cpp
src/opengl/legacy/ShaderUtils.h
src/opengl/legacy/ShaderUtils.cpp
src/resources/shaders/legacy/weather/atmosphere/vert.glsl
src/resources/shaders/legacy/weather/atmosphere/frag.glsl
src/resources/shaders/legacy/weather/timeofday/vert.glsl
src/resources/shaders/legacy/weather/timeofday/frag.glsl
src/resources/shaders/legacy/weather/simulation/vert.glsl
src/resources/shaders/legacy/weather/simulation/frag.glsl
src/resources/shaders/legacy/weather/particle/vert.glsl
src/resources/shaders/legacy/weather/particle/frag.glsl
src/opengl/legacy/AbstractShaderProgram.cpp
src/opengl/legacy/AbstractShaderProgram.h
Extend OpenGL utilities (VAO/VBO/TFO, blend modes, types) and textures to support weather rendering and transform feedback.
  • Add TFO wrapper for transform feedback objects and wire transform feedback-related functions into Legacy::Functions.
  • Extend OpenGLTypes with Viewport (moved) and WeatherParticleVert; add BlendModeEnum::MAX_ALPHA and corresponding handling in BlendBinder.
  • Expose shared functions to GLWeather via OpenGL::getSharedFunctions Badge and ensure Legacy.cpp includes new TFO/VAO headers.
  • Add a tileable RGBA noise texture generator, store it in MapCanvasTextures as textures.noise, and allocate it in MapCanvas::initTextures; extend MMTexture to track forbidUpdates and allow constructing from images with that flag.
src/opengl/legacy/TFO.h
src/opengl/legacy/TFO.cpp
src/opengl/OpenGLTypes.h
src/opengl/legacy/Binders.h
src/opengl/legacy/Binders.cpp
src/opengl/OpenGL.h
src/opengl/legacy/VAO.cpp
src/opengl/legacy/VAO.h
src/display/Textures.cpp
src/display/Textures.h
Hook weather/time-of-day into configuration, UI, and game integration.
  • Add three canvas settings for weather intensities (atmosphere, precipitation, time-of-day), persist them via QSettings, and clamp to [0,100].
  • Wire new sliders in GraphicsPage UI to these settings and ensure loading/saving reflects configuration; adjust AdvancedGraphics FpSpinBox to cache multiplier/fraction and simplify setIntValue.
  • Integrate GameObserver into MapCanvas/MapWindow/MainWindow construction so GLWeather can consume in-game weather/fog/time-of-day signals.
src/configuration/configuration.h
src/configuration/configuration.cpp
src/preferences/graphicspage.cpp
src/preferences/graphicspage.ui
src/preferences/AdvancedGraphics.cpp
src/display/mapcanvas.h
src/display/mapcanvas.cpp
src/display/mapwindow.h
src/display/mapwindow.cpp
src/mainwindow/mainwindow.cpp
Update NamedColors to feed UBOs and provide default weather colors for time-of-day overlays.
  • Replace the vec4 vector with a NamedColorsBlock backing store, return it via getAllColorsAsBlock, and keep colors synchronized on updates.
  • Add new named colors for weather (dawn, dusk, night, night-moon) with default RGBA values tuned for overlays, and update XNamedColor interface accordingly.
  • Include UboBlocks.h where needed so NamedColors can populate the UBO block used by shaders.
src/global/NamedColors.h
src/global/NamedColors.cpp
Wire everything into build and minor related tweaks.
  • Register new weather and legacy mesh sources/headers plus Weather/TFO files in CMakeLists.
  • Remove hard-coded ROOM_Z_SCALE in ProjectionUtils.cpp and expose it as ProjectionUtils::ROOM_Z_SCALE, used when populating CameraBlock.playerPos.w.
  • Make small fixes like avoiding unnecessary view/proj recompute on unchanged viewport size and using mmqt::toStdStringUtf8 for shader file loading.
src/CMakeLists.txt
src/display/ProjectionUtils.h
src/display/ProjectionUtils.cpp
src/opengl/legacy/Shaders.cpp
src/display/mapcanvas_gl.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In UboManager::syncFields the template parameter pack Us T::*...members is misused: the sizeof(Us) expression inside the parameter pack expansion will use only the last Us type rather than the type of each member, which makes the upload size incorrect for all but (at best) one field; consider computing the size per member using sizeof(std::decay_t<decltype(blockData.*members)>) or similar inside the fold expression.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `UboManager::syncFields` the template parameter pack `Us T::*...members` is misused: the `sizeof(Us)` expression inside the parameter pack expansion will use only the last `Us` type rather than the type of each member, which makes the upload size incorrect for all but (at best) one field; consider computing the size per member using `sizeof(std::decay_t<decltype(blockData.*members)>)` or similar inside the fold expression.

## Individual Comments

### Comment 1
<location path="src/opengl/Weather.cpp" line_range="213-218" />
<code_context>
+    m_gl.getUboManager().unregisterRebuildFunction(Legacy::SharedVboEnum::WeatherBlock);
+}
+
+void GLWeather::updateFromGame()
+{
+    auto w = m_observer.getWeather();
+    auto f = m_observer.getFog();
+
+    switch (w) {
+    case PromptWeatherEnum::NICE:
+        m_gameRainIntensity = 0.0f;
</code_context>
<issue_to_address>
**issue (bug_risk):** Weather switch does not reset all intensity channels, causing stale rain/snow when switching to CLOUDS

In `updateFromGame()`, only the `NICE` case resets all precipitation intensities to 0. When switching from RAIN or SNOW to `CLOUDS`, we only set `m_gameCloudsIntensity = 0.5f` and leave `m_gameRainIntensity` / `m_gameSnowIntensity` as-is, so prior values can still affect the targets under cloudy weather. To avoid this stale state, either clear all precipitation-related intensities at the start of the function or ensure each weather case sets all four channels (rain, snow, clouds, fog) explicitly.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Adds GLWeather with CameraBlock, TimeBlock, and WeatherBlock UBO support.
Includes particle simulation via transform feedback, atmospheric overlay,
and time-of-day color transitions driven by MUME weather state. Exposes
weather intensity controls in the graphics preferences UI.
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 26, 2026

Codecov Report

❌ Patch coverage is 2.28571% with 684 lines in your changes missing coverage. Please review.
✅ Project coverage is 25.17%. Comparing base (26d1a9d) to head (659fb4a).
⚠️ Report is 222 commits behind head on master.

Files with missing lines Patch % Lines
src/opengl/Weather.cpp 0.00% 269 Missing ⚠️
src/opengl/legacy/WeatherMeshes.cpp 0.00% 110 Missing ⚠️
src/display/Textures.cpp 0.00% 44 Missing ⚠️
src/opengl/legacy/Shaders.cpp 0.00% 44 Missing ⚠️
src/opengl/UboManager.h 0.00% 36 Missing ⚠️
src/opengl/legacy/ShaderUtils.cpp 0.00% 35 Missing ⚠️
src/display/FrameManager.cpp 0.00% 20 Missing ⚠️
src/display/mapcanvas_gl.cpp 0.00% 20 Missing ⚠️
src/preferences/graphicspage.cpp 0.00% 15 Missing ⚠️
src/display/MapCanvasData.cpp 0.00% 13 Missing ⚠️
... and 15 more
Additional details and impacted files
@@             Coverage Diff             @@
##           master     #478       +/-   ##
===========================================
- Coverage   66.48%   25.17%   -41.31%     
===========================================
  Files          85      511      +426     
  Lines        4186    42182    +37996     
  Branches      255     4560     +4305     
===========================================
+ Hits         2783    10619     +7836     
- Misses       1403    31563    +30160     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@nschimme nschimme merged commit fc3649b into MUME:master Mar 26, 2026
18 of 20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant