Skip to content
Snippets Groups Projects
  1. Feb 25, 2023
    • Danny Lin's avatar
      blur: Reduce floating-point precision for UV coordinates · ea8b9fdb
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      
      While blur rendering is mostly memory-bound, reducing ALU utilization is
      still helpful. This doesn't result in any noticeable artifacts in the
      blurred image.
      
      When tested with 2 layers of another 6-pass blur implementation, this
      saves ~50 µs of rendering time on an Adreno 640 GPU at 1440x3040
      resolution.
      
      Change-Id: I09798e0d98665b92771e601704653609a240c065
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      ea8b9fdb
    • Danny Lin's avatar
      blur: Downscale image before blurring · 1e45cfa9
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      
      Unintuitively, combining the initial blur pass with downscaling makes
      the rendering process slower because sampling from the high-resolution
      image with bilinear sampling uses more memory bandwidth. It also
      increases the total amount of ALU work because it effectively introduces
      an unnecessary blur pass.
      
      By downscaling the image with glBlitFramebuffer before running blur
      passes, we can save a blur pass and render a more correct result. When
      tested with 2 layers of another 6-pass blur implementation, this saves
      ~800 µs of rendering time on an Adreno 640 GPU at 1440x3040 resolution.
      
      Change-Id: Ie897a52f1628e40d34c3c31f5f779020594bb091
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      1e45cfa9
    • Danny Lin's avatar
      blur: Only set constant shader uniforms once · 02315785
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      
      The values of the 2D texture sampler uniforms never change, so set them
      when initializing the BlurFilter instance instead of updating them every
      frame. This reduces clutter in the rendering path and results in a
      negligible performance gain from reducing API overhead.
      
      Change-Id: I335ea0dbdd2d4409ea71b58b7c7f8b87b04a18d7
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      02315785
    • Danny Lin's avatar
      blur: Dither output using triangular RGB blue noise · 071ea161
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      Blurring images usually creates a lot of gradual color transitions,
      especially at higher radii. When the output is quantized to 8-bit RGB
      (8 bpc / 24 bpp) for display, the lost information (quantization error)
      results in visible banding. This is most apparent in scenes that are
      predominantly grayscale because of the reduced color fidelity, but it
      can still be an issue in scenes with many colors.
      
      To fix the banding, this commit dithers the blur output during
      quantization. This is done in the final output mixing step because
      dithering works best when it operates on each individual pixel;
      upscaling a dithered image will not help much.
      
      Error diffusion dithering is ideal, but it is not practical for GPU
      fragment shaders because it requires processing each pixel sequentually.
      Instead, we use ordered dithering, which tiles a pattern across the
      entire image to influence rounding during quantization.
      
      The most visually-appealing pattern is used for ordered dithering: blue
      noise [1]. Other patterns considered:
        - Bayer matrix: visible pattern in output
        - White (random) noise: high-frequency components are distracting and
          make tiling repetitions apparent
        - Interleaved gradient noise, generated in shader [2]: aliasing
          artifacts, somewhat visible pattern, and expensive ALU operations
        - Oculus Dither17 pattern, generated in shader [3]: same issues as
          interleaved gradient noise
      Blue noise contains very few low-frequency components, making it ideal
      for dithering because it tiles seamlessly and does not distract from the
      actual image.
      
      When dithering, the blue noise is reshaped from uniform distribution to
      a triangular PDF distribution. This makes the noise appear more uniform
      when used for dithering: instead of some areas having less visible noise
      than others, the noise appears to be evenly spread across the entire
      image [4] [5]. A naïve implementation of triangular reshaping is
      relatively expensive (+60 µs), but using an optimized implementation of
      sign() reduces the cost to ~30 µs [6].
      
      Finally, to avoid adding noise to pure black (#000000) images or
      affecting saturation, the dithering implementation needs to perform
      gamma correction [5]. The real sRGB transfer function is relatively
      expensive because it's a piecewise function with linear and exponential
      (gamma 2.4) parts that average to gamma 2.2, so we approximate it
      instead with gamma 2. This makes the performance cost of gamma
      correction negligible while still producing acceptable results.
      
      Most applications of dithering add up to 1x LSB (least significant bit -
      i.e. 1/256 for 8-bpc output) of noise, but this implementation adds up
      to 4x LSB (i.e. 1/64 for 8-bpc) of noise. While this adds more noise to
      the output, it was empirically determined to be more effective for
      reducing banding in color gradients than 1x LSB. There are still nearly
      no visible noise artifacts when using blue noise and gamma correction.
      
      Note that dithering requires the blurred image to be rendered at 10-bit
      HDR (10 bpc / 30 bpp) internally; otherwise, it would just add noise
      without fixing banding.
      
      This increases rendering time by ~300 µs on an Adreno 640 GPU at
      1440x3040 resolution, which is a worthwhile tradeoff for the
      significant improvement in quality.
      
      [1] http://momentsingraphics.de/BlueNoise.html
      [2] http://www.iryoku.com/downloads/Next-Generation-Post-Processing-in-Call-of-Duty-Advanced-Warfare-v18.pptx
      [3] https://developer.oculus.com/blog/tech-note-shader-snippets-for-efficient-2d-dithering/
      [4] https://loopit.dk/banding_in_games.pdf
      [5] https://loopit.dk/rendering_inside.pdf
      [6] https://twitter.com/SebAaltonen/status/878250919879639040
      
      
      
      Change-Id: I80559654a19c6cc6f2f53c94b64963d0bb888af5
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      071ea161
    • Danny Lin's avatar
      blur: Skip processing of alpha channel by swizzling RGB · 43710493
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      
      This reduces ALU utilization by avoiding unnecessary calculations that
      are discarded in the final fragment color. This saves ~100 µs in another
      6-pass blur implementation.
      
      Change-Id: I4ec24518eefce369dbb592ac03a14caeea86df9a
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      43710493
    • Danny Lin's avatar
      blur: Improve terminology used in mix shader · 6baa812c
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      
      This improved terminology helps clarify what each uniform refers to,
      which will become more important once we add dithering.
      
      Change-Id: I607a08b63c6370d091412905d32bd7d89ae71769
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      6baa812c
    • Danny Lin's avatar
      blur: Limit blur to the two frontmost layers · 31193591
      Danny Lin authored and Simão Gomes Viana's avatar Simão Gomes Viana committed
      
      Rendering 3 or more layers of blur on top of each other makes little to
      no visual difference in the final result, but it comes at a big
      performance penalty. Only blurring the two frontmost layers saves a lot
      of GPU time with minimal difference in output quality.
      
      Change-Id: I9ec8129751a183db00ad200080207434f086a63e
      Signed-off-by: default avatarMohammad Hasan Keramat J <ikeramat@protonmail.com>
      Signed-off-by: default avatarSimão Gomes Viana <devel@superboring.dev>
      31193591
  2. Feb 18, 2023
  3. Feb 07, 2023
  4. Jan 27, 2023
  5. Jan 26, 2023
  6. Jan 13, 2023
  7. Jan 10, 2023
  8. Jan 07, 2023
  9. Jan 01, 2023
Loading