protected override void OnEnable() { base.OnEnable(); geometryOverrideLayer = FindProperty((Config x) => x.geometryOverrideLayer); geometryLayerID = FindProperty((Config x) => x.geometryLayerID); geometryTag = FindProperty((Config x) => x.geometryTag); geometryRenderQueue = FindProperty((Config x) => x.geometryRenderQueue); renderPipeline = FindProperty((Config x) => x.renderPipeline); renderingMode = FindProperty((Config x) => x.renderingMode); beamShader1Pass = serializedObject.FindProperty("beamShader1Pass"); beamShader2Pass = serializedObject.FindProperty("beamShader2Pass"); sharedMeshSides = FindProperty((Config x) => x.sharedMeshSides); sharedMeshSegments = FindProperty((Config x) => x.sharedMeshSegments); globalNoiseScale = FindProperty((Config x) => x.globalNoiseScale); globalNoiseVelocity = FindProperty((Config x) => x.globalNoiseVelocity); noise3DData = FindProperty((Config x) => x.noise3DData); noise3DSize = FindProperty((Config x) => x.noise3DSize); dustParticlesPrefab = FindProperty((Config x) => x.dustParticlesPrefab); RenderQueueGUIInit(); Noise3D.LoadIfNeeded(); // Try to load Noise3D, maybe for the 1st time }
public override void OnInspectorGUI() { base.OnInspectorGUI(); EditorGUILayout.LabelField(string.Format("Current Plugin Version: {0}", Version.Current), EditorStyles.miniBoldLabel); Header("Beam Geometry"); EditorGUI.BeginChangeCheck(); geometryLayerID.intValue = EditorGUILayout.LayerField(new GUIContent("Layer", "The layer the GameObjects holding the procedural cone meshes are created on"), geometryLayerID.intValue); geometryTag.stringValue = EditorGUILayout.TagField(new GUIContent("Tag", "The tag applied on the procedural geometry GameObjects"), geometryTag.stringValue); if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllMeshesDirty(); } EditorGUILayout.PropertyField(beamShader, new GUIContent("Shader", "Main shader applied to the cone beam geometry")); Header("Global 3D Noise"); EditorGUILayout.PropertyField(globalNoiseScale, new GUIContent("Scale", "Global 3D Noise texture scaling: higher scale make the noise more visible, but potentially less realistic")); EditorGUILayout.PropertyField(globalNoiseVelocity, new GUIContent("Velocity", "Global World Space direction and speed of the noise scrolling, simulating the fog/smoke movement")); Header("3D Noise Texture Data"); bool reloadNoise = false; EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(noise3DData, new GUIContent("Binary file", "Binary file holding the 3D Noise texture data (a 3D array). Must be exactly Size * Size * Size bytes long.")); int newSizeValue = EditorGUILayout.IntField(new GUIContent("Data dimension", "Size (of one dimension) of the 3D Noise data. Must be power of 2. So if the binary file holds a 32x32x32 texture, this value must be 32.") , noise3DSize.intValue); noise3DSize.intValue = Mathf.Max(2, Mathf.NextPowerOfTwo(newSizeValue)); if (EditorGUI.EndChangeCheck()) { reloadNoise = true; } if (Noise3D.isSupported && !Noise3D.isProperlyLoaded) { EditorGUILayout.HelpBox("Fail to load 3D noise texture", MessageType.Error); } Header("Volumetric Dust Particles"); EditorGUILayout.PropertyField(dustParticlesPrefab, new GUIContent("Prefab", "ParticleSystem prefab instantiated for the Volumetric Dust Particles feature (Unity 5.5 or above)")); EditorGUILayout.Space(); if (GUILayout.Button(new GUIContent("Default values", "Reset properties to their default values."), EditorStyles.miniButton)) { UnityEditor.Undo.RecordObject(target, "Reset Config Properties"); (target as Config).Reset(); } serializedObject.ApplyModifiedProperties(); if (reloadNoise) { Noise3D._EditorForceReloadData(); // Should be called AFTER ApplyModifiedProperties so the Config instance has the proper values when reloading data } }
protected override void OnEnable() { base.OnEnable(); geometryLayerID = FindProperty((Config x) => x.geometryLayerID); geometryTag = FindProperty((Config x) => x.geometryTag); beamShader = FindProperty((Config x) => x.beamShader); globalNoiseScale = FindProperty((Config x) => x.globalNoiseScale); globalNoiseVelocity = FindProperty((Config x) => x.globalNoiseVelocity); noise3DData = FindProperty((Config x) => x.noise3DData); noise3DSize = FindProperty((Config x) => x.noise3DSize); dustParticlesPrefab = FindProperty((Config x) => x.dustParticlesPrefab); Noise3D.LoadIfNeeded(); // Try to load Noise3D, maybe for the 1st time }
public static void LoadIfNeeded() { if (!Noise3D.isSupported) { return; } if (Noise3D.ms_NoiseTexture == null) { Noise3D.ms_NoiseTexture = Noise3D.LoadTexture3D(Config.Instance.noise3DData, Config.Instance.noise3DSize); if (Noise3D.ms_NoiseTexture) { Noise3D.ms_NoiseTexture.hideFlags = HideFlags.HideAndDontSave; } } Shader.SetGlobalTexture("_VLB_NoiseTex3D", Noise3D.ms_NoiseTexture); Shader.SetGlobalVector("_VLB_NoiseGlobal", Config.Instance.globalNoiseParam); }
public static void LoadIfNeeded() { if (!Noise3D.isSupported) { return; } if (Object.op_Equality((Object)Noise3D.ms_NoiseTexture, (Object)null)) { Noise3D.ms_NoiseTexture = Noise3D.LoadTexture3D(Config.Instance.noise3DData, Config.Instance.noise3DSize); if (Object.op_Implicit((Object)Noise3D.ms_NoiseTexture)) { ((Object)Noise3D.ms_NoiseTexture).set_hideFlags((HideFlags)61); } } Shader.SetGlobalTexture("_VLB_NoiseTex3D", (Texture)Noise3D.ms_NoiseTexture); Shader.SetGlobalVector("_VLB_NoiseGlobal", Config.Instance.globalNoiseParam); }
protected override void OnEnable() { base.OnEnable(); geometryOverrideLayer = FindProperty((Config x) => x.geometryOverrideLayer); geometryLayerID = FindProperty((Config x) => x.geometryLayerID); geometryTag = FindProperty((Config x) => x.geometryTag); geometryRenderQueue = FindProperty((Config x) => x.geometryRenderQueue); renderPipeline = serializedObject.FindProperty("_RenderPipeline"); renderingMode = serializedObject.FindProperty("_RenderingMode"); sharedMeshSides = FindProperty((Config x) => x.sharedMeshSides); sharedMeshSegments = FindProperty((Config x) => x.sharedMeshSegments); globalNoiseScale = FindProperty((Config x) => x.globalNoiseScale); globalNoiseVelocity = FindProperty((Config x) => x.globalNoiseVelocity); fadeOutCameraTag = FindProperty((Config x) => x.fadeOutCameraTag); noise3DData = FindProperty((Config x) => x.noise3DData); noise3DSize = FindProperty((Config x) => x.noise3DSize); dustParticlesPrefab = FindProperty((Config x) => x.dustParticlesPrefab); ditheringFactor = FindProperty((Config x) => x.ditheringFactor); ditheringNoiseTexture = FindProperty((Config x) => x.ditheringNoiseTexture); featureEnabledColorGradient = FindProperty((Config x) => x.featureEnabledColorGradient); featureEnabledDepthBlend = FindProperty((Config x) => x.featureEnabledDepthBlend); featureEnabledNoise3D = FindProperty((Config x) => x.featureEnabledNoise3D); featureEnabledDynamicOcclusion = FindProperty((Config x) => x.featureEnabledDynamicOcclusion); featureEnabledMeshSkewing = FindProperty((Config x) => x.featureEnabledMeshSkewing); featureEnabledShaderAccuracyHigh = FindProperty((Config x) => x.featureEnabledShaderAccuracyHigh); RenderQueueGUIInit(); Noise3D.LoadIfNeeded(); // Try to load Noise3D, maybe for the 1st time m_TargetConfig = this.target as Config; }
protected override void OnEnable() { base.OnEnable(); geometryLayerID = FindProperty((Config x) => x.geometryLayerID); beamShader = FindProperty((Config x) => x.beamShader); globalNoiseScale = FindProperty((Config x) => x.globalNoiseScale); globalNoiseVelocity = FindProperty((Config x) => x.globalNoiseVelocity); noise3DData = FindProperty((Config x) => x.noise3DData); noise3DSize = FindProperty((Config x) => x.noise3DSize); dustParticlesPrefab = FindProperty((Config x) => x.dustParticlesPrefab); SharedMesh = FindProperty((Config x) => x.SharedMeshConeZ); Noise3D.LoadIfNeeded(); // Try to load Noise3D, maybe for the 1st time L1_Texture = FindProperty((Config x) => x.L1_LightTexture); L1_Noise = FindProperty((Config x) => x.L1_LightNoise); L1_beamShader = FindProperty((Config x) => x.L1_beamShader); }
public void UpdateMaterialAndBounds() { Debug.Assert(m_Master); float slopeRad = (m_Master.coneAngle * Mathf.Deg2Rad) / 2; // use coneAngle (instead of spotAngle) which is more correct with the geometry var coneRadius = new Vector2(m_Master.coneRadiusStart, m_Master.coneRadiusEnd); material.SetVector("_ConeSlopeCosSin", new Vector2(Mathf.Cos(slopeRad), Mathf.Sin(slopeRad))); material.SetVector("_ConeRadius", coneRadius); material.SetFloat("_ConeApexOffsetZ", m_Master.coneApexOffsetZ); if (m_Master.colorMode == ColorMode.Gradient) { var precision = Utils.GetFloatPackingPrecision(); material.EnableKeyword(precision == Utils.FloatPackingPrecision.High ? "VLB_COLOR_GRADIENT_MATRIX_HIGH" : "VLB_COLOR_GRADIENT_MATRIX_LOW"); m_ColorGradientMatrix = m_Master.colorGradient.SampleInMatrix((int)precision); // pass the gradient matrix in OnWillRenderObject() } else { material.DisableKeyword("VLB_COLOR_GRADIENT_MATRIX_HIGH"); material.DisableKeyword("VLB_COLOR_GRADIENT_MATRIX_LOW"); material.SetColor("_ColorFlat", m_Master.color); } // Blending Mode if (Consts.BlendingMode_AlphaAsBlack[m_Master.blendingModeAsInt]) { material.EnableKeyword("ALPHA_AS_BLACK"); } else { material.DisableKeyword("ALPHA_AS_BLACK"); } material.SetInt("_BlendSrcFactor", (int)Consts.BlendingMode_SrcFactor[m_Master.blendingModeAsInt]); material.SetInt("_BlendDstFactor", (int)Consts.BlendingMode_DstFactor[m_Master.blendingModeAsInt]); material.SetFloat("_AlphaInside", m_Master.alphaInside); material.SetFloat("_AlphaOutside", m_Master.alphaOutside); material.SetFloat("_AttenuationLerpLinearQuad", m_Master.attenuationLerpLinearQuad); material.SetFloat("_DistanceFadeStart", m_Master.fadeStart); material.SetFloat("_DistanceFadeEnd", m_Master.fadeEnd); material.SetFloat("_DistanceCamClipping", m_Master.cameraClippingDistance); material.SetFloat("_FresnelPow", Mathf.Max(0.001f, m_Master.fresnelPow)); // no pow 0, otherwise will generate inf fresnel and issues on iOS material.SetFloat("_GlareBehind", m_Master.glareBehind); material.SetFloat("_GlareFrontal", m_Master.glareFrontal); if (m_Master.depthBlendDistance > 0f) { material.EnableKeyword("VLB_DEPTH_BLEND"); material.SetFloat("_DepthBlendDistance", m_Master.depthBlendDistance); } else { material.DisableKeyword("VLB_DEPTH_BLEND"); } if (m_Master.noiseEnabled && m_Master.noiseIntensity > 0f && Noise3D.isSupported) // test Noise3D.isSupported the last { Noise3D.LoadIfNeeded(); material.EnableKeyword("VLB_NOISE_3D"); material.SetVector("_NoiseLocal", new Vector4(m_Master.noiseVelocityLocal.x, m_Master.noiseVelocityLocal.y, m_Master.noiseVelocityLocal.z, m_Master.noiseScaleLocal)); material.SetVector("_NoiseParam", new Vector3(m_Master.noiseIntensity, m_Master.noiseVelocityUseGlobal ? 1f : 0f, m_Master.noiseScaleUseGlobal ? 1f : 0f)); } else { material.DisableKeyword("VLB_NOISE_3D"); } // Need to manually compute mesh bounds since the shape of the cone is generated in the Vertex Shader ComputeBounds(); #if DEBUG_SHOW_MESH_NORMALS for (int vertexInd = 0; vertexInd < coneMesh.vertexCount; vertexInd++) { var vertex = coneMesh.vertices[vertexInd]; // apply modification done inside VS vertex.x *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.y *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.z *= m_Master.fadeEnd; var cosSinFlat = new Vector2(vertex.x, vertex.y).normalized; var normal = new Vector3(cosSinFlat.x * Mathf.Cos(slopeRad), cosSinFlat.y * Mathf.Cos(slopeRad), -Mathf.Sin(slopeRad)).normalized; vertex = transform.TransformPoint(vertex); normal = transform.TransformDirection(normal); Debug.DrawRay(vertex, normal * 0.25f); } #endif }
public override void OnInspectorGUI() { base.OnInspectorGUI(); Debug.Assert(m_TargetConfig != null); m_NeedToReloadNoise = false; m_NeedToRefreshShader = false; m_IsUsedInstance = m_TargetConfig.IsCurrentlyUsedInstance(); // Config per plaftorm #if UNITY_2018_1_OR_NEWER { bool hasValidName = m_TargetConfig.HasValidAssetName(); bool isCurrentPlatformSuffix = m_TargetConfig.GetAssetSuffix() == PlatformHelper.GetCurrentPlatformSuffix(); var platformSuffix = m_TargetConfig.GetAssetSuffix(); string platformStr = "Default Config asset"; if (!string.IsNullOrEmpty(platformSuffix)) { platformStr = string.Format("Config asset for platform '{0}'", m_TargetConfig.GetAssetSuffix()); } if (!hasValidName) { platformStr += " (INVALID)"; } EditorGUILayout.LabelField(platformStr, EditorStyles.boldLabel); if (GUILayout.Button(EditorStrings.Beam.ButtonCreateOverridePerPlatform, EditorStyles.miniButton)) { var menu = new GenericMenu(); foreach (var platform in System.Enum.GetValues(typeof(RuntimePlatform))) { menu.AddItem(new GUIContent(platform.ToString()), false, OnAddConfigPerPlatform, platform); } menu.ShowAsContext(); } if (!hasValidName) { EditorGUILayout.Separator(); EditorGUILayout.HelpBox(EditorStrings.Config.InvalidPlatformOverride, MessageType.Error); ButtonOpenConfig(); } else if (!m_IsUsedInstance) { EditorGUILayout.Separator(); if (isCurrentPlatformSuffix) { EditorGUILayout.HelpBox(EditorStrings.Config.WrongAssetLocation, MessageType.Error); } else { EditorGUILayout.HelpBox(EditorStrings.Config.NotCurrentAssetInUse, MessageType.Warning); } ButtonOpenConfig(); } DrawLineSeparator(); } #endif { EditorGUI.BeginChangeCheck(); { if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderBeamGeometry)) { using (new EditorGUILayout.HorizontalScope()) { geometryOverrideLayer.boolValue = EditorGUILayout.Toggle(EditorStrings.Config.GeometryOverrideLayer, geometryOverrideLayer.boolValue); using (new EditorGUI.DisabledGroupScope(!geometryOverrideLayer.boolValue)) { geometryLayerID.intValue = EditorGUILayout.LayerField(geometryLayerID.intValue); } } geometryTag.stringValue = EditorGUILayout.TagField(EditorStrings.Config.GeometryTag, geometryTag.stringValue); } FoldableHeader.End(); if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderRendering)) { RenderQueueGUIDraw(); if (BeamGeometry.isCustomRenderPipelineSupported) { EditorGUI.BeginChangeCheck(); { renderPipeline.CustomEnum <RenderPipeline>(EditorStrings.Config.GeometryRenderPipeline, EditorStrings.Config.GeometryRenderPipelineEnumDescriptions); } if (EditorGUI.EndChangeCheck()) { SetDirty(DirtyFlags.AllBeamGeom | DirtyFlags.Shader); // need to fully reset the BeamGeom to update the shader } } if (m_TargetConfig.hasRenderPipelineMismatch) { EditorGUILayout.HelpBox(EditorStrings.Config.ErrorRenderPipelineMismatch, MessageType.Error); } EditorGUI.BeginChangeCheck(); { EditorGUILayout.PropertyField(renderingMode, EditorStrings.Config.GeometryRenderingMode); if (renderPipeline.enumValueIndex == (int)RenderPipeline.BuiltIn) { if (renderingMode.enumValueIndex == (int)RenderingMode.SRPBatcher) { EditorGUILayout.HelpBox(EditorStrings.Config.ErrorSrpBatcherOnlyCompatibleWithSrp, MessageType.Error); } } else { if (renderingMode.enumValueIndex == (int)RenderingMode.SRPBatcher && SRPHelper.renderPipelineType == SRPHelper.RenderPipeline.LWRP) { EditorGUILayout.HelpBox(EditorStrings.Config.ErrorSrpBatcherNotCompatibleWithLWRP, MessageType.Error); } if (renderingMode.enumValueIndex == (int)RenderingMode.MultiPass) { EditorGUILayout.HelpBox(EditorStrings.Config.ErrorSrpAndMultiPassNotCompatible, MessageType.Error); } } #pragma warning disable 0162 // warning CS0162: Unreachable code detected if (renderingMode.enumValueIndex == (int)RenderingMode.GPUInstancing && !BatchingHelper.isGpuInstancingSupported) { EditorGUILayout.HelpBox(EditorStrings.Config.ErrorGeometryGpuInstancingNotSupported, MessageType.Error); } #pragma warning restore 0162 } if (EditorGUI.EndChangeCheck()) { SetDirty(DirtyFlags.AllBeamGeom | DirtyFlags.GlobalMesh | DirtyFlags.Shader); // need to fully reset the BeamGeom to update the shader } if (m_TargetConfig.beamShader == null) { EditorGUILayout.HelpBox(EditorStrings.Config.GetErrorInvalidShader(), MessageType.Error); } if (ditheringFactor.FloatSlider(EditorStrings.Config.DitheringFactor, 0.0f, 1.0f)) { SetDirty(DirtyFlags.Shader); } } FoldableHeader.End(); } if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllMeshesDirty(); } if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderSharedMesh)) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(sharedMeshSides, EditorStrings.Config.SharedMeshSides); EditorGUILayout.PropertyField(sharedMeshSegments, EditorStrings.Config.SharedMeshSegments); if (EditorGUI.EndChangeCheck()) { SetDirty(DirtyFlags.GlobalMesh | DirtyFlags.AllMeshes); } var meshInfo = "These properties will change the mesh tessellation of each Volumetric Light Beam with 'Shared' MeshType.\nAdjust them carefully since they could impact performance."; meshInfo += string.Format("\nShared Mesh stats: {0} vertices, {1} triangles", MeshGenerator.GetSharedMeshVertexCount(), MeshGenerator.GetSharedMeshIndicesCount() / 3); EditorGUILayout.HelpBox(meshInfo, MessageType.Info); } FoldableHeader.End(); if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderGlobal3DNoise)) { EditorGUILayout.PropertyField(globalNoiseScale, EditorStrings.Config.GlobalNoiseScale); EditorGUILayout.PropertyField(globalNoiseVelocity, EditorStrings.Config.GlobalNoiseVelocity); } FoldableHeader.End(); if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderFadeOutCamera)) { EditorGUI.BeginChangeCheck(); fadeOutCameraTag.stringValue = EditorGUILayout.TagField(EditorStrings.Config.FadeOutCameraTag, fadeOutCameraTag.stringValue); if (EditorGUI.EndChangeCheck() && Application.isPlaying) { m_TargetConfig.ForceUpdateFadeOutCamera(); } } FoldableHeader.End(); if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderFeaturesEnabled)) { EditorGUI.BeginChangeCheck(); { EditorGUILayout.PropertyField(featureEnabledColorGradient, EditorStrings.Config.FeatureEnabledColorGradient); EditorGUILayout.PropertyField(featureEnabledDepthBlend, EditorStrings.Config.FeatureEnabledDepthBlend); EditorGUILayout.PropertyField(featureEnabledNoise3D, EditorStrings.Config.FeatureEnabledNoise3D); EditorGUILayout.PropertyField(featureEnabledDynamicOcclusion, EditorStrings.Config.FeatureEnabledDynamicOcclusion); EditorGUILayout.PropertyField(featureEnabledMeshSkewing, EditorStrings.Config.FeatureEnabledMeshSkewing); EditorGUILayout.PropertyField(featureEnabledShaderAccuracyHigh, EditorStrings.Config.FeatureEnabledShaderAccuracyHigh); } if (EditorGUI.EndChangeCheck()) { SetDirty(DirtyFlags.Shader | DirtyFlags.AllBeamGeom); } } FoldableHeader.End(); if (FoldableHeader.Begin(this, EditorStrings.Config.HeaderInternalData)) { EditorGUILayout.PropertyField(dustParticlesPrefab, EditorStrings.Config.DustParticlesPrefab); EditorGUILayout.PropertyField(ditheringNoiseTexture, EditorStrings.Config.DitheringNoiseTexture); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(noise3DData, EditorStrings.Config.Noise3DData); EditorGUILayout.PropertyField(noise3DSize, EditorStrings.Config.Noise3DSize); if (EditorGUI.EndChangeCheck()) { SetDirty(DirtyFlags.Noise); } if (Noise3D.isSupported && !Noise3D.isProperlyLoaded) { EditorGUILayout.HelpBox(EditorStrings.Common.HelpNoiseLoadingFailed, MessageType.Error); } } FoldableHeader.End(); if (GUILayout.Button(EditorStrings.Config.OpenDocumentation, EditorStyles.miniButton)) { UnityEditor.Help.BrowseURL(Consts.HelpUrlConfig); } using (new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(EditorStrings.Config.ResetToDefaultButton, EditorStyles.miniButton)) { UnityEditor.Undo.RecordObject(target, "Reset Config Properties"); m_TargetConfig.Reset(); SetDirty(DirtyFlags.Target | DirtyFlags.Noise); } if (GUILayout.Button(EditorStrings.Config.ResetInternalDataButton, EditorStyles.miniButton)) { UnityEditor.Undo.RecordObject(target, "Reset Internal Data"); m_TargetConfig.ResetInternalData(); SetDirty(DirtyFlags.Target | DirtyFlags.Noise); } } } serializedObject.ApplyModifiedProperties(); if (m_NeedToRefreshShader) { m_TargetConfig.RefreshShader(Config.RefreshShaderFlags.All); // need to be done AFTER ApplyModifiedProperties } if (m_NeedToReloadNoise) { Noise3D._EditorForceReloadData(); // Should be called AFTER ApplyModifiedProperties so the Config instance has the proper values when reloading data } }
private static void OnStartUp() { Noise3D.LoadIfNeeded(); }
public void UpdateMaterialAndBounds() { object obj; Debug.Assert(this.m_Master); this.material.renderQueue = Config.Instance.geometryRenderQueue; float mMaster = this.m_Master.coneAngle * 0.0174532924f / 2f; this.material.SetVector("_ConeSlopeCosSin", new Vector2(Mathf.Cos(mMaster), Mathf.Sin(mMaster))); Vector2 vector2 = new Vector2(Mathf.Max(this.m_Master.coneRadiusStart, 0.0001f), Mathf.Max(this.m_Master.coneRadiusEnd, 0.0001f)); this.material.SetVector("_ConeRadius", vector2); float single = Mathf.Sign(this.m_Master.coneApexOffsetZ) * Mathf.Max(Mathf.Abs(this.m_Master.coneApexOffsetZ), 0.0001f); this.material.SetFloat("_ConeApexOffsetZ", single); if (this.m_Master.colorMode != ColorMode.Gradient) { this.material.DisableKeyword("VLB_COLOR_GRADIENT_MATRIX_HIGH"); this.material.DisableKeyword("VLB_COLOR_GRADIENT_MATRIX_LOW"); this.material.SetColor("_ColorFlat", this.m_Master.color); } else { Utils.FloatPackingPrecision floatPackingPrecision = Utils.GetFloatPackingPrecision(); this.material.EnableKeyword((floatPackingPrecision == Utils.FloatPackingPrecision.High ? "VLB_COLOR_GRADIENT_MATRIX_HIGH" : "VLB_COLOR_GRADIENT_MATRIX_LOW")); this.m_ColorGradientMatrix = this.m_Master.colorGradient.SampleInMatrix((int)floatPackingPrecision); } if (!Consts.BlendingMode_AlphaAsBlack[this.m_Master.blendingModeAsInt]) { this.material.DisableKeyword("ALPHA_AS_BLACK"); } else { this.material.EnableKeyword("ALPHA_AS_BLACK"); } this.material.SetInt("_BlendSrcFactor", (int)Consts.BlendingMode_SrcFactor[this.m_Master.blendingModeAsInt]); this.material.SetInt("_BlendDstFactor", (int)Consts.BlendingMode_DstFactor[this.m_Master.blendingModeAsInt]); this.material.SetFloat("_AlphaInside", this.m_Master.alphaInside); this.material.SetFloat("_AlphaOutside", this.m_Master.alphaOutside); this.material.SetFloat("_AttenuationLerpLinearQuad", this.m_Master.attenuationLerpLinearQuad); this.material.SetFloat("_DistanceFadeStart", this.m_Master.fadeStart); this.material.SetFloat("_DistanceFadeEnd", this.m_Master.fadeEnd); this.material.SetFloat("_DistanceCamClipping", this.m_Master.cameraClippingDistance); this.material.SetFloat("_FresnelPow", Mathf.Max(0.001f, this.m_Master.fresnelPow)); this.material.SetFloat("_GlareBehind", this.m_Master.glareBehind); this.material.SetFloat("_GlareFrontal", this.m_Master.glareFrontal); Material material = this.material; if (this.m_Master.geomCap) { obj = 1; } else { obj = null; } material.SetFloat("_DrawCap", (float)obj); if (this.m_Master.depthBlendDistance <= 0f) { this.material.DisableKeyword("VLB_DEPTH_BLEND"); } else { this.material.EnableKeyword("VLB_DEPTH_BLEND"); this.material.SetFloat("_DepthBlendDistance", this.m_Master.depthBlendDistance); } if (!this.m_Master.noiseEnabled || this.m_Master.noiseIntensity <= 0f || !Noise3D.isSupported) { this.material.DisableKeyword("VLB_NOISE_3D"); } else { Noise3D.LoadIfNeeded(); this.material.EnableKeyword("VLB_NOISE_3D"); this.material.SetVector("_NoiseLocal", new Vector4(this.m_Master.noiseVelocityLocal.x, this.m_Master.noiseVelocityLocal.y, this.m_Master.noiseVelocityLocal.z, this.m_Master.noiseScaleLocal)); this.material.SetVector("_NoiseParam", new Vector3(this.m_Master.noiseIntensity, (this.m_Master.noiseVelocityUseGlobal ? 1f : 0f), (this.m_Master.noiseScaleUseGlobal ? 1f : 0f))); } this.ComputeLocalMatrix(); }
public void UpdateMaterialAndBounds() { Debug.Assert(m_Master); if (ApplyMaterial() == false) { return; } MaterialChangeStart(); { if (m_CustomMaterial == null) { if (m_MaterialModifierCallback != null) { m_MaterialModifierCallback(this); } } float slopeRad = (m_Master.coneAngle * Mathf.Deg2Rad) / 2; // use coneAngle (instead of spotAngle) which is more correct with the geometry SetMaterialProp(ShaderProperties.ConeSlopeCosSin, new Vector2(Mathf.Cos(slopeRad), Mathf.Sin(slopeRad))); // kMinRadius and kMinApexOffset prevents artifacts when fresnel computation is done in the vertex shader const float kMinRadius = 0.0001f; var coneRadius = new Vector2(Mathf.Max(m_Master.coneRadiusStart, kMinRadius), Mathf.Max(m_Master.coneRadiusEnd, kMinRadius)); SetMaterialProp(ShaderProperties.ConeRadius, coneRadius); const float kMinApexOffset = 0.0001f; float nonNullApex = Mathf.Sign(m_Master.coneApexOffsetZ) * Mathf.Max(Mathf.Abs(m_Master.coneApexOffsetZ), kMinApexOffset); SetMaterialProp(ShaderProperties.ConeApexOffsetZ, nonNullApex); if (m_Master.usedColorMode == ColorMode.Flat) { SetMaterialProp(ShaderProperties.ColorFlat, m_Master.color); } else { var precision = Utils.GetFloatPackingPrecision(); m_ColorGradientMatrix = m_Master.colorGradient.SampleInMatrix((int)precision); // pass the gradient matrix in OnWillRenderObject() } float intensityInside, intensityOutside; m_Master.GetInsideAndOutsideIntensity(out intensityInside, out intensityOutside); SetMaterialProp(ShaderProperties.AlphaInside, intensityInside); SetMaterialProp(ShaderProperties.AlphaOutside, intensityOutside); SetMaterialProp(ShaderProperties.AttenuationLerpLinearQuad, m_Master.attenuationLerpLinearQuad); SetMaterialProp(ShaderProperties.DistanceFallOff, new Vector3(m_Master.fallOffStart, m_Master.fallOffEnd, m_Master.maxGeometryDistance)); SetMaterialProp(ShaderProperties.DistanceCamClipping, m_Master.cameraClippingDistance); SetMaterialProp(ShaderProperties.FresnelPow, Mathf.Max(0.001f, m_Master.fresnelPow)); // no pow 0, otherwise will generate inf fresnel and issues on iOS SetMaterialProp(ShaderProperties.GlareBehind, m_Master.glareBehind); SetMaterialProp(ShaderProperties.GlareFrontal, m_Master.glareFrontal); SetMaterialProp(ShaderProperties.DrawCap, m_Master.geomCap ? 1 : 0); SetMaterialProp(ShaderProperties.TiltVector, m_Master.tiltFactor); SetMaterialProp(ShaderProperties.AdditionalClippingPlaneWS, m_Master.additionalClippingPlane); if (isDepthBlendEnabled) { SetMaterialProp(ShaderProperties.DepthBlendDistance, m_Master.depthBlendDistance); } if (isNoiseEnabled) { Noise3D.LoadIfNeeded(); var noiseVelocity = m_Master.noiseVelocityUseGlobal ? Config.Instance.globalNoiseVelocity : m_Master.noiseVelocityLocal; var noiseScale = m_Master.noiseScaleUseGlobal ? Config.Instance.globalNoiseScale : m_Master.noiseScaleLocal; SetMaterialProp(ShaderProperties.NoiseVelocityAndScale, new Vector4( noiseVelocity.x, noiseVelocity.y, noiseVelocity.z, noiseScale)); SetMaterialProp(ShaderProperties.NoiseParam, new Vector2( m_Master.noiseIntensity, m_Master.noiseMode == NoiseMode.WorldSpace ? 0f : 1f)); } var localScale = ComputeLocalMatrix(); // compute matrix before sending it to the shader if (m_Master.hasMeshSkewing) { var localForwardDirectionNormalized = m_Master.skewingLocalForwardDirectionNormalized; SetMaterialProp(ShaderProperties.LocalForwardDirection, localForwardDirectionNormalized); if (coneMesh != null) // coneMesh can be null few frames with Dynamic Occlusion & GPU Instancing { var localForwardDirectionN = localForwardDirectionNormalized; localForwardDirectionN /= localForwardDirectionN.z; localForwardDirectionN *= m_Master.fallOffEnd; localForwardDirectionN.x /= localScale.x; localForwardDirectionN.y /= localScale.y; var bounds = MeshGenerator.ComputeBounds(1f, 1f, 1f); var min = bounds.min; var max = bounds.max; if (localForwardDirectionN.x > 0.0f) { max.x += localForwardDirectionN.x; } else { min.x += localForwardDirectionN.x; } if (localForwardDirectionN.y > 0.0f) { max.y += localForwardDirectionN.y; } else { min.y += localForwardDirectionN.y; } bounds.min = min; bounds.max = max; coneMesh.bounds = bounds; } } #if VLB_SRP_SUPPORT // This update is to make QA test 'ReflectionObliqueProjection' pass UpdateMatricesPropertiesForGPUInstancingSRP(); #endif } MaterialChangeStop(); #if DEBUG_SHOW_MESH_NORMALS for (int vertexInd = 0; vertexInd < coneMesh.vertexCount; vertexInd++) { var vertex = coneMesh.vertices[vertexInd]; // apply modification done inside VS vertex.x *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.y *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.z *= m_Master.fallOffEnd; var cosSinFlat = new Vector2(vertex.x, vertex.y).normalized; var normal = new Vector3(cosSinFlat.x * Mathf.Cos(slopeRad), cosSinFlat.y * Mathf.Cos(slopeRad), -Mathf.Sin(slopeRad)).normalized; vertex = transform.TransformPoint(vertex); normal = transform.TransformDirection(normal); Debug.DrawRay(vertex, normal * 0.25f); } #endif }
public void UpdateMaterialAndBounds() { Debug.Assert(m_Master); float slopeRad = (m_Master.coneAngle * Mathf.Deg2Rad) / 2; // use coneAngle (instead of spotAngle) which is more correct with the geometry var coneRadius = new Vector2(m_Master.coneRadiusStart, m_Master.coneRadiusEnd); material.SetVector("_ConeSlopeCosSin", new Vector2(Mathf.Cos(slopeRad), Mathf.Sin(slopeRad))); material.SetVector("_ConeRadius", coneRadius); material.SetColor("_Color", m_Master.color); material.SetFloat("_AlphaInside", m_Master.alphaInside); material.SetFloat("_AlphaOutside", m_Master.alphaOutside); material.SetFloat("_AttenuationLerpLinearQuad", m_Master.attenuationLerpLinearQuad); material.SetFloat("_DistanceFadeStart", m_Master.fadeStart); material.SetFloat("_DistanceFadeEnd", m_Master.fadeEnd); material.SetFloat("_DistanceCamClipping", m_Master.cameraClippingDistance); material.SetFloat("_FresnelPow", m_Master.fresnelPow); material.SetFloat("_GlareBehind", m_Master.glareBehind); material.SetFloat("_GlareFrontal", m_Master.glareFrontal); if (m_Master.depthBlendDistance > 0f) { material.EnableKeyword("VLB_DEPTH_BLEND"); material.SetFloat("_DepthBlendDistance", m_Master.depthBlendDistance); material.SetFloat("_DepthBlendStart", kDepthBlendStart); } else { material.DisableKeyword("VLB_DEPTH_BLEND"); } if (Noise3D.isSupported && m_Master.noiseEnabled && m_Master.noiseIntensity > 0f) { Noise3D.LoadIfNeeded(); material.EnableKeyword("VLB_NOISE_3D"); material.SetVector("_NoiseLocal", new Vector4(m_Master.noiseVelocityLocal.x, m_Master.noiseVelocityLocal.y, m_Master.noiseVelocityLocal.z, m_Master.noiseScaleLocal)); material.SetVector("_NoiseParam", new Vector3(m_Master.noiseIntensity, m_Master.noiseVelocityUseGlobal ? 1f : 0f, m_Master.noiseScaleUseGlobal ? 1f : 0f)); } else { material.DisableKeyword("VLB_NOISE_3D"); } // Need to manually compute mesh bounds since the shape of the cone is generated in the Vertex Shader ComputeBounds(); #if DEBUG_SHOW_MESH_NORMALS for (int vertexInd = 0; vertexInd < coneMesh.vertexCount; vertexInd++) { var vertex = coneMesh.vertices[vertexInd]; // apply modification done inside VS vertex.x *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.y *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.z *= m_Master.fadeEnd; var cosSinFlat = new Vector2(vertex.x, vertex.y).normalized; var normal = new Vector3(cosSinFlat.x * Mathf.Cos(slopeRad), cosSinFlat.y * Mathf.Cos(slopeRad), -Mathf.Sin(slopeRad)).normalized; vertex = transform.TransformPoint(vertex); normal = transform.TransformDirection(normal); Debug.DrawRay(vertex, normal * 0.25f); } #endif }
public void UpdateMaterialAndBounds() { Debug.Assert(Object.op_Implicit((Object)this.m_Master)); this.material.set_renderQueue(Config.Instance.geometryRenderQueue); float num = (float)((double)this.m_Master.coneAngle * (Math.PI / 180.0) / 2.0); this.material.SetVector("_ConeSlopeCosSin", Vector4.op_Implicit(new Vector2(Mathf.Cos(num), Mathf.Sin(num)))); Vector2 vector2; ((Vector2) ref vector2).\u002Ector(Mathf.Max(this.m_Master.coneRadiusStart, 0.0001f), Mathf.Max(this.m_Master.coneRadiusEnd, 0.0001f)); this.material.SetVector("_ConeRadius", Vector4.op_Implicit(vector2)); this.material.SetFloat("_ConeApexOffsetZ", Mathf.Sign(this.m_Master.coneApexOffsetZ) * Mathf.Max(Mathf.Abs(this.m_Master.coneApexOffsetZ), 0.0001f)); if (this.m_Master.colorMode == ColorMode.Gradient) { Utils.FloatPackingPrecision packingPrecision = Utils.GetFloatPackingPrecision(); this.material.EnableKeyword(packingPrecision == Utils.FloatPackingPrecision.High ? "VLB_COLOR_GRADIENT_MATRIX_HIGH" : "VLB_COLOR_GRADIENT_MATRIX_LOW"); this.m_ColorGradientMatrix = this.m_Master.colorGradient.SampleInMatrix((int)packingPrecision); } else { this.material.DisableKeyword("VLB_COLOR_GRADIENT_MATRIX_HIGH"); this.material.DisableKeyword("VLB_COLOR_GRADIENT_MATRIX_LOW"); this.material.SetColor("_ColorFlat", this.m_Master.color); } if (Consts.BlendingMode_AlphaAsBlack[this.m_Master.blendingModeAsInt]) { this.material.EnableKeyword("ALPHA_AS_BLACK"); } else { this.material.DisableKeyword("ALPHA_AS_BLACK"); } this.material.SetInt("_BlendSrcFactor", (int)Consts.BlendingMode_SrcFactor[this.m_Master.blendingModeAsInt]); this.material.SetInt("_BlendDstFactor", (int)Consts.BlendingMode_DstFactor[this.m_Master.blendingModeAsInt]); this.material.SetFloat("_AlphaInside", this.m_Master.alphaInside); this.material.SetFloat("_AlphaOutside", this.m_Master.alphaOutside); this.material.SetFloat("_AttenuationLerpLinearQuad", this.m_Master.attenuationLerpLinearQuad); this.material.SetFloat("_DistanceFadeStart", this.m_Master.fadeStart); this.material.SetFloat("_DistanceFadeEnd", this.m_Master.fadeEnd); this.material.SetFloat("_DistanceCamClipping", this.m_Master.cameraClippingDistance); this.material.SetFloat("_FresnelPow", Mathf.Max(1f / 1000f, this.m_Master.fresnelPow)); this.material.SetFloat("_GlareBehind", this.m_Master.glareBehind); this.material.SetFloat("_GlareFrontal", this.m_Master.glareFrontal); this.material.SetFloat("_DrawCap", this.m_Master.geomCap ? 1f : 0.0f); if ((double)this.m_Master.depthBlendDistance > 0.0) { this.material.EnableKeyword("VLB_DEPTH_BLEND"); this.material.SetFloat("_DepthBlendDistance", this.m_Master.depthBlendDistance); } else { this.material.DisableKeyword("VLB_DEPTH_BLEND"); } if (this.m_Master.noiseEnabled && (double)this.m_Master.noiseIntensity > 0.0 && Noise3D.isSupported) { Noise3D.LoadIfNeeded(); this.material.EnableKeyword("VLB_NOISE_3D"); this.material.SetVector("_NoiseLocal", new Vector4((float)this.m_Master.noiseVelocityLocal.x, (float)this.m_Master.noiseVelocityLocal.y, (float)this.m_Master.noiseVelocityLocal.z, this.m_Master.noiseScaleLocal)); this.material.SetVector("_NoiseParam", Vector4.op_Implicit(new Vector3(this.m_Master.noiseIntensity, this.m_Master.noiseVelocityUseGlobal ? 1f : 0.0f, this.m_Master.noiseScaleUseGlobal ? 1f : 0.0f))); } else { this.material.DisableKeyword("VLB_NOISE_3D"); } this.ComputeLocalMatrix(); }
public void UpdateMaterialAndBounds() { bool change = false; bool noise = material.IsKeywordEnabled("VLB_NOISE_3D"); bool depthBlend = material.IsKeywordEnabled("VLB_DEPTH_BLEND"); bool ClippingPlane = material.IsKeywordEnabled("VLB_CLIPPING_PLANE"); Debug.Assert(m_Master); if (m_Master.lod != Lod) { change = true; } if (m_Master.OverrideTexture != overrideTexture) { change = true; } float slopeRad = (m_Master.coneAngle * Mathf.Deg2Rad) / 2; // use coneAngle (instead of spotAngle) which is more correct with the geometry var coneRadius = new Vector2(m_Master.coneRadiusStart, m_Master.coneRadiusEnd); var block = meshRenderer.GetPropertyBlock(); block.SetVector("_ConeSlopeCosSin", new Vector2(Mathf.Cos(slopeRad), Mathf.Sin(slopeRad))); block.SetVector("_ConeRadius", coneRadius); block.SetFloat("_ConeApexOffsetZ", m_Master.coneApexOffsetZ); block.SetFloat("_Intensity", m_Master.Intensity); block.SetColor("_Color", m_Master.color); block.SetFloat("_AlphaInside", m_Master.alphaInside); block.SetFloat("_AlphaOutside", m_Master.alphaOutside); block.SetFloat("_AttenuationLerpLinearQuad", m_Master.attenuationLerpLinearQuad); block.SetFloat("_DistanceFadeStart", m_Master.fadeStart); block.SetFloat("_DistanceFadeEnd", m_Master.fadeEnd); block.SetFloat("_DistanceCamClipping", m_Master.cameraClippingDistance); block.SetFloat("_FresnelPow", m_Master.fresnelPow); block.SetFloat("_GlareBehind", m_Master.glareBehind); block.SetFloat("_GlareFrontal", m_Master.glareFrontal); if (m_Master.depthBlendDistance > 0f) { if (depthBlend == false) { depthBlend = true; change = true; } // material.EnableKeyword("VLB_DEPTH_BLEND"); block.SetFloat("_DepthBlendDistance", m_Master.depthBlendDistance); } else { if (depthBlend) { depthBlend = false; change = true; } } /* material.DisableKeyword("VLB_DEPTH_BLEND");*/ if (m_Master.noiseEnabled && m_Master.noiseIntensity > 0f && Noise3D.isSupported) // test Noise3D.isSupported the last { Noise3D.LoadIfNeeded(); if (noise == false) { noise = true; change = true; } /* material.EnableKeyword("VLB_NOISE_3D");*/ block.SetVector("_NoiseLocal", new Vector4(m_Master.noiseVelocityLocal.x, m_Master.noiseVelocityLocal.y, m_Master.noiseVelocityLocal.z, m_Master.noiseScaleLocal)); block.SetVector("_NoiseParam", new Vector3(m_Master.noiseIntensity, m_Master.noiseVelocityUseGlobal ? 1f : 0f, m_Master.noiseScaleUseGlobal ? 1f : 0f)); } else { if (noise) { noise = false; change = true; } } /* material.DisableKeyword("VLB_NOISE_3D");*/ if (change) { ChangeMat(noise, depthBlend, ClippingPlane); } meshRenderer.SetPropertyBlock(block); // Need to manually compute mesh bounds since the shape of the cone is generated in the Vertex Shader ComputeBounds(); #if DEBUG_SHOW_MESH_NORMALS for (int vertexInd = 0; vertexInd < coneMesh.vertexCount; vertexInd++) { var vertex = coneMesh.vertices[vertexInd]; // apply modification done inside VS vertex.x *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.y *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.z *= m_Master.fadeEnd; var cosSinFlat = new Vector2(vertex.x, vertex.y).normalized; var normal = new Vector3(cosSinFlat.x * Mathf.Cos(slopeRad), cosSinFlat.y * Mathf.Cos(slopeRad), -Mathf.Sin(slopeRad)).normalized; vertex = transform.TransformPoint(vertex); normal = transform.TransformDirection(normal); Debug.DrawRay(vertex, normal * 0.25f); } #endif }
public override void OnInspectorGUI() { base.OnInspectorGUI(); bool reloadNoise = false; if ((Object)Config.Instance != this.target) { EditorGUILayout.HelpBox(EditorStrings.ConfigMultipleAssets, MessageType.Error); EditorGUILayout.Separator(); ButtonOpenConfig(); } else { EditorGUI.BeginChangeCheck(); { if (HeaderFoldable("Beam Geometry")) { using (new EditorGUILayout.HorizontalScope()) { geometryOverrideLayer.boolValue = EditorGUILayout.Toggle(EditorStrings.ConfigGeometryOverrideLayer, geometryOverrideLayer.boolValue); using (new EditorGUI.DisabledGroupScope(!geometryOverrideLayer.boolValue)) { geometryLayerID.intValue = EditorGUILayout.LayerField(geometryLayerID.intValue); } } geometryTag.stringValue = EditorGUILayout.TagField(EditorStrings.ConfigGeometryTag, geometryTag.stringValue); } DrawLineSeparator(); if (HeaderFoldable("Rendering")) { RenderQueueGUIDraw(); if (BeamGeometry.isCustomRenderPipelineSupported) { EditorGUI.BeginChangeCheck(); { renderPipeline.CustomEnum <RenderPipeline>(EditorStrings.ConfigGeometryRenderPipeline, EditorStrings.ConfigGeometryRenderPipelineEnumDescriptions); } if (EditorGUI.EndChangeCheck()) { Config.OnRenderPipelineChanged((RenderPipeline)renderPipeline.enumValueIndex); VolumetricLightBeam._EditorSetAllBeamGeomDirty(); // need to fully reset the BeamGeom to update the shader ReimportShaders(); } } EditorGUI.BeginChangeCheck(); { EditorGUILayout.PropertyField(renderingMode, EditorStrings.ConfigGeometryRenderingMode); if (renderPipeline.enumValueIndex == (int)RenderPipeline.SRP_4_0_0_or_higher && renderingMode.enumValueIndex == (int)RenderingMode.MultiPass) { EditorGUILayout.HelpBox(EditorStrings.ConfigSrpAndMultiPassNoCompatible, MessageType.Error); } #pragma warning disable 0162 // warning CS0162: Unreachable code detected if (renderingMode.enumValueIndex == (int)RenderingMode.GPUInstancing && !GpuInstancing.isSupported) { EditorGUILayout.HelpBox(EditorStrings.ConfigGeometryGpuInstancingNotSupported, MessageType.Warning); } #pragma warning restore 0162 } if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllBeamGeomDirty(); // need to fully reset the BeamGeom to update the shader GlobalMesh.Destroy(); ReimportShaders(); } } } if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllMeshesDirty(); } DrawLineSeparator(); if (HeaderFoldable("Shared Mesh")) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(sharedMeshSides, EditorStrings.ConfigSharedMeshSides); EditorGUILayout.PropertyField(sharedMeshSegments, EditorStrings.ConfigSharedMeshSegments); if (EditorGUI.EndChangeCheck()) { GlobalMesh.Destroy(); VolumetricLightBeam._EditorSetAllMeshesDirty(); } var meshInfo = "These properties will change the mesh tessellation of each Volumetric Light Beam with 'Shared' MeshType.\nAdjust them carefully since they could impact performance."; meshInfo += string.Format("\nShared Mesh stats: {0} vertices, {1} triangles", MeshGenerator.GetSharedMeshVertexCount(), MeshGenerator.GetSharedMeshIndicesCount() / 3); EditorGUILayout.HelpBox(meshInfo, MessageType.Info); } DrawLineSeparator(); if (HeaderFoldable("Global 3D Noise")) { EditorGUILayout.PropertyField(globalNoiseScale, EditorStrings.ConfigGlobalNoiseScale); EditorGUILayout.PropertyField(globalNoiseVelocity, EditorStrings.ConfigGlobalNoiseVelocity); } DrawLineSeparator(); if (HeaderFoldable("Internal Data (do not change)")) { EditorGUILayout.PropertyField(beamShader1Pass, EditorStrings.ConfigBeamShader1Pass); EditorGUILayout.PropertyField(beamShader2Pass, EditorStrings.ConfigBeamShader2Pass); EditorGUILayout.PropertyField(dustParticlesPrefab, EditorStrings.ConfigDustParticlesPrefab); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(noise3DData, EditorStrings.ConfigNoise3DData); EditorGUILayout.PropertyField(noise3DSize, EditorStrings.ConfigNoise3DSize); if (EditorGUI.EndChangeCheck()) { reloadNoise = true; } if (Noise3D.isSupported && !Noise3D.isProperlyLoaded) { EditorGUILayout.HelpBox(EditorStrings.HelpNoiseLoadingFailed, MessageType.Error); } } DrawLineSeparator(); using (new EditorGUILayout.HorizontalScope()) { if (GUILayout.Button(EditorStrings.ConfigOpenDocumentation, EditorStyles.miniButton)) { UnityEditor.Help.BrowseURL(Consts.HelpUrlConfig); } if (GUILayout.Button(EditorStrings.ConfigResetToDefaultButton, EditorStyles.miniButton)) { UnityEditor.Undo.RecordObject(target, "Reset Config Properties"); (target as Config).Reset(); } } } serializedObject.ApplyModifiedProperties(); if (reloadNoise) { Noise3D._EditorForceReloadData(); // Should be called AFTER ApplyModifiedProperties so the Config instance has the proper values when reloading data } }
public void UpdateMaterialAndBounds() { Debug.Assert(m_Master); if (ApplyMaterial() == false) { return; } if (isClippingPlaneEnabled && m_CustomMaterial == null) { SendMaterialClippingPlaneProp(); } float slopeRad = (m_Master.coneAngle * Mathf.Deg2Rad) / 2; // use coneAngle (instead of spotAngle) which is more correct with the geometry SetMaterialProp("_ConeSlopeCosSin", new Vector2(Mathf.Cos(slopeRad), Mathf.Sin(slopeRad))); // kMinRadius and kMinApexOffset prevents artifacts when fresnel computation is done in the vertex shader const float kMinRadius = 0.0001f; var coneRadius = new Vector2(Mathf.Max(m_Master.coneRadiusStart, kMinRadius), Mathf.Max(m_Master.coneRadiusEnd, kMinRadius)); SetMaterialProp("_ConeRadius", coneRadius); const float kMinApexOffset = 0.0001f; float nonNullApex = Mathf.Sign(m_Master.coneApexOffsetZ) * Mathf.Max(Mathf.Abs(m_Master.coneApexOffsetZ), kMinApexOffset); SetMaterialProp("_ConeApexOffsetZ", nonNullApex); if (m_Master.colorMode == ColorMode.Flat) { SetMaterialProp("_ColorFlat", m_Master.color); } else { var precision = Utils.GetFloatPackingPrecision(); m_ColorGradientMatrix = m_Master.colorGradient.SampleInMatrix((int)precision); // pass the gradient matrix in OnWillRenderObject() } SetMaterialProp("_AlphaInside", m_Master.alphaInside); SetMaterialProp("_AlphaOutside", m_Master.alphaOutside); SetMaterialProp("_AttenuationLerpLinearQuad", m_Master.attenuationLerpLinearQuad); SetMaterialProp("_DistanceFadeStart", m_Master.fadeStart); SetMaterialProp("_DistanceFadeEnd", m_Master.fadeEnd); SetMaterialProp("_DistanceCamClipping", m_Master.cameraClippingDistance); SetMaterialProp("_FresnelPow", Mathf.Max(0.001f, m_Master.fresnelPow)); // no pow 0, otherwise will generate inf fresnel and issues on iOS SetMaterialProp("_GlareBehind", m_Master.glareBehind); SetMaterialProp("_GlareFrontal", m_Master.glareFrontal); SetMaterialProp("_DrawCap", m_Master.geomCap ? 1 : 0); if (isDepthBlendEnabled) { SetMaterialProp("_DepthBlendDistance", m_Master.depthBlendDistance); } if (isNoiseEnabled) { Noise3D.LoadIfNeeded(); SetMaterialProp("_NoiseLocal", new Vector4(m_Master.noiseVelocityLocal.x, m_Master.noiseVelocityLocal.y, m_Master.noiseVelocityLocal.z, m_Master.noiseScaleLocal)); SetMaterialProp("_NoiseParam", new Vector3(m_Master.noiseIntensity, m_Master.noiseVelocityUseGlobal ? 1f : 0f, m_Master.noiseScaleUseGlobal ? 1f : 0f)); } if (m_CustomMaterial == null) { meshRenderer.SetPropertyBlock(MaterialManager.materialPropertyBlock); } ComputeLocalMatrix(); #if DEBUG_SHOW_MESH_NORMALS for (int vertexInd = 0; vertexInd < coneMesh.vertexCount; vertexInd++) { var vertex = coneMesh.vertices[vertexInd]; // apply modification done inside VS vertex.x *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.y *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.z *= m_Master.fadeEnd; var cosSinFlat = new Vector2(vertex.x, vertex.y).normalized; var normal = new Vector3(cosSinFlat.x * Mathf.Cos(slopeRad), cosSinFlat.y * Mathf.Cos(slopeRad), -Mathf.Sin(slopeRad)).normalized; vertex = transform.TransformPoint(vertex); normal = transform.TransformDirection(normal); Debug.DrawRay(vertex, normal * 0.25f); } #endif }
public void UpdateMaterialAndBounds() { Debug.Assert(m_Master); if (ApplyMaterial() == false) { return; } MaterialChangeStart(); { if (m_CustomMaterial == null) { if (m_MaterialModifierCallback != null) { m_MaterialModifierCallback(this); } } float slopeRad = (m_Master.coneAngle * Mathf.Deg2Rad) / 2; // use coneAngle (instead of spotAngle) which is more correct with the geometry SetMaterialProp(ShaderProperties.ConeSlopeCosSin, new Vector2(Mathf.Cos(slopeRad), Mathf.Sin(slopeRad))); // kMinRadius and kMinApexOffset prevents artifacts when fresnel computation is done in the vertex shader const float kMinRadius = 0.0001f; var coneRadius = new Vector2(Mathf.Max(m_Master.coneRadiusStart, kMinRadius), Mathf.Max(m_Master.coneRadiusEnd, kMinRadius)); SetMaterialProp(ShaderProperties.ConeRadius, coneRadius); const float kMinApexOffset = 0.0001f; float nonNullApex = Mathf.Sign(m_Master.coneApexOffsetZ) * Mathf.Max(Mathf.Abs(m_Master.coneApexOffsetZ), kMinApexOffset); SetMaterialProp(ShaderProperties.ConeApexOffsetZ, nonNullApex); if (m_Master.colorMode == ColorMode.Flat) { SetMaterialProp(ShaderProperties.ColorFlat, m_Master.color); } else { var precision = Utils.GetFloatPackingPrecision(); m_ColorGradientMatrix = m_Master.colorGradient.SampleInMatrix((int)precision); // pass the gradient matrix in OnWillRenderObject() } SetMaterialProp(ShaderProperties.AlphaInside, m_Master.intensityInside); SetMaterialProp(ShaderProperties.AlphaOutside, m_Master.intensityOutside); SetMaterialProp(ShaderProperties.AttenuationLerpLinearQuad, m_Master.attenuationLerpLinearQuad); SetMaterialProp(ShaderProperties.DistanceFadeStart, m_Master.fallOffStart); SetMaterialProp(ShaderProperties.DistanceFadeEnd, m_Master.fallOffEnd); SetMaterialProp(ShaderProperties.DistanceCamClipping, m_Master.cameraClippingDistance); SetMaterialProp(ShaderProperties.FresnelPow, Mathf.Max(0.001f, m_Master.fresnelPow)); // no pow 0, otherwise will generate inf fresnel and issues on iOS SetMaterialProp(ShaderProperties.GlareBehind, m_Master.glareBehind); SetMaterialProp(ShaderProperties.GlareFrontal, m_Master.glareFrontal); SetMaterialProp(ShaderProperties.DrawCap, m_Master.geomCap ? 1 : 0); if (isDepthBlendEnabled) { SetMaterialProp(ShaderProperties.DepthBlendDistance, m_Master.depthBlendDistance); } if (isNoiseEnabled) { Noise3D.LoadIfNeeded(); SetMaterialProp(ShaderProperties.NoiseLocal, new Vector4( m_Master.noiseVelocityLocal.x, m_Master.noiseVelocityLocal.y, m_Master.noiseVelocityLocal.z, m_Master.noiseScaleLocal)); SetMaterialProp(ShaderProperties.NoiseParam, new Vector4( m_Master.noiseIntensity, m_Master.noiseVelocityUseGlobal ? 1f : 0f, m_Master.noiseScaleUseGlobal ? 1f : 0f, m_Master.noiseMode == NoiseMode.WorldSpace ? 0f : 1f)); } ComputeLocalMatrix(); // compute matrix before sending it to the shader #if VLB_SRP_SUPPORT // This update is to make QA test 'ReflectionObliqueProjection' pass UpdateMatricesPropertiesForGPUInstancingSRP(); #endif } MaterialChangeStop(); #if DEBUG_SHOW_MESH_NORMALS for (int vertexInd = 0; vertexInd < coneMesh.vertexCount; vertexInd++) { var vertex = coneMesh.vertices[vertexInd]; // apply modification done inside VS vertex.x *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.y *= Mathf.Lerp(coneRadius.x, coneRadius.y, vertex.z); vertex.z *= m_Master.fallOffEnd; var cosSinFlat = new Vector2(vertex.x, vertex.y).normalized; var normal = new Vector3(cosSinFlat.x * Mathf.Cos(slopeRad), cosSinFlat.y * Mathf.Cos(slopeRad), -Mathf.Sin(slopeRad)).normalized; vertex = transform.TransformPoint(vertex); normal = transform.TransformDirection(normal); Debug.DrawRay(vertex, normal * 0.25f); } #endif }
public override void OnInspectorGUI() { base.OnInspectorGUI(); Header("Beam Geometry"); EditorGUI.BeginChangeCheck(); { using (new EditorGUILayout.HorizontalScope()) { geometryOverrideLayer.boolValue = EditorGUILayout.Toggle(EditorStrings.ConfigGeometryOverrideLayer, geometryOverrideLayer.boolValue); using (new EditorGUI.DisabledGroupScope(!geometryOverrideLayer.boolValue)) { geometryLayerID.intValue = EditorGUILayout.LayerField(geometryLayerID.intValue); } } geometryTag.stringValue = EditorGUILayout.TagField(EditorStrings.ConfigGeometryTag, geometryTag.stringValue); } Header("Rendering"); { RenderQueueGUIDraw(); EditorGUI.BeginChangeCheck(); { forceSinglePass.boolValue = EditorGUILayout.Toggle(EditorStrings.ConfigGeometryForceSinglePass, forceSinglePass.boolValue); } if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllBeamGeomDirty(); // need to fully reset the BeamGeom to update the shader GlobalMesh.Destroy(); } } if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllMeshesDirty(); } EditorGUILayout.PropertyField(beamShader1Pass, EditorStrings.ConfigBeamShader1Pass); EditorGUILayout.PropertyField(beamShader2Pass, EditorStrings.ConfigBeamShader2Pass); Header("Shared Mesh"); EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(sharedMeshSides, EditorStrings.ConfigSharedMeshSides); EditorGUILayout.PropertyField(sharedMeshSegments, EditorStrings.ConfigSharedMeshSegments); if (EditorGUI.EndChangeCheck()) { GlobalMesh.Destroy(); VolumetricLightBeam._EditorSetAllMeshesDirty(); } var meshInfo = "These properties will change the mesh tessellation of each Volumetric Light Beam with 'Shared' MeshType.\nAdjust them carefully since they could impact performance."; meshInfo += string.Format("\nShared Mesh stats: {0} vertices, {1} triangles", MeshGenerator.GetSharedMeshVertexCount(), MeshGenerator.GetSharedMeshIndicesCount() / 3); EditorGUILayout.HelpBox(meshInfo, MessageType.Info); Header("Global 3D Noise"); EditorGUILayout.PropertyField(globalNoiseScale, EditorStrings.ConfigGlobalNoiseScale); EditorGUILayout.PropertyField(globalNoiseVelocity, EditorStrings.ConfigGlobalNoiseVelocity); Header("3D Noise Texture Data"); bool reloadNoise = false; EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(noise3DData, EditorStrings.ConfigNoise3DData); EditorGUILayout.PropertyField(noise3DSize, EditorStrings.ConfigNoise3DSize); if (EditorGUI.EndChangeCheck()) { reloadNoise = true; } if (Noise3D.isSupported && !Noise3D.isProperlyLoaded) { EditorGUILayout.HelpBox(EditorStrings.HelpNoiseLoadingFailed, MessageType.Error); } Header("Volumetric Dust Particles"); EditorGUILayout.PropertyField(dustParticlesPrefab, EditorStrings.ConfigDustParticlesPrefab); EditorGUILayout.Separator(); EditorExtensions.HorizontalLineSeparator(); EditorGUILayout.Separator(); if (GUILayout.Button(EditorStrings.ConfigResetToDefaultButton, EditorStyles.miniButton)) { UnityEditor.Undo.RecordObject(target, "Reset Config Properties"); (target as Config).Reset(); } serializedObject.ApplyModifiedProperties(); if (reloadNoise) { Noise3D._EditorForceReloadData(); // Should be called AFTER ApplyModifiedProperties so the Config instance has the proper values when reloading data } }