CapsuleAO point light

This commit is contained in:
StarBeats 2025-09-28 19:40:35 +08:00
parent 4a9d7cc4ab
commit 45c479df00
6 changed files with 126 additions and 41 deletions

View File

@ -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<Light>();
if (mainLight == null )
if (mainLight == null)
{
mainLight = GameObject.FindObjectsOfType<Light>().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;
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)
@ -81,6 +115,11 @@ namespace X.Rendering.Scene
serializedObject.ApplyModifiedProperties();
}
private void OnDestroy()
{
Tools.hidden = false;
}
public void OnSceneGUI()
{
DrawBoundHandle();
@ -88,16 +127,44 @@ 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();
@ -125,18 +192,13 @@ namespace X.Rendering.Scene
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;

View File

@ -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: []

View File

@ -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);

View File

@ -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]

View File

@ -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]

View File

@ -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);