コード例 #1
0
        public static void RemoveRendererFromPipeline(ScriptableRendererData pass)
        {
            if (pass == null)
            {
                return;
            }

            BindingFlags bindings = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;

            ScriptableRendererData[]      m_rendererDataList = (ScriptableRendererData[])typeof(UniversalRenderPipelineAsset).GetField(renderDataListFieldName, bindings).GetValue(UniversalRenderPipeline.asset);
            List <ScriptableRendererData> rendererDataList   = new List <ScriptableRendererData>(m_rendererDataList);

            if (rendererDataList.Contains(pass))
            {
                rendererDataList.Remove((pass));
            }

            typeof(UniversalRenderPipelineAsset).GetField(renderDataListFieldName, bindings).SetValue(UniversalRenderPipeline.asset, rendererDataList.ToArray());
        }
コード例 #2
0
        /// <summary>
        /// Checks if a ScriptableRendererFeature is added to the default renderer
        /// </summary>
        /// <param name="addIfMissing"></param>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static bool RenderFeatureAdded <T>(bool addIfMissing = false)
        {
            ScriptableRendererData forwardRenderer = GetDefaultRenderer();
            bool isPresent = false;

            foreach (ScriptableRendererFeature feature in forwardRenderer.rendererFeatures)
            {
                if (feature.GetType() == typeof(T))
                {
                    isPresent = true;
                }
            }

            if (!isPresent && addIfMissing)
            {
                AddRenderFeature <T>(forwardRenderer);
            }

            return(isPresent);
        }
コード例 #3
0
        public static bool ValidEffectSetup<T>()
        {
            bool state = false;
#if URP
            ScriptableRendererData[] rendererDataList = (ScriptableRendererData[])typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(UniversalRenderPipeline.asset);
            ScriptableRendererData forwardRenderer = rendererDataList[0];

            foreach (ScriptableRendererFeature item in forwardRenderer.rendererFeatures)
            {
                if (item == null) continue;

                if (item.GetType() == typeof(T))
                {
                    state = true;
                }
            }
#endif

            return state;
        }
コード例 #4
0
        private static bool IsLightweightRenderPipelineSetupCorrectly()
        {
            if (s_pipelineSetupOk)
            {
                return(true);
            }
            // check if the current Forward Renderer has the ProjectorRendererFeature instance.
            LightweightRenderPipelineAsset renderPipelineAsset = LightweightRenderPipeline.asset;

            if (renderPipelineAsset == null)
            {
                return(false);
            }
            UnityEditor.SerializedObject   serializedObject     = new UnityEditor.SerializedObject(renderPipelineAsset);
            UnityEditor.SerializedProperty rendererDataProperty = serializedObject.FindProperty("m_RendererData");
            ScriptableRendererData         rendererData         = rendererDataProperty.objectReferenceValue as ScriptableRendererData;

            if (rendererData == null)
            {
                Debug.LogError("The current Lightweight Render Pipeline Asset does not have Forward Renderer Data! Please set a Forward Renderer Data which contains ProjectorRendererFeature to the current render pipeline asset.", renderPipelineAsset);
            }
            else
            {
                bool found = false;
                foreach (var rendererFeature in rendererData.rendererFeatures)
                {
                    if (rendererFeature is ProjectorRendererFeature)
                    {
                        found = true;
                        break;
                    }
                }
                if (!found)
                {
                    Debug.LogError("ProjectorRendererFeature is not added to the current Forward Renderer Data.", rendererData);
                    return(false);
                }
            }
            s_pipelineSetupOk = true;
            return(true);
        }
