diff --git a/Assets/Editor/SceneEffectEditor.cs b/Assets/Editor/SceneEffectEditor.cs index 6df893e..b7f87d8 100644 --- a/Assets/Editor/SceneEffectEditor.cs +++ b/Assets/Editor/SceneEffectEditor.cs @@ -1,6 +1,7 @@ using System.Linq; using Unity.Mathematics; using UnityEditor; +using UnityEditor.EditorTools; using UnityEditor.IMGUI.Controls; using UnityEditorInternal; using UnityEngine; @@ -18,17 +19,18 @@ namespace X.Rendering.Scene SerializedProperty boundsProperty; private BoxBoundsHandle boundsHandle = new(); + LightData[] lightDatas = null; public override VisualElement CreateInspectorGUI() { transform = (target as MonoBehaviour).transform; var mainLight = GameObject.FindGameObjectWithTag("MainLight")?.GetComponent(); - if (mainLight == null ) + if (mainLight == null) { mainLight = GameObject.FindObjectsOfType().Where(l => l.type == LightType.Directional).First(); } - if(mainLight != null ) + if (mainLight != null) { mainLightDir = (mainLight.transform.rotation * Vector3.forward).normalized; mainLightDir.w = 1; @@ -40,6 +42,8 @@ namespace X.Rendering.Scene Debug.Log($"{lightList.index}"); selectIndex = lightList.index; }; + var t = serializedObject.targetObject.GetType().GetField("capsuleLights", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + lightDatas = t.GetValue(serializedObject.targetObject) as LightData[]; lightList.onAddCallback += (_) => { @@ -48,8 +52,20 @@ namespace X.Rendering.Scene lightList.index = 0; } lightList.serializedProperty.InsertArrayElementAtIndex(lightList.index); - lightList.serializedProperty.GetArrayElementAtIndex(lightList.index).vector4Value = mainLightDir; - lightList.Select(lightList.index); + serializedObject.ApplyModifiedProperties(); + + var light = new LightData() + { + isPointLight = true, + lightIntensity = 1, + lightPosition = transform.position + Vector3.up + }; + + if (lightDatas != null) + { + lightDatas[lightList.index] = light; + lightList.Select(lightList.index); + } }; lightList.drawHeaderCallback = DrawHeader; @@ -63,8 +79,26 @@ namespace X.Rendering.Scene private void DrawListItems(Rect rect, int index, bool isActive, bool isFocused) { - SerializedProperty element = lightList.serializedProperty.GetArrayElementAtIndex(index); - EditorGUI.LabelField(new Rect(rect.x, rect.y, 200, EditorGUIUtility.singleLineHeight), $"{element.vector4Value}"); + if(index < 0 ) + { + return; + } + + EditorGUI.BeginChangeCheck(); + var light = lightDatas[index]; + float x = rect.x; + //EditorGUI.LabelField(new Rect(x, rect.y, 50, EditorGUIUtility.singleLineHeight), "点光"); + //x += 50; + EditorGUI.LabelField(new Rect(x, rect.y, 150, EditorGUIUtility.singleLineHeight), $"{light.lightPosition}"); + x += 140; + light.lightIntensity = EditorGUI.Slider(new Rect(x, rect.y, 200, EditorGUIUtility.singleLineHeight), light.lightIntensity, 0.2f, 2); + x += 210; + light.isPointLight = EditorGUI.ToggleLeft(new Rect(x, rect.y, 50, EditorGUIUtility.singleLineHeight), "点光", light.isPointLight); + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(target, "DrawListItems"); + CallValidate(); + } } private void DrawHeader(Rect rect) @@ -76,11 +110,16 @@ namespace X.Rendering.Scene public override void OnInspectorGUI() { serializedObject.Update(); - base.OnInspectorGUI(); + base.OnInspectorGUI(); lightList.DoLayoutList(); serializedObject.ApplyModifiedProperties(); } + private void OnDestroy() + { + Tools.hidden = false; + } + public void OnSceneGUI() { DrawBoundHandle(); @@ -88,30 +127,58 @@ namespace X.Rendering.Scene { return; } - SerializedProperty element = lightList.serializedProperty.GetArrayElementAtIndex(selectIndex); - - var rot = new float4(element.vector4Value).xyz; - - rot += DrawRotationHandle(element.vector4Value); - element.vector4Value = new float4(rot, element.vector4Value.w); + var light = lightDatas[selectIndex]; + Tools.hidden = true; + if (!light.isPointLight) + { + var rot = (float3)light.lightPosition; + rot += DrawRotationHandle(light.lightPosition); + light.lightPosition = rot; + } + else + { + var pos = (float3)light.lightPosition; + pos += DrawPositionHandle(light.lightPosition); + light.lightPosition = pos; + } serializedObject.ApplyModifiedProperties(); } + protected void CallValidate() + { + target.GetType().GetMethod("OnValidate", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Invoke(target, null); + } + + protected float3 DrawPositionHandle(Vector3 vec) + { + EditorGUI.BeginChangeCheck(); + var newPos = Handles.PositionHandle(vec, Quaternion.identity); + float3 delta = float3.zero; + if (EditorGUI.EndChangeCheck()) + { + Undo.RecordObject(target, "DrawPositionHandle"); + delta = newPos - vec; + CallValidate(); + } + + return delta; + } + protected float3 DrawRotationHandle(Vector3 vec) { EditorGUI.BeginChangeCheck(); var rotation = Quaternion.LookRotation(vec); Vector3 newEuler = Vector3.zero; Vector3 oldEuler = rotation.eulerAngles; - + var col = Handles.color; var pos = transform.position; if (boundsProperty != null) { pos = boundsProperty.boundsValue.center; } - + Handles.color = Handles.xAxisColor; newEuler.x = Handles.Disc(Quaternion.Euler(oldEuler.x, 0, 0), pos, Vector3.left, HandleUtility.GetHandleSize(pos) * 1.5f, false, 0.1f).eulerAngles.x; @@ -122,21 +189,16 @@ namespace X.Rendering.Scene EditorGUI.EndChangeCheck(); Handles.ConeHandleCap(0, pos, Quaternion.Euler(newEuler), HandleUtility.GetHandleSize(pos), EventType.Repaint); - + Handles.color = col; - float3 delta; + float3 delta = float3.zero; var newVec = (Quaternion.Euler(newEuler) * Vector3.forward).normalized; if (newVec != vec) { Undo.RecordObject(target, "DrawRotationHandle"); - - // Perform the handle move and update the serialized data delta = newVec - vec; - } - else - { - delta = float3.zero; + CallValidate(); } return delta; @@ -146,7 +208,7 @@ namespace X.Rendering.Scene { if (boundsProperty == null) { - return; + return; } EditorGUI.BeginChangeCheck(); @@ -156,7 +218,7 @@ namespace X.Rendering.Scene var newPos = Handles.PositionHandle(bounds.center, transform.rotation); boundsHandle.center = bounds.center; boundsHandle.size = bounds.size; - boundsHandle.DrawHandle(); + boundsHandle.DrawHandle(); if (EditorGUI.EndChangeCheck()) { Undo.RecordObject(target, "DrawBoundHandle"); diff --git a/Assets/Scenes/Terminal/TerminalScene.unity b/Assets/Scenes/Terminal/TerminalScene.unity index c80398f..64d17fe 100644 --- a/Assets/Scenes/Terminal/TerminalScene.unity +++ b/Assets/Scenes/Terminal/TerminalScene.unity @@ -14550,16 +14550,18 @@ MonoBehaviour: CascadeShadowOffset: {x: 0, y: 0, z: 1} updateInterval: 1 capsuleLights: - - {x: 0.009531173, y: -0.76794606, z: -0.6404436, w: 1} + - lightPosition: {x: 0.30918866, y: -0.7392774, z: -0.5982234} + lightIntensity: 0.92 + isPointLight: 0 capsuleAOSetting: AmbientIntensity: 3.5 - ConeAngle: 10.72 + ConeAngle: 7.86 ShadowIntensity: 0.28 - ShadowSharpness: 10.59 + ShadowSharpness: 10.3 lightStartID: 0 lightEndID: 1 CapsuleLightsDir: - - {x: -0.009531173, y: 0.76794606, z: 0.6404436, w: 1} + - {x: -0.30918866, y: 0.7392774, z: 0.5982234, w: 0.92} - {x: 0, y: 0, z: 0, w: 0} - {x: 0, y: 0, z: 0, w: 0} - {x: 0, y: 0, z: 0, w: 0} @@ -14594,9 +14596,9 @@ MonoBehaviour: CapsuleLightsDirCount: 1 capsuleAOAreaSettings: - AmbientIntensity: 3.5 - ConeAngle: 10.72 + ConeAngle: 7.86 ShadowIntensity: 0.28 - ShadowSharpness: 10.59 + ShadowSharpness: 10.3 lightStartID: 0 lightEndID: 1 sceneAreaEffects: [] diff --git a/Assets/Scripts/CapsuleShadowAreaEffect.cs b/Assets/Scripts/CapsuleShadowAreaEffect.cs index c7bbd2d..20a4029 100644 --- a/Assets/Scripts/CapsuleShadowAreaEffect.cs +++ b/Assets/Scripts/CapsuleShadowAreaEffect.cs @@ -9,7 +9,7 @@ namespace X.Rendering.Scene [SerializeField] internal CapsuleShadowAreaSetting capsuleAOSetting = CapsuleShadowAreaSetting.GetDefault(); [SerializeField, HideInInspector] - internal Vector4[] capsuleLights; + internal LightData[] capsuleLights; [SerializeField, HideInInspector] internal Bounds Bounds = new Bounds(Vector3.zero, Vector3.one); diff --git a/Assets/Scripts/CapsuleShadowPass.cs b/Assets/Scripts/CapsuleShadowPass.cs index 738649a..79fb9ae 100644 --- a/Assets/Scripts/CapsuleShadowPass.cs +++ b/Assets/Scripts/CapsuleShadowPass.cs @@ -46,6 +46,14 @@ namespace X.Rendering.Scene } } + [Serializable] + public class LightData + { + public Vector3 lightPosition; + public float lightIntensity = 1; + public bool isPointLight = true; + } + internal class CapsuleShadowPass : ScriptableRenderPass, IDisposable { [Serializable] diff --git a/Assets/Scripts/SceneEffect.cs b/Assets/Scripts/SceneEffect.cs index 8aa7d76..b7d72ff 100644 --- a/Assets/Scripts/SceneEffect.cs +++ b/Assets/Scripts/SceneEffect.cs @@ -64,8 +64,7 @@ namespace X.Rendering.Scene private void OnDestroy() { - Shader.DisableKeyword(MultiCapsuleAO); - Shader.DisableKeyword(MultiCapsuleShadowAndAO); + SetEnable(false); shadowRemapPass?.Dispose(); capsuleAOPass?.Dispose(); Instance = null; @@ -87,6 +86,8 @@ namespace X.Rendering.Scene } else { + Shader.DisableKeyword(MultiCapsuleAO); + Shader.DisableKeyword(MultiCapsuleShadowAndAO); RenderPipelineManager.beginCameraRendering -= OnBeginCamera; } } @@ -108,6 +109,7 @@ namespace X.Rendering.Scene UpdateCapsuleLights(); } + private void OnValidate() { UpdateRenderAssetsSettings(); @@ -127,13 +129,18 @@ namespace X.Rendering.Scene for (int i = 0; i < capsuleLights?.Length; i++) { var light = capsuleLights[i]; - var v = -Vector3.Normalize(light); + var v = light.lightPosition; + if(!light.isPointLight) + { + v = -Vector3.Normalize(light.lightPosition); + } + lightDirs.Add(new Vector4() { x = v.x, y = v.y, z = v.z, - w = light.w + w = light.lightIntensity }); } capsuleAOSetting.lightStartID = 0; @@ -148,13 +155,18 @@ namespace X.Rendering.Scene for (int j = 0; j < sceneAreaEffect.capsuleLights.Length; j++) { var light = sceneAreaEffect.capsuleLights[j]; - var v = -Vector3.Normalize(light); + var v = light.lightPosition; + if (!light.isPointLight) + { + v = -Vector3.Normalize(light.lightPosition); + } + lightDirs.Add(new Vector4() { x = v.x, y = v.y, z = v.z, - w = light.w + w = light.lightIntensity }); } @@ -236,7 +248,7 @@ namespace X.Rendering.Scene #region CapsuleAO [SerializeField , HideInInspector] - private Vector4[] capsuleLights; + private LightData[] capsuleLights; [SerializeField] private CapsuleShadowAreaSetting capsuleAOSetting = CapsuleShadowAreaSetting.GetDefault(); [HideInInspector] diff --git a/Packages/com.unity.render-pipelines.universal@14.0.11/ShaderLibrary/CapsuleShadow.hlsl b/Packages/com.unity.render-pipelines.universal@14.0.11/ShaderLibrary/CapsuleShadow.hlsl index 46e0cff..1992787 100644 --- a/Packages/com.unity.render-pipelines.universal@14.0.11/ShaderLibrary/CapsuleShadow.hlsl +++ b/Packages/com.unity.render-pipelines.universal@14.0.11/ShaderLibrary/CapsuleShadow.hlsl @@ -256,8 +256,9 @@ void CalcCapsuleShadow(float3 worldPos, float3 worldNormal, out float shadow, o for (uint b = area.lightStartID; b < area.lightEndID; ++b) { float4 lightDir = _CapsuleLightsDir[b]; - float4 cone = GetConeProperties(lightDir.xyz, area.ConeAngle); - float tempIntensity = intensity / saturate(1 * smoothstep(0.1, 2, lightDir.w)); + //float4 cone = GetConeProperties(lightDir.xyz, area.ConeAngle); + float4 cone = GetConeProperties(normalize(lightDir.xyz - worldPos), area.ConeAngle); + float tempIntensity = intensity / smoothstep(0.1, 2, lightDir.w); float tempShadow = CalcCapsuleShadowByIndex(worldPos, cone.xyz, c.capsuleStartID, c.capsuleEndID, area.ShadowSharpness, tempIntensity, area.ShadowIntensity); // float tempShadow = CalcCapsuleShadowByIndexV2(worldPos, cone, c.capsuleStartID, c.capsuleEndID, tempIntensity, area.ShadowIntensity); shadow = min(shadow, tempShadow);