Meteoros Volumetric Cloudscape Renderer

repository·master·Indexed 42 days ago

https://github.com/amansachan1/meteoros

A high-performance, real-time volumetric cloudscape renderer built with Vulkan, inspired by the NUBIS system used in Guerrilla Games' Decima Engine.

Tokens
20.3K
Snippets
50
Records
93
Agent score
53%

What's inside Meteoros

  1. Introduction to GLFW

    master

    GLFW is an open-source, multi-platform library designed for OpenGL, OpenGL ES, and Vulkan application development. It provides a platform-independent API for common windowing and input tasks, including:

    • Creating windows, contexts, and surfaces
    • Reading input (keyboard, mouse, etc.)
    • Handling events

    Supported Platforms:

    • Windows
    • macOS
    • Linux and other Unix-like systems (including experimental support for Wayland and Mir)

    License: zlib/libpng license.

  2. Overview of OpenGL Mathematics (GLM)

    master

    GLM is a header-only C++ mathematics library designed for graphics software. It is based on the OpenGL Shading Language (GLSL) specifications, meaning it uses the same naming conventions and functionality as GLSL. This allows developers familiar with GLSL to use the same logic in C++.

    Key features include:

    • GLSL Compatibility: Core classes and functions mirror GLSL.
    • Extension System: Provides extended capabilities like matrix transformations, quaternions, data packing, random numbers, and noise using GLSL-style extension conventions.
    • Interoperability: Works with OpenGL and is compatible with other third-party libraries and SDKs.
    • Versatility: Suitable for software rendering (raytracing/rasterisation), image processing, and physics simulations.
  3. Overview of Meteoros

    master
    Meteoros is a real-time volumetric cloudscape renderer built using the Vulkan API. It is based on the 'NUBIS' cloud system used in the Decima Engine (notably in Horizon Zero Dawn). The renderer is designed for high performance, achieving sub-3ms per frame at Full HD resolution on a GTX 1070. It implements cloud modeling, lighting, and rendering algorithms as described in SIGGRAPH 2015 and 2017 presentations.
  4. Current features of Meteoros

    master

    The current implementation includes:

    • An extensible, heavily commented Vulkan framework.
    • Synchronized Compute and Graphics pipelines.
    • Cloud modeling, lighting, and rendering models based on NUBIS.
    • HDR color space support (32-bit RGBA).
    • Post-processing effects: God-Rays and Tone Mapping.
    • Optimizations: Raymarching, cloud rendering, and fully functional Reprojection.
    • Temporal Anti-Aliasing (TXAA).
  5. Manage mouse cursor lag and rendering

    master

    ImGui typically has zero frames of lag for most behaviors, but some behaviors may have one frame of lag. At 60 FPS, this is generally unnoticeable, but you may notice a difference between hardware-accelerated OS cursors and GPU-rendered software cursors.

    To visualize or manage this, you can use the io.MouseDrawCursor flag. This requests ImGui to draw the mouse cursor itself, which can help you visualize the lag between a hardware cursor and a software cursor. It may be beneficial to switch to a software-rendered cursor when an interactive drag is in progress to improve user experience.

  6. Implementation details of the Reprojection technique

    master

    Reprojection is implemented using the following technical steps:

    1. Store the previous frame in a texture.
    2. Store the previous camera information.
    3. For a given pixel in the current frame, ray cast using the current camera's ray and the current pixel's UV coordinates.
    4. Intersect the ray with the sphere representing the inner layer of the atmosphere to find the world space position.
    5. Convert that world space position back into UV coordinates using the old camera's view and projection matrices.
    6. If the resulting UV coordinate is within the range [0,1], sample the pixel from the old frame to fill the current pixel.
  7. Optimize font texture size

    master

    Large numbers of glyphs or multiple fonts can exceed graphics driver texture size limits. To minimize the resulting texture height/width:

    1. Set io.Fonts.TexDesiredWidth: Specify a target texture width to control the aspect ratio.
    2. Reduce Oversampling: Lower config.OversampleH (e.g., to 2 or 1) in ImFontConfig.
    3. Limit Glyph Ranges: Use GlyphRangesBuilder to only include necessary characters, or use specific range functions like GetGlyphRangesDefault(), GetGlyphRangesJapanese(), or GetGlyphRangesChinese() instead of loading full Unicode sets.
  8. L-value Swizzling with Visual C++

    master

    On compilers that support anonymous struct as union members (like Visual C++), GLM_FORCE_SWIZZLE enables true GLSL-like swizzling, allowing both R-value and L-value expressions.

    Note: Swizzle objects returned by this method are implementation-specific and implicitly convert to vector types. They cannot be passed directly to GLM functions; you must use an explicit constructor or the () operator.

    Example of L-value usage:

    ColorRGBA.bgra = ColorRGBA.rgba;

    Example of required conversion for GLM functions:

    // ERROR: Color.rgba is not a vector type
    vec4 ClampedA = glm::clamp(Color.rgba, 0.f, 1.f);
    
    // OK: Explicit conversion
    vec4 ClampedB = glm::clamp(vec4(Color.rgba), 0.f, 1.f);
    // OK: Explicit conversion via operator()
    vec4 ClampedC = glm::clamp(Color.rgba(), 0.f, 1.f);
    #define GLM_FORCE_SWIZZLE
    #include <glm/glm.hpp>
    using glm::vec4;
    
    void foo()
    {
      vec4 Color(1.0f, 0.5f, 0.0f, 1.0f);
    
      // Generates compiler errors. Color.rgba is not a vector type.
      vec4 ClampedA = glm::clamp(Color.rgba, 0.f, 1.f); // ERROR
    
      // Explicit conversion through a constructor
      vec4 ClampedB = glm::clamp(vec4(Color.rgba), 0.f, 1.f); // OK
    
      // Explicit conversion through operator()
      vec4 ClampedC = glm::clamp(Color.rgba(), 0.f, 1.f); // OK
    }
  9. Synchronization in the Meteoros Pipeline

    master

    Meteoros uses a compositing model where clouds are generated first, then rasterized geometry is painted over them, followed by god-ray effects.

    • Compute to Graphics Synchronization: To prevent the graphics pipeline from accessing an image while the compute pipeline is still writing to it, an Image Barrier is used. This ensures the compute stage completes its writes before the graphics stage begins compositing.
    • Graphics to Post-Process Synchronization: No explicit synchronization point is required between these stages because their commands are stored in the same Queue. Since commands in a single command buffer are executed in order, the post-process effects naturally wait for the graphics stage to finish.
  10. Handle UTF-8 encoding for strings

    master

    All strings used in ImGui must be encoded in UTF-8. Using local code pages (like CP-923 or CP-1251) in your source code will not work.

    In C++11 and later, you can use the u8"string" syntax to ensure literals are UTF-8 encoded:

    ImGui::Text(u8"hello");
    ImGui::Text(u8"こんにちは");

    Alternatively, you can manually convert strings to UTF-8 or load text data from files that are already saved in UTF-8 format. You can also use font->AddRemapChar() to map local codepage characters to Unicode codepoints, though this may cause issues for international contributors.

  11. Understand Meteoros performance optimization techniques

    master

    Meteoros employs several optimization strategies to maintain performance during volumetric cloud rendering:

    1. Early Termination: During ray marching, if the accumulated density exceeds a value of 1, the ray march terminates early to save computation.
    2. Cheap Sampling: High-frequency erosion, cloud shaping, and expensive lighting calculations are only performed if the base density is greater than 0 (indicating the ray is inside a cloud).
    3. Reprojection: This technique uses pixels from the previous frame to color pixels in the current frame by projecting the old frame onto the current one. This allows the engine to only perform full ray marching for approximately 1/16th of the pixels, while the remaining 15/16ths are filled via reprojection. This has shown up to a 5.97x speed boost in preliminary tests.
  12. How cloud rendering works via Ray Marching

    master

    Meteoros uses ray marching, an image-based volumetric rendering technique, to render clouds. Unlike surface rendering, ray marching evaluates volumes by sampling a ray at various points along its length.

    The Rendering Pipeline:

    1. Skybox Setup: The sky is rendered as a dome using three concentric spheres representing the Earth, the inner atmosphere, and the outer atmosphere.
    2. Raycasting: Rays are cast from the camera. For every ray, the engine evaluates points at a fixed step size while the ray is within the two atmosphere layers.
    3. Density Evaluation: If a point along the ray has a non-zero density value, it is identified as being inside a cloud.
    4. Lighting: To color the point, a ray is shot towards the sun (the single light source) to determine energy levels.

    Optimization: Instead of naive ray shooting for lighting, Meteoros uses Cone Sampling. This involves taking 6 samples within a cone aligned with the light source. The final sample is placed further away to account for potential occlusion by distant clouds.