コード例 #5
0
ファイル: SCPE.cs プロジェクト: DragosPopse/LostAndFound
        public static void SetupEffect<T>()
        {
#if URP
            if(UniversalRenderPipeline.asset == null) return;

            ScriptableRendererData[] rendererDataList = (ScriptableRendererData[])typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(UniversalRenderPipeline.asset);
            int defaultRendererIndex = (int)typeof(UniversalRenderPipelineAsset).GetField("m_DefaultRendererIndex", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(UniversalRenderPipeline.asset);
            ScriptableRendererData forwardRenderer = rendererDataList[defaultRendererIndex];
            
            if (forwardRenderer.GetType() == typeof(Renderer2DData))
            {
                //Debug.LogError("2D renderer is not supported");
                return;
            }
            ScriptableRendererFeature feature = (ScriptableRendererFeature)ScriptableRendererFeature.CreateInstance(typeof(T).ToString());
            feature.name = "[SCPE] " + typeof(T).ToString().Replace("SCPE.", string.Empty);

            //Add component https://github.com/Unity-Technologies/Graphics/blob/d0473769091ff202422ad13b7b764c7b6a7ef0be/com.unity.render-pipelines.universal/Editor/ScriptableRendererDataEditor.cs#L180
            AssetDatabase.AddObjectToAsset(feature, forwardRenderer);
            AssetDatabase.TryGetGUIDAndLocalFileIdentifier(feature, out var guid, out long localId);

            //Get feature list
            FieldInfo renderFeaturesInfo = typeof(ScriptableRendererData).GetField("m_RendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic);
            List<ScriptableRendererFeature> m_RendererFeatures = (List<ScriptableRendererFeature>)renderFeaturesInfo.GetValue(forwardRenderer);

            //Modify and set list
            m_RendererFeatures.Add(feature);
            renderFeaturesInfo.SetValue(forwardRenderer, m_RendererFeatures);

            //Onvalidate will call ValidateRendererFeatures and update m_RendererPassMap
            MethodInfo validateInfo = typeof(ScriptableRendererData).GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic);
            validateInfo.Invoke(forwardRenderer, null);

#if UNITY_EDITOR
            EditorUtility.SetDirty(forwardRenderer);
            AssetDatabase.SaveAssets();
#endif
            Debug.Log("<b>" + feature.name + "</b> was added to the " + forwardRenderer.name + " renderer");
#endif
        }
コード例 #6
0
        private static void AddRendererToPipeline(ScriptableRendererData pass)
        {
            if (pass == null)
            {
                return;
            }

            BindingFlags bindings = System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance;

            ScriptableRendererData[]      m_rendererDataList = (ScriptableRendererData[])typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList", bindings).GetValue(UniversalRenderPipeline.asset);
            List <ScriptableRendererData> rendererDataList   = new List <ScriptableRendererData>();

            for (int i = 0; i < m_rendererDataList.Length; i++)
            {
                rendererDataList.Add(m_rendererDataList[i]);
            }
            rendererDataList.Add(pass);

            typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList", bindings).SetValue(UniversalRenderPipeline.asset, rendererDataList.ToArray());

            Debug.Log("The <i>" + DrawGrassBenders.AssetName + "</i> renderer is required and was automatically added to the \"" + UniversalRenderPipeline.asset.name + "\" pipeline asset");
        }
コード例 #7
0
        /// <summary>
        /// Adds a ScriptableRendererFeature to the renderer (default is none is supplied)
        /// </summary>
        /// <param name="forwardRenderer"></param>
        /// <typeparam name="T"></typeparam>
        public static void AddRenderFeature <T>(ScriptableRendererData forwardRenderer = null)
        {
            if (forwardRenderer == null)
            {
                forwardRenderer = GetDefaultRenderer();
            }

            ScriptableRendererFeature feature = (ScriptableRendererFeature)ScriptableRendererFeature.CreateInstance(typeof(T).ToString());

            feature.name = typeof(T).ToString();

            //Add component https://github.com/Unity-Technologies/Graphics/blob/d0473769091ff202422ad13b7b764c7b6a7ef0be/com.unity.render-pipelines.universal/Editor/ScriptableRendererDataEditor.cs#L180
#if UNITY_EDITOR
            AssetDatabase.AddObjectToAsset(feature, forwardRenderer);
            AssetDatabase.TryGetGUIDAndLocalFileIdentifier(feature, out var guid, out long localId);
#endif

            //Get feature list
            FieldInfo renderFeaturesInfo = typeof(ScriptableRendererData).GetField("m_RendererFeatures", BindingFlags.Instance | BindingFlags.NonPublic);
            List <ScriptableRendererFeature> m_RendererFeatures = (List <ScriptableRendererFeature>)renderFeaturesInfo.GetValue(forwardRenderer);

            //Modify and set list
            m_RendererFeatures.Add(feature);
            renderFeaturesInfo.SetValue(forwardRenderer, m_RendererFeatures);

            //Onvalidate will call ValidateRendererFeatures and update m_RendererPassMap
            MethodInfo validateInfo = typeof(ScriptableRendererData).GetMethod("OnValidate", BindingFlags.Instance | BindingFlags.NonPublic);
            validateInfo.Invoke(forwardRenderer, null);

#if UNITY_EDITOR
            EditorUtility.SetDirty(forwardRenderer);
            AssetDatabase.SaveAssets();
#endif

            Debug.Log("<b>" + feature.name + "</b> was added to the " + forwardRenderer.name + " renderer");
        }
コード例 #8
0
        /// <summary>
        /// Sets the renderer index of the related forward renderer
        /// </summary>
        /// <param name="camData"></param>
        /// <param name="renderer"></param>
        public static void AssignRendererToCamera(UniversalAdditionalCameraData camData, ScriptableRendererData renderer)
        {
            if (UniversalRenderPipeline.asset)
            {
                if (renderer)
                {
                    //list is internal, so perform reflection workaround
                    ScriptableRendererData[] rendererDataList = (ScriptableRendererData[])typeof(UniversalRenderPipelineAsset).GetField(renderDataListFieldName, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(UniversalRenderPipeline.asset);

                    for (int i = 0; i < rendererDataList.Length; i++)
                    {
                        if (rendererDataList[i] == renderer)
                        {
                            camData.SetRenderer(i);
                        }
                    }
                }
            }
            else
            {
                Debug.LogError("No Universal Render Pipeline is currently active.");
            }
        }
コード例 #9
0
        private static ShaderFeatures GetSupportedShaderFeatures(UniversalRenderPipelineAsset pipelineAsset)
        {
            ShaderFeatures shaderFeatures;

            shaderFeatures = ShaderFeatures.MainLight;

            if (pipelineAsset.supportsMainLightShadows)
            {
                shaderFeatures |= ShaderFeatures.MainLightShadows;
            }

            if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerVertex)
            {
                shaderFeatures |= ShaderFeatures.VertexLighting;
            }
            else if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerPixel)
            {
                shaderFeatures |= ShaderFeatures.AdditionalLights;

                if (pipelineAsset.supportsAdditionalLightShadows)
                {
                    shaderFeatures |= ShaderFeatures.AdditionalLightShadows;
                }
            }

            bool anyShadows = pipelineAsset.supportsMainLightShadows ||
                              (shaderFeatures & ShaderFeatures.AdditionalLightShadows) != 0;

            if (pipelineAsset.supportsSoftShadows && anyShadows)
            {
                shaderFeatures |= ShaderFeatures.SoftShadows;
            }

            if (pipelineAsset.supportsMixedLighting)
            {
                shaderFeatures |= ShaderFeatures.MixedLighting;
            }

            if (pipelineAsset.supportsTerrainHoles)
            {
                shaderFeatures |= ShaderFeatures.TerrainHoles;
            }

            if (pipelineAsset.useFastSRGBLinearConversion)
            {
                shaderFeatures |= ShaderFeatures.UseFastSRGBLinearConversion;
            }

            if (pipelineAsset.supportsLightLayers)
            {
                shaderFeatures |= ShaderFeatures.LightLayers;
            }

            bool hasScreenSpaceShadows         = false;
            bool hasScreenSpaceOcclusion       = false;
            bool hasDeferredRenderer           = false;
            bool withAccurateGbufferNormals    = false;
            bool withoutAccurateGbufferNormals = false;

            int rendererCount = pipelineAsset.m_RendererDataList.Length;

            for (int rendererIndex = 0; rendererIndex < rendererCount; ++rendererIndex)
            {
                ScriptableRenderer renderer = pipelineAsset.GetRenderer(rendererIndex);
                if (renderer is UniversalRenderer)
                {
                    UniversalRenderer universalRenderer = (UniversalRenderer)renderer;
                    if (universalRenderer.renderingMode == RenderingMode.Deferred)
                    {
                        hasDeferredRenderer           |= true;
                        withAccurateGbufferNormals    |= universalRenderer.accurateGbufferNormals;
                        withoutAccurateGbufferNormals |= !universalRenderer.accurateGbufferNormals;
                    }
                }

                // Check for Screen Space Ambient Occlusion Renderer Feature
                ScriptableRendererData rendererData = pipelineAsset.m_RendererDataList[rendererIndex];
                if (rendererData != null)
                {
                    for (int rendererFeatureIndex = 0; rendererFeatureIndex < rendererData.rendererFeatures.Count; rendererFeatureIndex++)
                    {
                        ScriptableRendererFeature rendererFeature = rendererData.rendererFeatures[rendererFeatureIndex];

                        ScreenSpaceShadows ssshadows = rendererFeature as ScreenSpaceShadows;
                        hasScreenSpaceShadows |= ssshadows != null;

                        ScreenSpaceAmbientOcclusion ssao = rendererFeature as ScreenSpaceAmbientOcclusion;
                        hasScreenSpaceOcclusion |= ssao != null;
                    }
                }
            }

            if (hasDeferredRenderer)
            {
                shaderFeatures |= ShaderFeatures.DeferredShading;
            }

            // We can only strip accurateGbufferNormals related variants if all DeferredRenderers use the same option.
            if (withAccurateGbufferNormals)
            {
                shaderFeatures |= ShaderFeatures.DeferredWithAccurateGbufferNormals;
            }

            if (withoutAccurateGbufferNormals)
            {
                shaderFeatures |= ShaderFeatures.DeferredWithoutAccurateGbufferNormals;
            }

            if (hasScreenSpaceShadows)
            {
                shaderFeatures |= ShaderFeatures.ScreenSpaceShadows;
            }

            if (hasScreenSpaceOcclusion)
            {
                shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusion;
            }

            return(shaderFeatures);
        }
コード例 #10
0
        private void DrawRendererFeature(int index, ref SerializedProperty renderFeatureProperty)
        {
            Object rendererFeatureObjRef = renderFeatureProperty.objectReferenceValue;

            if (rendererFeatureObjRef != null)
            {
                bool   hasChangedProperties = false;
                string title;

                bool hasCustomTitle = GetCustumTitle(rendererFeatureObjRef.GetType(), out title);

                if (!hasCustomTitle)
                {
                    title = ObjectNames.GetInspectorTitle(rendererFeatureObjRef);
                }

                // Get the serialized object for the editor script & update it
                Editor           rendererFeatureEditor            = m_Editors[index];
                SerializedObject serializedRendererFeaturesEditor = rendererFeatureEditor.serializedObject;
                serializedRendererFeaturesEditor.Update();

                // Foldout header
                EditorGUI.BeginChangeCheck();
                SerializedProperty activeProperty = serializedRendererFeaturesEditor.FindProperty("m_Active");
                bool displayContent = CoreEditorUtils.DrawHeaderToggle(title, renderFeatureProperty, activeProperty, pos => OnContextClick(pos, index));
                hasChangedProperties |= EditorGUI.EndChangeCheck();

                // ObjectEditor
                if (displayContent)
                {
                    if (!hasCustomTitle)
                    {
                        EditorGUI.BeginChangeCheck();
                        SerializedProperty nameProperty = serializedRendererFeaturesEditor.FindProperty("m_Name");
                        nameProperty.stringValue = ValidateName(EditorGUILayout.DelayedTextField(Styles.PassNameField, nameProperty.stringValue));
                        if (EditorGUI.EndChangeCheck())
                        {
                            hasChangedProperties = true;

                            // We need to update sub-asset name
                            rendererFeatureObjRef.name = nameProperty.stringValue;
                            AssetDatabase.SaveAssets();

                            // Triggers update for sub-asset name change
                            ProjectWindowUtil.ShowCreatedAsset(target);
                        }
                    }

                    EditorGUI.BeginChangeCheck();
                    rendererFeatureEditor.OnInspectorGUI();
                    hasChangedProperties |= EditorGUI.EndChangeCheck();

                    EditorGUILayout.Space(EditorGUIUtility.singleLineHeight);
                }

                // Apply changes and save if the user has modified any settings
                if (hasChangedProperties)
                {
                    serializedRendererFeaturesEditor.ApplyModifiedProperties();
                    serializedObject.ApplyModifiedProperties();
                    ForceSave();
                }
            }
            else
            {
                CoreEditorUtils.DrawHeaderToggle(Styles.MissingFeature, renderFeatureProperty, m_FalseBool, pos => OnContextClick(pos, index));
                m_FalseBool.boolValue = false; // always make sure false bool is false
                EditorGUILayout.HelpBox(Styles.MissingFeature.tooltip, MessageType.Error);
                if (GUILayout.Button("Attempt Fix", EditorStyles.miniButton))
                {
                    ScriptableRendererData data = target as ScriptableRendererData;
                    data.ValidateRendererFeatures();
                }
            }
        }
コード例 #11
0
        private static ShaderFeatures GetSupportedShaderFeatures(UniversalRenderPipelineAsset pipelineAsset)
        {
            ShaderFeatures shaderFeatures;

            shaderFeatures = ShaderFeatures.MainLight;

            if (pipelineAsset.supportsMainLightShadows)
            {
                shaderFeatures |= ShaderFeatures.MainLightShadows;
            }

            if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerVertex)
            {
                shaderFeatures |= ShaderFeatures.VertexLighting;
            }
            else if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerPixel)
            {
                shaderFeatures |= ShaderFeatures.AdditionalLights;
            }

            bool anyShadows = pipelineAsset.supportsMainLightShadows ||
                              (shaderFeatures & ShaderFeatures.AdditionalLightShadows) != 0;

            if (pipelineAsset.supportsSoftShadows && anyShadows)
            {
                shaderFeatures |= ShaderFeatures.SoftShadows;
            }

            if (pipelineAsset.supportsMixedLighting)
            {
                shaderFeatures |= ShaderFeatures.MixedLighting;
            }

            if (pipelineAsset.supportsTerrainHoles)
            {
                shaderFeatures |= ShaderFeatures.TerrainHoles;
            }

            if (pipelineAsset.useFastSRGBLinearConversion)
            {
                shaderFeatures |= ShaderFeatures.UseFastSRGBLinearConversion;
            }

            if (pipelineAsset.supportsLightLayers)
            {
                shaderFeatures |= ShaderFeatures.LightLayers;
            }

            bool hasScreenSpaceShadows         = false;
            bool hasScreenSpaceOcclusion       = false;
            bool hasDeferredRenderer           = false;
            bool withAccurateGbufferNormals    = false;
            bool withoutAccurateGbufferNormals = false;
            bool clusteredRendering            = false;
            bool onlyClusteredRendering        = false;
            bool usesRenderPass = false;

            int rendererCount = pipelineAsset.m_RendererDataList.Length;

            for (int rendererIndex = 0; rendererIndex < rendererCount; ++rendererIndex)
            {
                ScriptableRenderer renderer = pipelineAsset.GetRenderer(rendererIndex);
                if (renderer is UniversalRenderer)
                {
                    UniversalRenderer universalRenderer = (UniversalRenderer)renderer;
                    if (universalRenderer.renderingMode == RenderingMode.Deferred)
                    {
                        hasDeferredRenderer           |= true;
                        withAccurateGbufferNormals    |= universalRenderer.accurateGbufferNormals;
                        withoutAccurateGbufferNormals |= !universalRenderer.accurateGbufferNormals;
                        usesRenderPass |= universalRenderer.useRenderPassEnabled;
                    }
                }

                var rendererClustered = false;

                ScriptableRendererData rendererData = pipelineAsset.m_RendererDataList[rendererIndex];
                if (rendererData != null)
                {
                    for (int rendererFeatureIndex = 0; rendererFeatureIndex < rendererData.rendererFeatures.Count; rendererFeatureIndex++)
                    {
                        ScriptableRendererFeature rendererFeature = rendererData.rendererFeatures[rendererFeatureIndex];

                        ScreenSpaceShadows ssshadows = rendererFeature as ScreenSpaceShadows;
                        hasScreenSpaceShadows |= ssshadows != null;

                        // Check for Screen Space Ambient Occlusion Renderer Feature
                        ScreenSpaceAmbientOcclusion ssao = rendererFeature as ScreenSpaceAmbientOcclusion;
                        hasScreenSpaceOcclusion |= ssao != null;

                        // Check for Decal Renderer Feature
                        DecalRendererFeature decal = rendererFeature as DecalRendererFeature;
                        if (decal != null)
                        {
                            var technique = decal.GetTechnique(renderer);
                            switch (technique)
                            {
                            case DecalTechnique.DBuffer:
                                shaderFeatures |= GetFromDecalSurfaceData(decal.GetDBufferSettings().surfaceData);
                                break;

                            case DecalTechnique.ScreenSpace:
                                shaderFeatures |= GetFromNormalBlend(decal.GetScreenSpaceSettings().normalBlend);
                                shaderFeatures |= ShaderFeatures.DecalScreenSpace;
                                break;

                            case DecalTechnique.GBuffer:
                                shaderFeatures |= GetFromNormalBlend(decal.GetScreenSpaceSettings().normalBlend);
                                shaderFeatures |= ShaderFeatures.DecalGBuffer;
                                break;
                            }
                        }
                    }

                    if (rendererData is UniversalRendererData universalRendererData)
                    {
                        rendererClustered = universalRendererData.renderingMode == RenderingMode.Forward &&
                                            universalRendererData.clusteredRendering;
                    }
                }

                clusteredRendering     |= rendererClustered;
                onlyClusteredRendering &= rendererClustered;
            }

            if (hasDeferredRenderer)
            {
                shaderFeatures |= ShaderFeatures.DeferredShading;
            }

            // We can only strip accurateGbufferNormals related variants if all DeferredRenderers use the same option.
            if (withAccurateGbufferNormals)
            {
                shaderFeatures |= ShaderFeatures.DeferredWithAccurateGbufferNormals;
            }

            if (withoutAccurateGbufferNormals)
            {
                shaderFeatures |= ShaderFeatures.DeferredWithoutAccurateGbufferNormals;
            }

            if (hasScreenSpaceShadows)
            {
                shaderFeatures |= ShaderFeatures.ScreenSpaceShadows;
            }

            if (hasScreenSpaceOcclusion)
            {
                shaderFeatures |= ShaderFeatures.ScreenSpaceOcclusion;
            }

            if (usesRenderPass)
            {
                shaderFeatures |= ShaderFeatures.RenderPassEnabled;
            }

            if (pipelineAsset.reflectionProbeBlending)
            {
                shaderFeatures |= ShaderFeatures.ReflectionProbeBlending;
            }

            if (pipelineAsset.reflectionProbeBoxProjection)
            {
                shaderFeatures |= ShaderFeatures.ReflectionProbeBoxProjection;
            }

            if (clusteredRendering)
            {
                shaderFeatures |= ShaderFeatures.ClusteredRendering;
            }

            if (onlyClusteredRendering)
            {
                shaderFeatures &= ~(ShaderFeatures.AdditionalLights | ShaderFeatures.VertexLighting);
            }

            if (pipelineAsset.additionalLightsRenderingMode == LightRenderingMode.PerPixel || clusteredRendering)
            {
                if (pipelineAsset.supportsAdditionalLightShadows)
                {
                    shaderFeatures |= ShaderFeatures.AdditionalLightShadows;
                }
            }

            return(shaderFeatures);
        }
コード例 #12
0
        private Camera CreateCamera()
        {
            Camera cam = new GameObject().AddComponent <Camera>();

            cam.gameObject.name            = "GrassBendCamera " + GetInstanceID();
            cam.transform.localEulerAngles = new Vector3(90f, 0f, 0f);
            cam.gameObject.hideFlags       = HideFlags.HideAndDontSave;
            if (actualFollowTarget)
            {
                cam.gameObject.transform.position = new Vector3(actualFollowTarget.transform.position.x, actualFollowTarget.transform.position.y + renderExtends, actualFollowTarget.transform.position.z);
            }

            cam.orthographic = true;
            cam.depth        = -100f;
            cam.allowHDR     = false;
            cam.allowMSAA    = false;
            cam.clearFlags   = CameraClearFlags.SolidColor;
            cam.cullingMask  = 0;
            //Neutral bend direction and zero strength/mask
            cam.backgroundColor = neutralVector;

            cam.useOcclusionCulling    = false;
            cam.allowHDR               = true;
            cam.allowMSAA              = false;
            cam.forceIntoRenderTexture = true;

#if URP
            UniversalAdditionalCameraData camData = cam.gameObject.AddComponent <UniversalAdditionalCameraData>();
            camData.renderShadows        = false;
            camData.renderPostProcessing = false;
            camData.antialiasing         = AntialiasingMode.None;
            camData.requiresColorOption  = CameraOverrideOption.Off;
            camData.requiresDepthOption  = CameraOverrideOption.Off;
            camData.requiresColorTexture = false;
            camData.requiresDepthTexture = false;

            if (UniversalRenderPipeline.asset)
            {
#if UNITY_EDITOR
                //Only runs in editor, but will be referenced in instance from there on
                if (!bendRenderer)
                {
                    bendRenderer = GetGrassBendRenderer();
                }
                DrawGrassBenders.ValidatePipelineRenderers();
#endif

                if (bendRenderer)
                {
                    //Assign DrawGrassBenders renderer (list is internal, so perform reflection workaround)
                    ScriptableRendererData[] rendererDataList = (ScriptableRendererData[])typeof(UniversalRenderPipelineAsset).GetField("m_RendererDataList", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(UniversalRenderPipeline.asset);

                    for (int i = 0; i < rendererDataList.Length; i++)
                    {
                        if (rendererDataList[i] == bendRenderer)
                        {
                            camData.SetRenderer(i);
                        }
                    }
                }
                else
                {
                    this.enabled = false;
                }
            }
            else
            {
                Debug.LogError("[StylizedGrassRenderer] No Universal Render Pipeline is currently active.");
            }
#endif

            return(cam);
        }