Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Bug Reflection Probes are not used with IndirectInstanced Rendering using the Deferred path

Discussion in 'Universal Render Pipeline' started by Grigler_f, Sep 16, 2022.

  1. Grigler_f

    Grigler_f

    Joined:
    May 14, 2020
    Posts:
    24
    Hello,

    Our project makes heavy usage of instanced rendering, but we've found that only the environment reflections set in the lighting panel have any effect on it. I've managed to eliminate it being a shader issue as using it in the scene as and letting Unity render it results in it correctly using the reflection probe's cubemap. I captured a frame in RenderDoc, using the same shader in the scene for both instanced and non-instanced rendering,it seems as though the instanced version uses either UnityBlackCube for the specular cubemap or the custom one set in EnvironmentReflection if it is set.

    I've not found any documentation stating that reflection probes for IndirectInstancing isn't supported in URP, so it seems as though this must just be a bug.
     
  2. Spiraseven

    Spiraseven

    Joined:
    May 2, 2014
    Posts:
    25
    I also just ran into this while using DrawMeshInstanced. I'm going to try a few different versions of Unity and see if it works in any of them. But currently I can't seem to get Reflection Probes to work on my instanced meshes.
     
  3. peterbay

    peterbay

    Unity Technologies

    Joined:
    Nov 2, 2017
    Posts:
    100
    URP Forward and Deferred uses per-object reflection probes which are bound on the CPU based on the bounding box of the object. Since for indirect draws this is decided on the GPU, we don't have the necessary information to find the correct reflection probe. Also, it would have to bind the same reflection probes (maximum of 2) for the whole instanced draw.

    It will work in the upcoming Forward+ path, as we're currently working on bringing the reflection probes into the Forward+ data structure. This means that it decides which reflection probes to sample on a per-pixel basis on the GPU.

    I think you're right that this should be mentioned in the documentation though :)
     
    Spiraseven likes this.
  4. Grigler_f

    Grigler_f

    Joined:
    May 14, 2020
    Posts:
    24
    We've actually migrated this project from HDRP to URP, which is why this problem came as a surprise as it was never an issue in HDRP. Presumably this means that it's doing extra work on the GPU to find this information, similar to what you've described with the Forward+ path?
     

    Attached Files:

  5. peterbay

    peterbay

    Unity Technologies

    Joined:
    Nov 2, 2017
    Posts:
    100
    Yeah, that is correct. We're adopting the same strategy for reflection probes in the Forward+ rendering path, except for some differences in the spatial data structure. This also allows objects to be influenced by any number of reflection probes, as opposed to the current limitation of 2 per object, even if the probes do not overlap.
     
  6. Grigler_f

    Grigler_f

    Joined:
    May 14, 2020
    Posts:
    24
    As our project almost exclusively uses instanced rendering, we were exploring alternatives to being able to use reflection probes. We could get by using the Skybox mode in the environment reflections, however it seems as though updating the skybox at runtime seems to result in the renderer reverting to using UnityBlackCube for the environment cubemap. I've tried to find where people have solved this problem before and came across this post that had the same issue:
    https://forum.unity.com/threads/reflections-dont-update-when-changing-skybox-at-runtime.529442/

    Of course the reponse they had was to use reflection probes instead, but as that isn't an option for us with instanced rendering until some point in the future I'd like to know if it's possible to trigger an update to that environment reflection cubemap. I initially hackily experimented with inserting a ScriptableRenderFeature in the BeforeRenderingGBufferPass to overwrite the unity_SpecCube0, however this didn't yield any results and it seems as though that these properties are being internally set in the DrawRenderers call made in the GBufferPass.

    Are there any other options for us to update the environment reflections map or are we simply stuck without being able to update them at runtime?
     
  7. peterbay

    peterbay

    Unity Technologies

    Joined:
    Nov 2, 2017
    Posts:
    100
    Hmm yeah, I think you might be right about the overriding of unity_SpecCube0. If you enable reflection probe blending, then we use a URP-specific property _GlossyEnvironmentCubeMap and _GlossyEnvironmentCubeMap_HDR for the environment reflections, which you should be able to overwrite in a renderer feature. I realize that paying for unused probe blending is not great, but I hope this can at least provide a workaround for you.
     
  8. Grigler_f

    Grigler_f

    Joined:
    May 14, 2020
    Posts:
    24
    Thanks for the quick response, it's seeming as though this won't work either sadly. After looking at GlobalIllumination.hlsl and reading some of the shader values, both unity_SpecCube0 and unity_SpecCube1 have float4(-inf) and float4(inf) for their box bounds which if I'm reading the shader correctly will mean that their weight will be too high for the
    _GlossyEnvironmentCubeMap to be used. I'm going to keep tweaking and see if there's something I'm missing but hopefully you'll be able to confirm whether I'm correct on this.
     
  9. Grigler_f

    Grigler_f

    Joined:
    May 14, 2020
    Posts:
    24
    Update: I've copied the relevant parts of the GlobalIllumination.hlsl file into our own .cginc and have edited the Irradiance to just always read from the _GlossyEnvironmentCubeMap, this results in the behaviour that we were hoping from changing the skybox at runtime and will have to do until Forward+ supports reflection probes for instanced rendering
     
  10. cydashnine

    cydashnine

    Joined:
    Jul 15, 2022
    Posts:
    3
    We were having a similar issue with using a dynamic skybox for a reflection map and noticed the calls to Graphics.DrawMeshInstanced/RenderMeshInstanced either used a default unity black cubemap if there was no light info baked into the scene (and Lighting/Scene/WorkFlow Settings/Recalculate Environment Lighting was off) or it used a default baked reflection map which never changed (RenderDoc is useful here to see which maps are being accessed by your shaders and how). We were able to work around this by setting unity_SpecCube0 in the material properties list for the draw calls as our use case only needed a single environment reflection map.
     
  11. Jakub_Machowski

    Jakub_Machowski

    Joined:
    Mar 19, 2013
    Posts:
    647
    Seems like with additive scene loading one scene is using always white reflection or not updating skybox reflection. Maybe is there any documentation explaining how it exactly work cause for now it seems like behaviour for reflections for instancing indirect is uknown.
     
  12. IJM

    IJM

    Joined:
    Aug 31, 2010
    Posts:
    143
    For anyone having this problem in 2024.

    Use DrawMeshInstanced with "UnityEngine.Rendering.LightProbeUsage.Off" and pass in a MaterialPropertyBlock.

    You'll need to pass the reflection probe texture into the MaterialPropertyBlock:
    Code (CSharp):
    1. _mpb.SetTexture("unity_SpecCube0", _probeTexture);
    2. _mpb.SetTexture("unity_SpecCube1", _probeTexture);

    That's it.

    p.s.
    If you read the documentation (I know, why would anyone do that...), you'll find a misinformation that you should use "UnityEngine.Rendering.LightProbeUsage.CustomProvided". If you try doing it like that, reflection probes will work, but you won't get any ambient light. I assume that you can provide ambient light information to the MaterialPropertyBlock, but it's just more work. Rendering pipeline is pushing those variables to all shaders anyway.

    It would be great if Unity developers could provide intended examples on how to do this "the correct way", so that we don't have to decrypt their intentions from vague descriptions.
     
    kripto289 likes this.