上材质,有个新gameelement在basic主题包里记得改

This commit is contained in:
2025-11-23 14:13:18 +08:00
parent 117352182b
commit bcd2c82142
24 changed files with 17258 additions and 16609 deletions

View File

@@ -10,7 +10,7 @@ Shader "Custom/ImprovedPseudoShadow" {
_ShadowSmoothness ("Shadow Smoothness", Range(0,1)) = 0.1
[Header(Lighting Mode)]
[Toggle(USE_WORLD_LIGHT)] _UseWorldLight ("Use Fixed World Light?", Float) = 0
_UseWorldLight ("Use Fixed World Light?", Range(0,1)) = 0
_FakeLightDir ("Fake Light Dir (XYZ)", Vector) = (0.5, 1, 0.5, 0) // 模拟从右上方来的光
}
@@ -24,9 +24,6 @@ Shader "Custom/ImprovedPseudoShadow" {
#pragma fragment frag
// 开启 GPU Instancing 支持
#pragma multi_compile_instancing
// 开启着色器变体以支持两种光照模式
#pragma shader_feature USE_WORLD_LIGHT
#include "UnityCG.cginc"
struct appdata {
@@ -53,6 +50,7 @@ Shader "Custom/ImprovedPseudoShadow" {
UNITY_DEFINE_INSTANCED_PROP(float4, _FakeLightDir)
UNITY_DEFINE_INSTANCED_PROP(float, _ShadowThreshold)
UNITY_DEFINE_INSTANCED_PROP(float, _ShadowSmoothness)
UNITY_DEFINE_INSTANCED_PROP(float, _UseWorldLight)
UNITY_INSTANCING_BUFFER_END(Props)
v2f vert (appdata v) {
@@ -66,23 +64,14 @@ Shader "Custom/ImprovedPseudoShadow" {
float3 normalWorld = UnityObjectToWorldNormal(v.normal);
float3 lightDir;
#ifdef USE_WORLD_LIGHT
// 改进1使用固定的世界空间伪光照方向
lightDir = normalize(UNITY_ACCESS_INSTANCED_PROP(Props, _FakeLightDir).xyz);
#else
// 原版逻辑:使用视线方向 (Headlamp)
// 注意:为了获得类似漫反射的效果,这里通常不需要取反,
// 但如果要模拟“边缘光”则算法不同。这里沿用原文档的思路:面朝相机越亮。
lightDir = normalize(WorldSpaceViewDir(v.vertex));
#endif
float useWorldLight = UNITY_ACCESS_INSTANCED_PROP(Props, _UseWorldLight);
float3 fakeDir = normalize(UNITY_ACCESS_INSTANCED_PROP(Props, _FakeLightDir).xyz);
float3 viewDir = normalize(WorldSpaceViewDir(v.vertex));
// 用lerp实现分支
lightDir = normalize(lerp(viewDir, fakeDir, useWorldLight));
// 点积计算 (-1 到 1)
float dotProduct = dot(normalWorld, lightDir);
// 将点积结果保存,在片元阶段处理颜色,或者直接在这里计算
// 保持 Vertex Lighting 的高性能
o.lightFactor = dotProduct;
return o;
}

View File

@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 7526262760779641485}
- component: {fileID: 8960768024022624885}
- component: {fileID: 6324027245704733737}
- component: {fileID: 4483402955796276491}
- component: {fileID: 3704386079632660708}
m_Layer: 0
m_Name: Capsule
m_TagString: Untagged
@@ -84,7 +84,7 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &4483402955796276491
--- !u!114 &3704386079632660708
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -93,37 +93,18 @@ MonoBehaviour:
m_GameObject: {fileID: 4776931580326963019}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b73aa7982dc9e4261b2ff45db0112d48, type: 3}
m_Script: {fileID: 11500000, guid: a187146cbde41384fbdf7abcb0129f83, type: 3}
m_Name:
m_EditorClassIdentifier:
serializationData:
SerializedFormat: 2
SerializedBytes:
SerializedFormat: 0
SerializedBytes: 29010b00000065006c0065006d0065006e00740047007500690064000000000000000000000000000000000001010d0000007300750062006d006f00640075006c0065004c006900730074002f00000000015e000000530079007300740065006d002e0043006f006c006c0065006300740069006f006e0073002e00470065006e0065007200690063002e004c00690073007400600031005b005b004900630068006e0069002e00520068007900740068006d00470061006d0065002e005300750062006d006f00640075006c00650042006100730065002c00200041007300730065006d0062006c0079002d004300530068006100720070005d005d002c0020006d00730063006f0072006c00690062000000000006000000000000000007052d010b00000065006e00610062006c00650054007900700065007300
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: elementGuid
Entry: 2
Data: 00000000000000000000000000000000
- Name: submoduleList
Entry: 7
Data: 0|System.Collections.Generic.List`1[[Ichni.RhythmGame.SubmoduleBase,
Assembly-CSharp]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name: enableTypes
Entry: 6
Data:
SerializationNodes: []
elementName:
tags: []
parentElement: {fileID: 0}
@@ -132,3 +113,8 @@ MonoBehaviour:
themeBundleName:
objectName:
isStatic: 0
shadowRenderer: {fileID: 6324027245704733737}
shadowThreshold: 0.2
shadowSmoothness: 0.5
useWorldLight: 0
fakeLightDir: {x: 0.5, y: 1, z: 0.5}

View File

@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 8326979962366963383}
- component: {fileID: 5066471978068241793}
- component: {fileID: 4412636128543054888}
- component: {fileID: 4567346259325766961}
- component: {fileID: 3289815003423494910}
m_Layer: 0
m_Name: Cube
m_TagString: Untagged
@@ -84,7 +84,7 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &4567346259325766961
--- !u!114 &3289815003423494910
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -93,7 +93,7 @@ MonoBehaviour:
m_GameObject: {fileID: 8979559337900216953}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b73aa7982dc9e4261b2ff45db0112d48, type: 3}
m_Script: {fileID: 11500000, guid: a187146cbde41384fbdf7abcb0129f83, type: 3}
m_Name:
m_EditorClassIdentifier:
serializationData:
@@ -132,3 +132,8 @@ MonoBehaviour:
themeBundleName:
objectName:
isStatic: 0
shadowRenderer: {fileID: 4412636128543054888}
shadowThreshold: 0
shadowSmoothness: 0.1
useWorldLight: 0
fakeLightDir: {x: 0.5, y: 1, z: 0.5}

View File

@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 2900861413064581388}
- component: {fileID: 2026692739104920914}
- component: {fileID: 5197224235337463214}
- component: {fileID: 8321289235289763712}
- component: {fileID: 3515272920379503278}
m_Layer: 0
m_Name: Cylinder
m_TagString: Untagged
@@ -84,7 +84,7 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &8321289235289763712
--- !u!114 &3515272920379503278
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -93,37 +93,18 @@ MonoBehaviour:
m_GameObject: {fileID: 3921473257109109097}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b73aa7982dc9e4261b2ff45db0112d48, type: 3}
m_Script: {fileID: 11500000, guid: a187146cbde41384fbdf7abcb0129f83, type: 3}
m_Name:
m_EditorClassIdentifier:
serializationData:
SerializedFormat: 2
SerializedBytes:
SerializedFormat: 0
SerializedBytes: 29010b00000065006c0065006d0065006e00740047007500690064000000000000000000000000000000000001010d0000007300750062006d006f00640075006c0065004c006900730074002f00000000015e000000530079007300740065006d002e0043006f006c006c0065006300740069006f006e0073002e00470065006e0065007200690063002e004c00690073007400600031005b005b004900630068006e0069002e00520068007900740068006d00470061006d0065002e005300750062006d006f00640075006c00650042006100730065002c00200041007300730065006d0062006c0079002d004300530068006100720070005d005d002c0020006d00730063006f0072006c00690062000000000006000000000000000007052d010b00000065006e00610062006c00650054007900700065007300
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: elementGuid
Entry: 2
Data: 00000000000000000000000000000000
- Name: submoduleList
Entry: 7
Data: 0|System.Collections.Generic.List`1[[Ichni.RhythmGame.SubmoduleBase,
Assembly-CSharp]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name: enableTypes
Entry: 6
Data:
SerializationNodes: []
elementName:
tags: []
parentElement: {fileID: 0}
@@ -132,3 +113,8 @@ MonoBehaviour:
themeBundleName:
objectName:
isStatic: 0
shadowRenderer: {fileID: 5197224235337463214}
shadowThreshold: 0.2
shadowSmoothness: 0.5
useWorldLight: 0
fakeLightDir: {x: 0.5, y: 1, z: 0.5}

View File

@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 7354592236656138398}
- component: {fileID: 6487775561638814823}
- component: {fileID: 366093218188168963}
- component: {fileID: 3744871356660366508}
- component: {fileID: 1747556452555736861}
m_Layer: 0
m_Name: Plane
m_TagString: Untagged
@@ -84,7 +84,7 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &3744871356660366508
--- !u!114 &1747556452555736861
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -93,37 +93,18 @@ MonoBehaviour:
m_GameObject: {fileID: 1806162637330541972}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b73aa7982dc9e4261b2ff45db0112d48, type: 3}
m_Script: {fileID: 11500000, guid: a187146cbde41384fbdf7abcb0129f83, type: 3}
m_Name:
m_EditorClassIdentifier:
serializationData:
SerializedFormat: 2
SerializedBytes:
SerializedFormat: 0
SerializedBytes: 29010b00000065006c0065006d0065006e00740047007500690064000000000000000000000000000000000001010d0000007300750062006d006f00640075006c0065004c006900730074002f00000000015e000000530079007300740065006d002e0043006f006c006c0065006300740069006f006e0073002e00470065006e0065007200690063002e004c00690073007400600031005b005b004900630068006e0069002e00520068007900740068006d00470061006d0065002e005300750062006d006f00640075006c00650042006100730065002c00200041007300730065006d0062006c0079002d004300530068006100720070005d005d002c0020006d00730063006f0072006c00690062000000000006000000000000000007052d010b00000065006e00610062006c00650054007900700065007300
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: elementGuid
Entry: 2
Data: 00000000000000000000000000000000
- Name: submoduleList
Entry: 7
Data: 0|System.Collections.Generic.List`1[[Ichni.RhythmGame.SubmoduleBase,
Assembly-CSharp]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name: enableTypes
Entry: 6
Data:
SerializationNodes: []
elementName:
tags: []
parentElement: {fileID: 0}
@@ -132,3 +113,8 @@ MonoBehaviour:
themeBundleName:
objectName:
isStatic: 0
shadowRenderer: {fileID: 366093218188168963}
shadowThreshold: 0.2
shadowSmoothness: 0.5
useWorldLight: 0
fakeLightDir: {x: 0.5, y: 1, z: 0.5}

View File

@@ -11,7 +11,7 @@ GameObject:
- component: {fileID: 1384644069406249078}
- component: {fileID: 7001667112651328718}
- component: {fileID: 6336689653934561026}
- component: {fileID: 8389141473485471111}
- component: {fileID: 6450138934524257130}
m_Layer: 0
m_Name: Sphere
m_TagString: Untagged
@@ -84,7 +84,7 @@ MeshRenderer:
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!114 &8389141473485471111
--- !u!114 &6450138934524257130
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
@@ -93,37 +93,18 @@ MonoBehaviour:
m_GameObject: {fileID: 4338808605130404764}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: b73aa7982dc9e4261b2ff45db0112d48, type: 3}
m_Script: {fileID: 11500000, guid: a187146cbde41384fbdf7abcb0129f83, type: 3}
m_Name:
m_EditorClassIdentifier:
serializationData:
SerializedFormat: 2
SerializedBytes:
SerializedFormat: 0
SerializedBytes: 29010b00000065006c0065006d0065006e00740047007500690064000000000000000000000000000000000001010d0000007300750062006d006f00640075006c0065004c006900730074002f00000000015e000000530079007300740065006d002e0043006f006c006c0065006300740069006f006e0073002e00470065006e0065007200690063002e004c00690073007400600031005b005b004900630068006e0069002e00520068007900740068006d00470061006d0065002e005300750062006d006f00640075006c00650042006100730065002c00200041007300730065006d0062006c0079002d004300530068006100720070005d005d002c0020006d00730063006f0072006c00690062000000000006000000000000000007052d010b00000065006e00610062006c00650054007900700065007300
ReferencedUnityObjects: []
SerializedBytesString:
Prefab: {fileID: 0}
PrefabModificationsReferencedUnityObjects: []
PrefabModifications: []
SerializationNodes:
- Name: elementGuid
Entry: 2
Data: 00000000000000000000000000000000
- Name: submoduleList
Entry: 7
Data: 0|System.Collections.Generic.List`1[[Ichni.RhythmGame.SubmoduleBase,
Assembly-CSharp]], mscorlib
- Name:
Entry: 12
Data: 0
- Name:
Entry: 13
Data:
- Name:
Entry: 8
Data:
- Name: enableTypes
Entry: 6
Data:
SerializationNodes: []
elementName:
tags: []
parentElement: {fileID: 0}
@@ -132,3 +113,8 @@ MonoBehaviour:
themeBundleName:
objectName:
isStatic: 0
shadowRenderer: {fileID: 6336689653934561026}
shadowThreshold: 0.2
shadowSmoothness: 0.5
useWorldLight: 0
fakeLightDir: {x: 0.5, y: 1, z: 0.5}

View File

@@ -0,0 +1,113 @@
using System;
using UnityEngine;
using Ichni.Editor;
using Ichni.RhythmGame;
using Ichni.RhythmGame.Beatmap;
using System.Collections.Generic;
using Beatmap;
namespace Ichni.RhythmGame
{
// 以EnvironmentObject为基底支持伪阴影shader参数刷新
public class BasicEnvironmentObject : EnvironmentObject
{
[Header("Pseudo Shadow Settings")]
public Renderer shadowRenderer; // 指向带有伪阴影shader的Renderer
[Range(-1, 1)] public float shadowThreshold = 0.2f;
[Range(0, 1)] public float shadowSmoothness = 0.5f;
public bool useWorldLight = false;
public Vector3 fakeLightDir = new Vector3(0.5f, 1, 0.5f);
public override bool haveEmissionColor => true;
public static BasicEnvironmentObject GenerateElement(string elementName, Guid id, List<string> tags,
bool isFirstGenerated, string themeBundleName, string objectName, GameElement parentElement,
bool isStatic,
float shadowThreshold, float shadowSmoothness, bool useWorldLight, Vector3 fakeLightDir)
{
BasicEnvironmentObject basicEnvObj = EnvironmentObject.GenerateElement(elementName, id, tags,
isFirstGenerated, themeBundleName, objectName, parentElement, isStatic).GetComponent<BasicEnvironmentObject>();
basicEnvObj.shadowThreshold = shadowThreshold;
basicEnvObj.shadowSmoothness = shadowSmoothness;
basicEnvObj.useWorldLight = useWorldLight;
basicEnvObj.fakeLightDir = fakeLightDir;
return basicEnvObj;
}
public override void Refresh()
{
base.Refresh();
if (shadowRenderer == null || shadowRenderer.material == null) return;
var mat = shadowRenderer.material;
mat.SetColor("_Color", colorSubmodule.currentBaseColor);
mat.SetColor("_ShadowColor", colorSubmodule.currentEmissionColor);
mat.SetFloat("_ShadowThreshold", shadowThreshold);
mat.SetFloat("_ShadowSmoothness", shadowSmoothness);
mat.SetVector("_FakeLightDir", new Vector4(fakeLightDir.x, fakeLightDir.y, fakeLightDir.z, 0));
mat.SetFloat("_UseWorldLight", useWorldLight ? 1 : 0);
}
// 可选:在属性变更时自动刷新
public override void SetUpInspector()
{
base.SetUpInspector();
IHaveInspection inspector = EditorManager.instance.uiManager.inspector;
var container = inspector.GenerateContainer("Basic Environment Object");
var shadowSettings = container.GenerateSubcontainer(3);
var i = inspector.GenerateInputField(this, shadowSettings, "Shadow Threshold (-1 to 1)", nameof(shadowThreshold));
var j = inspector.GenerateInputField(this, shadowSettings, "Shadow Smoothness (0 to 1)", nameof(shadowSmoothness));
var u = inspector.GenerateToggle(this, shadowSettings, "Use World Light", nameof(useWorldLight));
var shadowSettings2 = container.GenerateSubcontainer(1);
var w = inspector.GenerateVector3InputField(this, shadowSettings2, "Fake Light Direction", nameof(fakeLightDir));
}
public override void SaveBM()
{
base.SaveBM();
matchedBM = new BasicEnvironmentObject_BM(elementName, elementGuid, tags, parentElement.matchedBM as GameElement_BM,
themeBundleName, objectName, isStatic,
shadowThreshold, shadowSmoothness, useWorldLight, fakeLightDir);
}
}
}
namespace Beatmap
{
public class BasicEnvironmentObject_BM : EnvironmentObject_BM
{
public float shadowThreshold;
public float shadowSmoothness;
public bool useWorldLight;
public Vector3 fakeLightDir;
public BasicEnvironmentObject_BM() { }
public BasicEnvironmentObject_BM(string elementName, Guid elementGuid, List<string> tags, GameElement_BM parentElement,
string themeBundleName, string objectName, bool isStatic,
float shadowThreshold, float shadowSmoothness, bool useWorldLight, Vector3 fakeLightDir)
: base(elementName, elementGuid, tags, parentElement, themeBundleName, objectName, isStatic)
{
this.shadowThreshold = shadowThreshold;
this.shadowSmoothness = shadowSmoothness;
this.useWorldLight = useWorldLight;
this.fakeLightDir = fakeLightDir;
}
public override void ExecuteBM()
{
matchedElement = BasicEnvironmentObject.GenerateElement(elementName, elementGuid, tags, false,
themeBundleName, objectName, GetElement(attachedElementGuid), isStatic,
shadowThreshold, shadowSmoothness, useWorldLight, fakeLightDir);
}
public override GameElement DuplicateBM(GameElement parent)
{
return BasicEnvironmentObject.GenerateElement(elementName, Guid.NewGuid(), tags, false,
themeBundleName, objectName, parent, isStatic,
shadowThreshold, shadowSmoothness, useWorldLight, fakeLightDir);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a187146cbde41384fbdf7abcb0129f83
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: