user 010beaea75 Chore: NiloToonURP 업데이트 및 배경 썸네일 갱신
- NiloToonURP 외부 에셋 업데이트
- 배경 씬 썸네일 16:9 해상도로 갱신
- 렌더 파이프라인 설정 업데이트
- 외부 셰이더 그래프 업데이트 (LEDScreen, PIDI Planar Reflections)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 01:28:02 +09:00

1861 lines
101 KiB
C#

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEditor;
using UnityEditor.Rendering;
using UnityEditor.Rendering.Universal;
using System.Linq;
using NiloToon.NiloToonURP;
using UnityEngine.Rendering;
using Object = UnityEngine.Object;
namespace NiloToon.NiloToonURP
{
public static class NiloToonMaterialConvertor
{
private static readonly int SurfaceTypePreset = Shader.PropertyToID("_SurfaceTypePreset");
private static readonly int RenderOutline = Shader.PropertyToID("_RenderOutline");
private static readonly int IsSkin = Shader.PropertyToID("_IsSkin");
private static readonly int IsFace = Shader.PropertyToID("_IsFace");
private static readonly int PerMaterialEnableDepthTextureRimLightAndShadow =
Shader.PropertyToID("_PerMaterialEnableDepthTextureRimLightAndShadow");
public enum NiloToonSurfaceTypePreset
{
Opaque_Outline = 0,
Opaque = 1,
Transparent_ZWrite_Outline = 2,
Transparent = 3,
Transparent_ZWrite = 4,
CutoutOpaque_Outline = 5,
CutoutOpaque = 6,
CutoutTransparent_ZWrite_Outline = 7,
CutoutTransparent = 8,
CutoutTransparent_ZWrite = 9,
TransparentQueueTransparent_ZWrite_Outline = 10,
TransparentQueueTransparent_ZWrite = 11,
CutoutTransparentQueueTransparent_ZWrite_Outline = 12,
CutoutTransparentQueueTransparent_ZWrite = 13,
}
enum RenderQueueGroup
{
Opaque,
Cutout,
Transparent
}
public static void AutoConvertMaterialsToNiloToon(List<Material> allTargetMaterials)
{
Shader niloToonCharShader = Shader.Find("Universal Render Pipeline/NiloToon/NiloToon_Character");
Shader URPComplexLitShader = Shader.Find("Universal Render Pipeline/Complex Lit");
Shader URPLitShader = Shader.Find("Universal Render Pipeline/Lit");
Shader URPSimpleLitShader = Shader.Find("Universal Render Pipeline/Simple Lit");
Shader URPUnlitShader = Shader.Find("Universal Render Pipeline/Unlit");
Shader UniGLTFUnlitShader = Shader.Find("UniGLTF/UniUnlit");
Shader VRMBRPMToon00Shader = Shader.Find("VRM/MToon"); // has it's own shader properties
Shader VRMBRPMToon10Shader =
Shader.Find("VRM10/MToon10"); // share the exact same shader properties with URP version
Shader VRMURPMToon10Shader =
Shader.Find(
"VRM10/Universal Render Pipeline/MToon10"); // share the exact same shader properties with BRP version
Shader builtinRPStandardShader = Shader.Find("Standard");
// clone all original materials to a new List with the same order, for later reference, since we will edit the real material later
List<Material> allOriginalMaterialsClone = new List<Material>(allTargetMaterials);
for (int i = 0; i < allTargetMaterials.Count; i++)
{
allOriginalMaterialsClone[i] = Object.Instantiate(allTargetMaterials[i]);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Find the correct NiloToonSurfaceTypePreset index of each original material
// (matching the index of NiloToonCharacter_SurfaceType_LWGUI_ShaderPropertyPreset.asset)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
NiloToonSurfaceTypePreset[] niloToonSurfaceTypePresetIDArray =
new NiloToonSurfaceTypePreset[allTargetMaterials.Count];
for (int i = 0; i < niloToonSurfaceTypePresetIDArray.Length; i++)
{
niloToonSurfaceTypePresetIDArray[i] =
NiloToonSurfaceTypePreset
.Opaque_Outline; // init as Opaque+Outline(index is 0), it is the default preset
}
for (int i = 0; i < allOriginalMaterialsClone.Count; i++)
{
Material matOriginal = allOriginalMaterialsClone[i];
if (matOriginal.shader == UniGLTFUnlitShader)
{
//public enum UniUnlitRenderMode
//{
// Opaque = 0,
// Cutout = 1,
// Transparent = 2,
//}
int _BlendMode = (int)matOriginal.GetFloat("_BlendMode");
switch (_BlendMode)
{
case 0:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline;
break;
case 1:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
break;
case 2:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent;
break;
default:
throw new NotImplementedException(
"seems that VRM shader(UniGLTF/UniUnlit) added a new UniUnlitRenderMode that is not handled by NiloToon yet, contact NiloToon's developer to support this.");
}
}
if (matOriginal.shader == URPComplexLitShader ||
matOriginal.shader == URPLitShader ||
matOriginal.shader == URPSimpleLitShader ||
matOriginal.shader == URPUnlitShader)
{
//public enum SurfaceType
//{
// Opaque = 0,
// Transparent = 1,
//}
int _Surface = (int)matOriginal.GetFloat("_Surface");
bool _AlphaClip = matOriginal.GetFloat("_AlphaClip") > 0.5f;
switch (_Surface)
{
case 0:
niloToonSurfaceTypePresetIDArray[i] = _AlphaClip
? NiloToonSurfaceTypePreset.CutoutOpaque_Outline
: NiloToonSurfaceTypePreset.Opaque_Outline;
break;
case 1:
niloToonSurfaceTypePresetIDArray[i] = _AlphaClip
? NiloToonSurfaceTypePreset.CutoutTransparent
: NiloToonSurfaceTypePreset.Transparent;
break;
default:
throw new NotImplementedException(
"seems that URP's Lit,Complex Lit,Simple Lit or Unlit added a new SurfaceType that is not handled by NiloToon yet, contact NiloToon's developer to support this.");
}
}
if (matOriginal.shader == builtinRPStandardShader)
{
// Opaque = 0,
// Cutout = 1,
// Fade = 2, (ZWrite is off)
// Transparent = 3, (ZWrite is on)
int _Mode = (int)matOriginal.GetFloat("_Mode");
switch (_Mode)
{
case 0:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline;
break;
case 1:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
break;
case 2:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent;
break;
case 3:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline;
break;
default:
throw new NotImplementedException(
"seems that BRP Standard shader added a new Mode that is not handled by NiloToon yet, contact NiloToon's developer to support this.");
}
}
// for any VRM00 migrated material's shader
if (matOriginal.shader == VRMBRPMToon00Shader)
{
//public enum RenderMode
//{
// Opaque = 0,
// Cutout = 1,
// Transparent = 2,
// TransparentWithZWrite = 3,
//}
int _BlendMode =
(int)matOriginal
.GetFloat(
"_BlendMode"); // '_BlendMode' in vrm00's MToon shader is the 'Rendering Type' in UI, 'RenderMode' in C#
// vrm00 MToon's _OutlineWidthMode
//public enum OutlineWidthMode
//{
// None = 0,
// WorldCoordinates = 1,
// ScreenCoordinates = 2,
//}
int _OutlineWidthMode = (int)matOriginal.GetFloat("_OutlineWidthMode");
bool hasOutline = _OutlineWidthMode > 0;
switch (_BlendMode)
{
case 0:
niloToonSurfaceTypePresetIDArray[i] = hasOutline
? NiloToonSurfaceTypePreset.Opaque_Outline
: NiloToonSurfaceTypePreset.Opaque;
break;
case 1:
niloToonSurfaceTypePresetIDArray[i] = hasOutline
? NiloToonSurfaceTypePreset.CutoutOpaque_Outline
: NiloToonSurfaceTypePreset.CutoutOpaque;
break;
case 2:
niloToonSurfaceTypePresetIDArray[i] =
NiloToonSurfaceTypePreset.Transparent; // 'Transparent' don't have outline in NiloToon
break;
case 3:
niloToonSurfaceTypePresetIDArray[i] = hasOutline
? NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline
: NiloToonSurfaceTypePreset.Transparent_ZWrite;
break;
default:
throw new NotImplementedException(
"seems that VRM MToon shader(VRM/MToon) added a new Rendering Type that is not handled by NiloToon yet, contact NiloToon's developer to support this.");
}
}
// for any VRM10 migrated material's shader
if (matOriginal.shader == VRMBRPMToon10Shader ||
matOriginal.shader == VRMURPMToon10Shader)
{
// all VRM1 shader(BRP/URP) share the same properties{}!
//public enum MToon10AlphaMode
//{
// Opaque = 0,
// Cutout = 1,
// Transparent = 2,
//}
int _AlphaMode = (int)matOriginal.GetFloat("_AlphaMode");
switch (_AlphaMode)
{
case 0:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline;
break;
case 1:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
break;
case 2:
bool _TransparentWithZWrite = matOriginal.GetFloat("_TransparentWithZWrite") > 0.5f;
niloToonSurfaceTypePresetIDArray[i] = _TransparentWithZWrite
? NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline
: NiloToonSurfaceTypePreset.Transparent;
break;
default:
throw new NotImplementedException(
"seems that VRM1 MToon shader(VRM10's MToon10) added a new MToon10AlphaMode that is not handled by NiloToon yet, contact NiloToon's developer to support this.");
}
}
if (matOriginal.shader == niloToonCharShader)
{
// NiloToon->NiloToon, so nothing to do, just pass SurfaceType without edit
niloToonSurfaceTypePresetIDArray[i] =
(NiloToonSurfaceTypePreset)(int)matOriginal.GetFloat("_SurfaceTypePreset");
}
if (matOriginal.shader.name.Contains("lilToon"))
{
/*
// [Rendering Mode]
// Opaque = 0
// Cutout = 1
// Transparent = 2
// Refraction
// Fur
// FurCutout
// Gem
int _RenderingMode = ... there is no rendering mode in material info. _TransparentMode is not what we are looking for
switch (_RenderingMode)
{
case 0:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline;
break;
case 1:
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
break;
case 2:
bool _ZWrite = matOriginal.GetFloat("_ZWrite") > 0.5f;
niloToonSurfaceTypePresetIDArray[i] = _ZWrite ? NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline : NiloToonSurfaceTypePreset.Transparent;
break;
default:
// it is not support, use a generic preset
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
break;
}
*/
// so we need some complex logic to find out the correct NiloToonSurfaceType,
// copy from lilInspector.cs -> CheckShaderType(Material material)
bool isCutout = matOriginal.shader.name.Contains("Cutout");
bool isTransparent = matOriginal.shader.name.Contains("Transparent") ||
matOriginal.shader.name.Contains("Overlay");
bool isOutl = matOriginal.shader.name.Contains("Outline");
bool isTransparentQueue = matOriginal.renderQueue > 2500;
bool isZWrite = matOriginal.GetFloat("_ZWrite") > 0.5f;
// if ZWrite is off, we treat the material as transparent
if (!isCutout && !isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque; // 1
else if (!isCutout && !isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 2
else if (!isCutout && !isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite; // 3
else if (!isCutout && !isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 4
else if (!isCutout && !isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Opaque_Outline; // 5
else if (!isCutout && !isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 6
else if (!isCutout && !isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline; // 7
else if (!isCutout && !isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 8
else if (!isCutout && isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite; // 9
else if (!isCutout && isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 10
else if (!isCutout && isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite; // 11
else if (!isCutout && isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 12
else if (!isCutout && isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline; // 13
else if (!isCutout && isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 14
else if (!isCutout && isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite; // 15
else if (!isCutout && isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.Transparent; // 16
else if ( isCutout && !isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque; // 17
else if ( isCutout && !isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 18
else if ( isCutout && !isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque; // 19
else if ( isCutout && !isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 20
else if ( isCutout && !isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline; // 21
else if ( isCutout && !isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 22
else if ( isCutout && !isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline; // 23
else if ( isCutout && !isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 24
else if ( isCutout && isTransparent && !isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite; // 25
else if ( isCutout && isTransparent && !isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 26
else if ( isCutout && isTransparent && !isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite; // 27
else if ( isCutout && isTransparent && !isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 28
else if ( isCutout && isTransparent && isOutl && !isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite_Outline; // 29
else if ( isCutout && isTransparent && isOutl && !isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 30
else if ( isCutout && isTransparent && isOutl && isTransparentQueue && isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline; //31
else if ( isCutout && isTransparent && isOutl && isTransparentQueue && !isZWrite) niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutTransparent; // 32
}
// since there are many model's texture that alpha is not used for transparency(e.g. store special data that is not alpha),
// we will not use texture's alpha to decide if Cutout should be enabled or not anymore
/*
// [feature removed]
// If the NiloToonSurfaceTypePreset is the default one that ignores alpha, use _BaseMap's alpha to determine if cutout is needed
// this step is useful when there is no information about what NiloToonSurfaceTypePreset should be,
// the only information we have is the _BaseMap's alpha, the alpha will hint us what NiloToonSurfaceTypePreset is suitable
if (matOriginal.shader == URPLitShader && niloToonSurfaceTypePresetIDArray[i] == NiloToonSurfaceTypePreset.Opaque_Outline)
{
Texture2D baseMapTexture;
// try to get _MainTex first from any BRP material
baseMapTexture = matOriginal.mainTexture as Texture2D;
// if we can't get one, try to get _BaseMap from any URP material
if (!baseMapTexture)
{
if(matOriginal.HasProperty("_BaseMap"))
{
baseMapTexture = matOriginal.GetTexture("_BaseMap") as Texture2D;
}
}
// if the material has a _MainTex or _BaseMap
if (baseMapTexture != null)
{
// and if texture has alpha value
if(TextureHasAlpha(baseMapTexture))
{
// convert Opaque_Outline -> CutoutOpaque_Outline
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque_Outline;
}
}
}
*/
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the material is not a URP shader, it won't have _BaseMap property,
// so it should be using a built-in RP only shader currently(e.g. Built-in RP vrm/mtoon or any error shader material),
// we will first switch the material's shader to built-in RP's "Standard" shader for auto material convertion by URP in the next section
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
foreach (var mat in allTargetMaterials)
{
// skip for vrm mtoon, since we will not rely on URP's material upgrader, and handle everything by ourself
if (mat.shader == VRMBRPMToon00Shader ||
mat.shader == VRMBRPMToon10Shader ||
mat.shader == VRMURPMToon10Shader)
continue;
// Ensure not a variant
BreakMaterialVariant(mat);
// support these special shaders from URP's package:
// - PhysicalMaterial3DsMax
// - ArnoldStandardSurface
if (mat.HasProperty("_BASE_COLOR_MAP"))
{
Texture basmeap = mat.GetTexture("_BASE_COLOR_MAP");
if (basmeap)
{
mat.shader = builtinRPStandardShader;
mat.mainTexture = basmeap;
}
}
if (!mat.HasProperty("_BaseMap") || !mat.GetTexture("_BaseMap"))
{
// switch material to use built-in RP's standard shader first, so that it is prepared for URP's material upgrade
mat.shader = builtinRPStandardShader;
EditorUtility.SetDirty(mat);
}
}
AssetDatabase.SaveAssets();
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the material is not a URP's shader, we have converted it to built-in RP's "Standard"
// we then simulate a click to "Edit/Rendering/Materials/Convert Selected Built-in Materials to URP",
// which means calling to UniversalRenderPipelineMaterialUpgrader.UpgradeSelectedMaterials().
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
List<MaterialUpgrader> upgraders = new List<MaterialUpgrader>();
GetUpgraders(ref upgraders);
HashSet<string> shaderNamesToIgnore = new HashSet<string>();
GetShaderNamesToIgnore(ref shaderNamesToIgnore);
// set selection to materials that we want to upgrade
UnityEngine.Object[] targets = new UnityEngine.Object[allTargetMaterials.Count];
targets = allTargetMaterials.ToArray();
var originalSelectionObjects = Selection.objects;
Selection.objects = targets;
// call SRP's UpgradeSelection()
MaterialUpgrader.UpgradeSelection(upgraders, shaderNamesToIgnore, "Upgrade to UniversalRP Materials",
MaterialUpgrader.UpgradeFlags.LogMessageWhenNoUpgraderFound);
// restore Selection
Selection.objects = originalSelectionObjects;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// switch material to "NiloToon_Character" shader,
// and edit any important properties
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
for (int i = 0; i < allTargetMaterials.Count; i++)
{
Material mat = allTargetMaterials[i];
Material originalMatClone = allOriginalMaterialsClone[i];
NiloToonSurfaceTypePreset nilotoonSurfaceTypePresetID = niloToonSurfaceTypePresetIDArray[i];
// Ensure not a variant
BreakMaterialVariant(mat);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if material is URP package's material (e.g. Lit.mat),
// skip editing the material,
// else we will be editing URP's default material that is inside URP package
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
{
string path = UnityEditor.AssetDatabase.GetAssetPath(mat);
if (path.StartsWith("Packages/com.unity.render-pipelines.universal"))
{
continue;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if material is Particle or Sprite shader, skip editing it
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (mat.shader.name.Contains("Particle") ||
mat.shader.name.Contains("Sprite"))
{
continue;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the current shader is not any NiloToon shader
// switch this shader to NiloToon_Character shader
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (!mat.shader.name.Contains("NiloToon"))
{
int originalRenderQueue = mat.renderQueue;
// this line will reset render queue to shader's default!
mat.shader = niloToonCharShader;
// so we restore the render queue
mat.renderQueue = originalRenderQueue;
EditorUtility.SetDirty(mat);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if the current shader is NiloToon_Character shader (not NiloToon's sticker/environment shaders)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (mat.shader == niloToonCharShader)
{
string[] IsFaceTargetNames = { "face", "facial", "express", "kao", "head" };
string[]
IsFaceBanNames =
{
"Kaoru", "Surface", "phone", "headset"
}; // avoid "Kaoru" treated as face due to "kao", avoid "headphone" or "headset" treated as head
// TODO: should we include "facial" as eye target name?
string[] IsEyeTargetNames =
{
"eye", "iris", "pupil", "lash", "brow", "mayu", "hitomi", "shirome", "matsuge", "matuge",
"hairaito",
"doukou", "guruguru", ".me", "Canthus", "sclera", "cornea", "limbus"
};
string[] IsEyeBanNames = { "brown" }; // avoid "brown" treated as eye due to "brow"
string[] IsMouthTargetNames = { "mouth", "oral", "tongue", "kuchi", ".ha", "kounai", "shita" };
string[] IsMouthBanNames = { ".hada" };
string[] IsTeethTargetNames = { "teeth", "tooth" };
string[] IsTeethBanNames = { };
string[]
IsSkinTargetNames =
{
"skin", "hada", "body", "karada"
}; // material with a name "body / karada" is not always skin, but we still put "body" into this array,
// since a skin material without enabling "IsSkin" is far worse than a non-skin material enabled "IsSkin" wrongly.
string[] IsSkinBanNames = { };
string[] IsNoOutlineTargetNames = { "noline", "nooutline", "no_line", "no_outline" };
string[] IsNoOutlineBanNames = { };
//----------------------------------------------------
// FaceFinal = face + (eye + mouth + teeth)
string[] IsFaceFinalTargetNames = new string[] { };
IsFaceFinalTargetNames = IsFaceFinalTargetNames.Concat(IsFaceTargetNames).ToArray();
IsFaceFinalTargetNames = IsFaceFinalTargetNames.Concat(IsEyeTargetNames).ToArray();
IsFaceFinalTargetNames = IsFaceFinalTargetNames.Concat(IsMouthTargetNames).ToArray();
IsFaceFinalTargetNames = IsFaceFinalTargetNames.Concat(IsTeethTargetNames).ToArray();
string[] IsFaceExactTargetNames = new string[]{ "me", "ha"};
string[] IsFaceFinalBanNames = new string[] { };
IsFaceFinalBanNames = IsFaceFinalBanNames.Concat(IsFaceBanNames).ToArray();
IsFaceFinalBanNames = IsFaceFinalBanNames.Concat(IsEyeBanNames).ToArray();
IsFaceFinalBanNames = IsFaceFinalBanNames.Concat(IsMouthBanNames).ToArray();
IsFaceFinalBanNames = IsFaceFinalBanNames.Concat(IsTeethBanNames).ToArray();
//----------------------------------------------------
// SkinFinal = skin + (face + mouth)
string[] IsSkinFinalTargetNames = new string[] { };
IsSkinFinalTargetNames = IsSkinFinalTargetNames.Concat(IsSkinTargetNames).ToArray();
IsSkinFinalTargetNames = IsSkinFinalTargetNames.Concat(IsFaceTargetNames).ToArray();
IsSkinFinalTargetNames = IsSkinFinalTargetNames.Concat(IsMouthTargetNames).ToArray();
string[] IsSkinFinalBanNames = new string[] { };
IsSkinFinalBanNames = IsSkinFinalBanNames.Concat(IsSkinBanNames).ToArray();
IsSkinFinalBanNames = IsSkinFinalBanNames.Concat(IsFaceBanNames).ToArray();
//IsSkinFinalBanNames = IsSkinFinalBanNames.Concat(IsMouthBanNames).ToArray();
//----------------------------------------------------
List<string> IsNoOutlineFinalTargetNames =
IsFaceFinalTargetNames.Where(x => x != "face" && x != "head").ToList();
IsNoOutlineFinalTargetNames.Concat(IsNoOutlineTargetNames);
List<string> IsNoOutlineExactTargetNames = new List<string>();
IsNoOutlineExactTargetNames.Concat(IsFaceExactTargetNames);
List<string> IsNoOutlineFinalBanNames = IsFaceFinalBanNames.ToList();
IsNoOutlineFinalBanNames.Concat(IsNoOutlineBanNames);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto disable classic outline if material name contain face/outline related keywords that should not render classic outline
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool isNoOutline = false;
foreach (var keyword in IsNoOutlineFinalTargetNames)
{
isNoOutline |= NiloToonUtils.NameHasKeyword(mat.name, keyword);
}
foreach (var keyword in IsNoOutlineExactTargetNames)
{
isNoOutline |= NiloToonUtils.NameEqualsKeywordIgnoreCase(mat.name, keyword);
}
foreach (var keyword in IsNoOutlineFinalBanNames)
{
isNoOutline &= !NiloToonUtils.NameHasKeyword(mat.name, keyword);
}
if (isNoOutline)
{
switch (nilotoonSurfaceTypePresetID)
{
case NiloToonSurfaceTypePreset.Opaque_Outline:
nilotoonSurfaceTypePresetID = NiloToonSurfaceTypePreset.Opaque;
break;
case NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline:
nilotoonSurfaceTypePresetID = NiloToonSurfaceTypePreset.Transparent_ZWrite;
break;
case NiloToonSurfaceTypePreset.CutoutOpaque_Outline:
nilotoonSurfaceTypePresetID = NiloToonSurfaceTypePreset.CutoutOpaque;
break;
case NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite_Outline:
nilotoonSurfaceTypePresetID = NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite;
break;
case NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite_Outline:
nilotoonSurfaceTypePresetID =
NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite;
break;
case NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline:
nilotoonSurfaceTypePresetID = NiloToonSurfaceTypePreset
.CutoutTransparentQueueTransparent_ZWrite;
break;
default:
// do nothing for non-outline material input
break;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto set SurfaceType preset
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
SetMaterialNiloToonSurfaceTypeAndProperties(mat, nilotoonSurfaceTypePresetID);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// port common vrm00 mtoon00 & vrm10 mtoon10 to nilotoon
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.shader == VRMBRPMToon00Shader ||
originalMatClone.shader == VRMBRPMToon10Shader ||
originalMatClone.shader == VRMURPMToon10Shader)
{
// port base map
mat.SetTexture("_BaseMap", originalMatClone.GetTexture("_MainTex"));
// port base color (all vrm00 & vrm10 rely on _Color)
mat.SetFloat("_MultiplyBRPColor", 1);
//mat.SetColor("_BaseColor", originalMatClone.GetColor("_Color")); // not replacing _BaseColor as _Color, since we now * _Color already, so _BaseColor should be in default value(1,1,1,1)
// port outline tint color
mat.SetColor("_OutlineTintColor", originalMatClone.GetColor("_OutlineColor"));
// TODO: handle 'outline color = replace' mode
// cancel skin outline override
Color skinOutlineOverrideShadowColor = mat.GetColor("_OutlineTintColorSkinAreaOverride");
skinOutlineOverrideShadowColor.a = 0;
mat.SetColor("_OutlineTintColorSkinAreaOverride", skinOutlineOverrideShadowColor);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto set outline extra mul for VRM00 mtoon00 material
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.shader == VRMBRPMToon00Shader)
{
const float niloToonWidthRelativeToMToon00 = 12; //12~18 is good
mat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeToMToon00);
// extra check to limit any unexpected large outline width
float maxFinalWidth = 0.5f; // 0.5 is NiloToon's default outline width
float finalWidth = Mathf.Min(maxFinalWidth,
mat.GetFloat("_OutlineWidth") * niloToonWidthRelativeToMToon00);
mat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeToMToon00);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto set outline extra mul for VRM10 mtoon10 material
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.shader == VRMBRPMToon10Shader ||
originalMatClone.shader == VRMURPMToon10Shader)
{
const float niloToonWidthRelativeToMToon10 = 512;
mat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeToMToon10);
// extra check to limit any unexpected large outline width
float maxFinalWidth = 0.5f; // 0.5 is NiloToon's default outline width
float finalWidth = Mathf.Min(maxFinalWidth,
mat.GetFloat("_OutlineWidth") * niloToonWidthRelativeToMToon10);
mat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeToMToon10);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// port vrm00 mtoon00 properties to nilotoon
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.shader == VRMBRPMToon00Shader)
{
float MToonScrollX = originalMatClone.GetFloat("_UvAnimScrollX");
float MToonScrollY = originalMatClone.GetFloat("_UvAnimScrollY");
float MToonRotate = originalMatClone.GetFloat("_UvAnimRotation");
Vector4 _UV0ScrollSpeed = new Vector4();
_UV0ScrollSpeed.x = MToonScrollX;
_UV0ScrollSpeed.y = MToonScrollY;
mat.SetVector("_UV0ScrollSpeed", _UV0ScrollSpeed);
mat.SetFloat("_UV0RotateSpeed", MToonRotate);
if (MToonScrollX != 0 || MToonScrollY != 0 || MToonRotate != 0)
{
mat.SetFloat("_EnableUVEditGroup", 1);
}
//public enum CullMode
//{
// Off = 0,
// Front = 1,
// Back = 2,
//}
int _CullMode = (int)originalMatClone.GetFloat("_CullMode");
switch (_CullMode)
{
// Cull Off = Render Both
case 0:
mat.SetFloat("_RenderFacePreset", 2);
mat.SetFloat("_Cull", 0);
mat.SetFloat("_CullOutline", 1);
break;
// Cull Front = Render Back
case 1:
mat.SetFloat("_RenderFacePreset", 1);
mat.SetFloat("_Cull", 1);
mat.SetFloat("_CullOutline", 2);
break;
// Cull Back = Render Front
case 2:
mat.SetFloat("_RenderFacePreset", 0);
mat.SetFloat("_Cull", 2);
mat.SetFloat("_CullOutline", 1);
break;
}
Texture2D _ShadeTexture = originalMatClone.GetTexture("_ShadeTexture") as Texture2D;
if (_ShadeTexture)
{
mat.SetTexture("_OverrideShadowColorTex", _ShadeTexture);
mat.SetFloat("_UseOverrideShadowColorByTexture", 1);
mat.EnableKeyword("_OVERRIDE_SHADOWCOLOR_BY_TEXTURE");
mat.SetColor("_OverrideShadowColorTexTintColor",
originalMatClone.GetColor("_ShadeColor"));
}
Texture2D _OutlineWidthTexture =
originalMatClone.GetTexture("_OutlineWidthTexture") as Texture2D;
if (_OutlineWidthTexture)
{
mat.SetTexture("_OutlineWidthTex", _OutlineWidthTexture);
}
// TODO: matcap additive direct port
// TODO: additive param rim
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// port vrm10 mtoon10 properties to nilotoon
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.shader == VRMBRPMToon10Shader ||
originalMatClone.shader == VRMURPMToon10Shader)
{
float MToonScrollX = originalMatClone.GetFloat("_UvAnimScrollXSpeed");
float MToonScrollY = originalMatClone.GetFloat("_UvAnimScrollYSpeed");
float MToonRotate = originalMatClone.GetFloat("_UvAnimRotationSpeed");
Vector4 _UV0ScrollSpeed = new Vector4();
_UV0ScrollSpeed.x = MToonScrollX;
_UV0ScrollSpeed.y = MToonScrollY;
mat.SetVector("_UV0ScrollSpeed", _UV0ScrollSpeed);
mat.SetFloat("_UV0RotateSpeed", -MToonRotate);
if (MToonScrollX != 0 || MToonScrollY != 0 || MToonRotate != 0)
{
mat.SetFloat("_EnableUVEditGroup", 1);
}
int _M_CullMode = (int)originalMatClone.GetFloat("_M_CullMode");
switch (_M_CullMode)
{
// Cull Off = Render Both
case 0:
mat.SetFloat("_RenderFacePreset", 2);
mat.SetFloat("_Cull", 0);
mat.SetFloat("_CullOutline", 1);
break;
// Cull Front = Render Back
case 1:
mat.SetFloat("_RenderFacePreset", 1);
mat.SetFloat("_Cull", 1);
mat.SetFloat("_CullOutline", 2);
break;
// Cull Back = Render Front
case 2:
mat.SetFloat("_RenderFacePreset", 0);
mat.SetFloat("_Cull", 2);
mat.SetFloat("_CullOutline", 1);
break;
}
mat.renderQueue += (int)originalMatClone.GetFloat("_RenderQueueOffset");
Texture2D _ShadeTex = originalMatClone.GetTexture("_ShadeTex") as Texture2D;
if (_ShadeTex)
{
mat.SetTexture("_OverrideShadowColorTex", _ShadeTex);
mat.SetFloat("_UseOverrideShadowColorByTexture", 1);
mat.EnableKeyword("_OVERRIDE_SHADOWCOLOR_BY_TEXTURE");
mat.SetColor("_OverrideShadowColorTexTintColor",
originalMatClone.GetColor("_ShadeColor"));
}
// TODO: matcap additive direct port
// TODO: additive param rim
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// port liltoon properties to nilotoon
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.shader.name.Contains("lilToon"))
{
Port_lilToon_properties_To_NiloToon(originalMatClone, mat);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Auto enable NiloToon mat's texture feature(uniform+keyword) if any textures are assigned.
// *Skip if the input material is:
// - NiloToon_Character shader
// - any lilToon shader
// since we handled them already, if we do it again here, we may enable texture features that should be keep disabled)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if ((originalMatClone.shader != niloToonCharShader) &&
!(originalMatClone.name.Contains("lilToon")))
{
if (mat.GetTexture("_OutlineWidthTex"))
{
mat.SetFloat("_UseOutlineWidthTex", 1);
mat.EnableKeyword("_OUTLINEWIDTHMAP");
mat.SetVector("_OutlineWidthTexChannelMask",
new Vector4(0, 1, 0, 0)); // vrmc mtoon's _OutlineWidthTex use G channel
}
if (mat.GetTexture("_BumpMap"))
{
mat.SetFloat("_UseNormalMap", 1);
mat.EnableKeyword("_NORMALMAP");
}
if (mat.GetTexture("_EmissionMap"))
{
mat.SetFloat("_UseEmission", 1);
mat.EnableKeyword("_EMISSION");
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Reset _Parallax from 0.02 -> 0.005(default value) if _ParallaxMap doesn't exist
// so _Parallax is not a modified property which confuses user
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (originalMatClone.HasProperty("_ParallaxMap"))
{
if (!originalMatClone.GetTexture("_ParallaxMap"))
{
mat.SetFloat("_Parallax", 0.005f);
}
}
else
{
mat.SetFloat("_Parallax", 0.005f);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto enable 'IsFace' if material name contains 'face' related keywords
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool isFace = false;
foreach (var keyword in IsFaceFinalTargetNames)
{
isFace |= NiloToonUtils.NameHasKeyword(mat.name, keyword);
}
foreach (var keyword in IsFaceExactTargetNames)
{
isFace |= NiloToonUtils.NameEqualsKeywordIgnoreCase(mat.name,keyword);
}
foreach (var keyword in IsFaceFinalBanNames)
{
isFace &= !NiloToonUtils.NameHasKeyword(mat.name, keyword);
}
if (isFace)
{
SetMaterialAsIsFace(mat);
// *do not set material as skin
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto enable 'IsSkin' if material name contains 'skin' related keywords
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
bool isSkin = false;
foreach (var keyword in IsSkinFinalTargetNames)
{
isSkin |= NiloToonUtils.NameHasKeyword(mat.name, keyword);
}
foreach (var keyword in IsSkinFinalBanNames)
{
isSkin &= !NiloToonUtils.NameHasKeyword(mat.name, keyword);
}
if (isSkin)
{
SetMaterialAsIsSkin(mat);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// auto disable depth tex shadow if
// - it is eye (e.g. eye white material)
// - it doesn't draw depth texture (e.g., render queue >= 2500)
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (NiloToonUtils.NameHasKeyword(mat.name, "eye") ||
mat.renderQueue >= 2500)
{
mat.SetFloat(PerMaterialEnableDepthTextureRimLightAndShadow, 0);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Stencil preset matching
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int _StencilComp = (int)mat.GetFloat("_StencilComp");
int _StencilPass = (int)mat.GetFloat("_StencilPass");
int resultStencilPresetID = 0; // default = Disabled
// [copy logic from NiloToonCharacter_StencilPreset_LWGUI_ShaderPropertyPreset]
// matching [1]: 1st>Writer (Eyebrow)
if (_StencilComp == 8 && _StencilPass == 2)
{
resultStencilPresetID = 1;
}
// matching [2]: 2nd>Reader (Original Hair)
if (_StencilComp == 6 && _StencilPass == 0)
{
resultStencilPresetID = 2;
}
// matching [3]: 3rd>Reader-Invert (Redraw Hair)
if (_StencilComp == 3 && _StencilPass == 0)
{
resultStencilPresetID = 3;
}
mat.SetFloat("_StencilPreset", resultStencilPresetID);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// tell unity we edited material
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
EditorUtility.SetDirty(mat);
}
}
}
private static void Port_lilToon_properties_To_NiloToon(Material fromlilToonMat, Material toNiloToonMat)
{
// try to match as many lilToon 1.7.2's lts_o.shader properties as possible
// (?) _***** means a liltoon property not yet supported by nilotoon, under consideration
// (X) _***** means a liltoon property not supported by nilotoon by design
// (XV) _***** means a liltoon property not supported by nilotoon material by design, but it should be controlled by nilotoon's volume
// (Same) _***** means a liltoon property is supported by nilotoon already, since the name is the same, no action needed
//----------------------------------------------------------------------------------------------------------------------
// Dummy
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Base
toNiloToonMat.SetFloat("_EnableRendering",
fromlilToonMat.GetFloat("_Invisible") > 0.5
? 0
: 1); // (lilToon: early return "init as 0 struct" in vertex shader, same as NiloToon)
// (XV) _AsUnlit (lilToon: lerp main light color to white, lerp additional light color to black)
// (Same)_Cutoff (lilToon: standard alpha clip threshold, same as NiloToon/Lit)
// (?) _SubpassCutoff (NiloToon: similar to _CutOff, but only for "subpass", not sure what Subpass is)
// (X) _FlipNormal (NiloToon: always perform flipNormal, there is no option in material) (lilToon: sFlipBackfaceNormal -> N = facing < (_FlipNormal-1.0) ? -N : N. Similar to NiloToon)
// (?) _ShiftBackfaceUV (NiloToon: too specific, not sure if it is a good idea to add it) (lilToon: back face UV += (1,0) or not. lilToon's doc: Shift the UVs on the back by 1.0 in the X-axis direction. By turning this on and setting the Tiling's X to 0.5, and doubling the texture's resolution horizontally to place two textures side by side, you can create an expression where different textures are applied to the front and back.)
toNiloToonMat.SetFloat("_BackFaceForceShadow",
fromlilToonMat.GetFloat(
"_BackfaceForceShadow")); // lilToon: float bfshadow = (fd.facing < 0.0) ? 1.0 - _BackfaceForceShadow : 1.0;
toNiloToonMat.SetColor("_BackFaceBaseMapReplaceColor",
fromlilToonMat.GetColor(
"_BackfaceColor")); // lilToon: fd.col.rgb = (fd.facing < 0.0) ? lerp(fd.col.rgb, _BackfaceColor.rgb * fd.lightColor, _BackfaceColor.a) : fd.col.rgb;
// (X) _VertexLightStrength (NiloToon: this lil prop is for BRP only, ignored) (lilToon: for BRP only)
// (XV) _LightMinLimit (lilToon: lightColor = clamp(lightColor, _LightMinLimit, _LightMaxLimit);)
// (XV) _LightMaxLimit (lilToon: lightColor = clamp(lightColor, _LightMinLimit, _LightMaxLimit);)
// (X) _BeforeExposureLimit (NiloToon: this lilToon prop is for HDRP only, ignored)
// (XV) _MonochromeLighting (lilToon: lightColor = lerp(lightColor, lilGray(lightColor), _MonochromeLighting);)
// (X) _AlphaBoostFA (NiloToon: this lilToon prop is for forward add (FA) pass, ignored)(lilToon: fd.col.rgb *= saturate(fd.col.a * _AlphaBoostFA);)
// (XV) _lilDirectionalLightStrength (lilToon: lightColor *= _lilDirectionalLightStrength)
// (XV) _LightDirectionOverride (lilToon: add a object->world space light vector to light dir, re-normalize? (not sure))
// (?) _AAStrength (lilToon: for value with sharp change, apply fwidth AA by -> (value - borderMin) / saturate(borderMax - borderMin + fwidth(value) * aascale))
// (?) _UseDither (lilToon: dither fade0out per material)
// (?) _DitherTex (lilToon: dither fadeout per material)
// (?) _DitherMaxValue (lilToon: dither fadeout per material)
//----------------------------------------------------------------------------------------------------------------------
// Main
toNiloToonMat.SetColor("_BaseColor", fromlilToonMat.GetColor("_Color"));
toNiloToonMat.SetTexture("_BaseMap", fromlilToonMat.GetTexture("_MainTex"));
toNiloToonMat.SetVector("_BaseMap_ST", fromlilToonMat.GetVector("_MainTex_ST")); // auto uniform by Unity
// (!) _MainTex_ScrollRotate // TODO: apply the BaseMap's uv, not UV0!
// (?) _MainTexHSVG (lilToon: hsv = float3(hsv.x+hsvg.x,saturate(hsv.y*hsvg.y),saturate(hsv.z*hsvg.z));)
// (X) _MainGradationStrength (NiloToon: too specific, ignored)(lilToon: rgb per channel color 1D remap)
// (X) _MainGradationTex (NiloToon: too specific, ignored)(lilToon: rgb per channel color 1D remap)
// (?) _MainColorAdjustMask (lilToon: mask of _MainTexHSVG)
//----------------------------------------------------------------------------------------------------------------------
// Main2nd (port to NiloToon's BaseMapStackingLayer1)
float _UseMain2ndTex = fromlilToonMat.GetFloat("_UseMain2ndTex");
toNiloToonMat.SetFloat("_BaseMapStackingLayer1Enable", _UseMain2ndTex);
if (_UseMain2ndTex > 0.5)
{
toNiloToonMat.EnableKeyword("_BASEMAP_STACKING_LAYER1");
}
else
{
toNiloToonMat.DisableKeyword("_BASEMAP_STACKING_LAYER1");
}
toNiloToonMat.SetColor("_BaseMapStackingLayer1TintColor", fromlilToonMat.GetColor("_Color2nd"));
toNiloToonMat.SetTexture("_BaseMapStackingLayer1Tex", fromlilToonMat.GetTexture("_Main2ndTex"));
toNiloToonMat.SetVector("_BaseMapStackingLayer1TexUVScaleOffset",
fromlilToonMat.GetVector("_Main2ndTex_ST"));
// liltoon / nilotoon are both in degree
toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVRotatedAngle",
fromlilToonMat.GetFloat("_Main2ndTexAngle") * 180f / Mathf.PI);
{
Vector4 _Main2ndTex_ScrollRotate = fromlilToonMat.GetVector("_Main2ndTex_ScrollRotate");
toNiloToonMat.SetVector("_BaseMapStackingLayer1TexUVAnimSpeed",
new Vector4(_Main2ndTex_ScrollRotate.x, _Main2ndTex_ScrollRotate.y, 0, 0));
// [Don't use _Main2ndTex_ScrollRotate.z since it is not used by liltoon]
// [use the above _Main2ndTexAngle instead]
//toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVRotatedAngle", _Main2ndTex_ScrollRotate.z * Mathf.Rad2Deg);
// liltoon's speed is "cycle per second", nilotoon is "degree per second"
toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVRotateSpeed", _Main2ndTex_ScrollRotate.w * 360);
}
// liltoon's _Main2ndTex_UVMode = UV0|UV1|UV2|UV3|MatCap
toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVIndex", fromlilToonMat.GetFloat("_Main2ndTex_UVMode"));
toNiloToonMat.SetFloat("_BaseMapStackingLayer1ApplytoFaces", fromlilToonMat.GetFloat("_Main2ndTex_Cull"));
// (X) _Main2ndTexDecalAnimation
// (X) _Main2ndTexDecalSubParam
// (X) _Main2ndTexIsDecal
// (X) _Main2ndTexIsLeftOnly
// (X) _Main2ndTexIsRightOnly
// (X) _Main2ndTexShouldCopy
// (X) _Main2ndTexShouldFlipMirror
// (X) _Main2ndTexShouldFlipCopy
// (X) _Main2ndTexIsMSDF
toNiloToonMat.SetTexture("_BaseMapStackingLayer1MaskTex", fromlilToonMat.GetTexture("_Main2ndBlendMask"));
{
// liltoon's blend mode:
// 0: Normal
// 1: Add
// 2: Screen
// 3: Multiply
// NiloToon's blend mode:
// 0: Normal RGBA
// 1: Normal (same as liltoon)
// 2: Add (same as liltoon)
// 3: Screen (same as liltoon)
// 4: Multiply (same as liltoon)
// 5: None
float _Main2ndTexBlendMode = fromlilToonMat.GetFloat("_Main2ndTexBlendMode");
float NiloToonBlendMode = 0; // default 0 (Normal RGBA)
switch (_Main2ndTexBlendMode)
{
case 0:
NiloToonBlendMode = 1;
break;
case 1:
NiloToonBlendMode = 2;
break;
case 2:
NiloToonBlendMode = 3;
break;
case 3:
NiloToonBlendMode = 4;
break;
}
toNiloToonMat.SetFloat("_BaseMapStackingLayer1ColorBlendMode", NiloToonBlendMode);
}
// (X) _Main2ndTexAlphaMode // TODO?
// (X) _Main2ndEnableLighting
// (X) _Main2ndDissolveMask
// (X) _Main2ndDissolveNoiseMask
// (X) _Main2ndDissolveNoiseMask_ScrollRotate
// (X) _Main2ndDissolveNoiseStrength
// (X) _Main2ndDissolveColor
// (X) _Main2ndDissolveParams
// (X) _Main2ndDissolvePos
// (X) _Main2ndDistanceFade
//----------------------------------------------------------------------------------------------------------------------
// Main3rd (port to NiloToon's BaseMapStackingLayer2)
float _UseMain3rdTex = fromlilToonMat.GetFloat("_UseMain3rdTex");
toNiloToonMat.SetFloat("_BaseMapStackingLayer2Enable", _UseMain3rdTex);
if (_UseMain3rdTex == 1)
{
toNiloToonMat.EnableKeyword("_BASEMAP_STACKING_LAYER2");
}
else
{
toNiloToonMat.DisableKeyword("_BASEMAP_STACKING_LAYER2");
}
toNiloToonMat.SetColor("_BaseMapStackingLayer2TintColor", fromlilToonMat.GetColor("_Color3rd"));
toNiloToonMat.SetTexture("_BaseMapStackingLayer2Tex", fromlilToonMat.GetTexture("_Main3rdTex"));
toNiloToonMat.SetVector("_BaseMapStackingLayer2TexUVScaleOffset",
fromlilToonMat.GetVector("_Main3rdTex_ST"));
// liltoon / nilotoon are both in degree
toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVRotatedAngle",
fromlilToonMat.GetFloat("_Main3rdTexAngle"));
{
Vector4 _Main3rdTex_ScrollRotate = fromlilToonMat.GetVector("_Main3rdTex_ScrollRotate");
toNiloToonMat.SetVector("_BaseMapStackingLayer2TexUVAnimSpeed",
new Vector4(_Main3rdTex_ScrollRotate.x, _Main3rdTex_ScrollRotate.y, 0, 0));
// [Don't use _Main3rdTex_ScrollRotate.z since it is not used by liltoon]
// [use the above _Main3rdTexAngle instead]
//toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVRotatedAngle", _Main3rdTex_ScrollRotate.z * Mathf.Rad2Deg);
// liltoon's speed is "cycle per second", nilotoon is "degree per second"
toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVRotateSpeed", _Main3rdTex_ScrollRotate.w * 360);
}
// liltoon's _Main3rdTex_UVMode = UV0|UV1|UV2|UV3|MatCap
toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVIndex", fromlilToonMat.GetFloat("_Main3rdTex_UVMode"));
toNiloToonMat.SetFloat("_BaseMapStackingLayer2ApplytoFaces", fromlilToonMat.GetFloat("_Main3rdTex_Cull"));
// (X) _Main3rdTexDecalAnimation
// (X) _Main3rdTexDecalSubParam
// (X) _Main3rdTexIsDecal
// (X) _Main3rdTexIsLeftOnly
// (X) _Main3rdTexIsRightOnly
// (X) _Main3rdTexShouldCopy
// (X) _Main3rdTexShouldFlipMirror
// (X) _Main3rdTexShouldFlipCopy
// (X) _Main3rdTexIsMSDF
toNiloToonMat.SetTexture("_BaseMapStackingLayer2MaskTex", fromlilToonMat.GetTexture("_Main3rdBlendMask"));
{
// liltoon's blend mode:
// 0: Normal
// 1: Add
// 2: Screen
// 3: Multiply
// NiloToon's blend mode:
// 0: Normal RGBA
// 1: Normal (same as liltoon)
// 2: Add (same as liltoon)
// 3: Screen (same as liltoon)
// 4: Multiply (same as liltoon)
// 5: None
float _Main3rdTexBlendMode = fromlilToonMat.GetFloat("_Main3rdTexBlendMode");
float NiloToonBlendMode = 0; // default 0 (Normal RGBA)
switch (_Main3rdTexBlendMode)
{
case 0:
NiloToonBlendMode = 1;
break;
case 1:
NiloToonBlendMode = 2;
break;
case 2:
NiloToonBlendMode = 3;
break;
case 3:
NiloToonBlendMode = 4;
break;
}
toNiloToonMat.SetFloat("_BaseMapStackingLayer2ColorBlendMode", NiloToonBlendMode);
}
// (X) _Main3rdTexAlphaMode // TODO?
// (X) _Main3rdEnableLighting
// (X) _Main3rdDissolveMask
// (X) _Main3rdDissolveNoiseMask
// (X) _Main3rdDissolveNoiseMask_ScrollRotate
// (X) _Main3rdDissolveNoiseStrength
// (X) _Main3rdDissolveColor
// (X) _Main3rdDissolveParams
// (X) _Main3rdDissolvePos
// (X) _Main3rdDistanceFade
//----------------------------------------------------------------------------------------------------------------------
// Alpha Mask
// lilToon's _AlphaMaskMode
// 0 = None
// 1 = Replace
// 2 = Multiply
// 3 = Add
// 4 = Subtract
int _AlphaMaskMode = (int)fromlilToonMat.GetFloat("_AlphaMaskMode");
if (_AlphaMaskMode != 0)
{
toNiloToonMat.SetFloat("_UseAlphaOverrideTex", 1);
toNiloToonMat.EnableKeyword("_ALPHAOVERRIDEMAP");
toNiloToonMat.SetVector("_AlphaOverrideTexChannelMask", new Vector4(1f, 0f, 0f, 0f)); //r channel
// convert to nilotoon
// 0 = Replace
// 1 = Multiply
// 2 = Add
// 3 = Subtract
toNiloToonMat.SetFloat("_AlphaOverrideMode", Mathf.Min(3, _AlphaMaskMode - 1));
}
else
{
toNiloToonMat.SetFloat("_UseAlphaOverrideTex", 0);
toNiloToonMat.DisableKeyword("_ALPHAOVERRIDEMAP");
}
toNiloToonMat.SetTexture("_AlphaOverrideTex", fromlilToonMat.GetTexture("_AlphaMask"));
// liltoon GUI's invert toggle is not a property, it translate to a MAD (* scale + value)
toNiloToonMat.SetFloat("_AlphaOverrideTexValueScale", fromlilToonMat.GetFloat("_AlphaMaskScale"));
toNiloToonMat.SetFloat("_AlphaOverrideTexValueOffset", fromlilToonMat.GetFloat("_AlphaMaskValue"));
//----------------------------------------------------------------------------------------------------------------------
// NormalMap
int _UseBumpMap = (int)fromlilToonMat.GetFloat("_UseBumpMap");
if (_UseBumpMap == 1)
{
toNiloToonMat.SetFloat("_UseNormalMap", 1);
toNiloToonMat.EnableKeyword("_NORMALMAP");
}
else
{
toNiloToonMat.SetFloat("_UseNormalMap", 0);
toNiloToonMat.DisableKeyword("_NORMALMAP");
}
// (Same)_BumpMap
// (Same)_BumpScale
//----------------------------------------------------------------------------------------------------------------------
// NormalMap 2nd (apply to nilotoon's detail map?)
// (?) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Anisotropy
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Backlight
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Shadow
toNiloToonMat.SetFloat("_EnableShadowColor", fromlilToonMat.GetFloat("_UseShadow"));
Texture2D occlusionMap = fromlilToonMat.GetTexture("_ShadowBorderMask") as Texture2D;
toNiloToonMat.SetTexture("_OcclusionMap", occlusionMap);
if (occlusionMap)
{
toNiloToonMat.SetFloat("_UseOcclusion", 1);
toNiloToonMat.EnableKeyword("_OCCLUSIONMAP");
}
else
{
toNiloToonMat.SetFloat("_UseOcclusion", 0);
toNiloToonMat.DisableKeyword("_OCCLUSIONMAP");
}
//----------------------------------------------------------------------------------------------------------------------
// Rim Shade
//----------------------------------------------------------------------------------------------------------------------
// Reflection
// TODO
//----------------------------------------------------------------------------------------------------------------------
// MatCap
// TODO (apply to basemap stacking layer3, base on blend mode)
//----------------------------------------------------------------------------------------------------------------------
// MatCap 2nd
// TODO (apply to basemap stacking layer4, apply base on blend mode)
//----------------------------------------------------------------------------------------------------------------------
// Rim
// TODO (we should write a ALU rim in NiloToon, similar to lilToon)
//----------------------------------------------------------------------------------------------------------------------
// Glitter
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Emission
int _UseEmission = (int)fromlilToonMat.GetFloat("_UseEmission");
if (_UseEmission == 1)
{
toNiloToonMat.SetFloat("_UseEmission", 1);
toNiloToonMat.EnableKeyword("_EMISSION");
}
else
{
toNiloToonMat.SetFloat("_UseEmission", 0);
toNiloToonMat.DisableKeyword("_EMISSION");
}
// (Same)_EmissionColor
toNiloToonMat.SetFloat("_EmissionIntensity",
fromlilToonMat.GetColor("_EmissionColor").a); // lilToon's _EmissionColor.a is the intensity
// (Same)_EmissionMap
toNiloToonMat.SetVector("_EmissionMapUVScrollSpeed",
fromlilToonMat.GetVector("_EmissionMap_ScrollRotate"));
// (X) _EmissionMap_UVMode
toNiloToonMat.SetFloat("_MultiplyBaseColorToEmissionColor",
fromlilToonMat.GetFloat("_EmissionMainStrength"));
//_EmissionBlend
//_EmissionBlendMask
// (X) _EmissionBlendMask_ScrollRot
// (X) _EmissionBlendMode
// (X) _EmissionBlink
// (X) _EmissionUseGrad
// (X) _EmissionGradTex
// (X) _EmissionGradSpeed
// (X) _EmissionParallaxDepth
// (X) _EmissionFluorescence
//----------------------------------------------------------------------------------------------------------------------
// Emission2nd
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Parallax
int _UseParallax = (int)fromlilToonMat.GetFloat("_UseParallax");
if (_UseParallax == 1)
{
toNiloToonMat.SetFloat("_ParallaxMapEnable", 1);
toNiloToonMat.EnableKeyword("_PARALLAXMAP");
}
else
{
toNiloToonMat.SetFloat("_ParallaxMapEnable", 0);
toNiloToonMat.DisableKeyword("_PARALLAXMAP");
}
// (X) _UsePOM
// (Same) _ParallaxMap
// (Same) _Parallax
// (X) _ParallaxOffset
//----------------------------------------------------------------------------------------------------------------------
// Distance Fade
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// AudioLink
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Dissolve
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// ID Mask
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Encryption
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// Outline
toNiloToonMat.SetColor("_OutlineTintColor", fromlilToonMat.GetColor("_OutlineColor"));
// _OutlineWidth (same, no need to convert)
// make 2 outline system's width matching
float _OutlineWidth = fromlilToonMat.GetFloat("_OutlineWidth");
const float niloToonWidthRelativeTolilToon = 4;
toNiloToonMat.SetFloat("_OutlineWidthExtraMultiplier", niloToonWidthRelativeTolilToon);
// extra check to limit any unexpected large outline width
float maxFinalWidth = 0.5f; // 0.5 is NiloToon's default outline width
float finalWidth = Mathf.Min(maxFinalWidth, _OutlineWidth * niloToonWidthRelativeTolilToon);
toNiloToonMat.SetFloat("_OutlineWidth", finalWidth / niloToonWidthRelativeTolilToon);
Texture2D _OutlineWidthMask = fromlilToonMat.GetTexture("_OutlineWidthMask") as Texture2D;
if (_OutlineWidthMask)
{
toNiloToonMat.SetFloat("_UseOutlineWidthTex", 1);
toNiloToonMat.EnableKeyword("_OUTLINEWIDTHMAP");
toNiloToonMat.SetVector("_OutlineWidthTexChannelMask", new Vector4(1, 0, 0, 0));
toNiloToonMat.SetTexture("_OutlineWidthTex", _OutlineWidthMask);
}
else
{
toNiloToonMat.SetFloat("_UseOutlineWidthTex", 0);
toNiloToonMat.DisableKeyword("_OUTLINEWIDTHMAP");
toNiloToonMat.SetVector("_OutlineWidthTexChannelMask", new Vector4(0, 1, 0, 0));
}
float _OutlineVertexR2Width = fromlilToonMat.GetFloat("_OutlineVertexR2Width");
if (_OutlineVertexR2Width == 0)
{
// no vertex color used
toNiloToonMat.SetFloat("_UseOutlineWidthMaskFromVertexColor", 0);
toNiloToonMat.SetVector("_OutlineWidthMaskFromVertexColor", new Vector4(0, 1, 0, 0));
}
if (_OutlineVertexR2Width == 1)
{
// vertex color.r
toNiloToonMat.SetFloat("_UseOutlineWidthMaskFromVertexColor", 1);
toNiloToonMat.SetVector("_OutlineWidthMaskFromVertexColor", new Vector4(1, 0, 0, 0));
}
if (_OutlineVertexR2Width == 2)
{
// vertex color.a
toNiloToonMat.SetFloat("_UseOutlineWidthMaskFromVertexColor", 1);
toNiloToonMat.SetVector("_OutlineWidthMaskFromVertexColor", new Vector4(0, 0, 0, 1));
}
toNiloToonMat.SetFloat("_OutlineBaseZOffset", fromlilToonMat.GetFloat("_OutlineZBias"));
//----------------------------------------------------------------------------------------------------------------------
// Tessellation
// (X) ...All...
//----------------------------------------------------------------------------------------------------------------------
// For Multi
//----------------------------------------------------------------------------------------------------------------------
// Save (Unused)
//----------------------------------------------------------------------------------------------------------------------
// Advanced
//----------------------------------------------------------------------------------------------------------------------
// Outline Advanced
}
static void SetMaterialAsIsSkin(Material m)
{
m.SetFloat(IsSkin, 1);
// no keyword on/off is needed for _IsSkin
// ...
}
static void SetMaterialAsIsFace(Material m)
{
m.SetFloat(IsFace, 1);
m.EnableKeyword("_ISFACE");
}
static void SetMaterialAsNoOutline(Material m)
{
// TODO: update
if (m.GetFloat(SurfaceTypePreset) == 0)
{
m.SetFloat(SurfaceTypePreset, 1);
}
m.SetFloat(RenderOutline, 0);
// no keyword on/off is needed for _RenderOutline
// ...
}
public static void SetMaterialNiloToonSurfaceTypeAndProperties(Material m,
NiloToonSurfaceTypePreset niloToonSurfaceTypePreset)
{
// fix render queue when it is out of expected range
void ClampRenderQueueMinMax(Material m, int minRenderQueue, int maxRenderQueue)
{
if (m.renderQueue < minRenderQueue) m.renderQueue = minRenderQueue;
if (m.renderQueue > maxRenderQueue) m.renderQueue = maxRenderQueue;
}
void ClampRenderQueueToGroup(Material m, RenderQueueGroup renderQueueGroup)
{
// from Unity's RenderQueue enum
//public enum RenderQueue
//{
// /// This render queue is rendered before any others.
// Background = 1000,
// /// Opaque geometry uses this queue.
// Geometry = 2000,
// /// Alpha tested geometry uses this queue.
// AlphaTest = 2450,
// /// Last render queue that is considered "opaque".
// GeometryLast = 2500,
// /// This render queue is rendered after Geometry and AlphaTest, in back-to-front order.
// Transparent = 3000,
// /// This render queue is meant for overlay effects.
// Overlay = 4000,
//}
switch (renderQueueGroup)
{
case RenderQueueGroup.Opaque:
ClampRenderQueueMinMax(m, 2000, 2450 - 1);
break;
case RenderQueueGroup.Cutout:
ClampRenderQueueMinMax(m, 2450, 2500 - 1);
break;
// 2500 is SkyBox
case RenderQueueGroup.Transparent:
ClampRenderQueueMinMax(m, 2501, 4000 - 1);
break;
}
}
// hardcode matching NiloToonCharacter_SurfaceType_LWGUI_ShaderPropertyPreset.asset
switch (niloToonSurfaceTypePreset)
{
case NiloToonSurfaceTypePreset.Opaque_Outline:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.Opaque_Outline);
m.SetFloat("_SrcBlend", 1);
m.SetFloat("_DstBlend", 0);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 1);
//m.renderQueue = 2000; // matching preset, not -1
ClampRenderQueueToGroup(m, RenderQueueGroup.Opaque);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.Opaque:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.Opaque);
m.SetFloat("_SrcBlend", 1);
m.SetFloat("_DstBlend", 0);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = 2000; // matching preset, not -1
ClampRenderQueueToGroup(m, RenderQueueGroup.Opaque);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 1);
//m.renderQueue = 2499;
ClampRenderQueueToGroup(m, RenderQueueGroup.Cutout);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.Transparent:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.Transparent);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 0);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
ClampRenderQueueToGroup(m, RenderQueueGroup.Transparent);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.Transparent_ZWrite:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.Transparent_ZWrite);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = 2499;
ClampRenderQueueToGroup(m, RenderQueueGroup.Cutout);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutOpaque_Outline:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.CutoutOpaque_Outline);
m.SetFloat("_SrcBlend", 1);
m.SetFloat("_DstBlend", 0);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 1);
//m.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
ClampRenderQueueToGroup(m, RenderQueueGroup.Cutout);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutOpaque:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.CutoutOpaque);
m.SetFloat("_SrcBlend", 1);
m.SetFloat("_DstBlend", 0);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest;
ClampRenderQueueToGroup(m, RenderQueueGroup.Cutout);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite_Outline:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite_Outline);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 1);
//m.renderQueue = 2499;
ClampRenderQueueToGroup(m, RenderQueueGroup.Cutout);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutTransparent:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.CutoutTransparent);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 0);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent;
ClampRenderQueueToGroup(m, RenderQueueGroup.Transparent);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.CutoutTransparent_ZWrite);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = 2499;
ClampRenderQueueToGroup(m, RenderQueueGroup.Cutout);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite_Outline:
m.SetFloat(SurfaceTypePreset,
(int)NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite_Outline);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 1);
//m.renderQueue = 3000;
ClampRenderQueueToGroup(m, RenderQueueGroup.Transparent);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite:
m.SetFloat(SurfaceTypePreset, (int)NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = 3000;
ClampRenderQueueToGroup(m, RenderQueueGroup.Transparent);
m.SetFloat("_AlphaClip", 0);
m.DisableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline:
m.SetFloat(SurfaceTypePreset,
(int)NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite_Outline);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 1);
//m.renderQueue = 3000;
ClampRenderQueueToGroup(m, RenderQueueGroup.Transparent);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
case NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite:
m.SetFloat(SurfaceTypePreset,
(int)NiloToonSurfaceTypePreset.CutoutTransparentQueueTransparent_ZWrite);
m.SetFloat("_SrcBlend", 5);
m.SetFloat("_DstBlend", 10);
m.SetFloat("_ZWrite", 1);
m.SetFloat("_RenderOutline", 0);
//m.renderQueue = 3000;
ClampRenderQueueToGroup(m, RenderQueueGroup.Transparent);
m.SetFloat("_AlphaClip", 1);
m.EnableKeyword("_ALPHATEST_ON");
break;
default:
throw new NotImplementedException("Contact NiloToon's developer to support a new SurfaceType.");
}
}
static bool TextureHasAlpha(Texture2D texture)
{
// Blit texture to a new RT to avoid non-Readable texture problem
RenderTexture tempRT = RenderTexture.GetTemporary(texture.width, texture.height);
Graphics.Blit(texture, tempRT);
RenderTexture RTactiveCache = RenderTexture.active;
RenderTexture.active = tempRT;
// apply RT to our new Texture2D, so we can read it's per pixel alpha
Texture2D readableTexture = new Texture2D(texture.width, texture.height);
readableTexture.ReadPixels(new Rect(0, 0, tempRT.width, tempRT.height), 0, 0);
readableTexture.Apply();
RenderTexture.active = RTactiveCache;
RenderTexture.ReleaseTemporary(tempRT);
Color[] pixels = readableTexture.GetPixels();
// this loop maybe slow depending on Texture size
foreach (Color pixel in pixels)
{
if (pixel.a < 1f)
{
return true;
}
}
return false;
}
/// <summary>
/// Breaks the variant link of a material
/// </summary>
public static void BreakMaterialVariant(Material mat)
{
if (mat == null)
return;
// break (Material.parent only exists in Unity2022.1 or later)
#if UNITY_2022_3_OR_NEWER
mat.parent = null;
#endif
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// copy from UniversalRenderPipelineMaterialUpgrader.cs
////////////////////////////////////////////////////////////////////////////////////////////////////////
static void GetShaderNamesToIgnore(ref HashSet<string> shadersToIgnore)
{
// all URP shader don't need an upgrade, since it is URP shader already!
shadersToIgnore.Add("Universal Render Pipeline/Baked Lit");
shadersToIgnore.Add("Universal Render Pipeline/Lit");
shadersToIgnore.Add("Universal Render Pipeline/Particles/Lit");
shadersToIgnore.Add("Universal Render Pipeline/Particles/Simple Lit");
shadersToIgnore.Add("Universal Render Pipeline/Particles/Unlit");
shadersToIgnore.Add("Universal Render Pipeline/Simple Lit");
shadersToIgnore.Add("Universal Render Pipeline/Complex Lit");
shadersToIgnore.Add("Universal Render Pipeline/Nature/SpeedTree7");
shadersToIgnore.Add("Universal Render Pipeline/Nature/SpeedTree7 Billboard");
shadersToIgnore.Add("Universal Render Pipeline/Nature/SpeedTree8");
shadersToIgnore.Add("Universal Render Pipeline/2D/Sprite-Lit-Default");
shadersToIgnore.Add("Universal Render Pipeline/Terrain/Lit");
shadersToIgnore.Add("Universal Render Pipeline/Unlit");
shadersToIgnore.Add("Sprites/Default");
// NiloToonURP added all character shader to ignore list:
shadersToIgnore.Add("Universal Render Pipeline/NiloToon/NiloToon_Character");
shadersToIgnore.Add("Universal Render Pipeline/NiloToon/NiloToon_Character Sticker(Multiply)");
shadersToIgnore.Add("Universal Render Pipeline/NiloToon/NiloToon_Character Sticker(Additive)");
// lilToon shader will be upgraded by NiloToon's script
shadersToIgnore.Add("lilToon");
shadersToIgnore.Add("Hidden/lilToonOutline");
shadersToIgnore.Add("Hidden/lilToonTransparent");
shadersToIgnore.Add("Hidden/lilToonCutoutOutline");
shadersToIgnore.Add("Hidden/lilToonTransparentOutline");
// vrm mtoon will be upgraded by NiloToon's script
shadersToIgnore.Add("UniGLTF/UniUnlit");
shadersToIgnore.Add("VRM/MToon");
shadersToIgnore.Add("VRM10/MToon10");
shadersToIgnore.Add("VRM10/Universal Render Pipeline/MToon10");
}
static void GetUpgraders(ref List<MaterialUpgrader> upgraders)
{
/////////////////////////////////////
// Unity Standard Upgraders //
/////////////////////////////////////
upgraders.Add(new StandardUpgrader("Standard"));
upgraders.Add(new StandardUpgrader("Standard (Specular setup)"));
////////////////////////////////////
// Particle Upgraders //
////////////////////////////////////
upgraders.Add(new ParticleUpgrader("Particles/Standard Surface"));
upgraders.Add(new ParticleUpgrader("Particles/Standard Unlit"));
upgraders.Add(new ParticleUpgrader("Particles/VertexLit Blended"));
////////////////////////////////////
// Autodesk Interactive //
////////////////////////////////////
upgraders.Add(new AutodeskInteractiveUpgrader("Autodesk Interactive"));
}
#if UNITY_EDITOR
[MenuItem("Window/NiloToonURP/[Material] Convert Selected Materials to NiloToon", priority = 2)]
[MenuItem("Assets/NiloToon/[Material] Convert Selected Materials to NiloToon", priority = 1100 + 2)]
public static void ConvertSelectedMaterialsToNiloToon_Character()
{
var allselectedObjects = Selection.objects;
List<Material> allInputMaterials = new List<Material>();
foreach (var selectedObject in allselectedObjects)
{
if (selectedObject is Material mat)
{
if (mat != null)
{
allInputMaterials.Add(mat);
}
}
}
AutoConvertMaterialsToNiloToon(allInputMaterials);
}
[MenuItem("Window/NiloToonURP/[Material] Convert Selected Materials to NiloToon", priority = 2, validate = true)]
[MenuItem("Assets/NiloToon/[Material] Convert Selected Materials to NiloToon", priority = 1100 + 2, validate = true)]
public static bool ValidateConvertSelectedMaterialsToNiloToon_Character()
{
var allselectedObjects = Selection.objects;
return allselectedObjects.Any(selectedObject => selectedObject is Material);
}
#endif
}
}