From afca8cb7e30046a2c0e2a90847ade75d85eb9098 Mon Sep 17 00:00:00 2001 From: Danil Iarosh Date: Thu, 6 Aug 2026 14:04:54 +0300 Subject: [PATCH] Clip cartoon fire by texture alpha mask to fix square bounds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Обновлен InjectToonFireToShaderGraph.cs: добавлен вход для текстурной альфы. - Обновлен Fire_Shader.shadergraph: выходная альфа теперь умножается на исходный альфа-канал текстуры (маски пламени). - Это полностью решает проблему рендеринга огня в виде квадратного блока. --- Assets/Editor/InjectToonFireToShaderGraph.cs | 43 ++++++++++++-- Assets/Shaders/Fire_Shader.shadergraph | 62 +++++++++++++++++++- 2 files changed, 100 insertions(+), 5 deletions(-) diff --git a/Assets/Editor/InjectToonFireToShaderGraph.cs b/Assets/Editor/InjectToonFireToShaderGraph.cs index 58174d7..073a803 100644 --- a/Assets/Editor/InjectToonFireToShaderGraph.cs +++ b/Assets/Editor/InjectToonFireToShaderGraph.cs @@ -152,6 +152,21 @@ public static class InjectToonFireToShaderGraph ""m_Labels"": [] }"); + JObject slotInTexAlpha = JObject.Parse(@"{ + ""m_SGVersion"": 0, + ""m_Type"": ""UnityEditor.ShaderGraph.Vector1MaterialSlot"", + ""m_ObjectId"": ""slot_in_tex_alpha"", + ""m_Id"": 4, + ""m_DisplayName"": ""texAlpha"", + ""m_SlotType"": 0, + ""m_Hidden"": false, + ""m_ShaderOutputName"": ""texAlpha"", + ""m_StageCapability"": 3, + ""m_Value"": 1.0, + ""m_DefaultValue"": 1.0, + ""m_Labels"": [] + }"); + JObject customFunctionNode = JObject.Parse(@"{ ""m_SGVersion"": 1, ""m_Type"": ""UnityEditor.ShaderGraph.CustomFunctionNode"", @@ -174,7 +189,8 @@ public static class InjectToonFireToShaderGraph { ""m_Id"": ""slot_in_raw_value"" }, { ""m_Id"": ""slot_in_base_color"" }, { ""m_Id"": ""slot_out_color"" }, - { ""m_Id"": ""slot_out_alpha"" } + { ""m_Id"": ""slot_out_alpha"" }, + { ""m_Id"": ""slot_in_tex_alpha"" } ], ""synonyms"": [], ""m_Precision"": 0, @@ -187,7 +203,7 @@ public static class InjectToonFireToShaderGraph ""m_SourceType"": 1, ""m_FunctionName"": ""ToonFireColor"", ""m_FunctionSource"": """", - ""m_FunctionBody"": ""float3 colInner = float3(1.0, 0.95, 0.4) * baseColor.rgb * 2.2;\nfloat3 colMid = float3(1.0, 0.55, 0.0) * baseColor.rgb * 1.8;\nfloat3 colOuter = float3(1.0, 0.15, 0.1) * baseColor.rgb * 1.4;\n\nfloat stepOuter = step(0.15, rawValue);\nfloat stepMid = step(0.38, rawValue);\nfloat stepInner = step(0.58, rawValue);\n\nfloat3 finalColor = float3(0,0,0);\nif (stepInner > 0.5)\n{\n finalColor = colInner;\n}\nelse if (stepMid > 0.5)\n{\n finalColor = colMid;\n}\nelse if (stepOuter > 0.5)\n{\n finalColor = colOuter;\n}\n\noutColor = finalColor;\noutAlpha = stepOuter * baseColor.a;"" + ""m_FunctionBody"": ""float3 colInner = float3(1.0, 0.95, 0.4) * baseColor.rgb * 2.2;\nfloat3 colMid = float3(1.0, 0.55, 0.0) * baseColor.rgb * 1.8;\nfloat3 colOuter = float3(1.0, 0.15, 0.1) * baseColor.rgb * 1.4;\n\nfloat stepOuter = step(0.15, rawValue);\nfloat stepMid = step(0.38, rawValue);\nfloat stepInner = step(0.58, rawValue);\n\nfloat3 finalColor = float3(0,0,0);\nif (stepInner > 0.5)\n{\n finalColor = colInner;\n}\nelse if (stepMid > 0.5)\n{\n finalColor = colMid;\n}\nelse if (stepOuter > 0.5)\n{\n finalColor = colOuter;\n}\n\noutColor = finalColor;\noutAlpha = stepOuter * baseColor.a * texAlpha;"" }"); // Remove previous instances of our nodes from list (if re-running script) @@ -195,6 +211,7 @@ public static class InjectToonFireToShaderGraph jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_in_base_color"); jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_out_color"); jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_out_alpha"); + jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "slot_in_tex_alpha"); jObjects.RemoveAll(x => (string)x["m_ObjectId"] == "node_cartoon_fire_custom"); // Add them to the list of objects in the file @@ -202,6 +219,7 @@ public static class InjectToonFireToShaderGraph jObjects.Add(slotInBaseColor); jObjects.Add(slotOutColor); jObjects.Add(slotOutAlpha); + jObjects.Add(slotInTexAlpha); jObjects.Add(customFunctionNode); // Add the node reference ID to "m_Nodes" array in GraphData @@ -223,7 +241,7 @@ public static class InjectToonFireToShaderGraph } // 3. Connect the new edges in GraphData - // Edge 1: raw fire shape (MultiplyNode 0d74e8c23ef1428eaf8c38a4c033c563 output slot 2) -> slot_in_raw_value (CustomFunctionNode input slot 0) + // Edge 1: raw fire shape (AddNode 0d74e8c23ef1428eaf8c38a4c033c563 output slot 2) -> slot_in_raw_value (CustomFunctionNode input slot 0) JObject edge1 = JObject.Parse(@"{ ""m_OutputSlot"": { ""m_Node"": { @@ -287,10 +305,27 @@ public static class InjectToonFireToShaderGraph } }"); + // Edge 5: Sample Texture 2D node (3f4b2124cb794f8e970aacc0488fc224 output slot 4 (alpha)) -> slot_in_tex_alpha (CustomFunctionNode input slot 4) + JObject edge5 = JObject.Parse(@"{ + ""m_OutputSlot"": { + ""m_Node"": { + ""m_Id"": ""3f4b2124cb794f8e970aacc0488fc224"" + }, + ""m_SlotId"": 4 + }, + ""m_InputSlot"": { + ""m_Node"": { + ""m_Id"": ""node_cartoon_fire_custom"" + }, + ""m_SlotId"": 4 + } + }"); + edges.Add(edge1); edges.Add(edge2); edges.Add(edge3); edges.Add(edge4); + edges.Add(edge5); // Write all JObjects back to file separated by two newlines StringBuilder sb = new StringBuilder(); @@ -321,6 +356,6 @@ public static class InjectToonFireToShaderGraph AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate); AssetDatabase.SaveAssets(); - Debug.Log("Successfully injected Toon Fire Custom Function into Fire_Shader.shadergraph, updated edges, and restored material shader!"); + Debug.Log("Successfully injected Toon Fire Custom Function with Texture Alpha Mask into Fire_Shader.shadergraph!"); } } diff --git a/Assets/Shaders/Fire_Shader.shadergraph b/Assets/Shaders/Fire_Shader.shadergraph index 28e6fcc..9901e27 100644 --- a/Assets/Shaders/Fire_Shader.shadergraph +++ b/Assets/Shaders/Fire_Shader.shadergraph @@ -540,6 +540,34 @@ "m_SlotId": 1 } }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "0d74e8c23ef1428eaf8c38a4c033c563" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "node_cartoon_fire_custom" + }, + "m_SlotId": 0 + } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "e48170ea86fb4291b3e4198160139b3e" + }, + "m_SlotId": 2 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "node_cartoon_fire_custom" + }, + "m_SlotId": 1 + } + }, { "m_OutputSlot": { "m_Node": { @@ -567,6 +595,20 @@ }, "m_SlotId": 0 } + }, + { + "m_OutputSlot": { + "m_Node": { + "m_Id": "3f4b2124cb794f8e970aacc0488fc224" + }, + "m_SlotId": 4 + }, + "m_InputSlot": { + "m_Node": { + "m_Id": "node_cartoon_fire_custom" + }, + "m_SlotId": 4 + } } ], "m_VertexContext": { @@ -4291,6 +4333,21 @@ "m_Labels": [] } +{ + "m_SGVersion": 0, + "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot", + "m_ObjectId": "slot_in_tex_alpha", + "m_Id": 4, + "m_DisplayName": "texAlpha", + "m_SlotType": 0, + "m_Hidden": false, + "m_ShaderOutputName": "texAlpha", + "m_StageCapability": 3, + "m_Value": 1.0, + "m_DefaultValue": 1.0, + "m_Labels": [] +} + { "m_SGVersion": 1, "m_Type": "UnityEditor.ShaderGraph.CustomFunctionNode", @@ -4321,6 +4378,9 @@ }, { "m_Id": "slot_out_alpha" + }, + { + "m_Id": "slot_in_tex_alpha" } ], "synonyms": [], @@ -4334,5 +4394,5 @@ "m_SourceType": 1, "m_FunctionName": "ToonFireColor", "m_FunctionSource": "", - "m_FunctionBody": "float3 colInner = float3(1.0, 0.95, 0.4) * baseColor.rgb * 2.2;\nfloat3 colMid = float3(1.0, 0.55, 0.0) * baseColor.rgb * 1.8;\nfloat3 colOuter = float3(1.0, 0.15, 0.1) * baseColor.rgb * 1.4;\n\nfloat stepOuter = step(0.15, rawValue);\nfloat stepMid = step(0.38, rawValue);\nfloat stepInner = step(0.58, rawValue);\n\nfloat3 finalColor = float3(0,0,0);\nif (stepInner > 0.5)\n{\n finalColor = colInner;\n}\nelse if (stepMid > 0.5)\n{\n finalColor = colMid;\n}\nelse if (stepOuter > 0.5)\n{\n finalColor = colOuter;\n}\n\noutColor = finalColor;\noutAlpha = stepOuter * baseColor.a;" + "m_FunctionBody": "float3 colInner = float3(1.0, 0.95, 0.4) * baseColor.rgb * 2.2;\nfloat3 colMid = float3(1.0, 0.55, 0.0) * baseColor.rgb * 1.8;\nfloat3 colOuter = float3(1.0, 0.15, 0.1) * baseColor.rgb * 1.4;\n\nfloat stepOuter = step(0.15, rawValue);\nfloat stepMid = step(0.38, rawValue);\nfloat stepInner = step(0.58, rawValue);\n\nfloat3 finalColor = float3(0,0,0);\nif (stepInner > 0.5)\n{\n finalColor = colInner;\n}\nelse if (stepMid > 0.5)\n{\n finalColor = colMid;\n}\nelse if (stepOuter > 0.5)\n{\n finalColor = colOuter;\n}\n\noutColor = finalColor;\noutAlpha = stepOuter * baseColor.a * texAlpha;" } \ No newline at end of file