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()); }
/// <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); }
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; }
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); }
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 }
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"); }
/// <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"); }
/// <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."); } }
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); }
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(); } } }
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); }
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); }