Unity-Technologies / UniversalRenderingExamples

This project contains a collection of Custom Renderer examples. This will be updated as we refine the feature and add more options.
2.03k stars 412 forks source link

Gradient Fog for Oculus Quest VR #43

Open SiriusA7 opened 3 years ago

SiriusA7 commented 3 years ago

I tested the gradient fog sample for Oculus Quest because I've been wanting to learn more about custom post-processing effects/shaders, and I've been looking for a good looking + performant way of doing fog for Quest VR. But I came up on a handful of issues, some I was able to solve, not sure if correctly though. But I haven't found a way to get past the last issue.

Unity Version: 2020.2.0b14 URP Version: 10.2.1 Device: Oculus Quest 2

1st Issue: When building out the sample scene, or when switching between scenes using the same gradient fog render pipeline assets, this error was spat out seemingly every frame with nothing being displayed in either scene or game views:

Your script should either check if it is null or you should not destroy the object.
UnityEngine.Material.SetFloat (System.String name, System.Single value) (at <e414e10bfe5f45729ff122f3359de21b>:0)
GradientFog+GradientFogPass.Setup (UnityEngine.Rendering.RenderTargetIdentifier cameraColorTarget) (at Assets/_CompletedDemos/GradientFog/Rendering/GradientFog.cs:36)
GradientFog.AddRenderPasses (UnityEngine.Rendering.Universal.ScriptableRenderer renderer, UnityEngine.Rendering.Universal.RenderingData& renderingData) (at Assets/_CompletedDemos/GradientFog/Rendering/GradientFog.cs:98)
UnityEngine.Rendering.Universal.ScriptableRenderer.AddRenderPasses (UnityEngine.Rendering.Universal.RenderingData& renderingData) (at Library/PackageCache/com.unity.render-pipelines.universal@10.2.1/Runtime/ScriptableRenderer.cs:648)
UnityEngine.Rendering.Universal.ForwardRenderer.Setup (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Rendering.Universal.RenderingData& renderingData) (at Library/PackageCache/com.unity.render-pipelines.universal@10.2.1/Runtime/ForwardRenderer.cs:289)
UnityEngine.Rendering.Universal.UniversalRenderPipeline.RenderSingleCamera (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Rendering.Universal.CameraData cameraData, System.Boolean anyPostProcessingEnabled) (at Library/PackageCache/com.unity.render-pipelines.universal@10.2.1/Runtime/UniversalRenderPipeline.cs:377)
UnityEngine.Rendering.Universal.UniversalRenderPipeline.RenderSingleCamera (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera camera) (at Library/PackageCache/com.unity.render-pipelines.universal@10.2.1/Runtime/UniversalRenderPipeline.cs:296)
UnityEngine.Rendering.Universal.UniversalRenderPipeline.Render (UnityEngine.Rendering.ScriptableRenderContext renderContext, UnityEngine.Camera[] cameras) (at Library/PackageCache/com.unity.render-pipelines.universal@10.2.1/Runtime/UniversalRenderPipeline.cs:251)
UnityEngine.Rendering.RenderPipeline.InternalRender (UnityEngine.Rendering.ScriptableRenderContext context, UnityEngine.Camera[] cameras) (at <e414e10bfe5f45729ff122f3359de21b>:0)
UnityEngine.Rendering.RenderPipelineManager.DoRenderLoop_Internal (UnityEngine.Rendering.RenderPipelineAsset pipe, System.IntPtr loopPtr, System.Collections.Generic.List`1[T] renderRequests, Unity.Collections.LowLevel.Unsafe.AtomicSafetyHandle safety) (at <e414e10bfe5f45729ff122f3359de21b>:0)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)

Solution: I was able to get past this by updating the Setup method in GradientFog.cs to this:

public void Setup(RenderTargetIdentifier cameraColorTarget)
        {
            source = cameraColorTarget;
            if (fogMaterial)
            {
                fogMaterial.SetFloat("_StartDist", settings.StartDistance);
                fogMaterial.SetFloat("_EndDist", settings.EndDistance);
                fogMaterial.SetColor("_NearCol", settings.NearColor);
                fogMaterial.SetColor("_MidCol", settings.MiddleColor);
                fogMaterial.SetColor("_FarCol", settings.FarColor);
            }
            else
            {
                Debug.LogWarning("No fogMaterial? making new...");
                m_TempTex.Init("_TempTex");
                fogMaterial = new Material(Shader.Find("Shader Graphs/GradientFogGraph"));
            }
        }

Seemed to let me switch scenes and build successfully after this change.

2nd Issue: After 1st successful build, I tried running in headset, but nothing ever showed up. I checked the adb device log and found this being spat out repetitiously:

2020/12/06 19:24:26.005 19820 19843 Error Unity ArgumentNullException: Value cannot be null.
2020/12/06 19:24:26.005 19820 19843 Error Unity Parameter name: shader
2020/12/06 19:24:26.005 19820 19843 Error Unity   at GradientFog+GradientFogPass..ctor () [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at GradientFog.Create () [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at UnityEngine.Rendering.Universal.ScriptableRenderer..ctor (UnityEngine.Rendering.Universal.ScriptableRendererData data) [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at UnityEngine.Rendering.Universal.ForwardRenderer..ctor (UnityEngine.Rendering.Universal.ForwardRendererData data) [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at UnityEngine.Rendering.Universal.ForwardRendererData.Create () [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.CreateRenderers () [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset.CreatePipeline () [0x00000] in <00000000000000000000000000000000>:0 
2020/12/06 19:24:26.005 19820 19843 Error Unity   at UnityEngine.Rendering.RenderPipelineAsset.Inte

Solution: So to get past this I figured to include the 'GradientFogGraph' shader graph within "Always Included Shaders" in Graphics in Project Settings. Not sure if that was the correct way to handle it, but it kind of worked and the error no longer showed up in the adb log for the second build.

3rd Issue: After the above fix, when running in headset, all I see is white. But I can tell the app is running and not frozen because adb says it's running at 72fps, and when the app started I could see the Oculus OVR Screen Fade happen. Which is simply a plane in-front of the cameras that fade from black to transparent as an intro loader thing.

I tried fiddling with different settings for the gradient fog, but nothing changed the outcome of a solid white display in the build. I also test through oculus link in editor and the fog looked great in both multi-pass and multi-view. Not sure what to try next to try and get it to work the same in build so any help/suggestions would be greatly appreciated!