Skip to content

Commit

Permalink
improve shader converson logic and add more conversion cases
Browse files Browse the repository at this point in the history
  • Loading branch information
hybridherbst committed Apr 19, 2023
1 parent ed69382 commit 1f5c1a2
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 42 deletions.
Expand Up @@ -131,7 +131,7 @@ public static void ValidateMaterialKeywords(Material material)
if (material.HasProperty("emissiveFactor"))
material.globalIlluminationFlags = MaterialEditor.FixupEmissiveFlag(material.GetColor("emissiveFactor"), material.globalIlluminationFlags);

if (!material.IsKeywordEnabled("_TEXTURE_TRANSFORM_ON"))
if (!material.IsKeywordEnabled("_TEXTURE_TRANSFORM_ON") && material.HasProperty("baseColorTexture"))
{
if (material.GetTextureScale("baseColorTexture") != Vector2.one || material.GetTextureOffset("baseColorTexture") != Vector2.zero)
{
Expand All @@ -143,9 +143,15 @@ public static void ValidateMaterialKeywords(Material material)
public static void SetKeyword(Material material, string keyword, bool state)
{
if (state)
{
material.EnableKeyword(keyword + "_ON");
material.EnableKeyword(keyword);
}
else
{
material.DisableKeyword(keyword + "_ON");
material.DisableKeyword(keyword);
}

if (material.HasProperty(keyword))
material.SetFloat(keyword, state ? 1 : 0);
Expand Down
Expand Up @@ -408,11 +408,12 @@ protected void _DrawSurfaceInputs(Material mat)

private static bool HasPropertyButNoTex(Material targetMaterial, string name)
{
return targetMaterial.HasProperty(name) &&
#if UNITY_2021_2_OR_NEWER
targetMaterial.HasTexture(name) &&
#endif
!targetMaterial.GetTexture(name);
// turns out HasProperty can return true when someone sets the property on a material - but the shader doesn't actually have that property
var hasProperty = targetMaterial.shader.FindPropertyIndex(name) > -1;
#if UNITY_2021_2_OR_NEWER
hasProperty &= targetMaterial.HasTexture(name);
#endif
return hasProperty && !targetMaterial.GetTexture(name);
}

private void DrawProperties(Material targetMaterial, MaterialProperty[] properties)
Expand Down
@@ -1,6 +1,8 @@
using System.Linq;
using System;
using System.Linq;
using GLTF.Schema;
using UnityEngine;
using Object = UnityEngine.Object;

#if UNITY_EDITOR
using UnityEditor;
Expand Down Expand Up @@ -53,35 +55,64 @@ private static bool ConvertUnityGLTFGraphs(Material material, Shader oldShader,

private static bool ConvertStandardAndURPLit(Material material, Shader oldShader, Shader newShader)
{
// Conversion time!
// convert from
// - "Standard"
// - "URP/Lit"

if (oldShader.name != StandardShader && oldShader.name != URPLitShader) return false;

var isStandard = oldShader.name == StandardShader;
var needsEmissiveColorSpaceConversion = isStandard && QualitySettings.activeColorSpace == ColorSpace.Linear;
var colorProp = oldShader.name == StandardShader ? _Color : _BaseColor;
var colorTexProp = oldShader.name == StandardShader ? _MainTex : _BaseMap;

var color = material.GetColor(colorProp);
var albedo = material.GetTexture(colorTexProp);
var albedoOffset = material.GetTextureOffset(colorTexProp);
var albedoTiling = material.GetTextureScale(colorTexProp);

var metallic = material.GetFloat(_Metallic);
var smoothness = material.HasProperty(_Smoothness) ? material.GetFloat(_Smoothness) : material.GetFloat(_Glossiness);
var metallicGloss = material.GetTexture(_MetallicGlossMap);
var normal = material.GetTexture(_BumpMap);
var normalStrength = material.GetFloat(_BumpScale);
var occlusion = material.GetTexture(_OcclusionMap);
var occlusionStrength = material.GetFloat(_Strength);
var emission = material.GetTexture(_EmissionMap);
var emissionColor = material.GetColor(_EmissionColor);
var cutoff = material.GetFloat(_Cutoff);

var isCutoff = material.IsKeywordEnabled("_ALPHATEST_ON") || material.IsKeywordEnabled("_BUILTIN_ALPHATEST_ON");
var allowedConversions = new[] {
StandardShader,
UnlitColorShader,
UnlitTextureShader,
UnlitTransparentShader,
UnlitTransparentCutoutShader,
URPLitShader,
URPUnlitShader,
};

var unlitSources = new[] {
UnlitColorShader,
UnlitTextureShader,
URPUnlitShader,
UnlitTransparentShader,
UnlitTransparentCutoutShader,
};

var birpShaders = new[] {
StandardShader,
UnlitColorShader,
UnlitTextureShader,
UnlitTransparentShader,
UnlitTransparentCutoutShader,
};

if (!allowedConversions.Contains(oldShader.name)) return false;

var sourceIsUnlit = unlitSources.Contains(oldShader.name);
var targetIsUnlit = newShader.name == URPUnlitShader;
var sourceIsTransparent = oldShader.name == UnlitTransparentShader || oldShader.name == UnlitTransparentCutoutShader;

var sourceIsBirp = birpShaders.Contains(oldShader.name);
var needsEmissiveColorSpaceConversion = sourceIsBirp && QualitySettings.activeColorSpace == ColorSpace.Linear;
var colorProp = sourceIsBirp ? _Color : _BaseColor;
var colorTexProp = sourceIsBirp ? _MainTex : _BaseMap;

var color = material.GetColor(colorProp, Color.white);
var albedo = material.GetTexture(colorTexProp, null);
var albedoOffset = material.GetTextureOffset(colorTexProp, Vector2.zero);
var albedoTiling = material.GetTextureScale(colorTexProp, Vector2.one);
var isTransparent = material.GetTag("RenderType", false) == "Transparent" || sourceIsTransparent;

var metallic = material.GetFloat(_Metallic, 0);
var smoothness = material.HasProperty(_Smoothness) ? material.GetFloat(_Smoothness, 0) : material.GetFloat(_Glossiness, 0);
var metallicGloss = material.GetTexture(_MetallicGlossMap, null);
var normal = material.GetTexture(_BumpMap, null);
var normalStrength = material.GetFloat(_BumpScale, 1);
var occlusion = material.GetTexture(_OcclusionMap, null);
var occlusionStrength = material.GetFloat(_Strength, 1);
var emission = material.GetTexture(_EmissionMap, null);
var emissionColor = material.GetColor(_EmissionColor, Color.black);
var cutoff = material.GetFloat(_Cutoff, 0.5f);

var isCutoff = material.IsKeywordEnabled("_ALPHATEST_ON") ||
material.IsKeywordEnabled("_BUILTIN_ALPHATEST_ON") ||
material.IsKeywordEnabled("_BUILTIN_AlphaClip") ||
oldShader.name == UnlitTransparentCutoutShader;

material.shader = newShader;

Expand Down Expand Up @@ -129,12 +160,9 @@ private static bool ConvertStandardAndURPLit(Material material, Shader oldShader
material.SetFloat(occlusionStrength1, occlusionStrength);
material.SetTexture(emissiveTexture, emission);
material.SetFloat(alphaCutoff, cutoff);
if (isCutoff)
{
GLTFMaterialHelper.SetKeyword(material, "_ALPHATEST", true);
GLTFMaterialHelper.SetKeyword(material, "_BUILTIN_ALPHATEST", true);
material.EnableKeyword("_BUILTIN_AlphaClip");
}

var map = new PBRGraphMap(material);
map.AlphaMode = isCutoff ? AlphaMode.MASK : (isTransparent ? AlphaMode.BLEND : AlphaMode.OPAQUE);

material.SetColor(emissiveFactor, needsEmissiveColorSpaceConversion ? emissionColor.linear : emissionColor);

Expand All @@ -150,7 +178,12 @@ private static bool ConvertStandardAndURPLit(Material material, Shader oldShader

// ReSharper disable InconsistentNaming
private const string StandardShader = "Standard";
private const string UnlitColorShader = "Unlit/Color";
private const string UnlitTextureShader = "Unlit/Texture";
private const string UnlitTransparentShader = "Unlit/Transparent";
private const string UnlitTransparentCutoutShader = "Unlit/Transparent Cutout";
private const string URPLitShader = "Universal Render Pipeline/Lit";
private const string URPUnlitShader = "Universal Render Pipeline/Unlit";

// Standard and URP-Lit property names
private static readonly int _Color = Shader.PropertyToID("_Color");
Expand Down Expand Up @@ -237,4 +270,42 @@ private static void SelectAllMaterialsWithShader(MenuCommand command)
return false;
}
}

static class MaterialHelper
{
public static float GetFloat(this Material material, int propertyIdx, float fallback)
{
if (material.HasProperty(propertyIdx))
return material.GetFloat(propertyIdx);
return fallback;
}

public static Color GetColor(this Material material, int propertyIdx, Color fallback)
{
if (material.HasProperty(propertyIdx))
return material.GetColor(propertyIdx);
return fallback;
}

public static Texture GetTexture(this Material material, int propertyIdx, Texture fallback)
{
if (material.HasProperty(propertyIdx))
return material.GetTexture(propertyIdx);
return fallback;
}

public static Vector2 GetTextureScale(this Material material, int propertyIdx, Vector2 fallback)
{
if (material.HasProperty(propertyIdx))
return material.GetTextureScale(propertyIdx);
return fallback;
}

public static Vector2 GetTextureOffset(this Material material, int propertyIdx, Vector2 fallback)
{
if (material.HasProperty(propertyIdx))
return material.GetTextureOffset(propertyIdx);
return fallback;
}
}
}

0 comments on commit 1f5c1a2

Please sign in to comment.