2876 lines
150 KiB
C#
2876 lines
150 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 DepthTexRimLight3DRimMaskEnable =
|
|
Shader.PropertyToID("_DepthTexRimLight3DRimMaskEnable");
|
|
|
|
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
|
|
}
|
|
|
|
private sealed class MaterialCloneList : IDisposable
|
|
{
|
|
private readonly List<Material> materials;
|
|
|
|
public MaterialCloneList(IReadOnlyList<Material> sourceMaterials)
|
|
{
|
|
materials = new List<Material>(sourceMaterials.Count);
|
|
for (int i = 0; i < sourceMaterials.Count; i++)
|
|
{
|
|
Material material = sourceMaterials[i];
|
|
materials.Add(material != null ? Object.Instantiate(material) : null);
|
|
}
|
|
}
|
|
|
|
public int Count => materials.Count;
|
|
|
|
public Material this[int index] => materials[index];
|
|
|
|
public void Dispose()
|
|
{
|
|
foreach (Material material in materials)
|
|
{
|
|
if (material)
|
|
{
|
|
Object.DestroyImmediate(material);
|
|
}
|
|
}
|
|
|
|
materials.Clear();
|
|
}
|
|
}
|
|
|
|
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");
|
|
var renderQueueRepackItems = new List<RenderQueueRepackItem>();
|
|
var renderQueueRepackMaterials = new HashSet<Material>();
|
|
|
|
// clone all original materials to a new List with the same order, for later reference, since we will edit the real material later
|
|
using MaterialCloneList allOriginalMaterialsClone = new MaterialCloneList(allTargetMaterials);
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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 (!HasUsableShader(matOriginal))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
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 (IsLilToonMultiFamilyShader(matOriginal.shader))
|
|
{
|
|
niloToonSurfaceTypePresetIDArray[i] = ResolveLilToonMultiSurfaceTypePreset(matOriginal);
|
|
}
|
|
else 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
|
|
}
|
|
|
|
if (IsLilToonFurMaterial(matOriginal))
|
|
{
|
|
// NiloToonFurPass renders the opaque queue only. Keep converted fur renderable even when the lilToon source used a transparent fur mode.
|
|
niloToonSurfaceTypePresetIDArray[i] = NiloToonSurfaceTypePreset.CutoutOpaque;
|
|
}
|
|
|
|
// Do not use texture alpha to infer cutout: many models store non-transparency data in alpha.
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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)
|
|
{
|
|
if (mat == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// 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);
|
|
|
|
if (!HasUsableShader(mat))
|
|
{
|
|
mat.shader = builtinRPStandardShader;
|
|
EditorUtility.SetDirty(mat);
|
|
continue;
|
|
}
|
|
|
|
// 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);
|
|
|
|
for (int i = 0; i < allTargetMaterials.Count; i++)
|
|
{
|
|
Material material = allTargetMaterials[i];
|
|
if (!ShouldUpgradeMaterialNonInteractively(material, shaderNamesToIgnore))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
MaterialUpgrader.Upgrade(material, upgraders,
|
|
MaterialUpgrader.UpgradeFlags.LogMessageWhenNoUpgraderFound);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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 (!HasUsableShader(mat))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
bool hasUsableOriginalShader = HasUsableShader(originalMatClone);
|
|
string currentShaderName = mat.shader.name;
|
|
string originalShaderName = hasUsableOriginalShader ? originalMatClone.shader.name : string.Empty;
|
|
int sourceRenderQueue = hasUsableOriginalShader ? originalMatClone.renderQueue : mat.renderQueue;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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 (currentShaderName.Contains("Particle") ||
|
|
currentShaderName.Contains("Sprite"))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// if the current shader is not any NiloToon shader
|
|
// switch this shader to NiloToon_Character shader
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
if (!currentShaderName.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 = IsNoOutlineFinalTargetNames.Concat(IsNoOutlineTargetNames).ToList();
|
|
|
|
List<string> IsNoOutlineExactTargetNames = new List<string>();
|
|
IsNoOutlineExactTargetNames = IsNoOutlineExactTargetNames.Concat(IsFaceExactTargetNames).ToList();
|
|
|
|
List<string> IsNoOutlineFinalBanNames = IsFaceFinalBanNames.ToList();
|
|
IsNoOutlineFinalBanNames = IsNoOutlineFinalBanNames.Concat(IsNoOutlineBanNames).ToList();
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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);
|
|
// Group by the converted NiloToon preset. Source queues only preserve order inside the chosen opaque/transparent group.
|
|
bool targetUsesOpaqueQueue = mat.renderQueue <= (int)RenderQueue.GeometryLast;
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// port common vrm00 mtoon00 & vrm10 mtoon10 to nilotoon
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
if (hasUsableOriginalShader &&
|
|
(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 (hasUsableOriginalShader && 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 (hasUsableOriginalShader &&
|
|
(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 (hasUsableOriginalShader && 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 (hasUsableOriginalShader &&
|
|
(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;
|
|
}
|
|
|
|
// Batch repack normally overwrites this value and uses originalMatClone.renderQueue as the ordering signal.
|
|
// Validated UniVRM MToon10 already includes this offset there; this legacy add only matters if repack falls back.
|
|
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 (originalShaderName.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 (!hasUsableOriginalShader ||
|
|
((originalMatClone.shader != niloToonCharShader) &&
|
|
!originalShaderName.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 (hasUsableOriginalShader && 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);
|
|
}
|
|
|
|
if (renderQueueRepackMaterials.Add(mat))
|
|
{
|
|
renderQueueRepackItems.Add(new RenderQueueRepackItem(
|
|
mat,
|
|
sourceRenderQueue,
|
|
i,
|
|
targetUsesOpaqueQueue));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
RepackRenderQueuesPreservingRelativeOrder(renderQueueRepackItems);
|
|
foreach (RenderQueueRepackItem item in renderQueueRepackItems)
|
|
{
|
|
AutoDisableDepthTextureRimLightAndShadowIfNeeded(item.Material);
|
|
EditorUtility.SetDirty(item.Material);
|
|
}
|
|
}
|
|
|
|
private readonly struct RenderQueueRepackItem
|
|
{
|
|
public RenderQueueRepackItem(
|
|
Material material,
|
|
int sourceRenderQueue,
|
|
int originalIndex,
|
|
bool targetUsesOpaqueQueue)
|
|
{
|
|
Material = material;
|
|
SourceRenderQueue = sourceRenderQueue;
|
|
OriginalIndex = originalIndex;
|
|
TargetUsesOpaqueQueue = targetUsesOpaqueQueue;
|
|
}
|
|
|
|
public Material Material { get; }
|
|
public int SourceRenderQueue { get; }
|
|
public int OriginalIndex { get; }
|
|
public bool TargetUsesOpaqueQueue { get; }
|
|
}
|
|
|
|
private sealed class RenderQueueBucket
|
|
{
|
|
public int SourceRenderQueue;
|
|
public int AssignedRenderQueue;
|
|
public readonly List<RenderQueueRepackItem> Items = new List<RenderQueueRepackItem>();
|
|
}
|
|
|
|
private static void RepackRenderQueuesPreservingRelativeOrder(List<RenderQueueRepackItem> items)
|
|
{
|
|
RepackRenderQueueGroup(items, true, 0, (int)RenderQueue.GeometryLast);
|
|
RepackRenderQueueGroup(items, false, (int)RenderQueue.GeometryLast + 1, (int)RenderQueue.Overlay - 1);
|
|
}
|
|
|
|
private static void RepackRenderQueueGroup(
|
|
List<RenderQueueRepackItem> allItems,
|
|
bool targetUsesOpaqueQueue,
|
|
int minQueue,
|
|
int maxQueue)
|
|
{
|
|
List<RenderQueueRepackItem> groupItems = allItems
|
|
.Where(item => item.TargetUsesOpaqueQueue == targetUsesOpaqueQueue)
|
|
.OrderBy(item => item.SourceRenderQueue)
|
|
.ThenBy(item => item.OriginalIndex)
|
|
.ToList();
|
|
|
|
if (groupItems.Count == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
List<RenderQueueBucket> buckets = CreateRenderQueueBuckets(groupItems);
|
|
if (buckets.Count > maxQueue - minQueue + 1)
|
|
{
|
|
Debug.LogWarning(
|
|
$"[NiloToon] Too many distinct render queues ({buckets.Count}) to preserve relative order inside {minQueue}..{maxQueue}.");
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < buckets.Count; i++)
|
|
{
|
|
buckets[i].AssignedRenderQueue = Mathf.Clamp(buckets[i].SourceRenderQueue, minQueue, maxQueue);
|
|
if (i > 0 && buckets[i].AssignedRenderQueue <= buckets[i - 1].AssignedRenderQueue)
|
|
{
|
|
buckets[i].AssignedRenderQueue = buckets[i - 1].AssignedRenderQueue + 1;
|
|
}
|
|
}
|
|
|
|
if (buckets[buckets.Count - 1].AssignedRenderQueue > maxQueue)
|
|
{
|
|
buckets[buckets.Count - 1].AssignedRenderQueue = maxQueue;
|
|
for (int i = buckets.Count - 2; i >= 0; i--)
|
|
{
|
|
if (buckets[i].AssignedRenderQueue >= buckets[i + 1].AssignedRenderQueue)
|
|
{
|
|
buckets[i].AssignedRenderQueue = buckets[i + 1].AssignedRenderQueue - 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (RenderQueueBucket bucket in buckets)
|
|
{
|
|
foreach (RenderQueueRepackItem item in bucket.Items)
|
|
{
|
|
item.Material.renderQueue = bucket.AssignedRenderQueue;
|
|
}
|
|
}
|
|
}
|
|
|
|
private static List<RenderQueueBucket> CreateRenderQueueBuckets(List<RenderQueueRepackItem> sortedItems)
|
|
{
|
|
var buckets = new List<RenderQueueBucket>();
|
|
foreach (RenderQueueRepackItem item in sortedItems)
|
|
{
|
|
RenderQueueBucket bucket = buckets.Count > 0 && buckets[buckets.Count - 1].SourceRenderQueue == item.SourceRenderQueue
|
|
? buckets[buckets.Count - 1]
|
|
: null;
|
|
if (bucket == null)
|
|
{
|
|
bucket = new RenderQueueBucket { SourceRenderQueue = item.SourceRenderQueue };
|
|
buckets.Add(bucket);
|
|
}
|
|
|
|
bucket.Items.Add(item);
|
|
}
|
|
|
|
return buckets;
|
|
}
|
|
|
|
private static void AutoDisableDepthTextureRimLightAndShadowIfNeeded(Material mat)
|
|
{
|
|
if (NiloToonUtils.NameHasKeyword(mat.name, "eye") ||
|
|
mat.renderQueue > (int)RenderQueue.GeometryLast)
|
|
{
|
|
mat.SetFloat(PerMaterialEnableDepthTextureRimLightAndShadow, 0);
|
|
}
|
|
}
|
|
|
|
private static bool IsLilToonMultiFamilyShader(Shader shader)
|
|
{
|
|
return shader != null &&
|
|
shader.name.Contains("lilToonMulti", StringComparison.Ordinal);
|
|
}
|
|
|
|
private static bool IsLilToonFurMaterial(Material material)
|
|
{
|
|
if (!HasUsableShader(material))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string shaderName = material.shader.name;
|
|
bool isLilToonFamily = shaderName.Contains("lilToon", StringComparison.Ordinal);
|
|
if (!isLilToonFamily)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (shaderName.Contains("Fur", StringComparison.Ordinal))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (IsLilToonMultiFamilyShader(material.shader) && material.HasProperty("_TransparentMode"))
|
|
{
|
|
int transparentMode = Mathf.RoundToInt(material.GetFloat("_TransparentMode"));
|
|
return transparentMode == 4 || transparentMode == 5;
|
|
}
|
|
|
|
return material.HasProperty("_FurNoiseMask") ||
|
|
material.HasProperty("_FurMask") ||
|
|
material.HasProperty("_FurLengthMask") ||
|
|
material.HasProperty("_FurVector") ||
|
|
material.HasProperty("_FurLayerNum");
|
|
}
|
|
|
|
private static NiloToonSurfaceTypePreset ResolveLilToonMultiSurfaceTypePreset(Material matOriginal)
|
|
{
|
|
int transparentMode = matOriginal.HasProperty("_TransparentMode")
|
|
? Mathf.RoundToInt(matOriginal.GetFloat("_TransparentMode"))
|
|
: 0;
|
|
bool useOutline = matOriginal.HasProperty("_UseOutline") && matOriginal.GetFloat("_UseOutline") > 0.5f;
|
|
bool zWrite = !matOriginal.HasProperty("_ZWrite") || matOriginal.GetFloat("_ZWrite") > 0.5f;
|
|
bool isTransparentQueue = matOriginal.renderQueue > 2500;
|
|
|
|
switch (transparentMode)
|
|
{
|
|
case 0:
|
|
return ResolveLilToonMultiOpaquePreset(useOutline, zWrite);
|
|
case 1:
|
|
return ResolveLilToonMultiCutoutPreset(useOutline, zWrite);
|
|
case 2:
|
|
return ResolveLilToonMultiTransparentPreset(useOutline, zWrite, isTransparentQueue);
|
|
case 3:
|
|
// lilToonMulti refraction uses its own shader path without outline and falls back closest to opaque surface family.
|
|
return ResolveLilToonMultiOpaquePreset(false, zWrite);
|
|
case 4:
|
|
// NiloToonFurPass renders opaque queue only, so converted fur must stay in the cutout/opaque family.
|
|
return ResolveLilToonMultiCutoutPreset(false, true);
|
|
case 5:
|
|
// lilToonMulti fur cutout uses alpha clip but does not expose an outline variant.
|
|
return ResolveLilToonMultiCutoutPreset(false, zWrite);
|
|
case 6:
|
|
// lilToonMulti gem is additive/transparent and does not expose an outline variant.
|
|
return ResolveLilToonMultiTransparentPreset(false, zWrite, isTransparentQueue);
|
|
default:
|
|
Debug.LogWarning(
|
|
$"Unsupported lilToonMulti _TransparentMode '{transparentMode}' on material '{matOriginal.name}'. Falling back to opaque surface family.");
|
|
return ResolveLilToonMultiOpaquePreset(false, zWrite);
|
|
}
|
|
}
|
|
|
|
private static NiloToonSurfaceTypePreset ResolveLilToonMultiOpaquePreset(
|
|
bool useOutline,
|
|
bool zWrite)
|
|
{
|
|
if (!zWrite)
|
|
{
|
|
return NiloToonSurfaceTypePreset.Transparent;
|
|
}
|
|
|
|
return useOutline
|
|
? NiloToonSurfaceTypePreset.Opaque_Outline
|
|
: NiloToonSurfaceTypePreset.Opaque;
|
|
}
|
|
|
|
private static NiloToonSurfaceTypePreset ResolveLilToonMultiTransparentPreset(
|
|
bool useOutline,
|
|
bool zWrite,
|
|
bool isTransparentQueue)
|
|
{
|
|
if (!zWrite)
|
|
{
|
|
return NiloToonSurfaceTypePreset.Transparent;
|
|
}
|
|
|
|
if (isTransparentQueue)
|
|
{
|
|
return useOutline
|
|
? NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite_Outline
|
|
: NiloToonSurfaceTypePreset.TransparentQueueTransparent_ZWrite;
|
|
}
|
|
|
|
return useOutline
|
|
? NiloToonSurfaceTypePreset.Transparent_ZWrite_Outline
|
|
: NiloToonSurfaceTypePreset.Transparent_ZWrite;
|
|
}
|
|
|
|
private static NiloToonSurfaceTypePreset ResolveLilToonMultiCutoutPreset(
|
|
bool useOutline,
|
|
bool zWrite)
|
|
{
|
|
if (!zWrite)
|
|
{
|
|
return NiloToonSurfaceTypePreset.CutoutTransparent;
|
|
}
|
|
|
|
// NiloToon has no cutout-opaque + transparent-queue preset, so the closest representable family stays in cutout opaque.
|
|
return useOutline
|
|
? NiloToonSurfaceTypePreset.CutoutOpaque_Outline
|
|
: NiloToonSurfaceTypePreset.CutoutOpaque;
|
|
}
|
|
|
|
private static void SetKeyword(Material material, string keyword, bool enabled)
|
|
{
|
|
if (enabled)
|
|
{
|
|
material.EnableKeyword(keyword);
|
|
}
|
|
else
|
|
{
|
|
material.DisableKeyword(keyword);
|
|
}
|
|
}
|
|
|
|
private static readonly Vector4 DefaultTextureScaleOffset = new Vector4(1f, 1f, 0f, 0f);
|
|
|
|
private static bool HasShaderProperty(Material material, string property, ShaderPropertyType propertyType)
|
|
{
|
|
if (!material || !material.shader)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int propertyIndex = material.shader.FindPropertyIndex(property);
|
|
return propertyIndex >= 0 && material.shader.GetPropertyType(propertyIndex) == propertyType;
|
|
}
|
|
|
|
private static bool HasFloatProperty(Material material, string property)
|
|
{
|
|
if (!material || !material.shader)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
int propertyIndex = material.shader.FindPropertyIndex(property);
|
|
if (propertyIndex < 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ShaderPropertyType propertyType = material.shader.GetPropertyType(propertyIndex);
|
|
return propertyType == ShaderPropertyType.Float ||
|
|
propertyType == ShaderPropertyType.Range ||
|
|
propertyType.ToString() == "Int";
|
|
}
|
|
|
|
private static float GetFloatOrDefault(Material material, string property, float defaultValue = 0f)
|
|
{
|
|
return HasFloatProperty(material, property) ? material.GetFloat(property) : defaultValue;
|
|
}
|
|
|
|
private static Color GetColorOrDefault(Material material, string property, Color defaultValue)
|
|
{
|
|
return HasShaderProperty(material, property, ShaderPropertyType.Color) ? material.GetColor(property) : defaultValue;
|
|
}
|
|
|
|
private static Vector4 GetVectorOrDefault(Material material, string property, Vector4 defaultValue)
|
|
{
|
|
return HasShaderProperty(material, property, ShaderPropertyType.Vector) ? material.GetVector(property) : defaultValue;
|
|
}
|
|
|
|
private static Texture GetTextureOrNull(Material material, string property)
|
|
{
|
|
return HasShaderProperty(material, property, ShaderPropertyType.Texture) ? material.GetTexture(property) : null;
|
|
}
|
|
|
|
private static Vector4 GetTextureScaleOffsetOrDefault(Material material, string textureProperty)
|
|
{
|
|
if (!HasShaderProperty(material, textureProperty, ShaderPropertyType.Texture))
|
|
{
|
|
return DefaultTextureScaleOffset;
|
|
}
|
|
|
|
Vector2 scale = material.GetTextureScale(textureProperty);
|
|
Vector2 offset = material.GetTextureOffset(textureProperty);
|
|
return new Vector4(scale.x, scale.y, offset.x, offset.y);
|
|
}
|
|
|
|
private static void CopyFloat(Material source, Material destination, string sourceProperty, string destinationProperty)
|
|
{
|
|
if (!HasFloatProperty(source, sourceProperty) || !HasFloatProperty(destination, destinationProperty))
|
|
{
|
|
return;
|
|
}
|
|
|
|
destination.SetFloat(destinationProperty, source.GetFloat(sourceProperty));
|
|
}
|
|
|
|
private static void CopyColor(Material source, Material destination, string sourceProperty, string destinationProperty)
|
|
{
|
|
if (!HasShaderProperty(source, sourceProperty, ShaderPropertyType.Color) ||
|
|
!HasShaderProperty(destination, destinationProperty, ShaderPropertyType.Color))
|
|
{
|
|
return;
|
|
}
|
|
|
|
destination.SetColor(destinationProperty, source.GetColor(sourceProperty));
|
|
}
|
|
|
|
private static void CopyVector(Material source, Material destination, string sourceProperty, string destinationProperty)
|
|
{
|
|
if (!HasShaderProperty(source, sourceProperty, ShaderPropertyType.Vector) ||
|
|
!HasShaderProperty(destination, destinationProperty, ShaderPropertyType.Vector))
|
|
{
|
|
return;
|
|
}
|
|
|
|
destination.SetVector(destinationProperty, source.GetVector(sourceProperty));
|
|
}
|
|
|
|
private static void CopyTextureWithScaleOffset(Material source, Material destination, string sourceProperty, string destinationProperty)
|
|
{
|
|
if (!HasShaderProperty(source, sourceProperty, ShaderPropertyType.Texture) ||
|
|
!HasShaderProperty(destination, destinationProperty, ShaderPropertyType.Texture))
|
|
{
|
|
return;
|
|
}
|
|
|
|
destination.SetTexture(destinationProperty, source.GetTexture(sourceProperty));
|
|
destination.SetTextureScale(destinationProperty, source.GetTextureScale(sourceProperty));
|
|
destination.SetTextureOffset(destinationProperty, source.GetTextureOffset(sourceProperty));
|
|
}
|
|
|
|
private static void SetFloatIfHasProperty(Material material, string property, float value)
|
|
{
|
|
if (!HasFloatProperty(material, property))
|
|
{
|
|
return;
|
|
}
|
|
|
|
material.SetFloat(property, value);
|
|
}
|
|
|
|
private static void SetColorIfHasProperty(Material material, string property, Color value)
|
|
{
|
|
if (!material.HasProperty(property))
|
|
{
|
|
return;
|
|
}
|
|
|
|
material.SetColor(property, value);
|
|
}
|
|
|
|
private static void SetTextureIfHasProperty(Material material, string property, Texture value)
|
|
{
|
|
if (!material.HasProperty(property))
|
|
{
|
|
return;
|
|
}
|
|
|
|
material.SetTexture(property, value);
|
|
}
|
|
|
|
private static void SetLilToonShadowAOMinMax(Material material, string minProperty, string maxProperty, float scale, float offset)
|
|
{
|
|
if (Mathf.Abs(scale) < 0.00001f)
|
|
{
|
|
SetFloatIfHasProperty(material, minProperty, 0f);
|
|
SetFloatIfHasProperty(material, maxProperty, 1f);
|
|
return;
|
|
}
|
|
|
|
SetFloatIfHasProperty(material, minProperty, Mathf.Clamp(-offset / scale, -0.01f, 1.01f));
|
|
SetFloatIfHasProperty(material, maxProperty, Mathf.Clamp((1f - offset) / scale, -0.01f, 1.01f));
|
|
}
|
|
|
|
private static void PortLilToonShadowAORemap(Material source, Material destination)
|
|
{
|
|
if (HasShaderProperty(source, "_ShadowAOShift", ShaderPropertyType.Vector))
|
|
{
|
|
Vector4 shadowAOShift = source.GetVector("_ShadowAOShift");
|
|
SetLilToonShadowAOMinMax(destination, "_lilShadowAO1Min", "_lilShadowAO1Max", shadowAOShift.x, shadowAOShift.y);
|
|
SetLilToonShadowAOMinMax(destination, "_lilShadowAO2Min", "_lilShadowAO2Max", shadowAOShift.z, shadowAOShift.w);
|
|
}
|
|
|
|
if (HasShaderProperty(source, "_ShadowAOShift2", ShaderPropertyType.Vector))
|
|
{
|
|
Vector4 shadowAOShift2 = source.GetVector("_ShadowAOShift2");
|
|
SetLilToonShadowAOMinMax(destination, "_lilShadowAO3Min", "_lilShadowAO3Max", shadowAOShift2.x, shadowAOShift2.y);
|
|
}
|
|
}
|
|
|
|
private static void PortLilToonShadowModeProperties(Material source, Material destination)
|
|
{
|
|
CopyFloat(source, destination, "_ShadowMaskType", "_lilShadowMaskType");
|
|
CopyTextureWithScaleOffset(source, destination, "_ShadowStrengthMask", "_lilShadowStrengthMask");
|
|
CopyFloat(source, destination, "_ShadowStrength", "_lilShadowStrength");
|
|
CopyFloat(source, destination, "_ShadowStrengthMaskLOD", "_lilShadowStrengthMaskLOD");
|
|
CopyFloat(source, destination, "_ShadowFlatBorder", "_lilShadowFlatBorder");
|
|
CopyFloat(source, destination, "_ShadowFlatBlur", "_lilShadowFlatBlur");
|
|
|
|
CopyFloat(source, destination, "_ShadowColorType", "_lilShadowColorType");
|
|
CopyTextureWithScaleOffset(source, destination, "_ShadowColorTex", "_lilShadowColorTex");
|
|
CopyTextureWithScaleOffset(source, destination, "_Shadow2ndColorTex", "_lilShadow2ndColorTex");
|
|
CopyTextureWithScaleOffset(source, destination, "_Shadow3rdColorTex", "_lilShadow3rdColorTex");
|
|
CopyColor(source, destination, "_ShadowColor", "_lilShadowColor");
|
|
CopyColor(source, destination, "_Shadow2ndColor", "_lilShadow2ndColor");
|
|
CopyColor(source, destination, "_Shadow3rdColor", "_lilShadow3rdColor");
|
|
CopyFloat(source, destination, "_ShadowBorder", "_lilShadowBorder");
|
|
CopyFloat(source, destination, "_ShadowBlur", "_lilShadowBlur");
|
|
CopyFloat(source, destination, "_ShadowNormalStrength", "_lilShadowNormalStrength");
|
|
CopyFloat(source, destination, "_ShadowReceive", "_lilShadowReceive");
|
|
CopyFloat(source, destination, "_Shadow2ndBorder", "_lilShadow2ndBorder");
|
|
CopyFloat(source, destination, "_Shadow2ndBlur", "_lilShadow2ndBlur");
|
|
CopyFloat(source, destination, "_Shadow2ndNormalStrength", "_lilShadow2ndNormalStrength");
|
|
CopyFloat(source, destination, "_Shadow2ndReceive", "_lilShadow2ndReceive");
|
|
CopyFloat(source, destination, "_Shadow3rdBorder", "_lilShadow3rdBorder");
|
|
CopyFloat(source, destination, "_Shadow3rdBlur", "_lilShadow3rdBlur");
|
|
CopyFloat(source, destination, "_Shadow3rdNormalStrength", "_lilShadow3rdNormalStrength");
|
|
CopyFloat(source, destination, "_Shadow3rdReceive", "_lilShadow3rdReceive");
|
|
|
|
CopyColor(source, destination, "_ShadowBorderColor", "_lilShadowBorderColor");
|
|
CopyFloat(source, destination, "_ShadowBorderRange", "_lilShadowBorderRange");
|
|
CopyFloat(source, destination, "_ShadowMainStrength", "_lilShadowMainStrength");
|
|
CopyFloat(source, destination, "_ShadowEnvStrength", "_lilShadowEnvStrength");
|
|
CopyFloat(source, destination, "_AAStrength", "_lilAAStrength");
|
|
|
|
CopyTextureWithScaleOffset(source, destination, "_ShadowBlurMask", "_lilShadowBlurMask");
|
|
CopyFloat(source, destination, "_ShadowBlurMaskLOD", "_lilShadowBlurMaskLOD");
|
|
CopyTextureWithScaleOffset(source, destination, "_ShadowBorderMask", "_lilShadowBorderMask");
|
|
CopyFloat(source, destination, "_ShadowBorderMaskLOD", "_lilShadowBorderMaskLOD");
|
|
CopyFloat(source, destination, "_ShadowPostAO", "_lilShadowPostAO");
|
|
}
|
|
|
|
private static void DisableNativeNiloMatCapGroups(Material material)
|
|
{
|
|
material.SetFloat("_UseMatCapAlphaBlend", 0);
|
|
material.SetFloat("_UseMatCapAdditive", 0);
|
|
material.SetFloat("_UseMatCapOcclusion", 0);
|
|
material.DisableKeyword("_MATCAP_BLEND");
|
|
material.DisableKeyword("_MATCAP_ADD");
|
|
material.DisableKeyword("_MATCAP_OCCLUSION");
|
|
}
|
|
|
|
private static void PortLilToonMatCapLayerToGeneric(
|
|
Material source,
|
|
Material destination,
|
|
string sourceUse,
|
|
string destinationUse,
|
|
string destinationKeyword,
|
|
string sourceColor,
|
|
string destinationColor,
|
|
string sourceMap,
|
|
string destinationMap,
|
|
string sourceMainStrength,
|
|
string destinationMainStrength,
|
|
string sourceBlendUv1,
|
|
string destinationBlendUv1,
|
|
string sourceZRotCancel,
|
|
string destinationZRotCancel,
|
|
string sourcePerspective,
|
|
string destinationPerspective,
|
|
string sourceVrParallaxStrength,
|
|
string destinationVrParallaxStrength,
|
|
string sourceBlend,
|
|
string destinationBlend,
|
|
string sourceMask,
|
|
string destinationMask,
|
|
string sourceEnableLighting,
|
|
string destinationEnableLighting,
|
|
string sourceShadowMask,
|
|
string destinationShadowMask,
|
|
string sourceBackfaceMask,
|
|
string destinationBackfaceMask,
|
|
string sourceLod,
|
|
string destinationLod,
|
|
string sourceBlendMode,
|
|
string destinationBlendMode,
|
|
string sourceApplyTransparency,
|
|
string destinationApplyTransparency,
|
|
string sourceNormalStrength,
|
|
string destinationNormalStrength,
|
|
string sourceUseCustomNormal,
|
|
string destinationUseCustomNormal,
|
|
string destinationCustomNormalKeyword,
|
|
string sourceBumpMap,
|
|
string destinationBumpMap,
|
|
string sourceBumpScale,
|
|
string destinationBumpScale)
|
|
{
|
|
CopyFloat(source, destination, sourceUse, destinationUse);
|
|
CopyColor(source, destination, sourceColor, destinationColor);
|
|
CopyTextureWithScaleOffset(source, destination, sourceMap, destinationMap);
|
|
CopyFloat(source, destination, sourceMainStrength, destinationMainStrength);
|
|
CopyVector(source, destination, sourceBlendUv1, destinationBlendUv1);
|
|
CopyFloat(source, destination, sourceZRotCancel, destinationZRotCancel);
|
|
CopyFloat(source, destination, sourcePerspective, destinationPerspective);
|
|
CopyFloat(source, destination, sourceVrParallaxStrength, destinationVrParallaxStrength);
|
|
CopyFloat(source, destination, sourceBlend, destinationBlend);
|
|
CopyTextureWithScaleOffset(source, destination, sourceMask, destinationMask);
|
|
CopyFloat(source, destination, sourceEnableLighting, destinationEnableLighting);
|
|
CopyFloat(source, destination, sourceShadowMask, destinationShadowMask);
|
|
CopyFloat(source, destination, sourceBackfaceMask, destinationBackfaceMask);
|
|
CopyFloat(source, destination, sourceLod, destinationLod);
|
|
CopyFloat(source, destination, sourceBlendMode, destinationBlendMode);
|
|
CopyFloat(source, destination, sourceApplyTransparency, destinationApplyTransparency);
|
|
CopyFloat(source, destination, sourceNormalStrength, destinationNormalStrength);
|
|
CopyFloat(source, destination, sourceUseCustomNormal, destinationUseCustomNormal);
|
|
CopyTextureWithScaleOffset(source, destination, sourceBumpMap, destinationBumpMap);
|
|
CopyFloat(source, destination, sourceBumpScale, destinationBumpScale);
|
|
|
|
bool isEnabled = HasFloatProperty(source, sourceUse) && source.GetFloat(sourceUse) > 0.5f;
|
|
bool useCustomNormal = HasFloatProperty(source, sourceUseCustomNormal) && source.GetFloat(sourceUseCustomNormal) > 0.5f;
|
|
|
|
SetKeyword(destination, destinationKeyword, isEnabled);
|
|
SetKeyword(destination, destinationCustomNormalKeyword, isEnabled && useCustomNormal);
|
|
}
|
|
|
|
private static void PortLilToonRimToGenericRimLight3D(Material source, Material destination)
|
|
{
|
|
CopyFloat(source, destination, "_UseRim", "_UseGenericRimLight3D");
|
|
CopyColor(source, destination, "_RimColor", "_GenericRimLight3DColor");
|
|
CopyTextureWithScaleOffset(source, destination, "_RimColorTex", "_GenericRimLight3DColorTex");
|
|
CopyFloat(source, destination, "_RimMainStrength", "_GenericRimLight3DMainStrength");
|
|
CopyFloat(source, destination, "_RimEnableLighting", "_GenericRimLight3DEnableLighting");
|
|
CopyFloat(source, destination, "_RimShadowMask", "_GenericRimLight3DShadowMask");
|
|
CopyFloat(source, destination, "_RimBackfaceMask", "_GenericRimLight3DBackfaceMask");
|
|
CopyFloat(source, destination, "_RimBlendMode", "_GenericRimLight3DBlendMode");
|
|
CopyFloat(source, destination, "_RimDirStrength", "_GenericRimLight3DDirStrength");
|
|
CopyFloat(source, destination, "_RimDirRange", "_GenericRimLight3DDirRange");
|
|
CopyFloat(source, destination, "_RimBorder", "_GenericRimLight3DBorder");
|
|
CopyFloat(source, destination, "_RimBlur", "_GenericRimLight3DBlur");
|
|
CopyFloat(source, destination, "_RimIndirRange", "_GenericRimLight3DIndirRange");
|
|
CopyColor(source, destination, "_RimIndirColor", "_GenericRimLight3DIndirColor");
|
|
CopyFloat(source, destination, "_RimIndirBorder", "_GenericRimLight3DIndirBorder");
|
|
CopyFloat(source, destination, "_RimIndirBlur", "_GenericRimLight3DIndirBlur");
|
|
CopyFloat(source, destination, "_RimNormalStrength", "_GenericRimLight3DNormalStrength");
|
|
CopyFloat(source, destination, "_RimFresnelPower", "_GenericRimLight3DFresnelPower");
|
|
CopyFloat(source, destination, "_RimVRParallaxStrength", "_GenericRimLight3DVRParallaxStrength");
|
|
|
|
if (destination.HasProperty("_GenericRimLight3DAlpha"))
|
|
{
|
|
destination.SetFloat("_GenericRimLight3DAlpha", 1f);
|
|
}
|
|
|
|
bool isEnabled = HasFloatProperty(source, "_UseRim") && source.GetFloat("_UseRim") > 0.5f;
|
|
SetKeyword(destination, "_GENERIC_RIMLIGHT3D", isEnabled);
|
|
}
|
|
|
|
private static void SetFloatClampedIfHasProperty(Material source, Material destination, string sourceProperty, string destinationProperty, float min, float max)
|
|
{
|
|
if (!source.HasProperty(sourceProperty) || !destination.HasProperty(destinationProperty))
|
|
{
|
|
return;
|
|
}
|
|
|
|
destination.SetFloat(destinationProperty, Mathf.Clamp(source.GetFloat(sourceProperty), min, max));
|
|
}
|
|
|
|
private static void SetNiloFurNoiseTilingFromLilToon(Material source, Material destination)
|
|
{
|
|
if (!source.HasProperty("_FurNoiseMask") || !destination.HasProperty("_NiloFurNoiseTiling"))
|
|
{
|
|
return;
|
|
}
|
|
|
|
Vector2 scale = source.GetTextureScale("_FurNoiseMask");
|
|
Vector2 offset = source.GetTextureOffset("_FurNoiseMask");
|
|
destination.SetVector("_NiloFurNoiseTiling", new Vector4(scale.x, scale.y, offset.x, offset.y));
|
|
}
|
|
|
|
private static void SetDefaultFurNoiseIfNeeded(Material destination)
|
|
{
|
|
if (!destination.HasProperty("_NiloFurNoiseTex") || destination.GetTexture("_NiloFurNoiseTex") != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Texture2D defaultFurNoise =
|
|
AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/NiloToonURP/Textures/NiloFurNoise.png");
|
|
if (defaultFurNoise != null)
|
|
{
|
|
destination.SetTexture("_NiloFurNoiseTex", defaultFurNoise);
|
|
}
|
|
}
|
|
|
|
private static void PortLilToonFurProperties(Material source, Material destination)
|
|
{
|
|
if (!IsLilToonFurMaterial(source))
|
|
{
|
|
return;
|
|
}
|
|
|
|
SetMaterialNiloToonSurfaceTypeAndProperties(destination, NiloToonSurfaceTypePreset.CutoutOpaque);
|
|
|
|
SetFloatIfHasProperty(destination, "_EnableFur", 1f);
|
|
SetFloatIfHasProperty(destination, "_NiloFurStrength", 1f);
|
|
SetFloatIfHasProperty(destination, "_AllowRenderURPUniversalForwardOnlyPass", 1f);
|
|
SetKeyword(destination, "_NILOTOON_FUR", true);
|
|
|
|
destination.SetShaderPassEnabled("UniversalForwardOnly", true);
|
|
destination.SetShaderPassEnabled("NiloToonFur", true);
|
|
destination.SetShaderPassEnabled("NiloToonFurDepthPrepass", true);
|
|
destination.SetShaderPassEnabled("NiloToonFurPrepassBufferDepth", true);
|
|
destination.SetShaderPassEnabled("NiloToonFurPrepassBufferAlpha", true);
|
|
|
|
CopyTextureWithScaleOffset(source, destination, "_FurNoiseMask", "_NiloFurNoiseTex");
|
|
SetNiloFurNoiseTilingFromLilToon(source, destination);
|
|
SetDefaultFurNoiseIfNeeded(destination);
|
|
|
|
CopyTextureWithScaleOffset(source, destination, "_FurMask", "_NiloFurMask");
|
|
CopyTextureWithScaleOffset(source, destination, "_FurLengthMask", "_NiloFurLengthMask");
|
|
CopyTextureWithScaleOffset(source, destination, "_FurVectorTex", "_NiloFurVectorTex");
|
|
bool hasVectorTexture = destination.HasProperty("_NiloFurVectorTex") &&
|
|
destination.GetTexture("_NiloFurVectorTex") != null;
|
|
SetKeyword(destination, "_NILOTOON_FUR_VECTORTEX", hasVectorTexture);
|
|
|
|
CopyFloat(source, destination, "_FurVectorScale", "_NiloFurVectorScale");
|
|
if (source.HasProperty("_FurVector") && destination.HasProperty("_NiloFurVector"))
|
|
{
|
|
Vector4 furVector = source.GetVector("_FurVector");
|
|
destination.SetVector("_NiloFurVector", new Vector4(furVector.x, furVector.y, furVector.z, 0f));
|
|
SetFloatIfHasProperty(destination, "_NiloFurLength", Mathf.Max(0f, furVector.w));
|
|
}
|
|
|
|
CopyFloat(source, destination, "_VertexColor2FurVector", "_VertexColor2FurVector");
|
|
CopyFloat(source, destination, "_FurGravity", "_NiloFurGravity");
|
|
CopyFloat(source, destination, "_FurRandomize", "_NiloFurRandomize");
|
|
CopyFloat(source, destination, "_FurRootOffset", "_NiloFurRootOffset");
|
|
CopyFloat(source, destination, "_FurCutoutLength", "_NiloFurCutoutLength");
|
|
CopyFloat(source, destination, "_FurCull", "_NiloFurCull");
|
|
CopyColor(source, destination, "_FurRimColor", "_NiloFurRimColor");
|
|
CopyFloat(source, destination, "_FurRimFresnelPower", "_NiloFurRimFresnelPower");
|
|
CopyFloat(source, destination, "_FurRimAntiLight", "_NiloFurRimAntiLight");
|
|
|
|
if (source.HasProperty("_FurAO"))
|
|
{
|
|
float furAO = source.GetFloat("_FurAO");
|
|
SetFloatIfHasProperty(destination, "_NiloFurOcclusionShadowAO", furAO);
|
|
SetFloatIfHasProperty(destination, "_NiloFurColorDarkenAO", furAO);
|
|
}
|
|
|
|
SetFloatClampedIfHasProperty(source, destination, "_FurLayerNum", "_NiloFurLayerNum", 1f, 2f);
|
|
}
|
|
|
|
private static void PortLilToonEnvironmentReflectionProperties(Material source, Material destination)
|
|
{
|
|
float useEnvironmentReflection =
|
|
GetFloatOrDefault(source, "_UseReflection", 0f) *
|
|
GetFloatOrDefault(source, "_ApplyReflection", 0f);
|
|
// Keep the native NiloToon environment reflection group as data-only for lilToon conversion.
|
|
// The actual lilToon-compatible shading path is handled separately by Generic Reflection.
|
|
SetFloatIfHasProperty(destination, "_ReceiveEnvironmentReflection", 0f);
|
|
SetKeyword(destination, "_ENVIRONMENTREFLECTIONS", false);
|
|
|
|
Color reflectionColor = GetColorOrDefault(source, "_ReflectionColor", Color.white);
|
|
Color cubeColor = GetColorOrDefault(source, "_ReflectionCubeColor", Color.white);
|
|
SetFloatIfHasProperty(destination, "_EnvironmentReflectionUsage", reflectionColor.a);
|
|
// lilToon uses _Reflectance as the dielectric Fresnel input, not as total environment brightness.
|
|
SetFloatIfHasProperty(destination, "_EnvironmentReflectionBrightness", 1f);
|
|
SetFloatIfHasProperty(destination, "_EnvironmentReflectionTintAlbedo",
|
|
GetFloatOrDefault(source, "_Metallic", 0f));
|
|
SetColorIfHasProperty(destination, "_EnvironmentReflectionColor",
|
|
new Color(
|
|
reflectionColor.r * cubeColor.r,
|
|
reflectionColor.g * cubeColor.g,
|
|
reflectionColor.b * cubeColor.b,
|
|
1f));
|
|
|
|
Texture reflectionColorTex = source.HasProperty("_ReflectionColorTex")
|
|
? source.GetTexture("_ReflectionColorTex")
|
|
: null;
|
|
SetTextureIfHasProperty(destination, "_EnvironmentReflectionColorMaskMap", reflectionColorTex);
|
|
|
|
float lilToonBlendMode = GetFloatOrDefault(source, "_ReflectionBlendMode", 1f);
|
|
bool useAdditiveBlend = Mathf.Approximately(lilToonBlendMode, 1f) || Mathf.Approximately(lilToonBlendMode, 2f);
|
|
SetFloatIfHasProperty(destination, "_EnvironmentReflectionApplyReplaceBlending", useAdditiveBlend ? 0f : 1f);
|
|
SetFloatIfHasProperty(destination, "_EnvironmentReflectionApplyAddBlending", useAdditiveBlend ? 1f : 0f);
|
|
|
|
Texture reflectionCubemap = source.HasProperty("_ReflectionCubeTex")
|
|
? source.GetTexture("_ReflectionCubeTex")
|
|
: null;
|
|
SetTextureIfHasProperty(destination, "_EnvironmentReflectionOverrideCubemap", reflectionCubemap);
|
|
|
|
bool useOverrideCubemap =
|
|
useEnvironmentReflection > 0.5f &&
|
|
GetFloatOrDefault(source, "_ReflectionCubeOverride", 0f) > 0.5f &&
|
|
reflectionCubemap != null;
|
|
SetFloatIfHasProperty(destination, "_EnvironmentReflectionOverrideCubemapOn", useOverrideCubemap ? 1f : 0f);
|
|
SetKeyword(destination, "_ENVIRONMENTREFLECTIONS_OVERRIDE_CUBEMAP", false);
|
|
}
|
|
|
|
private static void PortLilToonReflectionToGenericReflection(Material source, Material destination)
|
|
{
|
|
float useReflection = GetFloatOrDefault(source, "_UseReflection", 0f);
|
|
float applySpecular = GetFloatOrDefault(source, "_ApplySpecular", 1f);
|
|
float applyReflection = GetFloatOrDefault(source, "_ApplyReflection", 0f);
|
|
Texture reflectionCubemap = source.HasProperty("_ReflectionCubeTex")
|
|
? source.GetTexture("_ReflectionCubeTex")
|
|
: null;
|
|
bool useGenericReflection = useReflection > 0.5f;
|
|
|
|
SetFloatIfHasProperty(destination, "_UseGenericReflection", useGenericReflection ? 1f : 0f);
|
|
SetKeyword(destination, "_GENERIC_REFLECTION", useGenericReflection);
|
|
|
|
SetTextureIfHasProperty(destination, "_GenericReflectionCubemap", reflectionCubemap);
|
|
CopyTextureWithScaleOffset(source, destination, "_SmoothnessTex", "_GenericReflectionSmoothnessMap");
|
|
CopyTextureWithScaleOffset(source, destination, "_ReflectionColorTex", "_GenericReflectionColorMaskMap");
|
|
CopyTextureWithScaleOffset(source, destination, "_MetallicGlossMap", "_GenericReflectionMetallicMap");
|
|
|
|
Color reflectionColor = GetColorOrDefault(source, "_ReflectionColor", Color.white);
|
|
SetColorIfHasProperty(destination, "_GenericReflectionColor", reflectionColor);
|
|
SetColorIfHasProperty(destination, "_GenericReflectionCubeColor",
|
|
GetColorOrDefault(source, "_ReflectionCubeColor", Color.black));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionBlend", 1f);
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionBlendMode",
|
|
GetFloatOrDefault(source, "_ReflectionBlendMode", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionSmoothness",
|
|
GetFloatOrDefault(source, "_Smoothness", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionGSAAStrength",
|
|
GetFloatOrDefault(source, "_GSAAStrength", 0f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionApplySpecular", applySpecular);
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionApplySpecularFA",
|
|
GetFloatOrDefault(source, "_ApplySpecularFA", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionSpecularToon",
|
|
GetFloatOrDefault(source, "_SpecularToon", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionSpecularNormalStrength",
|
|
GetFloatOrDefault(source, "_SpecularNormalStrength", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionSpecularBorder",
|
|
GetFloatOrDefault(source, "_SpecularBorder", 0.5f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionSpecularBlur",
|
|
GetFloatOrDefault(source, "_SpecularBlur", 0f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionApplyReflection", applyReflection);
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionReflectance",
|
|
GetFloatOrDefault(source, "_Reflectance", 0.04f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionMetallic",
|
|
GetFloatOrDefault(source, "_Metallic", 0f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionCubeOverride",
|
|
GetFloatOrDefault(source, "_ReflectionCubeOverride", 0f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionCubeEnableLighting",
|
|
GetFloatOrDefault(source, "_ReflectionCubeEnableLighting", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionApplyTransparency",
|
|
GetFloatOrDefault(source, "_ReflectionApplyTransparency", 1f));
|
|
SetFloatIfHasProperty(destination, "_GenericReflectionNormalStrength",
|
|
GetFloatOrDefault(source, "_ReflectionNormalStrength", 1f));
|
|
}
|
|
|
|
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",
|
|
GetFloatOrDefault(fromlilToonMat, "_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)
|
|
SetFloatIfHasProperty(toNiloToonMat, "_AsUnlit", 0f);
|
|
// (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",
|
|
GetFloatOrDefault(fromlilToonMat,
|
|
"_BackfaceForceShadow")); // lilToon: float bfshadow = (fd.facing < 0.0) ? 1.0 - _BackfaceForceShadow : 1.0;
|
|
toNiloToonMat.SetColor("_BackFaceBaseMapReplaceColor",
|
|
GetColorOrDefault(fromlilToonMat,
|
|
"_BackfaceColor",
|
|
Color.clear)); // 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))
|
|
// (Same via lilToon shadow mode) _lilAAStrength
|
|
// (?) _UseDither (lilToon: dither fade0out per material)
|
|
// (?) _DitherTex (lilToon: dither fadeout per material)
|
|
// (?) _DitherMaxValue (lilToon: dither fadeout per material)
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Main
|
|
toNiloToonMat.SetColor("_BaseColor", GetColorOrDefault(fromlilToonMat, "_Color", Color.white));
|
|
toNiloToonMat.SetTexture("_BaseMap", GetTextureOrNull(fromlilToonMat, "_MainTex"));
|
|
toNiloToonMat.SetVector("_BaseMap_ST", GetTextureScaleOffsetOrDefault(fromlilToonMat, "_MainTex")); // auto uniform by Unity
|
|
// (!) _MainTex_ScrollRotate // TODO: apply the BaseMap's uv, not UV0!
|
|
if (HasShaderProperty(fromlilToonMat, "_MainTexHSVG", ShaderPropertyType.Vector))
|
|
{
|
|
Vector4 mainTexHSVG = GetVectorOrDefault(fromlilToonMat, "_MainTexHSVG", new Vector4(0f, 1f, 1f, 1f));
|
|
toNiloToonMat.SetFloat("_BaseMapHue", mainTexHSVG.x);
|
|
toNiloToonMat.SetFloat("_BaseMapSaturation", mainTexHSVG.y);
|
|
toNiloToonMat.SetFloat("_BaseMapValue", mainTexHSVG.z);
|
|
toNiloToonMat.SetFloat("_BaseMapGamma", mainTexHSVG.w);
|
|
}
|
|
// (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)
|
|
Texture baseMapHSVGMaskTex = GetTextureOrNull(fromlilToonMat, "_MainColorAdjustMask");
|
|
toNiloToonMat.SetFloat("_UseBaseMapHSVGMask", baseMapHSVGMaskTex ? 1 : 0);
|
|
toNiloToonMat.SetTexture("_BaseMapHSVGMaskTex", baseMapHSVGMaskTex);
|
|
if (baseMapHSVGMaskTex)
|
|
{
|
|
toNiloToonMat.EnableKeyword("_BASEMAP_HSVG_MASK");
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.DisableKeyword("_BASEMAP_HSVG_MASK");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Main2nd (port to NiloToon's BaseMapStackingLayer1)
|
|
float _UseMain2ndTex = GetFloatOrDefault(fromlilToonMat, "_UseMain2ndTex");
|
|
toNiloToonMat.SetFloat("_BaseMapStackingLayer1Enable", _UseMain2ndTex);
|
|
if (_UseMain2ndTex > 0.5)
|
|
{
|
|
toNiloToonMat.EnableKeyword("_BASEMAP_STACKING_LAYER1");
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.DisableKeyword("_BASEMAP_STACKING_LAYER1");
|
|
}
|
|
|
|
toNiloToonMat.SetColor("_BaseMapStackingLayer1TintColor", GetColorOrDefault(fromlilToonMat, "_Color2nd", Color.white));
|
|
toNiloToonMat.SetTexture("_BaseMapStackingLayer1Tex", GetTextureOrNull(fromlilToonMat, "_Main2ndTex"));
|
|
toNiloToonMat.SetVector("_BaseMapStackingLayer1TexUVScaleOffset",
|
|
GetTextureScaleOffsetOrDefault(fromlilToonMat, "_Main2ndTex"));
|
|
|
|
// liltoon / nilotoon are both in degree
|
|
toNiloToonMat.SetFloat("_BaseMapStackingLayer1TexUVRotatedAngle",
|
|
GetFloatOrDefault(fromlilToonMat, "_Main2ndTexAngle") * 180f / Mathf.PI);
|
|
|
|
{
|
|
Vector4 _Main2ndTex_ScrollRotate = GetVectorOrDefault(fromlilToonMat, "_Main2ndTex_ScrollRotate", Vector4.zero);
|
|
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", GetFloatOrDefault(fromlilToonMat, "_Main2ndTex_UVMode"));
|
|
toNiloToonMat.SetFloat("_BaseMapStackingLayer1ApplytoFaces", GetFloatOrDefault(fromlilToonMat, "_Main2ndTex_Cull"));
|
|
// (X) _Main2ndTexDecalAnimation
|
|
// (X) _Main2ndTexDecalSubParam
|
|
// (X) _Main2ndTexIsDecal
|
|
// (X) _Main2ndTexIsLeftOnly
|
|
// (X) _Main2ndTexIsRightOnly
|
|
// (X) _Main2ndTexShouldCopy
|
|
// (X) _Main2ndTexShouldFlipMirror
|
|
// (X) _Main2ndTexShouldFlipCopy
|
|
// (X) _Main2ndTexIsMSDF
|
|
toNiloToonMat.SetTexture("_BaseMapStackingLayer1MaskTex", GetTextureOrNull(fromlilToonMat, "_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 = GetFloatOrDefault(fromlilToonMat, "_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 = GetFloatOrDefault(fromlilToonMat, "_UseMain3rdTex");
|
|
toNiloToonMat.SetFloat("_BaseMapStackingLayer2Enable", _UseMain3rdTex);
|
|
if (_UseMain3rdTex == 1)
|
|
{
|
|
toNiloToonMat.EnableKeyword("_BASEMAP_STACKING_LAYER2");
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.DisableKeyword("_BASEMAP_STACKING_LAYER2");
|
|
}
|
|
|
|
toNiloToonMat.SetColor("_BaseMapStackingLayer2TintColor", GetColorOrDefault(fromlilToonMat, "_Color3rd", Color.white));
|
|
toNiloToonMat.SetTexture("_BaseMapStackingLayer2Tex", GetTextureOrNull(fromlilToonMat, "_Main3rdTex"));
|
|
toNiloToonMat.SetVector("_BaseMapStackingLayer2TexUVScaleOffset",
|
|
GetTextureScaleOffsetOrDefault(fromlilToonMat, "_Main3rdTex"));
|
|
|
|
// liltoon / nilotoon are both in degree
|
|
toNiloToonMat.SetFloat("_BaseMapStackingLayer2TexUVRotatedAngle",
|
|
GetFloatOrDefault(fromlilToonMat, "_Main3rdTexAngle"));
|
|
|
|
{
|
|
Vector4 _Main3rdTex_ScrollRotate = GetVectorOrDefault(fromlilToonMat, "_Main3rdTex_ScrollRotate", Vector4.zero);
|
|
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", GetFloatOrDefault(fromlilToonMat, "_Main3rdTex_UVMode"));
|
|
toNiloToonMat.SetFloat("_BaseMapStackingLayer2ApplytoFaces", GetFloatOrDefault(fromlilToonMat, "_Main3rdTex_Cull"));
|
|
// (X) _Main3rdTexDecalAnimation
|
|
// (X) _Main3rdTexDecalSubParam
|
|
// (X) _Main3rdTexIsDecal
|
|
// (X) _Main3rdTexIsLeftOnly
|
|
// (X) _Main3rdTexIsRightOnly
|
|
// (X) _Main3rdTexShouldCopy
|
|
// (X) _Main3rdTexShouldFlipMirror
|
|
// (X) _Main3rdTexShouldFlipCopy
|
|
// (X) _Main3rdTexIsMSDF
|
|
toNiloToonMat.SetTexture("_BaseMapStackingLayer2MaskTex", GetTextureOrNull(fromlilToonMat, "_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 = GetFloatOrDefault(fromlilToonMat, "_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)GetFloatOrDefault(fromlilToonMat, "_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", GetTextureOrNull(fromlilToonMat, "_AlphaMask"));
|
|
|
|
// liltoon GUI's invert toggle is not a property, it translate to a MAD (* scale + value)
|
|
toNiloToonMat.SetFloat("_AlphaOverrideTexValueScale", GetFloatOrDefault(fromlilToonMat, "_AlphaMaskScale", 1f));
|
|
toNiloToonMat.SetFloat("_AlphaOverrideTexValueOffset", GetFloatOrDefault(fromlilToonMat, "_AlphaMaskValue"));
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// NormalMap
|
|
int _UseBumpMap = (int)GetFloatOrDefault(fromlilToonMat, "_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", GetFloatOrDefault(fromlilToonMat, "_UseShadow"));
|
|
SetFloatIfHasProperty(toNiloToonMat, "_ShadowColorMode", 1f);
|
|
SetKeyword(toNiloToonMat, "_SHADOW_MODE_LILTOON", true);
|
|
|
|
PortLilToonShadowModeProperties(fromlilToonMat, toNiloToonMat);
|
|
|
|
float shadowNormalStrength = GetFloatOrDefault(fromlilToonMat, "_ShadowNormalStrength", 1f);
|
|
toNiloToonMat.SetFloat("_MainLightSkinDiffuseNormalMapStrength", shadowNormalStrength);
|
|
toNiloToonMat.SetFloat("_MainLightNonSkinDiffuseNormalMapStrength", shadowNormalStrength);
|
|
PortLilToonShadowAORemap(fromlilToonMat, toNiloToonMat);
|
|
|
|
Texture2D occlusionMap = GetTextureOrNull(fromlilToonMat, "_ShadowBorderMask") as Texture2D;
|
|
toNiloToonMat.SetTexture("_OcclusionMap", occlusionMap);
|
|
toNiloToonMat.SetFloat("_UseOcclusion", 0);
|
|
toNiloToonMat.DisableKeyword("_OCCLUSIONMAP");
|
|
|
|
// _ShadowMainStrength -> _SelfShadowAlbedoMulStrength (both Range(0,1), copied 1:1).
|
|
// Note: lite variants (ltsl_*) don't declare _ShadowMainStrength; CopyFloat silently no-ops via HasProperty.
|
|
CopyFloat(fromlilToonMat, toNiloToonMat, "_ShadowMainStrength", "_SelfShadowAlbedoMulStrength");
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Rim Shade
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Reflection
|
|
PortLilToonEnvironmentReflectionProperties(fromlilToonMat, toNiloToonMat);
|
|
PortLilToonReflectionToGenericReflection(fromlilToonMat, toNiloToonMat);
|
|
|
|
bool genericReflectionOwnsLilToonSpecular =
|
|
GetFloatOrDefault(toNiloToonMat, "_UseGenericReflection", 0f) > 0.5f;
|
|
float useLilToonDirectSpecular =
|
|
genericReflectionOwnsLilToonSpecular
|
|
? 0f
|
|
: GetFloatOrDefault(fromlilToonMat, "_UseReflection") * GetFloatOrDefault(fromlilToonMat, "_ApplySpecular");
|
|
toNiloToonMat.SetFloat("_UseSpecular", useLilToonDirectSpecular);
|
|
if (useLilToonDirectSpecular > 0.5f)
|
|
{
|
|
toNiloToonMat.EnableKeyword("_SPECULARHIGHLIGHTS");
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.DisableKeyword("_SPECULARHIGHLIGHTS");
|
|
}
|
|
|
|
toNiloToonMat.SetFloat("_UseGGXDirectSpecular", GetFloatOrDefault(fromlilToonMat, "_SpecularToon", 1f) > 0.5f ? 0 : 1);
|
|
toNiloToonMat.SetFloat("_Smoothness", GetFloatOrDefault(fromlilToonMat, "_Smoothness", toNiloToonMat.GetFloat("_Smoothness")));
|
|
|
|
Texture2D smoothnessMap = GetTextureOrNull(fromlilToonMat, "_SmoothnessTex") as Texture2D;
|
|
toNiloToonMat.SetTexture("_SmoothnessMap", smoothnessMap);
|
|
if (smoothnessMap)
|
|
{
|
|
toNiloToonMat.SetFloat("_UseSmoothnessMap", 1);
|
|
toNiloToonMat.EnableKeyword("_SMOOTHNESSMAP");
|
|
toNiloToonMat.SetFloat("_SmoothnessMapInputIsRoughnessMap", 0);
|
|
toNiloToonMat.SetVector("_SmoothnessMapChannelMask", new Vector4(1, 0, 0, 0));
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.SetFloat("_UseSmoothnessMap", 0);
|
|
toNiloToonMat.DisableKeyword("_SMOOTHNESSMAP");
|
|
}
|
|
|
|
Color reflectionColor = GetColorOrDefault(fromlilToonMat, "_ReflectionColor", Color.white);
|
|
toNiloToonMat.SetFloat("_SpecularIntensity",
|
|
GetFloatOrDefault(fromlilToonMat, "_Reflectance") * reflectionColor.a);
|
|
toNiloToonMat.SetColor("_SpecularColor",
|
|
new Color(reflectionColor.r, reflectionColor.g, reflectionColor.b, 1));
|
|
toNiloToonMat.SetFloat("_MultiplyBaseColorToSpecularColor", GetFloatOrDefault(fromlilToonMat, "_Metallic"));
|
|
|
|
Texture2D reflectionColorTintMap = GetTextureOrNull(fromlilToonMat, "_ReflectionColorTex") as Texture2D;
|
|
toNiloToonMat.SetTexture("_SpecularColorTintMap", reflectionColorTintMap);
|
|
if (reflectionColorTintMap && !genericReflectionOwnsLilToonSpecular)
|
|
{
|
|
toNiloToonMat.SetFloat("_UseSpecularColorTintMap", 1);
|
|
toNiloToonMat.EnableKeyword("_SPECULARHIGHLIGHTS_TEX_TINT");
|
|
toNiloToonMat.SetFloat("_SpecularColorTintMapUsage", 1);
|
|
|
|
string reflectionColorTintMapPath = AssetDatabase.GetAssetPath(reflectionColorTintMap);
|
|
TextureImporter reflectionColorTintMapImporter =
|
|
string.IsNullOrEmpty(reflectionColorTintMapPath)
|
|
? null
|
|
: AssetImporter.GetAtPath(reflectionColorTintMapPath) as TextureImporter;
|
|
bool reflectionColorTintMapHasAlpha = reflectionColorTintMapImporter != null &&
|
|
reflectionColorTintMapImporter.DoesSourceTextureHaveAlpha();
|
|
if (reflectionColorTintMapHasAlpha)
|
|
{
|
|
toNiloToonMat.SetTexture("_SpecularMap", reflectionColorTintMap);
|
|
toNiloToonMat.SetVector("_SpecularMapChannelMask", new Vector4(0, 0, 0, 1));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.SetFloat("_UseSpecularColorTintMap", 0);
|
|
toNiloToonMat.DisableKeyword("_SPECULARHIGHLIGHTS_TEX_TINT");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// MatCap
|
|
DisableNativeNiloMatCapGroups(toNiloToonMat);
|
|
PortLilToonMatCapLayerToGeneric(
|
|
fromlilToonMat,
|
|
toNiloToonMat,
|
|
"_UseMatCap",
|
|
"_UseGenericMatCap1",
|
|
"_GENERIC_MATCAP1",
|
|
"_MatCapColor",
|
|
"_GenericMatCap1Color",
|
|
"_MatCapTex",
|
|
"_GenericMatCap1Map",
|
|
"_MatCapMainStrength",
|
|
"_GenericMatCap1MainStrength",
|
|
"_MatCapBlendUV1",
|
|
"_GenericMatCap1BlendUV1",
|
|
"_MatCapZRotCancel",
|
|
"_GenericMatCap1ZRotCancel",
|
|
"_MatCapPerspective",
|
|
"_GenericMatCap1Perspective",
|
|
"_MatCapVRParallaxStrength",
|
|
"_GenericMatCap1VRParallaxStrength",
|
|
"_MatCapBlend",
|
|
"_GenericMatCap1Blend",
|
|
"_MatCapBlendMask",
|
|
"_GenericMatCap1Mask",
|
|
"_MatCapEnableLighting",
|
|
"_GenericMatCap1EnableLighting",
|
|
"_MatCapShadowMask",
|
|
"_GenericMatCap1ShadowMask",
|
|
"_MatCapBackfaceMask",
|
|
"_GenericMatCap1BackfaceMask",
|
|
"_MatCapLod",
|
|
"_GenericMatCap1Lod",
|
|
"_MatCapBlendMode",
|
|
"_GenericMatCap1BlendMode",
|
|
"_MatCapApplyTransparency",
|
|
"_GenericMatCap1ApplyTransparency",
|
|
"_MatCapNormalStrength",
|
|
"_GenericMatCap1NormalStrength",
|
|
"_MatCapCustomNormal",
|
|
"_UseGenericMatCap1CustomNormal",
|
|
"_GENERIC_MATCAP1_CUSTOM_NORMAL",
|
|
"_MatCapBumpMap",
|
|
"_GenericMatCap1BumpMap",
|
|
"_MatCapBumpScale",
|
|
"_GenericMatCap1BumpScale");
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// MatCap 2nd
|
|
PortLilToonMatCapLayerToGeneric(
|
|
fromlilToonMat,
|
|
toNiloToonMat,
|
|
"_UseMatCap2nd",
|
|
"_UseGenericMatCap2",
|
|
"_GENERIC_MATCAP2",
|
|
"_MatCap2ndColor",
|
|
"_GenericMatCap2Color",
|
|
"_MatCap2ndTex",
|
|
"_GenericMatCap2Map",
|
|
"_MatCap2ndMainStrength",
|
|
"_GenericMatCap2MainStrength",
|
|
"_MatCap2ndBlendUV1",
|
|
"_GenericMatCap2BlendUV1",
|
|
"_MatCap2ndZRotCancel",
|
|
"_GenericMatCap2ZRotCancel",
|
|
"_MatCap2ndPerspective",
|
|
"_GenericMatCap2Perspective",
|
|
"_MatCap2ndVRParallaxStrength",
|
|
"_GenericMatCap2VRParallaxStrength",
|
|
"_MatCap2ndBlend",
|
|
"_GenericMatCap2Blend",
|
|
"_MatCap2ndBlendMask",
|
|
"_GenericMatCap2Mask",
|
|
"_MatCap2ndEnableLighting",
|
|
"_GenericMatCap2EnableLighting",
|
|
"_MatCap2ndShadowMask",
|
|
"_GenericMatCap2ShadowMask",
|
|
"_MatCap2ndBackfaceMask",
|
|
"_GenericMatCap2BackfaceMask",
|
|
"_MatCap2ndLod",
|
|
"_GenericMatCap2Lod",
|
|
"_MatCap2ndBlendMode",
|
|
"_GenericMatCap2BlendMode",
|
|
"_MatCap2ndApplyTransparency",
|
|
"_GenericMatCap2ApplyTransparency",
|
|
"_MatCap2ndNormalStrength",
|
|
"_GenericMatCap2NormalStrength",
|
|
"_MatCap2ndCustomNormal",
|
|
"_UseGenericMatCap2CustomNormal",
|
|
"_GENERIC_MATCAP2_CUSTOM_NORMAL",
|
|
"_MatCap2ndBumpMap",
|
|
"_GenericMatCap2BumpMap",
|
|
"_MatCap2ndBumpScale",
|
|
"_GenericMatCap2BumpScale");
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Rim
|
|
PortLilToonRimToGenericRimLight3D(fromlilToonMat, toNiloToonMat);
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Glitter
|
|
// (X) ...All...
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Emission
|
|
int _UseEmission = (int)GetFloatOrDefault(fromlilToonMat, "_UseEmission");
|
|
if (_UseEmission == 1)
|
|
{
|
|
toNiloToonMat.SetFloat("_UseEmission", 1);
|
|
toNiloToonMat.EnableKeyword("_EMISSION");
|
|
}
|
|
else
|
|
{
|
|
toNiloToonMat.SetFloat("_UseEmission", 0);
|
|
toNiloToonMat.DisableKeyword("_EMISSION");
|
|
}
|
|
|
|
// (Same)_EmissionColor
|
|
toNiloToonMat.SetFloat("_EmissionIntensity",
|
|
GetColorOrDefault(fromlilToonMat, "_EmissionColor", Color.clear).a); // lilToon's _EmissionColor.a is the intensity
|
|
|
|
// (Same)_EmissionMap
|
|
toNiloToonMat.SetVector("_EmissionMapUVScrollSpeed",
|
|
GetVectorOrDefault(fromlilToonMat, "_EmissionMap_ScrollRotate", Vector4.zero));
|
|
// (X) _EmissionMap_UVMode
|
|
toNiloToonMat.SetFloat("_MultiplyBaseColorToEmissionColor",
|
|
GetFloatOrDefault(fromlilToonMat, "_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)GetFloatOrDefault(fromlilToonMat, "_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", GetColorOrDefault(fromlilToonMat, "_OutlineColor", Color.white));
|
|
|
|
// _OutlineWidth (same, no need to convert)
|
|
|
|
// make 2 outline system's width matching
|
|
float _OutlineWidth = GetFloatOrDefault(fromlilToonMat, "_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 = GetTextureOrNull(fromlilToonMat, "_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 = GetFloatOrDefault(fromlilToonMat, "_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", GetFloatOrDefault(fromlilToonMat, "_OutlineZBias"));
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Tessellation
|
|
// (X) ...All...
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// For Multi
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Save (Unused)
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Advanced
|
|
|
|
//----------------------------------------------------------------------------------------------------------------------
|
|
// Outline Advanced
|
|
PortLilToonFurProperties(fromlilToonMat, toNiloToonMat);
|
|
}
|
|
|
|
static void SetMaterialAsIsSkin(Material m)
|
|
{
|
|
m.SetFloat(IsSkin, 1);
|
|
if (m.HasProperty(DepthTexRimLight3DRimMaskEnable))
|
|
{
|
|
m.SetFloat(DepthTexRimLight3DRimMaskEnable, 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)
|
|
{
|
|
int? clampedRenderQueue = null;
|
|
|
|
// 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;
|
|
clampedRenderQueue = m.renderQueue;
|
|
}
|
|
|
|
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:
|
|
// Preserve user-authored opaque/cutout ordering (e.g. 1999/2000 or 2450/2452) while keeping queues in Unity's opaque range.
|
|
ClampRenderQueueMinMax(m, 0, (int)RenderQueue.GeometryLast);
|
|
break;
|
|
|
|
case RenderQueueGroup.Cutout:
|
|
ClampRenderQueueMinMax(m, 0, (int)RenderQueue.GeometryLast);
|
|
break;
|
|
|
|
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.");
|
|
}
|
|
|
|
if (clampedRenderQueue.HasValue)
|
|
{
|
|
m.renderQueue = clampedRenderQueue.Value;
|
|
}
|
|
}
|
|
|
|
/// <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
|
|
}
|
|
|
|
static bool IsMaterialVariant(Material mat)
|
|
{
|
|
if (mat == null)
|
|
return false;
|
|
|
|
#if UNITY_2022_1_OR_NEWER
|
|
return mat.isVariant;
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
static bool HasUsableShader(Material mat)
|
|
{
|
|
return mat != null && mat.shader != null;
|
|
}
|
|
|
|
static bool ShouldUpgradeMaterialNonInteractively(Material material, HashSet<string> shaderNamesToIgnore)
|
|
{
|
|
if (!HasUsableShader(material))
|
|
return false;
|
|
|
|
if (IsMaterialVariant(material))
|
|
return false;
|
|
|
|
return !shaderNamesToIgnore.Contains(material.shader.name);
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// 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
|
|
}
|
|
}
|