void ComputeZone() { if (m_Beam) { var rangeEnd = m_Beam.fallOffEnd * rangeMultiplier; var lerpedRadiusEnd = Mathf.LerpUnclamped(m_Beam.coneRadiusStart, m_Beam.coneRadiusEnd, rangeMultiplier); if (m_Beam.dimensions == Dimensions.Dim3D) { var meshCollider = gameObject.GetOrAddComponent <MeshCollider>(); Debug.Assert(meshCollider); int sides = Mathf.Min(m_Beam.geomSides, kMeshColliderNumSides); var mesh = MeshGenerator.GenerateConeZ_Radius(rangeEnd, m_Beam.coneRadiusStart, lerpedRadiusEnd, sides, 0, false, false); mesh.hideFlags = Consts.ProceduralObjectsHideFlags; meshCollider.sharedMesh = mesh; meshCollider.convex = setIsTrigger; meshCollider.isTrigger = setIsTrigger; } else { if (m_PolygonCollider2D == null) { m_PolygonCollider2D = gameObject.GetOrAddComponent <PolygonCollider2D>(); Debug.Assert(m_PolygonCollider2D); } var polyCoordsLS = new Vector2[] // polygon coord in local space { new Vector2(0.0f, -m_Beam.coneRadiusStart), new Vector2(rangeEnd, -lerpedRadiusEnd), new Vector2(rangeEnd, lerpedRadiusEnd), new Vector2(0.0f, m_Beam.coneRadiusStart) }; if (m_DynamicOcclusionRaycasting && m_DynamicOcclusionRaycasting.planeEquationWS.IsValid()) { var plane3dWS = m_DynamicOcclusionRaycasting.planeEquationWS; if (Utils.IsAlmostZero(plane3dWS.normal.z)) { // Compute 2 points on the plane in world space // Use this technique instead of transforming the plane's normal to fully support scaling var ptOnPlane1 = plane3dWS.ClosestPointOnPlaneCustom(Vector3.zero); var ptOnPlane2 = plane3dWS.ClosestPointOnPlaneCustom(Vector3.up); if (Utils.IsAlmostZero(Vector3.SqrMagnitude(ptOnPlane1 - ptOnPlane2))) { ptOnPlane1 = plane3dWS.ClosestPointOnPlaneCustom(Vector3.right); } // Compute 2 points on the plane in local space ptOnPlane1 = transform.InverseTransformPoint(ptOnPlane1); ptOnPlane2 = transform.InverseTransformPoint(ptOnPlane2); // Compute plane equation in local space var plane2dLS = PolygonHelper.Plane2D.FromPoints(ptOnPlane1, ptOnPlane2); if (plane2dLS.normal.x > 0.0f) { plane2dLS.Flip(); } polyCoordsLS = plane2dLS.CutConvex(polyCoordsLS); } } m_PolygonCollider2D.points = polyCoordsLS; m_PolygonCollider2D.isTrigger = setIsTrigger; } } }
public override void OnInspectorGUI() { base.OnInspectorGUI(); bool reloadNoise = false; bool isUsedInstance = (Object)Config.Instance == this.target; if (!IsOverriddenInstance()) { if (isUsedInstance) { if (GUILayout.Button(EditorStrings.ConfigCreateOverrideAsset)) { ConfigOverrideEditor.CreateAsset(); } } else { ButtonOpenConfig(/*miniButton*/ false); } DrawLineSeparator(); } if (IsOverriddenInstance() && !isUsedInstance) { EditorGUILayout.HelpBox(EditorStrings.ConfigMultipleAssets, MessageType.Error); EditorGUILayout.Separator(); ButtonOpenConfig(); } else { EditorGUI.BeginDisabledGroup(IsDisabled()); { 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("Camera to compute Fade Out")) { EditorGUI.BeginChangeCheck(); fadeOutCameraTag.stringValue = EditorGUILayout.TagField(EditorStrings.ConfigFadeOutCameraTag, fadeOutCameraTag.stringValue); if (EditorGUI.EndChangeCheck() && Application.isPlaying) { (target as Config).ForceUpdateFadeOutCamera(); } } 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(); } } } EditorGUI.EndDisabledGroup(); } serializedObject.ApplyModifiedProperties(); if (reloadNoise) { Noise3D._EditorForceReloadData(); // Should be called AFTER ApplyModifiedProperties so the Config instance has the proper values when reloading data } }
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 } }
public static int GetSharedMeshVertexCount() { return(MeshGenerator.GetVertexCount(Config.Instance.sharedMeshSides, Config.Instance.sharedMeshSegments, true)); }
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 static Mesh GenerateConeZ_Radius(float lengthZ, float radiusStart, float radiusEnd, int numSides, int numSegments, bool cap) { Debug.Assert(lengthZ > 0f); Debug.Assert(radiusStart >= 0f); Debug.Assert(numSides >= 3); Debug.Assert(numSegments >= 0); Mesh mesh = new Mesh(); bool flag = false; flag = (!cap ? false : radiusStart > 0f); radiusStart = Mathf.Max(radiusStart, 0.001f); int num = numSides * (numSegments + 2); int num1 = num; if (flag) { num1 = num1 + numSides + 1; } Vector3[] vector3 = new Vector3[num1]; for (int i = 0; i < numSides; i++) { float single = 6.28318548f * (float)i / (float)numSides; float single1 = Mathf.Cos(single); float single2 = Mathf.Sin(single); for (int j = 0; j < numSegments + 2; j++) { float single3 = (float)j / (float)(numSegments + 1); Debug.Assert((single3 < 0f ? false : single3 <= 1f)); float single4 = Mathf.Lerp(radiusStart, radiusEnd, single3); vector3[i + j * numSides] = new Vector3(single4 * single1, single4 * single2, single3 * lengthZ); } } if (flag) { int num2 = num; vector3[num2] = Vector3.zero; num2++; for (int k = 0; k < numSides; k++) { float single5 = 6.28318548f * (float)k / (float)numSides; float single6 = Mathf.Cos(single5); float single7 = Mathf.Sin(single5); vector3[num2] = new Vector3(radiusStart * single6, radiusStart * single7, 0f); num2++; } Debug.Assert(num2 == (int)vector3.Length); } if (MeshGenerator.duplicateBackFaces) { Vector3[] vector3Array = new Vector3[(int)vector3.Length * 2]; vector3.CopyTo(vector3Array, 0); vector3.CopyTo(vector3Array, (int)vector3.Length); mesh.vertices = vector3Array; } else { mesh.vertices = vector3; } Vector2[] vector2 = new Vector2[num1]; int num3 = 0; for (int l = 0; l < num; l++) { int num4 = num3; num3 = num4 + 1; vector2[num4] = Vector2.zero; } if (flag) { for (int m = 0; m < numSides + 1; m++) { int num5 = num3; num3 = num5 + 1; vector2[num5] = new Vector2(1f, 0f); } } Debug.Assert(num3 == (int)vector2.Length); if (MeshGenerator.duplicateBackFaces) { Vector2[] vector2Array = new Vector2[(int)vector2.Length * 2]; vector2.CopyTo(vector2Array, 0); vector2.CopyTo(vector2Array, (int)vector2.Length); for (int n = 0; n < (int)vector2.Length; n++) { Vector2 vector21 = vector2Array[n + (int)vector2.Length]; vector2Array[n + (int)vector2.Length] = new Vector2(vector21.x, 1f); } mesh.uv = vector2Array; } else { mesh.uv = vector2; } int num6 = numSides * 2 * Mathf.Max(numSegments + 1, 1) * 3; if (flag) { num6 = num6 + numSides * 3; } int[] numArray = new int[num6]; int num7 = 0; for (int o = 0; o < numSides; o++) { int num8 = o + 1; if (num8 == numSides) { num8 = 0; } for (int p = 0; p < numSegments + 1; p++) { int num9 = p * numSides; int num10 = num7; num7 = num10 + 1; numArray[num10] = num9 + o; int num11 = num7; num7 = num11 + 1; numArray[num11] = num9 + num8; int num12 = num7; num7 = num12 + 1; numArray[num12] = num9 + o + numSides; int num13 = num7; num7 = num13 + 1; numArray[num13] = num9 + num8 + numSides; int num14 = num7; num7 = num14 + 1; numArray[num14] = num9 + o + numSides; int num15 = num7; num7 = num15 + 1; numArray[num15] = num9 + num8; } } if (flag) { for (int q = 0; q < numSides - 1; q++) { int num16 = num7; num7 = num16 + 1; numArray[num16] = num; int num17 = num7; num7 = num17 + 1; numArray[num17] = num + q + 2; int num18 = num7; num7 = num18 + 1; numArray[num18] = num + q + 1; } int num19 = num7; num7 = num19 + 1; numArray[num19] = num; int num20 = num7; num7 = num20 + 1; numArray[num20] = num + 1; int num21 = num7; num7 = num21 + 1; numArray[num21] = num + numSides; } Debug.Assert(num7 == (int)numArray.Length); if (MeshGenerator.duplicateBackFaces) { int[] numArray1 = new int[(int)numArray.Length * 2]; numArray.CopyTo(numArray1, 0); for (int r = 0; r < (int)numArray.Length; r += 3) { numArray1[(int)numArray.Length + r] = numArray[r] + num1; numArray1[(int)numArray.Length + r + 1] = numArray[r + 2] + num1; numArray1[(int)numArray.Length + r + 2] = numArray[r + 1] + num1; } mesh.triangles = numArray1; } else { mesh.triangles = numArray; } Bounds bound = new Bounds(new Vector3(0f, 0f, lengthZ * 0.5f), new Vector3(Mathf.Max(radiusStart, radiusEnd) * 2f, Mathf.Max(radiusStart, radiusEnd) * 2f, lengthZ)); mesh.bounds = bound; Debug.Assert(mesh.vertexCount == MeshGenerator.GetVertexCount(numSides, numSegments, flag)); Debug.Assert((int)mesh.triangles.Length == MeshGenerator.GetIndicesCount(numSides, numSegments, flag)); return(mesh); }
public static Mesh GenerateConeZ_Angle(float lengthZ, float coneAngle, int numSides, int numSegments, bool cap) { return(MeshGenerator.GenerateConeZ_RadiusAndAngle(lengthZ, 0f, coneAngle, numSides, numSegments, cap)); }
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(); { EditorGUILayout.PropertyField(renderingMode, EditorStrings.ConfigGeometryRenderingMode); #pragma warning disable 0162 // warning CS0162: Unreachable code detected if (renderingMode.intValue == (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(); } } if (EditorGUI.EndChangeCheck()) { VolumetricLightBeam._EditorSetAllMeshesDirty(); } 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); EditorGUILayout.Separator(); EditorExtensions.HorizontalLineSeparator(); Header("Internal Data (do not change)"); EditorGUILayout.PropertyField(beamShader1Pass, EditorStrings.ConfigBeamShader1Pass); EditorGUILayout.PropertyField(beamShader2Pass, EditorStrings.ConfigBeamShader2Pass); EditorGUILayout.PropertyField(dustParticlesPrefab, EditorStrings.ConfigDustParticlesPrefab); 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); } EditorGUILayout.Separator(); EditorExtensions.HorizontalLineSeparator(); EditorGUILayout.Separator(); 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 static Mesh GenerateConeZ_Radius( float lengthZ, float radiusStart, float radiusEnd, int numSides, int numSegments, bool cap) { Debug.Assert((double)lengthZ > 0.0); Debug.Assert((double)radiusStart >= 0.0); Debug.Assert(numSides >= 3); Debug.Assert(numSegments >= 0); Mesh mesh = new Mesh(); bool geomCap = cap && (double)radiusStart > 0.0; radiusStart = Mathf.Max(radiusStart, 1f / 1000f); int num1 = numSides * (numSegments + 2); int length1 = num1; if (geomCap) { length1 += numSides + 1; } Vector3[] vector3Array1 = new Vector3[length1]; for (int index1 = 0; index1 < numSides; ++index1) { double num2 = 6.28318548202515 * (double)index1 / (double)numSides; float num3 = Mathf.Cos((float)num2); float num4 = Mathf.Sin((float)num2); for (int index2 = 0; index2 < numSegments + 2; ++index2) { float num5 = (float)index2 / (float)(numSegments + 1); Debug.Assert((double)num5 >= 0.0 && (double)num5 <= 1.0); float num6 = Mathf.Lerp(radiusStart, radiusEnd, num5); vector3Array1[index1 + index2 * numSides] = new Vector3(num6 * num3, num6 * num4, num5 * lengthZ); } } if (geomCap) { int index1 = num1; vector3Array1[index1] = Vector3.get_zero(); int index2 = index1 + 1; for (int index3 = 0; index3 < numSides; ++index3) { double num2 = 6.28318548202515 * (double)index3 / (double)numSides; float num3 = Mathf.Cos((float)num2); float num4 = Mathf.Sin((float)num2); vector3Array1[index2] = new Vector3(radiusStart * num3, radiusStart * num4, 0.0f); ++index2; } Debug.Assert(index2 == vector3Array1.Length); } if (!MeshGenerator.duplicateBackFaces) { mesh.set_vertices(vector3Array1); } else { Vector3[] vector3Array2 = new Vector3[vector3Array1.Length * 2]; vector3Array1.CopyTo((Array)vector3Array2, 0); vector3Array1.CopyTo((Array)vector3Array2, vector3Array1.Length); mesh.set_vertices(vector3Array2); } Vector2[] vector2Array1 = new Vector2[length1]; int num7 = 0; for (int index = 0; index < num1; ++index) { vector2Array1[num7++] = Vector2.get_zero(); } if (geomCap) { for (int index = 0; index < numSides + 1; ++index) { vector2Array1[num7++] = new Vector2(1f, 0.0f); } } Debug.Assert(num7 == vector2Array1.Length); if (!MeshGenerator.duplicateBackFaces) { mesh.set_uv(vector2Array1); } else { Vector2[] vector2Array2 = new Vector2[vector2Array1.Length * 2]; vector2Array1.CopyTo((Array)vector2Array2, 0); vector2Array1.CopyTo((Array)vector2Array2, vector2Array1.Length); for (int index = 0; index < vector2Array1.Length; ++index) { Vector2 vector2 = vector2Array2[index + vector2Array1.Length]; vector2Array2[index + vector2Array1.Length] = new Vector2((float)vector2.x, 1f); } mesh.set_uv(vector2Array2); } int length2 = numSides * 2 * Mathf.Max(numSegments + 1, 1) * 3; if (geomCap) { length2 += numSides * 3; } int[] numArray1 = new int[length2]; int num8 = 0; for (int index1 = 0; index1 < numSides; ++index1) { int num2 = index1 + 1; if (num2 == numSides) { num2 = 0; } for (int index2 = 0; index2 < numSegments + 1; ++index2) { int num3 = index2 * numSides; int[] numArray2 = numArray1; int index3 = num8; int num4 = index3 + 1; int num5 = num3 + index1; numArray2[index3] = num5; int[] numArray3 = numArray1; int index4 = num4; int num6 = index4 + 1; int num9 = num3 + num2; numArray3[index4] = num9; int[] numArray4 = numArray1; int index5 = num6; int num10 = index5 + 1; int num11 = num3 + index1 + numSides; numArray4[index5] = num11; int[] numArray5 = numArray1; int index6 = num10; int num12 = index6 + 1; int num13 = num3 + num2 + numSides; numArray5[index6] = num13; int[] numArray6 = numArray1; int index7 = num12; int num14 = index7 + 1; int num15 = num3 + index1 + numSides; numArray6[index7] = num15; int[] numArray7 = numArray1; int index8 = num14; num8 = index8 + 1; int num16 = num3 + num2; numArray7[index8] = num16; } } if (geomCap) { for (int index1 = 0; index1 < numSides - 1; ++index1) { int[] numArray2 = numArray1; int index2 = num8; int num2 = index2 + 1; int num3 = num1; numArray2[index2] = num3; int[] numArray3 = numArray1; int index3 = num2; int num4 = index3 + 1; int num5 = num1 + index1 + 2; numArray3[index3] = num5; int[] numArray4 = numArray1; int index4 = num4; num8 = index4 + 1; int num6 = num1 + index1 + 1; numArray4[index4] = num6; } int[] numArray5 = numArray1; int index5 = num8; int num9 = index5 + 1; int num10 = num1; numArray5[index5] = num10; int[] numArray6 = numArray1; int index6 = num9; int num11 = index6 + 1; int num12 = num1 + 1; numArray6[index6] = num12; int[] numArray7 = numArray1; int index7 = num11; num8 = index7 + 1; int num13 = num1 + numSides; numArray7[index7] = num13; } Debug.Assert(num8 == numArray1.Length); if (!MeshGenerator.duplicateBackFaces) { mesh.set_triangles(numArray1); } else { int[] numArray2 = new int[numArray1.Length * 2]; numArray1.CopyTo((Array)numArray2, 0); for (int index = 0; index < numArray1.Length; index += 3) { numArray2[numArray1.Length + index] = numArray1[index] + length1; numArray2[numArray1.Length + index + 1] = numArray1[index + 2] + length1; numArray2[numArray1.Length + index + 2] = numArray1[index + 1] + length1; } mesh.set_triangles(numArray2); } Bounds bounds; ((Bounds) ref bounds).\u002Ector(new Vector3(0.0f, 0.0f, lengthZ * 0.5f), new Vector3(Mathf.Max(radiusStart, radiusEnd) * 2f, Mathf.Max(radiusStart, radiusEnd) * 2f, lengthZ)); mesh.set_bounds(bounds); Debug.Assert(mesh.get_vertexCount() == MeshGenerator.GetVertexCount(numSides, numSegments, geomCap)); Debug.Assert(mesh.get_triangles().Length == MeshGenerator.GetIndicesCount(numSides, numSegments, geomCap)); return(mesh); }
public override void OnInspectorGUI() { base.OnInspectorGUI(); Header("Beam Geometry"); EditorGUI.BeginChangeCheck(); { geometryLayerID.intValue = EditorGUILayout.LayerField(EditorStrings.ConfigGeometryLayerID, geometryLayerID.intValue); geometryTag.stringValue = EditorGUILayout.TagField(EditorStrings.ConfigGeometryTag, geometryTag.stringValue); RenderQueueGUIDraw(); EditorGUI.BeginChangeCheck(); { forceSinglePass.ToggleLeft(EditorStrings.ConfigGeometryForceSinglePass); } 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 } }