mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 14:29:25 +00:00
thirdperson, propundobutton, mirror clone test, you are a clone test, bettershadowclone test, nevermind, anotherlocaltestmod, and some changes to avatarscaling ???
This commit is contained in:
parent
df45fb50d9
commit
9944ad7611
43 changed files with 1076 additions and 173 deletions
|
@ -31,6 +31,14 @@ public static class ModSettings
|
|||
internal static readonly MelonPreferences_Entry<bool> EntryDebugHeadHide =
|
||||
Category.CreateEntry("Debug Head Hide", false,
|
||||
description: "Should head be hidden for first render?");
|
||||
|
||||
internal static readonly MelonPreferences_Entry<bool> EntryDebugShowShadow =
|
||||
Category.CreateEntry("Debug Show Shadow", false,
|
||||
description: "Should the shadow clone be shown?");
|
||||
|
||||
internal static readonly MelonPreferences_Entry<bool> EntryDebugShowInFront =
|
||||
Category.CreateEntry("Debug Show in Front", false,
|
||||
description: "Should the shadow clone be shown in front?");
|
||||
|
||||
|
||||
#endregion
|
||||
|
@ -46,5 +54,7 @@ public static class ModSettings
|
|||
TransformHiderManager.s_DisallowFprExclusions = EntryDontRespectFPR.Value;
|
||||
TransformHiderManager.s_DebugHeadHide = EntryDebugHeadHide.Value;
|
||||
ShadowCloneManager.s_CopyMaterialsToShadow = EntryCopyMaterialToShadow.Value;
|
||||
ShadowCloneManager.s_DebugShowShadow = EntryDebugShowShadow.Value;
|
||||
ShadowCloneManager.s_DebugShowInFront = EntryDebugShowInFront.Value;
|
||||
}
|
||||
}
|
Binary file not shown.
BIN
BetterShadowClone/Resources/bettershadowclone.assets_OLD
Normal file
BIN
BetterShadowClone/Resources/bettershadowclone.assets_OLD
Normal file
Binary file not shown.
|
@ -8,4 +8,5 @@ public interface IShadowClone : IDisposable
|
|||
bool Process();
|
||||
void RenderForShadow();
|
||||
void RenderForUiCulling();
|
||||
void ResetMainMesh();
|
||||
}
|
|
@ -28,6 +28,8 @@ public struct MeshShadowClone : IShadowClone
|
|||
|
||||
#region IShadowClone Methods
|
||||
|
||||
public void ResetMainMesh(){}
|
||||
|
||||
public bool IsValid => _mainMesh != null && _shadowMesh != null;
|
||||
|
||||
public MeshShadowClone(MeshRenderer meshRenderer)
|
||||
|
@ -88,7 +90,9 @@ public struct MeshShadowClone : IShadowClone
|
|||
|
||||
public void RenderForShadow()
|
||||
{
|
||||
_shadowMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
_shadowMesh.shadowCastingMode = ShadowCloneManager.s_DebugShowShadow
|
||||
? ShadowCastingMode.On : ShadowCastingMode.ShadowsOnly;
|
||||
|
||||
_shadowMesh.forceRenderingOff = !_shouldCastShadows;
|
||||
|
||||
// shadow casting needs clone to have original materials (uv discard)
|
||||
|
|
|
@ -8,6 +8,8 @@ public class SkinnedShadowClone : IShadowClone
|
|||
{
|
||||
private static readonly int s_SourceBufferId = Shader.PropertyToID("_sourceBuffer");
|
||||
private static readonly int s_TargetBufferId = Shader.PropertyToID("_targetBuffer");
|
||||
private static readonly int s_HiddenVerticiesId = Shader.PropertyToID("_hiddenVertices");
|
||||
private static readonly int s_HiddenVertexPos = Shader.PropertyToID("_hiddenVertexPos");
|
||||
private static readonly int s_SourceBufferLayoutId = Shader.PropertyToID("_sourceBufferLayout");
|
||||
private static readonly int s_SourceRootMatrix = Shader.PropertyToID("_rootBoneMatrix");
|
||||
|
||||
|
@ -26,6 +28,7 @@ public class SkinnedShadowClone : IShadowClone
|
|||
// clone copying
|
||||
private GraphicsBuffer _graphicsBuffer;
|
||||
private GraphicsBuffer _targetBuffer;
|
||||
private ComputeBuffer _computeBuffer;
|
||||
private int _threadGroups;
|
||||
private int _bufferLayout;
|
||||
|
||||
|
@ -39,7 +42,7 @@ public class SkinnedShadowClone : IShadowClone
|
|||
// anything player can touch is suspect to death
|
||||
public bool IsValid => _mainMesh != null && _shadowMesh != null && _rootBone != null;
|
||||
|
||||
internal SkinnedShadowClone(SkinnedMeshRenderer renderer)
|
||||
internal SkinnedShadowClone(SkinnedMeshRenderer renderer, FPRExclusion exclusion)
|
||||
{
|
||||
_mainMesh = renderer;
|
||||
|
||||
|
@ -52,11 +55,28 @@ public class SkinnedShadowClone : IShadowClone
|
|||
return; // no mesh!
|
||||
}
|
||||
|
||||
|
||||
FindExclusionVertList(_mainMesh, exclusion);
|
||||
|
||||
if (exclusion.affectedVertexIndices.Count == 0)
|
||||
{
|
||||
Dispose();
|
||||
return; // no affected verts!
|
||||
}
|
||||
|
||||
_computeBuffer = new ComputeBuffer(_mainMesh.sharedMesh.vertexCount, sizeof(int));
|
||||
_computeBuffer.SetData(exclusion.affectedVertexIndices.ToArray());
|
||||
exclusion.affectedVertexIndices.Clear();
|
||||
|
||||
|
||||
|
||||
_shouldCastShadows = _mainMesh.shadowCastingMode != ShadowCastingMode.Off;
|
||||
_mainMesh.shadowCastingMode = ShadowCastingMode.Off; // visual mesh doesn't cast shadows
|
||||
//_mainMesh.shadowCastingMode = ShadowCastingMode.On; // visual mesh doesn't cast shadows
|
||||
|
||||
(_shadowMesh, _shadowMeshFilter) = ShadowCloneManager.InstantiateShadowClone(_mainMesh);
|
||||
_shadowMesh.forceRenderingOff = true;
|
||||
_shadowMesh.shadowCastingMode = ShadowCastingMode.Off; // shadow mesh doesn't cast shadows
|
||||
_shadowMesh.forceRenderingOff = false;
|
||||
|
||||
|
||||
_rootBone = _mainMesh.rootBone;
|
||||
_rootBone ??= _mainMesh.transform; // fallback to transform if no root bone
|
||||
|
@ -133,6 +153,8 @@ public class SkinnedShadowClone : IShadowClone
|
|||
_graphicsBuffer = null;
|
||||
_targetBuffer?.Dispose();
|
||||
_targetBuffer = null;
|
||||
_computeBuffer?.Dispose();
|
||||
_computeBuffer = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -151,7 +173,7 @@ public class SkinnedShadowClone : IShadowClone
|
|||
if (mesh.HasVertexAttribute(VertexAttribute.Tangent)) _bufferLayout += 4;
|
||||
_bufferLayout *= 4; // 4 bytes per float
|
||||
|
||||
const float xThreadGroups = 64f;
|
||||
const float xThreadGroups = 32f;
|
||||
_threadGroups = Mathf.CeilToInt(mesh.vertexCount / xThreadGroups);
|
||||
|
||||
_mainMesh.vertexBufferTarget |= GraphicsBuffer.Target.Raw;
|
||||
|
@ -162,10 +184,66 @@ public class SkinnedShadowClone : IShadowClone
|
|||
//Debug.Log($"Initialized! BufferLayout: {_bufferLayout}, GraphicsBuffer: {_graphicsBuffer != null}, TargetBuffer: {_targetBuffer != null}");
|
||||
}
|
||||
|
||||
public static void FindExclusionVertList(SkinnedMeshRenderer renderer, FPRExclusion exclusion)
|
||||
{
|
||||
var boneWeights = renderer.sharedMesh.boneWeights;
|
||||
|
||||
HashSet<int> weights = new();
|
||||
for (int i = 0; i < renderer.bones.Length; i++)
|
||||
{
|
||||
if (exclusion.affectedChildren.Contains(renderer.bones[i]))
|
||||
weights.Add(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < boneWeights.Length; i++)
|
||||
{
|
||||
BoneWeight weight = boneWeights[i];
|
||||
|
||||
Transform bone = null;
|
||||
const float minWeightThreshold = 0.2f;
|
||||
if (weights.Contains(weight.boneIndex0) && weight.weight0 > minWeightThreshold)
|
||||
bone = renderer.bones[weight.boneIndex0];
|
||||
else if (weights.Contains(weight.boneIndex1) && weight.weight1 > minWeightThreshold)
|
||||
bone = renderer.bones[weight.boneIndex1];
|
||||
else if (weights.Contains(weight.boneIndex2) && weight.weight2 > minWeightThreshold)
|
||||
bone = renderer.bones[weight.boneIndex2];
|
||||
else if (weights.Contains(weight.boneIndex3) && weight.weight3 > minWeightThreshold)
|
||||
bone = renderer.bones[weight.boneIndex3];
|
||||
|
||||
exclusion.affectedVertexIndices.Add(bone != null ? i : -1);
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetMainMesh()
|
||||
{
|
||||
_mainMesh.shadowCastingMode = ShadowCastingMode.On;
|
||||
_mainMesh.forceRenderingOff = false;
|
||||
|
||||
_shadowMesh.transform.position = Vector3.positiveInfinity; // nan
|
||||
}
|
||||
|
||||
private void ResetShadowClone()
|
||||
{
|
||||
_shadowMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
_shadowMesh.forceRenderingOff = !_shouldCastShadows;
|
||||
if (ShadowCloneManager.s_DebugShowShadow)
|
||||
{
|
||||
_mainMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
_mainMesh.forceRenderingOff = false;
|
||||
|
||||
_shadowMesh.shadowCastingMode = ShadowCastingMode.On;
|
||||
_shadowMesh.forceRenderingOff = false;
|
||||
|
||||
_shadowMesh.transform.localPosition = Vector3.zero;
|
||||
}
|
||||
else
|
||||
{
|
||||
_mainMesh.shadowCastingMode = ShadowCastingMode.On;
|
||||
_mainMesh.forceRenderingOff = false;
|
||||
|
||||
_shadowMesh.shadowCastingMode = ShadowCastingMode.ShadowsOnly;
|
||||
_shadowMesh.forceRenderingOff = !_shouldCastShadows;
|
||||
}
|
||||
|
||||
//_shadowMesh.enabled = true;
|
||||
|
||||
// shadow casting needs clone to have original materials (uv discard)
|
||||
// we also want to respect material swaps... but this is fucking slow :(
|
||||
|
@ -173,12 +251,7 @@ public class SkinnedShadowClone : IShadowClone
|
|||
if (!ShadowCloneManager.s_CopyMaterialsToShadow)
|
||||
return;
|
||||
|
||||
if (_hasShadowMaterials)
|
||||
{
|
||||
_shadowMesh.sharedMaterials = _mainMesh.sharedMaterials;
|
||||
_hasShadowMaterials = false;
|
||||
}
|
||||
|
||||
_shadowMesh.sharedMaterials = _mainMesh.sharedMaterials;
|
||||
UpdateCloneMaterialProperties();
|
||||
}
|
||||
|
||||
|
@ -188,12 +261,10 @@ public class SkinnedShadowClone : IShadowClone
|
|||
_shadowMesh.forceRenderingOff = false;
|
||||
|
||||
// UI culling needs clone to have write-to-depth shader
|
||||
if (_hasShadowMaterials) return;
|
||||
_shadowMesh.sharedMaterials = _shadowMaterials;
|
||||
_hasShadowMaterials = true;
|
||||
|
||||
// Not needed- MaterialPropertyBlock applied to renderer in RenderForShadow
|
||||
//UpdateCloneMaterialProperties();
|
||||
UpdateCloneMaterialProperties();
|
||||
}
|
||||
|
||||
private void RenderShadowClone()
|
||||
|
@ -205,6 +276,10 @@ public class SkinnedShadowClone : IShadowClone
|
|||
ShadowCloneHelper.shader.SetMatrix(s_SourceRootMatrix, rootMatrix);
|
||||
ShadowCloneHelper.shader.SetBuffer(0, s_SourceBufferId, _graphicsBuffer);
|
||||
ShadowCloneHelper.shader.SetBuffer(0, s_TargetBufferId, _targetBuffer);
|
||||
|
||||
ShadowCloneHelper.shader.SetBuffer(0, s_HiddenVerticiesId, _computeBuffer);
|
||||
ShadowCloneHelper.shader.SetVector(s_HiddenVertexPos, Vector4.positiveInfinity); // temp
|
||||
|
||||
ShadowCloneHelper.shader.SetInt(s_SourceBufferLayoutId, _bufferLayout);
|
||||
ShadowCloneHelper.shader.Dispatch(0, _threadGroups, 1, 1);
|
||||
_graphicsBuffer.Release();
|
||||
|
|
|
@ -35,11 +35,14 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
|
||||
// Settings
|
||||
internal static bool s_CopyMaterialsToShadow = true;
|
||||
internal static bool s_DebugShowShadow = false;
|
||||
internal static bool s_DebugShowInFront = false;
|
||||
private static bool s_UseShadowToCullUi;
|
||||
private const string ShadowCullUiSettingName = "ExperimentalAvatarOverrenderUI";
|
||||
|
||||
// Implementation
|
||||
private bool _hasRenderedThisFrame;
|
||||
public static readonly List<FPRExclusion> s_Exclusions = new();
|
||||
|
||||
// Shadow Clones
|
||||
private readonly List<IShadowClone> s_ShadowClones = new();
|
||||
|
@ -64,15 +67,17 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
UpdatePlayerCameras();
|
||||
|
||||
s_CopyMaterialsToShadow = ModSettings.EntryCopyMaterialToShadow.Value;
|
||||
s_DebugShowShadow = ModSettings.EntryDebugShowShadow.Value;
|
||||
s_DebugShowInFront = ModSettings.EntryDebugShowInFront.Value;
|
||||
s_UseShadowToCullUi = MetaPort.Instance.settings.GetSettingsBool(ShadowCullUiSettingName);
|
||||
MetaPort.Instance.settings.settingBoolChanged.AddListener(OnSettingsBoolChanged);
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
=> Camera.onPreCull += MyOnPreCull;
|
||||
=> Camera.onPreRender += MyOnPreCull;
|
||||
|
||||
private void OnDisable()
|
||||
=> Camera.onPreCull -= MyOnPreCull;
|
||||
=> Camera.onPreRender -= MyOnPreCull;
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
|
@ -86,12 +91,25 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
private void Update()
|
||||
{
|
||||
_hasRenderedThisFrame = false;
|
||||
|
||||
for (int i = s_ShadowClones.Count - 1; i >= 0; i--)
|
||||
{
|
||||
IShadowClone clone = s_ShadowClones[i];
|
||||
if (clone is not { IsValid: true })
|
||||
{
|
||||
clone?.Dispose();
|
||||
s_ShadowClones.RemoveAt(i);
|
||||
continue; // invalid or dead
|
||||
}
|
||||
|
||||
clone.ResetMainMesh();
|
||||
}
|
||||
}
|
||||
|
||||
private void MyOnPreCull(Camera cam)
|
||||
{
|
||||
bool forceRenderForUiCull = s_UseShadowToCullUi && cam == s_UiCamera;
|
||||
if (_hasRenderedThisFrame && !forceRenderForUiCull)
|
||||
//bool forceRenderForUiCull = s_UseShadowToCullUi && cam == s_UiCamera;
|
||||
if (cam != s_MainCamera)
|
||||
return;
|
||||
|
||||
_hasRenderedThisFrame = true;
|
||||
|
@ -109,17 +127,13 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
}
|
||||
|
||||
if (!clone.Process()) continue; // not ready yet or disabled
|
||||
|
||||
if (forceRenderForUiCull)
|
||||
clone.RenderForUiCulling(); // last cam to render
|
||||
else
|
||||
clone.RenderForShadow(); // first cam to render
|
||||
|
||||
clone.RenderForShadow(); // first cam to render
|
||||
}
|
||||
|
||||
_stopWatch.Stop();
|
||||
if (_debugShadowProcessingTime) Debug.Log($"ShadowCloneManager.MyOnPreCull({forceRenderForUiCull}) took {_stopWatch.ElapsedMilliseconds}ms");
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Game Events
|
||||
|
@ -136,7 +150,12 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
private void OnSettingsBoolChanged(string settingName, bool settingValue)
|
||||
{
|
||||
if (settingName == ShadowCullUiSettingName)
|
||||
{
|
||||
s_UseShadowToCullUi = settingValue;
|
||||
s_UiCamera.cullingMask = settingValue // make UI camera not see CVRLayers.PlayerClone
|
||||
? s_UiCamera.cullingMask | (1 << CVRLayers.PlayerClone)
|
||||
: s_UiCamera.cullingMask & ~(1 << CVRLayers.PlayerClone);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnVRModeSwitchCompleted(bool _, Camera __)
|
||||
|
@ -152,6 +171,7 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
{
|
||||
s_MainCamera = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
|
||||
s_UiCamera = s_MainCamera.transform.Find("_UICamera").GetComponent<Camera>();
|
||||
|
||||
//s_PortableCamera = PortableCamera.Instance.cameraComponent;
|
||||
}
|
||||
|
||||
|
@ -159,11 +179,11 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
|
||||
#region Static Helpers
|
||||
|
||||
internal static IShadowClone CreateShadowClone(Renderer renderer)
|
||||
internal static IShadowClone CreateShadowClone(Renderer renderer, FPRExclusion exclusion)
|
||||
{
|
||||
return renderer switch
|
||||
{
|
||||
SkinnedMeshRenderer skinnedMeshRenderer => new SkinnedShadowClone(skinnedMeshRenderer),
|
||||
SkinnedMeshRenderer skinnedMeshRenderer => new SkinnedShadowClone(skinnedMeshRenderer, exclusion),
|
||||
MeshRenderer meshRenderer => new MeshShadowClone(meshRenderer),
|
||||
_ => null
|
||||
};
|
||||
|
@ -175,6 +195,14 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
shadowClone.transform.SetParent(meshRenderer.transform, false);
|
||||
shadowClone.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
|
||||
shadowClone.transform.localScale = Vector3.one;
|
||||
|
||||
if (s_DebugShowShadow && s_DebugShowInFront)
|
||||
{
|
||||
float scale = PlayerSetup.Instance.GetPlaySpaceScale();
|
||||
Transform playerTransform = PlayerSetup.Instance.transform;
|
||||
shadowClone.transform.position += playerTransform.forward * scale * 1f;
|
||||
shadowClone.transform.rotation = Quaternion.AngleAxis(180f, playerTransform.up) * shadowClone.transform.rotation;
|
||||
}
|
||||
|
||||
MeshRenderer newMesh = shadowClone.AddComponent<MeshRenderer>();
|
||||
MeshFilter newMeshFilter = shadowClone.AddComponent<MeshFilter>();
|
||||
|
@ -188,6 +216,9 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
newMeshFilter.sharedMesh = meshRenderer.sharedMesh;
|
||||
newMesh.sharedMaterials = meshRenderer.sharedMaterials;
|
||||
|
||||
// copy probe anchor
|
||||
newMesh.probeAnchor = meshRenderer.probeAnchor;
|
||||
|
||||
return (newMesh, newMeshFilter);
|
||||
}
|
||||
|
||||
|
@ -209,6 +240,9 @@ public class ShadowCloneManager : MonoBehaviour
|
|||
// copy mesh and materials
|
||||
newMeshFilter.sharedMesh = meshRenderer.GetComponent<MeshFilter>().sharedMesh;
|
||||
newMesh.sharedMaterials = meshRenderer.sharedMaterials;
|
||||
|
||||
// copy probe anchor
|
||||
newMesh.probeAnchor = meshRenderer.probeAnchor;
|
||||
|
||||
return (newMesh, newMeshFilter);
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ public static class ShadowCloneHelper
|
|||
return;
|
||||
}
|
||||
|
||||
ShadowCloneMod.Logger.Msg($"Found {renderers.Length} renderers. Processing...");
|
||||
|
||||
// create shadow clones
|
||||
ProcessRenderers(renderers, avatar.transform, headBone);
|
||||
}
|
||||
|
@ -48,6 +50,7 @@ public static class ShadowCloneHelper
|
|||
Stopwatch sw = Stopwatch.StartNew();
|
||||
|
||||
IReadOnlyDictionary<Transform, FPRExclusion> exclusions = CollectTransformToExclusionMap(root, headBone);
|
||||
var exclusion = headBone.gameObject.GetComponent<FPRExclusion>();
|
||||
|
||||
// log current time
|
||||
ShadowCloneMod.Logger.Msg($"CollectTransformToExclusionMap in {sw.ElapsedMilliseconds}ms");
|
||||
|
@ -58,12 +61,12 @@ public static class ShadowCloneHelper
|
|||
|
||||
if (ModSettings.EntryUseShadowClone.Value)
|
||||
{
|
||||
IShadowClone clone = ShadowCloneManager.CreateShadowClone(renderer);
|
||||
IShadowClone clone = ShadowCloneManager.CreateShadowClone(renderer, exclusion);
|
||||
if (clone != null) ShadowCloneManager.Instance.AddShadowClone(clone);
|
||||
}
|
||||
|
||||
ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions);
|
||||
if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider);
|
||||
// ITransformHider hider = TransformHiderManager.CreateTransformHider(renderer, exclusions);
|
||||
// if (hider != null) TransformHiderManager.Instance.AddTransformHider(hider);
|
||||
}
|
||||
|
||||
sw.Stop();
|
||||
|
@ -143,9 +146,9 @@ public static class ShadowCloneHelper
|
|||
// shadow clone optimizations (always MeshRenderer)
|
||||
if (isShadowClone)
|
||||
{
|
||||
renderer.receiveShadows = false;
|
||||
renderer.lightProbeUsage = LightProbeUsage.Off;
|
||||
renderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
|
||||
// renderer.receiveShadows = false;
|
||||
// renderer.lightProbeUsage = LightProbeUsage.Off;
|
||||
// renderer.reflectionProbeUsage = ReflectionProbeUsage.Off;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue