Skip to main content
Teeh
Contributor
View all authors

Why are Light Volumes cool?

· 6 min read
Teeh
Contributor

Hi, I'm Teeh. I recently started playing with VRC Light Volumes, and I have fallen in love. Let's explore a few of the foundations supporting VRC Light Volumes. This is absolutely not a tutorial and I'm not even going to touch on 90% of the cool stuff it can do.

For the most part, Volumes will replace Light Probe based lighting when it's available, so let's start there.

Probe Lighting

Probe Lighting

If you've ever set up a probe volume, you'll know that you (or whatever tool you're using) place something called a "probe" at each location in your scene that you want to store ambient lighting data for. Light probes measure diffuse environmental lighting, also known as irradiance, at a single point in your scene. It's important to understand that this measurement stores incoming light - it is up to the shader to run this through whatever shading function (typically some BRDF) to represent the target material's lighting characteristics. This lighting data is stored as a series of spherical harmonic coefficients in an array. At runtime, Renderers that are affected by probe lighting will have the CPU do a few things:

  • Find the four closest probes surrounding the renderer anchor point in a tetrahedron
    • If you have an 'Anchor Override' set it will use the transform of that object
    • If you don't, this defaults to the center of the bounding box for that mesh
  • Blend the influence of each probe based on the distance to the anchor
  • Ship that data off to the GPU as part of the draw call for that mesh

This happens for each dynamically lit mesh in your scene.

SHs Taking Ls

It's not inaccurate to say that Volumes store the exact same info as Probes, but that's not the whole story. They both store, instead of simple RGB color values, a set of Spherical Harmonic (SH) coefficients. Probes store up to 9 coefficients per RGB channel, which corresponds to L2 harmonics. Volumes only store 3 coefficients per RGB channel, which corresponds to L1 harmonics.

More harmonics let you encode the lighting at higher frequencies - effectively making them higher resolution. In layman's terms, more coefficients let you more sharply define environmental light, which for diffuse lighting luckily doesn't need to be super exact. There may still be a place for L2 Light Probes, especially considering how L1 harmonics need to be blurred (as in 'hanning window') a little to combat ringing artifacts. This is something I'll look more into, I'll share results if I find anything interesting. So far I think the benefits of lighting being volumetric with Volumes outweighs slightly increased lighting resolution with L2 Probes.

Spherical Harmonics

There are a few benefits to storing lighting in SH coefficients, as opposed to something like cubemaps: no projection stretching, no distortions when rotated (orthonormal basis vs world AABB basis), they're quick to do math on (e.g. blurring), they are super quick to use (shading with them ends up being a few dot products against the surface normal) and being as tiny as they are, they use way less memory bandwidth. These benefits come from working with lighting in frequency space, as opposed to something more immediately intuitive like a cubemap's position space.

If you want to expand your understanding of spherical harmonics I recommend reading Spherical Harmonics by PataBlog and Stupid SH Tricks by Peter Pike Sloan at Microsoft. The main point I want to drive here is that the 3D texture that Volumes bake down to are not simple RGB colors that you can sample directly.

So how does Volume lighting work?

Visualizing VRCLV Voxels I made a volume to store the light coming off of my little guy. You can't attach volumes to your avatar, this is just a demonstration.

So. You have:

  • A scene. In that scene is a
    • Volume that takes up some 3D space which is itself split into many
      • voxels which each store
        • SH coefficients for that position's environmental lighting
  • a mesh that's within the bounds of that 3D volume.

Instead of sampling a single point in 3D space and using that Probe to shade the entire mesh, we run a (fragment) shader on each pixel that:

  • Uses the pixel's world space position to sample the 3D volume
    • The 3D Texture sampled is an atlas of 3 3D Textures, so we need to tap it three times
      • Using a 3D texture gives us bilinear interpolation to smooth the lighting out for samples in between voxels.
  • Deliver the sampled SH coefficients to the shader.

VRCLV 3D Texture Atlas

This is an example of what a Light Volume Atlas can look like. First, all of the volumes in the scene are combined into an atlas (in this case there's a single volume) and that atlas is repeated 2 more times to store the additional SH coefficients.

No. Seriously. That's it. Light Volumes can be integrated into existing shaders so easily because the end product is a set of SH coefficients - just like with Light Probes!

Also notice how we didn't have to ask the CPU to do anything. The GPU already 'knows' the world space position of each pixel AND has the entirety of the Volume textures in VRAM, so it can do all that sampling itself. In theory we could skip all the light probe work being done on the CPU, but it's too closely integrated with the Built-In Rendering Pipeline for that juice to be worth the squeeze, also, very few worlds are going to have Volumes so you should maintain the ability to fall back to probes anyway.

Important differences

  • Probes can be placed arbitrarily in your scene. Volume voxels must be placed strictly on a grid.
  • Probe coefficients are stored in an array accessed by the CPU, volume coefficients are stored in a 3D texture accessed by the GPU.
  • Probes light meshes per-renderer based on an anchor sample position. Volumes light meshes per-pixel based on world-space position samples.

Goodbye

I haven't touched on a fraction of the cool stuff VRCLV does, and I'm tempted to make a tutorial or something on how to set up LV and use them in place of Unity's traditional lightmapping. Let me know what you think!

Poiyomi Toon 9.0.60 Update

· 5 min read
Teeh
Contributor

Hi! I'm Teeh. After a long wait, a new version of Poiyomi Shaders is finally ready to release! There's been a lot of bug fixes and new features added, so let me show you the highlights for Poiyomi Toon 9.0.60, and Poiyomi Pro 9.1.12.

See the video patch notes below for more information.

Major Changes

AMD Fixes

Some previously Pro-only AMD fixes are being rolled back into Toon. There's still work to be done, but we're not ignoring you guys! Keep an eye out for more details later on.

Unity 2019 Fixes

Compatibility with Unity 2019 has been fixed! This should now allow you to use the Shader for either ChilloutVR, Beat Saber, and VSeeFace (or other V-tubing software of your preference).

Bakery

We fixed issues with Emissive Materials on the Poiyomi World shader not appearing in Bakery, a third-party GPU Lightmapper.

This also includes the ability to preview the Emissive properties from Poiyomi World materials in Bakery as well.

Missing Locked Materials

If a Locked Material is missing for whatever reason, the UI will now indicate this and prompt you to unlock it. This should help alleviate issues with Materials unable to Unlock in cases where the generated OptimizedShaders files went missing or were accidentally deleted.

Major Shader Translator Upgrades

Last, but not least, is the Poiyomi Material Translator. The goal of this Tool is to easily translate Materials from any other Shader, including from older versions of Poiyomi, as accurate as possible. Shaders such as lilToon can be translated to Poiyomi Shaders easily, with all properties completely converted without any major differences. No more fiddling with MatCap masks and shading settings!

To use the new feature, a new context menu option was added in Unity. Right-Click on an Avatar or Mesh in the Hierarchy OR on a Material in your Files, and in the context menu, click Poiyomi -> Materials -> Translate to Poiyomi Toon to run the program. This will seamlessly convert the configuration of those Materials to appear properly in Poiyomi Shaders.

You can also have it make a Copy of the Material(s) with the converted properties. To use that, select Translate Copy to Poiyomi Toon from the same context menu instead. If there are multiple Materials, they will be organized automatically.

Full Changelog

  • Added new Documentation Links in the UI to the following sections (thanks @BluWizard10 for all the hard work on the Docs!)
    • Shading/Anisotropics
    • Shading/Backlight
    • Shading/LTCGI
    • Special FX/Depth FX
    • AudioLink
    • AudioLink/AL Spectrum
    • AudioLink/AL Volume Color
    • Global Modifiers & Data/Global Data & Masks/Global Mask
    • Global Modifiers & Data/UVs/Parallax Heightmapping
  • You can now translate from LilToon to Poiyomi. Right-Click your Avatar or any Material basically anywhere, then click Poiyomi -> Materials -> Translate to Poiyomi Toon.
    • The Translate to Poiyomi Toon function will translate the Materials in-place.
    • If you select Translate Copy to Poiyomi Toon, the program will create copies of the Materials and then translate them. Use this if you want to preserve the original Materials.
    • Pro Users: You can choose to Translate to Poiyomi Pro if you so wish.
  • Shader: Alpha Mask Blend Strength was internally named _AlphaMaskScale and had compatibility problems when converting from other Shaders to Poiyomi. It has been renamed to _AlphaMaskBlendStrength. If you were using this, the value will be reset to 1.0.
  • Shader: Added Mirrored UV Mode to Decals.
    • This helps control the visibility of Decals on models with overlapping UVs (or mirrored UVs). Set it to Flip on one side, or be on one side only.
  • Shader: Added Symmetry Mode to Decals.
    • If enabled, will put the Decal on both sides by dividing the UV down the center.
    • Works only on Models with perfect Symmetrized UVs.
  • Shader: Added Z Clip to Rendering, which commands the ZClip command in the Shader. ZClip on Unity Documentation
  • Shader: Added Color Space dropdown to various Color Adjust settings.
    • OKLab provides better and more accurate perceptive color changes. This can eliminate issues with noise and colors being washed out when adjusting the Hue.
    • HSV is the "legacy" method, reflecting how the Hue Shift behaved in 8.1 and older.
  • Fix: Fixed Alpha Offset being backwards when Alpha was inverted. It now functions the same way, inverted or not.
  • Fix: Grayscale for Cloth Shading now works as intended.
  • Fix: The first round of fixes for AMD computers have been implemented.
  • Fix: Improved compatibility with Unity 2019 all the way thru Unity 2022.
  • Fix: Fixed lightmapping code in Poiyomi World shaders, causing Emissive Materials to not work properly with Bakery.
  • UI: Added an Unlock Button to Locked Materials that have missing files, fixing an issue with Material properties being lost when the OptimizedShaders folder goes missing.
  • UI: Redesigned the Material UI Header. Example
    • Search is now shown as a Text field, instead of an Icon.
    • Presets is now a Button, instead of an Icon.
    • Both the Presets button and Rendering Presets dropdown are now aligned opposite of each other, underneath the Lock/Unlock button.
  • UI: ThryEditor updated to v2.56.5.

Some patch notes were lost because Poiyomi's Hard Drive failed. You may find some of them as Easter Eggs instead. Happy hunting!