mirror of
https://github.com/vrm-c/UniVRM.git
synced 2026-10-03 00:01:46 -05:00
Implements glTF PBR spec compatible shader with ShaderGraph
includes - Editor Import - Editor Export - Runtime Export TBD - Runtime Import
This commit is contained in:
@@ -38,16 +38,16 @@
|
||||
"expression": "",
|
||||
"define": "UNIGLTF_DISABLE_DEFAULT_GLTF_IMPORTER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.cloud.gltfast",
|
||||
"expression": "",
|
||||
"define": "UNIGLTF_DISABLE_DEFAULT_GLB_IMPORTER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.cloud.gltfast",
|
||||
"expression": "",
|
||||
"define": "UNIGLTF_DISABLE_DEFAULT_GLTF_IMPORTER"
|
||||
}
|
||||
{
|
||||
"name": "com.unity.cloud.gltfast",
|
||||
"expression": "",
|
||||
"define": "UNIGLTF_DISABLE_DEFAULT_GLB_IMPORTER"
|
||||
},
|
||||
{
|
||||
"name": "com.unity.cloud.gltfast",
|
||||
"expression": "",
|
||||
"define": "UNIGLTF_DISABLE_DEFAULT_GLTF_IMPORTER"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace UniGLTF
|
||||
{
|
||||
public override void OnImportAsset(AssetImportContext ctx)
|
||||
{
|
||||
Import(this, ctx, m_reverseAxis.ToAxes(), m_renderPipeline);
|
||||
Import(this, ctx, m_reverseAxis.ToAxes(), m_renderPipeline, m_pbrMaterialImportType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace UniGLTF
|
||||
{
|
||||
public override void OnImportAsset(AssetImportContext ctx)
|
||||
{
|
||||
Import(this, ctx, m_reverseAxis.ToAxes(), m_renderPipeline);
|
||||
Import(this, ctx, m_reverseAxis.ToAxes(), m_renderPipeline, m_pbrMaterialImportType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,9 @@ namespace UniGLTF
|
||||
[SerializeField]
|
||||
public ImporterRenderPipelineTypes m_renderPipeline;
|
||||
|
||||
[SerializeField]
|
||||
public PbrMaterialImportType m_pbrMaterialImportType;
|
||||
|
||||
/// <summary>
|
||||
/// glb をパースして、UnityObject化、さらにAsset化する
|
||||
/// </summary>
|
||||
@@ -28,7 +31,8 @@ namespace UniGLTF
|
||||
/// <param name="context"></param>
|
||||
/// <param name="reverseAxis"></param>
|
||||
/// <param name="renderPipeline"></param>
|
||||
protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, ImporterRenderPipelineTypes renderPipeline)
|
||||
/// <param name="pbrMaterialImportType"></param>
|
||||
protected static void Import(ScriptedImporter scriptedImporter, AssetImportContext context, Axes reverseAxis, ImporterRenderPipelineTypes renderPipeline, PbrMaterialImportType pbrMaterialImportType = PbrMaterialImportType.UnityStandard)
|
||||
{
|
||||
UniGLTFLogger.Log("OnImportAsset to " + scriptedImporter.assetPath);
|
||||
|
||||
@@ -41,7 +45,7 @@ namespace UniGLTF
|
||||
.Where(x => x.Value != null)
|
||||
.ToDictionary(kv => new SubAssetKey(kv.Value.GetType(), kv.Key.name), kv => kv.Value);
|
||||
|
||||
var materialGenerator = GetMaterialDescriptorGenerator(renderPipeline);
|
||||
var materialGenerator = GetMaterialDescriptorGenerator(renderPipeline, pbrMaterialImportType);
|
||||
var importerContextSettings = new ImporterContextSettings(loadAnimation: true, invertAxis: reverseAxis);
|
||||
|
||||
using (var data = new AutoGltfFileParser(scriptedImporter.assetPath).Parse())
|
||||
@@ -68,8 +72,15 @@ namespace UniGLTF
|
||||
}
|
||||
}
|
||||
|
||||
private static IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(ImporterRenderPipelineTypes renderPipeline)
|
||||
private static IMaterialDescriptorGenerator GetMaterialDescriptorGenerator(ImporterRenderPipelineTypes renderPipeline, PbrMaterialImportType pbrMaterialImportType)
|
||||
{
|
||||
if (pbrMaterialImportType == PbrMaterialImportType.GltfCompatible)
|
||||
{
|
||||
// NOTE: UniVRM 最適化 PBR (ShaderGraph) は 1 つのシェーダで Built-In / URP 両対応のため
|
||||
// RenderPipeline による分岐を行わない。
|
||||
return new InvariantGltfMaterialDescriptorGenerator();
|
||||
}
|
||||
|
||||
return renderPipeline switch
|
||||
{
|
||||
ImporterRenderPipelineTypes.Auto => MaterialDescriptorGeneratorUtility .GetValidGltfMaterialDescriptorGenerator(),
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace UniGLTF
|
||||
{
|
||||
public override void OnImportAsset(AssetImportContext ctx)
|
||||
{
|
||||
Import(this, ctx, m_reverseAxis.ToAxes(), m_renderPipeline);
|
||||
Import(this, ctx, m_reverseAxis.ToAxes(), m_renderPipeline, m_pbrMaterialImportType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"GUID:da3e51d19d51a544fa14d43fee843098",
|
||||
"GUID:60c8346e00a8ddd4cafc5a02eceeec57",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:9fe7352e1c749b94aa9194a537b768e6",
|
||||
"GUID:3d354272d3f2f4c3387dbccbaebd0f60"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace UniGLTF
|
||||
"Unlit/Texture",
|
||||
"Unlit/Transparent",
|
||||
"Unlit/Transparent Cutout",
|
||||
UniGltfPbrContext.ShaderName,
|
||||
};
|
||||
|
||||
public glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings)
|
||||
@@ -37,6 +38,9 @@ namespace UniGLTF
|
||||
case "Unlit/Transparent Cutout":
|
||||
if (BuiltInGenericUnlitMaterialExporter.TryExportMaterial(m, glTFBlendMode.MASK, textureExporter, out dst)) return dst;
|
||||
break;
|
||||
case UniGltfPbrContext.ShaderName:
|
||||
if (new InvariantRpUniGltfPbrMaterialExporter().TryExportMaterial(m, textureExporter, out dst)) return dst;
|
||||
break;
|
||||
}
|
||||
|
||||
UniGLTFLogger.Log($"Material `{m.name}` fallbacks.");
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1a30880fa75f3749950bf8be0a89e32
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da9bfbc669de45209e81fc260129d117
|
||||
timeCreated: 1784359347
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 457a0388491c4f41b3017a75679ad870
|
||||
timeCreated: 1784359510
|
||||
@@ -0,0 +1,173 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
public class InvariantRpUniGltfPbrMaterialExporter
|
||||
{
|
||||
public Shader Shader { get; set; }
|
||||
|
||||
public InvariantRpUniGltfPbrMaterialExporter(Shader shader = null)
|
||||
{
|
||||
Shader = shader ?? UniGltfPbrContext.GetShader();
|
||||
}
|
||||
|
||||
public bool TryExportMaterial(Material src, ITextureExporter textureExporter, out glTFMaterial dst)
|
||||
{
|
||||
if (src == null || src.shader == null || src.shader != Shader)
|
||||
{
|
||||
dst = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
dst = new glTFMaterial
|
||||
{
|
||||
name = src.name,
|
||||
pbrMetallicRoughness = new glTFPbrMetallicRoughness(),
|
||||
};
|
||||
|
||||
var context = new UniGltfPbrContext(src);
|
||||
|
||||
ExportSurfaceSettings(context, dst);
|
||||
ExportBaseColor(context, dst, textureExporter);
|
||||
ExportMetallicRoughness(context, dst, textureExporter);
|
||||
ExportOcclusion(context, dst, textureExporter);
|
||||
ExportNormal(context, dst, textureExporter);
|
||||
ExportEmission(context, dst, textureExporter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ExportSurfaceSettings(UniGltfPbrContext context, glTFMaterial dst)
|
||||
{
|
||||
dst.alphaMode = (context.SurfaceType, context.IsAlphaClipEnabled) switch
|
||||
{
|
||||
(UniGltfPbrSurfaceType.Opaque, false) => glTFBlendMode.OPAQUE.ToString(),
|
||||
(UniGltfPbrSurfaceType.Opaque, true) => glTFBlendMode.MASK.ToString(),
|
||||
(UniGltfPbrSurfaceType.Transparent, _) => glTFBlendMode.BLEND.ToString(),
|
||||
_ => glTFBlendMode.OPAQUE.ToString(),
|
||||
};
|
||||
dst.alphaCutoff = context.AlphaCutoff;
|
||||
dst.doubleSided = context.CullMode != CullMode.Back; // NOTE: cull front は glTF 非対応
|
||||
}
|
||||
|
||||
private static void ExportBaseColor(UniGltfPbrContext context, glTFMaterial dst, ITextureExporter textureExporter)
|
||||
{
|
||||
// _baseColorFactor は sRGB 格納なので sRGB->Linear で glTF に戻す
|
||||
dst.pbrMetallicRoughness.baseColorFactor = context.BaseColorSrgb.ToFloat4(ColorSpace.sRGB, ColorSpace.Linear);
|
||||
|
||||
if (context.BaseColorTexture != null)
|
||||
{
|
||||
var needsAlpha = context.SurfaceType != UniGltfPbrSurfaceType.Opaque;
|
||||
var index = textureExporter.RegisterExportingAsSRgb(context.BaseColorTexture, needsAlpha);
|
||||
if (index >= 0)
|
||||
{
|
||||
dst.pbrMetallicRoughness.baseColorTexture = new glTFMaterialBaseColorTextureInfo
|
||||
{
|
||||
index = index,
|
||||
texCoord = 0,
|
||||
};
|
||||
ExportTextureTransform(context.BaseColorTextureOffset, context.BaseColorTextureScale, dst.pbrMetallicRoughness.baseColorTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExportMetallicRoughness(UniGltfPbrContext context, glTFMaterial dst, ITextureExporter textureExporter)
|
||||
{
|
||||
// 反転・1 固定なし。factor とテクスチャは独立 (glTF セマンティクス通り)
|
||||
dst.pbrMetallicRoughness.metallicFactor = context.MetallicFactor;
|
||||
dst.pbrMetallicRoughness.roughnessFactor = context.RoughnessFactor;
|
||||
|
||||
if (context.MetallicRoughnessTexture != null)
|
||||
{
|
||||
// 既に glTF ネイティブ ORM パッキング -> Linear passthrough (チャンネル入替なし)
|
||||
var index = textureExporter.RegisterExportingAsLinear(context.MetallicRoughnessTexture, false);
|
||||
if (index >= 0)
|
||||
{
|
||||
dst.pbrMetallicRoughness.metallicRoughnessTexture = new glTFMaterialMetallicRoughnessTextureInfo
|
||||
{
|
||||
index = index,
|
||||
texCoord = 0,
|
||||
};
|
||||
ExportTextureTransform(context.MetallicRoughnessTextureOffset, context.MetallicRoughnessTextureScale, dst.pbrMetallicRoughness.metallicRoughnessTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExportOcclusion(UniGltfPbrContext context, glTFMaterial dst, ITextureExporter textureExporter)
|
||||
{
|
||||
if (context.OcclusionTexture != null)
|
||||
{
|
||||
// metallicRoughnessTexture と同一 Texture の場合は TextureExporter が index を dedupe する
|
||||
var index = textureExporter.RegisterExportingAsLinear(context.OcclusionTexture, false);
|
||||
if (index >= 0)
|
||||
{
|
||||
dst.occlusionTexture = new glTFMaterialOcclusionTextureInfo
|
||||
{
|
||||
index = index,
|
||||
texCoord = 0,
|
||||
strength = context.OcclusionStrength,
|
||||
};
|
||||
ExportTextureTransform(context.OcclusionTextureOffset, context.OcclusionTextureScale, dst.occlusionTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExportNormal(UniGltfPbrContext context, glTFMaterial dst, ITextureExporter textureExporter)
|
||||
{
|
||||
if (context.NormalTexture == null) return;
|
||||
|
||||
var index = textureExporter.RegisterExportingAsNormal(context.NormalTexture);
|
||||
if (index >= 0)
|
||||
{
|
||||
dst.normalTexture = new glTFMaterialNormalTextureInfo
|
||||
{
|
||||
index = index,
|
||||
texCoord = 0,
|
||||
scale = context.NormalScale,
|
||||
};
|
||||
ExportTextureTransform(context.NormalTextureOffset, context.NormalTextureScale, dst.normalTexture);
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExportEmission(UniGltfPbrContext context, glTFMaterial dst, ITextureExporter textureExporter)
|
||||
{
|
||||
var emissive = context.EmissiveFactorLinear; // linear
|
||||
var strength = context.EmissiveStrength;
|
||||
|
||||
// emissiveFactor * emissiveStrength を放射輝度とし、glTF-valid (factor<=1) になるよう正規化する。
|
||||
// maxComponent が 1 を超える分は KHR_materials_emissive_strength に逃がす。
|
||||
var total = new Vector3(emissive.r * strength, emissive.g * strength, emissive.b * strength);
|
||||
var maxComp = Mathf.Max(total.x, Mathf.Max(total.y, total.z));
|
||||
if (maxComp > 1.0f)
|
||||
{
|
||||
dst.emissiveFactor = new[] { total.x / maxComp, total.y / maxComp, total.z / maxComp };
|
||||
glTF_KHR_materials_emissive_strength.Serialize(ref dst.extensions, maxComp);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst.emissiveFactor = new[] { total.x, total.y, total.z };
|
||||
}
|
||||
|
||||
if (context.EmissiveTexture != null)
|
||||
{
|
||||
var index = textureExporter.RegisterExportingAsSRgb(context.EmissiveTexture, true);
|
||||
if (index >= 0)
|
||||
{
|
||||
dst.emissiveTexture = new glTFMaterialEmissiveTextureInfo
|
||||
{
|
||||
index = index,
|
||||
texCoord = 0,
|
||||
};
|
||||
ExportTextureTransform(context.EmissiveTextureOffset, context.EmissiveTextureScale, dst.emissiveTexture);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ExportTextureTransform(Vector2 offset, Vector2 scale, glTFTextureInfo dst)
|
||||
{
|
||||
// NOTE: シェーダは全テクスチャに ScaleOffset を持つため、各テクスチャ固有の transform を出力する
|
||||
GltfMaterialExportUtils.ExportTextureTransform(offset, scale, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7347686cba894aef8e19cffcf0bd2b86
|
||||
timeCreated: 1784359580
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce9e54afa9854733b9366f41c62aac2b
|
||||
timeCreated: 1784359298
|
||||
@@ -0,0 +1,41 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// glTF 準拠 PBR ShaderGraph (UniGltfPbr) を用いる IMaterialDescriptorGenerator。
|
||||
///
|
||||
/// オプトイン用。ImporterContext の materialGenerator 引数に渡して使う。
|
||||
/// RenderPipeline 非依存 (1 つの ShaderGraph が Built-In / URP の両 Target を持つ) なので
|
||||
/// 既定の RenderPipeline 分岐 (MaterialDescriptorGeneratorUtility) は経由しない。
|
||||
///
|
||||
/// 分岐順は既存 generator と同じ unlit -> pbr -> default。
|
||||
/// unlit は既存の BuiltInGltfUnlitMaterialImporter (UniGLTF/UniUnlit) を再利用する。
|
||||
/// </summary>
|
||||
public sealed class InvariantGltfMaterialDescriptorGenerator : IMaterialDescriptorGenerator
|
||||
{
|
||||
public InvariantRpUniGltfPbrMaterialImporter PbrMaterialImporter { get; }
|
||||
public BuiltInGltfUnlitMaterialImporter UnlitMaterialImporter { get; } = new();
|
||||
|
||||
public InvariantGltfMaterialDescriptorGenerator(Shader pbrShader = null)
|
||||
{
|
||||
PbrMaterialImporter = new InvariantRpUniGltfPbrMaterialImporter(pbrShader);
|
||||
}
|
||||
|
||||
public MaterialDescriptor Get(GltfData data, int i)
|
||||
{
|
||||
if (UnlitMaterialImporter.TryCreateParam(data, i, out var param)) return param;
|
||||
if (PbrMaterialImporter.TryCreateParam(data, i, out param)) return param;
|
||||
|
||||
// NOTE: Fallback to default material
|
||||
if (Symbols.VRM_DEVELOP)
|
||||
{
|
||||
UniGLTFLogger.Warning($"material: {i} out of range. fallback");
|
||||
}
|
||||
return GetGltfDefault(GltfMaterialImportUtils.ImportMaterialName(i, null));
|
||||
}
|
||||
|
||||
public MaterialDescriptor GetGltfDefault(string materialName = null)
|
||||
=> PbrMaterialImporter.CreateDefaultParam(materialName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fa5e67f09fd71c4c92bcd538b25ece8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3157f2650bb047adbc517f8cd35e962a
|
||||
timeCreated: 1784359319
|
||||
@@ -0,0 +1,199 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// glTF 準拠 PBR ShaderGraph (UniGltfPbr) 向けの MaterialDescriptor を生成する。
|
||||
///
|
||||
/// 既定の Standard / URP-Lit 経路との違い:
|
||||
/// - metallicRoughnessTexture / occlusionTexture を glTF のパッキングのまま Linear で取り込む
|
||||
/// (OcclusionMetallicRoughnessConverter による GPU blit + ReadPixels 変換を行わない)
|
||||
/// - metallicFactor / roughnessFactor をそのまま格納する (1.0 固定や smoothness 反転をしない)
|
||||
///
|
||||
/// 構造は UniGLTF.UrpGltfPbrMaterialImporter を踏襲する。
|
||||
/// https://registry.khronos.org/glTF/specs/2.0/glTF-2.0.html#materials
|
||||
/// </summary>
|
||||
public class InvariantRpUniGltfPbrMaterialImporter
|
||||
{
|
||||
public Shader Shader { get; set; }
|
||||
|
||||
public InvariantRpUniGltfPbrMaterialImporter(Shader shader = null)
|
||||
{
|
||||
Shader = shader ?? UniGltfPbrContext.GetShader();
|
||||
}
|
||||
|
||||
public bool TryCreateParam(GltfData data, int i, out MaterialDescriptor matDesc)
|
||||
{
|
||||
if (i < 0 || i >= data.GLTF.materials.Count)
|
||||
{
|
||||
matDesc = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
var src = data.GLTF.materials[i];
|
||||
matDesc = new MaterialDescriptor(
|
||||
GltfMaterialImportUtils.ImportMaterialName(i, src),
|
||||
Shader,
|
||||
new[] { (MaterialDescriptor.MaterialGenerateAsyncFunc)AsyncAction }
|
||||
);
|
||||
return true;
|
||||
|
||||
Task AsyncAction(Material x, GetTextureAsyncFunc y, IAwaitCaller z) => GenerateMaterialAsync(data, src, x, y, z);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// glTF default material (プロパティ既定値でシェーダを割り当てるだけ)。
|
||||
/// シェーダ側の既定値 (baseColor=white, metallic=1, roughness=1) が glTF default に一致する。
|
||||
/// </summary>
|
||||
public MaterialDescriptor CreateDefaultParam(string materialName)
|
||||
{
|
||||
return new MaterialDescriptor(
|
||||
materialName,
|
||||
Shader,
|
||||
new List<MaterialDescriptor.MaterialGenerateAsyncFunc>()
|
||||
);
|
||||
}
|
||||
|
||||
public static async Task GenerateMaterialAsync(GltfData data, glTFMaterial src, Material dst, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
|
||||
{
|
||||
var context = new UniGltfPbrContext(dst);
|
||||
|
||||
ImportSurfaceSettings(src, context);
|
||||
await ImportBaseColorAsync(data, src, context, getTextureAsync, awaitCaller);
|
||||
await ImportMetallicRoughnessAsync(data, src, context, getTextureAsync, awaitCaller);
|
||||
await ImportOcclusionAsync(data, src, context, getTextureAsync, awaitCaller);
|
||||
await ImportNormalAsync(data, src, context, getTextureAsync, awaitCaller);
|
||||
await ImportEmissionAsync(data, src, context, getTextureAsync, awaitCaller);
|
||||
|
||||
context.Validate();
|
||||
}
|
||||
|
||||
public static void ImportSurfaceSettings(glTFMaterial src, UniGltfPbrContext context)
|
||||
{
|
||||
context.SurfaceType = src.alphaMode switch
|
||||
{
|
||||
"OPAQUE" => UniGltfPbrSurfaceType.Opaque,
|
||||
"MASK" => UniGltfPbrSurfaceType.Opaque, // AlphaClip. Opaque queue (AlphaTest)
|
||||
"BLEND" => UniGltfPbrSurfaceType.Transparent,
|
||||
_ => UniGltfPbrSurfaceType.Opaque,
|
||||
};
|
||||
context.IsAlphaClipEnabled = src.alphaMode == "MASK";
|
||||
context.AlphaCutoff = src.alphaCutoff;
|
||||
context.CullMode = src.doubleSided ? CullMode.Off : CullMode.Back;
|
||||
}
|
||||
|
||||
public static async Task ImportBaseColorAsync(GltfData data, glTFMaterial src, UniGltfPbrContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
|
||||
{
|
||||
var baseColorFactor = GltfMaterialImportUtils.ImportLinearBaseColorFactor(data, src);
|
||||
if (baseColorFactor.HasValue)
|
||||
{
|
||||
// _baseColorFactor は Default(sRGB) カラー想定なので .gamma で格納する
|
||||
context.BaseColorSrgb = baseColorFactor.Value.gamma;
|
||||
}
|
||||
|
||||
if (src is { pbrMetallicRoughness: { baseColorTexture: { index: >= 0 } } })
|
||||
{
|
||||
if (GltfPbrTextureImporter.TryBaseColorTexture(data, src, out _, out var desc))
|
||||
{
|
||||
context.BaseColorTexture = await getTextureAsync(desc, awaitCaller);
|
||||
context.BaseColorTextureOffset = desc.Offset;
|
||||
context.BaseColorTextureScale = desc.Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ImportMetallicRoughnessAsync(GltfData data, glTFMaterial src, UniGltfPbrContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
|
||||
{
|
||||
if (src.pbrMetallicRoughness != null)
|
||||
{
|
||||
context.MetallicFactor = src.pbrMetallicRoughness.metallicFactor;
|
||||
context.RoughnessFactor = src.pbrMetallicRoughness.roughnessFactor;
|
||||
}
|
||||
|
||||
if (src is { pbrMetallicRoughness: { metallicRoughnessTexture: { index: >= 0 } } })
|
||||
{
|
||||
var info = src.pbrMetallicRoughness.metallicRoughnessTexture;
|
||||
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(info);
|
||||
// NOTE: glTF の ORM パッキングをそのまま Linear で取り込む (変換なし)
|
||||
if (GltfTextureImporter.TryCreateLinear(data, info.index, offset, scale, out _, out var desc))
|
||||
{
|
||||
context.MetallicRoughnessTexture = await getTextureAsync(desc, awaitCaller);
|
||||
context.MetallicRoughnessTextureOffset = desc.Offset;
|
||||
context.MetallicRoughnessTextureScale = desc.Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static async Task ImportOcclusionAsync(GltfData data, glTFMaterial src, UniGltfPbrContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
|
||||
{
|
||||
if (src is { occlusionTexture: { index: >= 0 } })
|
||||
{
|
||||
context.OcclusionStrength = src.occlusionTexture.strength;
|
||||
|
||||
var (offset, scale) = GltfTextureImporter.GetTextureOffsetAndScale(src.occlusionTexture);
|
||||
if (GltfTextureImporter.TryCreateLinear(data, src.occlusionTexture.index, offset, scale, out _, out var desc))
|
||||
{
|
||||
context.OcclusionTexture = await getTextureAsync(desc, awaitCaller);
|
||||
context.OcclusionTextureOffset = desc.Offset;
|
||||
context.OcclusionTextureScale = desc.Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task ImportNormalAsync(GltfData data, glTFMaterial src, UniGltfPbrContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
|
||||
{
|
||||
if (src.normalTexture is { index: >= 0 })
|
||||
{
|
||||
if (GltfPbrTextureImporter.TryNormalTexture(data, src, out _, out var desc))
|
||||
{
|
||||
context.NormalTexture = await getTextureAsync(desc, awaitCaller);
|
||||
context.NormalScale = src.normalTexture.scale;
|
||||
context.NormalTextureOffset = desc.Offset;
|
||||
context.NormalTextureScale = desc.Scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// emissiveFactor と KHR_materials_emissive_strength を分離して取り込む。
|
||||
/// (GltfMaterialImportUtils.ImportLinearEmissiveFactor は strength を factor に畳み込むため使わない)
|
||||
/// </summary>
|
||||
private static async Task ImportEmissionAsync(GltfData data, glTFMaterial src, UniGltfPbrContext context, GetTextureAsyncFunc getTextureAsync, IAwaitCaller awaitCaller)
|
||||
{
|
||||
if (src.emissiveFactor != null && src.emissiveFactor.Length == 3)
|
||||
{
|
||||
var emissive = new Vector3(src.emissiveFactor[0], src.emissiveFactor[1], src.emissiveFactor[2]);
|
||||
var linear = data.MigrationFlags.IsEmissiveFactorGamma
|
||||
? emissive.ToColor3(ColorSpace.sRGB, ColorSpace.Linear)
|
||||
: emissive.ToColor3(ColorSpace.Linear, ColorSpace.Linear);
|
||||
context.EmissiveFactorLinear = linear;
|
||||
}
|
||||
|
||||
var strength = 1.0f;
|
||||
if (glTF_KHR_materials_emissive_strength.TryGet(src.extensions, out var emissiveStrength))
|
||||
{
|
||||
strength = emissiveStrength.emissiveStrength;
|
||||
}
|
||||
context.EmissiveStrength = strength;
|
||||
|
||||
if (src is { emissiveTexture: { index: >= 0 } })
|
||||
{
|
||||
if (GltfPbrTextureImporter.TryEmissiveTexture(data, src, out _, out var desc))
|
||||
{
|
||||
context.EmissiveTexture = await getTextureAsync(desc, awaitCaller);
|
||||
context.EmissiveTextureOffset = desc.Offset;
|
||||
context.EmissiveTextureScale = desc.Scale;
|
||||
}
|
||||
}
|
||||
|
||||
var isEmissive = context.EmissiveFactorLinear.maxColorComponent > 0 || context.EmissiveTexture != null;
|
||||
context.Material.globalIlluminationFlags = isEmissive
|
||||
? context.Material.globalIlluminationFlags & ~MaterialGlobalIlluminationFlags.EmissiveIsBlack
|
||||
: context.Material.globalIlluminationFlags | MaterialGlobalIlluminationFlags.EmissiveIsBlack;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63c674962a3b65c4c910f8656909a10f
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// glTF PBR マテリアルの import 実装の選択。
|
||||
///
|
||||
/// RenderPipeline や具体的なシェーダ実装 (ShaderGraph 等) に依存しない名前とする。
|
||||
/// </summary>
|
||||
public enum PbrMaterialImportType
|
||||
{
|
||||
/// <summary>
|
||||
/// 既定。Unity 標準の PBR マテリアル実装を用いる。
|
||||
/// (Built-In: Unity "Standard" / URP: "Universal Render Pipeline/Lit")
|
||||
/// metallicRoughness/occlusion は import 時にテクスチャ変換される。
|
||||
/// </summary>
|
||||
UnityStandard = 0,
|
||||
|
||||
/// <summary>
|
||||
/// glTF 仕様に最適化 PBR マテリアル実装。
|
||||
/// glTF の ORM を無変換で取り込み、単一シェーダで複数 RenderPipeline をカバーする。
|
||||
/// (現状の実装は glTF 準拠 PBR ShaderGraph "UniGltfPbr")
|
||||
/// </summary>
|
||||
GltfCompatible = 1,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9daab18aa43e3714d9d39cadd243c5b1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -7,6 +7,7 @@ namespace UniGLTF
|
||||
public UrpLitMaterialExporter UrpLitExporter { get; set; } = new();
|
||||
public UrpUnlitMaterialExporter UrpUnlitExporter { get; set; } = new();
|
||||
public UrpUniUnlitMaterialExporter UrpUniUnlitExporter { get; set; } = new();
|
||||
public InvariantRpUniGltfPbrMaterialExporter InvariantRpUniGltfPbrMaterialExporter { get; set; } = new();
|
||||
public UrpFallbackMaterialExporter FallbackExporter { get; set; } = new();
|
||||
|
||||
public glTFMaterial ExportMaterial(Material m, ITextureExporter textureExporter, GltfExportSettings settings)
|
||||
@@ -14,6 +15,7 @@ namespace UniGLTF
|
||||
if (UrpLitExporter.TryExportMaterial(m, textureExporter, out var dst)) return dst;
|
||||
if (UrpUnlitExporter.TryExportMaterial(m, textureExporter, out dst)) return dst;
|
||||
if (UrpUniUnlitExporter.TryExportMaterial(m, textureExporter, out dst)) return dst;
|
||||
if (InvariantRpUniGltfPbrMaterialExporter.TryExportMaterial(m, textureExporter, out dst)) return dst;
|
||||
|
||||
UniGLTFLogger.Log($"Material `{m.name}` fallbacks.");
|
||||
return FallbackExporter.ExportMaterial(m, textureExporter);
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
"GUID:27619889b8ba8c24980f49ee34dbb44a",
|
||||
"GUID:0acc523941302664db1f4e527237feb3",
|
||||
"GUID:1cd941934d098654fa21a13f28346412",
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b"
|
||||
"GUID:d8b63aba1907145bea998dd612889d6b",
|
||||
"GUID:9fe7352e1c749b94aa9194a537b768e6"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
using NUnit.Framework;
|
||||
using UnityEngine;
|
||||
using UniJSON;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// glTF 準拠 PBR ShaderGraph (UniGltfPbr) の export パススルー検証。
|
||||
///
|
||||
/// ShaderGraph アセット (UniGltfPbr.shadergraph) が未作成の間は Assert.Ignore で
|
||||
/// スキップする。作成後に有効化される。仕様は Shaders/GltfPbr/README.md を参照。
|
||||
/// </summary>
|
||||
public class InvariantRpUniGltfPbrMaterialTests
|
||||
{
|
||||
private static Material TryCreateMaterialOrIgnore()
|
||||
{
|
||||
var material = new Material(UniGltfPbrContext.GetShader());
|
||||
if (!material.HasProperty("_metallicFactor") || !material.HasProperty("_roughnessFactor"))
|
||||
{
|
||||
Assert.Ignore("UniGltfPbr shader lacks glTF-native properties (_metallicFactor / _roughnessFactor). See README.md.");
|
||||
}
|
||||
return material;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MetallicRoughnessFactorPassthroughTest()
|
||||
{
|
||||
var material = TryCreateMaterialOrIgnore();
|
||||
var context = new UniGltfPbrContext(material)
|
||||
{
|
||||
MetallicFactor = 0.3f,
|
||||
RoughnessFactor = 0.7f,
|
||||
};
|
||||
|
||||
var textureExporter = new TextureExporter(new EditorTextureSerializer());
|
||||
Assert.IsTrue(new InvariantRpUniGltfPbrMaterialExporter().TryExportMaterial(material, textureExporter, out var dst));
|
||||
|
||||
// 反転しない / 1.0 に固定しない (glTF セマンティクスそのまま)
|
||||
Assert.AreEqual(0.3f, dst.pbrMetallicRoughness.metallicFactor, 1e-4f);
|
||||
Assert.AreEqual(0.7f, dst.pbrMetallicRoughness.roughnessFactor, 1e-4f);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void EmissiveStrengthExportTest()
|
||||
{
|
||||
var material = TryCreateMaterialOrIgnore();
|
||||
var context = new UniGltfPbrContext(material)
|
||||
{
|
||||
EmissiveFactorLinear = new Color(0f, 0.5f, 0f),
|
||||
EmissiveStrength = 4.0f,
|
||||
};
|
||||
|
||||
var textureExporter = new TextureExporter(new EditorTextureSerializer());
|
||||
Assert.IsTrue(new InvariantRpUniGltfPbrMaterialExporter().TryExportMaterial(material, textureExporter, out var dst));
|
||||
|
||||
// emissiveFactor * strength = (0, 2, 0) -> 正規化して factor=(0,1,0), strength=2
|
||||
Assert.AreEqual(0f, dst.emissiveFactor[0], 1e-4f);
|
||||
Assert.AreEqual(1f, dst.emissiveFactor[1], 1e-4f);
|
||||
Assert.AreEqual(0f, dst.emissiveFactor[2], 1e-4f);
|
||||
|
||||
var json = dst.ToJson();
|
||||
var parsed = json.ParseAsJson();
|
||||
Assert.AreEqual(
|
||||
2.0f,
|
||||
parsed["extensions"]["KHR_materials_emissive_strength"]["emissiveStrength"].GetSingle(),
|
||||
1e-4f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53ffd3dc3e180594e91a4009b7d66471
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/UniGLTF/UniGltfPbr.meta
Normal file
8
Packages/UniGLTF/UniGltfPbr.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dcbf6fd16720e14a825ae89d0654d04
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/UniGLTF/UniGltfPbr/Editor.meta
Normal file
8
Packages/UniGLTF/UniGltfPbr/Editor.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5bcc8913bbc87ef4d97c6c49948be2d2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "UniGLTF.UniGltfPbr.Editor",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:9fe7352e1c749b94aa9194a537b768e6",
|
||||
"GUID:3eae0364be2026648bf74846acb8a731"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1559e7155b5ec8240bd4abf00fdb3d4d
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
239
Packages/UniGLTF/UniGltfPbr/Editor/UniGltfPbrShaderGUI.cs
Normal file
239
Packages/UniGLTF/UniGltfPbr/Editor/UniGltfPbrShaderGUI.cs
Normal file
@@ -0,0 +1,239 @@
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Rendering;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// glTF 準拠 PBR ShaderGraph (UniGltfPbr) 用の Custom ShaderGUI。
|
||||
///
|
||||
/// - 見た目は URP/Lit に近づけ、CoreEditorUtils.DrawHeaderFoldout でセクション分けする。
|
||||
/// - 不透明/透明・Alpha Clip・Render Face の切替は副作用 (blend/zwrite/renderQueue/keyword) を伴うため、
|
||||
/// 生プロパティ (_Surface / _Blend / _SrcBlend ...) を直接露出せず、
|
||||
/// <see cref="UniGltfPbrContext"/> の SurfaceType / IsAlphaClipEnabled / CullMode + Validate() に
|
||||
/// 委譲して自動適用・隠蔽する。
|
||||
///
|
||||
/// アタッチ: UniGltfPbr.shadergraph の各 Target の Custom Editor GUI に "UniGLTF.UniGltfPbrShaderGUI" を設定。
|
||||
/// </summary>
|
||||
public class UniGltfPbrShaderGUI : ShaderGUI
|
||||
{
|
||||
private static class Styles
|
||||
{
|
||||
public static readonly GUIContent SurfaceType = new GUIContent("Surface Type", "Opaque / Transparent の切替。関連する Blend / ZWrite / RenderQueue は自動設定されます。");
|
||||
public static readonly GUIContent RenderFace = new GUIContent("Render Face", "描画する面。Front(片面 / doubleSided=false) または Both(doubleSided=true)。");
|
||||
public static readonly GUIContent AlphaClip = new GUIContent("Alpha Clipping", "Alpha が閾値未満のピクセルを破棄します (glTF MASK)。");
|
||||
public static readonly GUIContent Threshold = new GUIContent("Threshold", "Alpha Clipping の閾値 (alphaCutoff)。");
|
||||
|
||||
public static readonly GUIContent BaseMap = new GUIContent("Base Map", "baseColorTexture (sRGB) と baseColorFactor。");
|
||||
public static readonly GUIContent Metallic = new GUIContent("Metallic", "metallicFactor。");
|
||||
public static readonly GUIContent Roughness = new GUIContent("Roughness", "roughnessFactor。");
|
||||
public static readonly GUIContent MetallicRoughnessMap = new GUIContent("Metallic Roughness Map", "metallicRoughnessTexture (Linear, G:Roughness B:Metallic)。");
|
||||
public static readonly GUIContent OcclusionMap = new GUIContent("Occlusion Map", "occlusionTexture (Linear, R:Occlusion)。");
|
||||
public static readonly GUIContent OcclusionStrength = new GUIContent("Occlusion Strength", "occlusionTexture.strength。");
|
||||
public static readonly GUIContent NormalMap = new GUIContent("Normal Map", "normalTexture と normalScale。");
|
||||
public static readonly GUIContent Emission = new GUIContent("Emission", "emissiveFactor (HDR) と emissiveTexture (sRGB)。");
|
||||
public static readonly GUIContent EmissiveStrength = new GUIContent("Emissive Strength", "KHR_materials_emissive_strength。");
|
||||
}
|
||||
|
||||
// Render Face popup。ラベルは「描画する面」、CullMode は「カリングする面」で逆になる点に注意:
|
||||
// Front を描画 = 背面カリング = CullMode.Back (glTF: doubleSided=false)
|
||||
// Both = CullMode.Off (glTF: doubleSided=true)
|
||||
// 裏面のみ描画 (CullMode.Front) は glTF 非対応のため選択肢に用意しない。
|
||||
private static readonly string[] RenderFaceNames = { "Front", "Both" };
|
||||
private static readonly CullMode[] RenderFaceCull = { CullMode.Back, CullMode.Off };
|
||||
|
||||
// foldout state (editor セッション保持)
|
||||
private static bool s_surfaceOptions = true;
|
||||
private static bool s_surfaceInputs = true;
|
||||
private static bool s_advanced = false;
|
||||
|
||||
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
|
||||
{
|
||||
var baseColorFactor = FindProperty("_baseColorFactor", properties, false);
|
||||
var baseColorTexture = FindProperty("_baseColorTexture", properties, false);
|
||||
var metallicFactor = FindProperty("_metallicFactor", properties, false);
|
||||
var roughnessFactor = FindProperty("_roughnessFactor", properties, false);
|
||||
var metallicRoughnessTexture = FindProperty("_metallicRoughnessTexture", properties, false);
|
||||
var occlusionTexture = FindProperty("_occlusionTexture", properties, false);
|
||||
var occlusionStrength = FindProperty("_occlusionStrength", properties, false);
|
||||
var normalTexture = FindProperty("_normalTexture", properties, false);
|
||||
var normalScale = FindProperty("_normalScale", properties, false);
|
||||
var emissiveFactor = FindProperty("_emissiveFactor", properties, false);
|
||||
var emissiveTexture = FindProperty("_emissiveTexture", properties, false);
|
||||
var emissiveStrength = FindProperty("_emissiveStrength", properties, false);
|
||||
var alphaCutoff = FindProperty("_alphaCutoff", properties, false);
|
||||
|
||||
s_surfaceOptions = CoreEditorUtils.DrawHeaderFoldout("Surface Options", s_surfaceOptions);
|
||||
if (s_surfaceOptions)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
DrawSurfaceOptions(materialEditor, alphaCutoff);
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
s_surfaceInputs = CoreEditorUtils.DrawHeaderFoldout("Surface Inputs", s_surfaceInputs);
|
||||
if (s_surfaceInputs)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
DrawSurfaceInputs(
|
||||
materialEditor,
|
||||
baseColorTexture, baseColorFactor,
|
||||
metallicFactor, roughnessFactor, metallicRoughnessTexture,
|
||||
occlusionTexture, occlusionStrength,
|
||||
normalTexture, normalScale,
|
||||
emissiveTexture, emissiveFactor, emissiveStrength);
|
||||
EditorGUI.indentLevel--;
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
s_advanced = CoreEditorUtils.DrawHeaderFoldout("Advanced Options", s_advanced);
|
||||
if (s_advanced)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
DrawAdvanced(materialEditor);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawSurfaceOptions(MaterialEditor materialEditor, MaterialProperty alphaCutoff)
|
||||
{
|
||||
var materials = materialEditor.targets.OfType<Material>().ToArray();
|
||||
if (materials.Length == 0) return;
|
||||
|
||||
// Surface Type (Opaque / Transparent)
|
||||
{
|
||||
var current = new UniGltfPbrContext(materials[0]).SurfaceType;
|
||||
EditorGUI.showMixedValue = materials.Any(m => new UniGltfPbrContext(m).SurfaceType != current);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var next = (UniGltfPbrSurfaceType)EditorGUILayout.EnumPopup(Styles.SurfaceType, current);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo("Surface Type");
|
||||
foreach (var m in materials)
|
||||
{
|
||||
var context = new UniGltfPbrContext(m) { SurfaceType = next };
|
||||
context.Validate();
|
||||
}
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
// Render Face (cull)
|
||||
{
|
||||
var currentCull = new UniGltfPbrContext(materials[0]).CullMode;
|
||||
var currentIndex = Mathf.Max(0, System.Array.IndexOf(RenderFaceCull, currentCull));
|
||||
EditorGUI.showMixedValue = materials.Any(m => new UniGltfPbrContext(m).CullMode != currentCull);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var nextIndex = EditorGUILayout.Popup(Styles.RenderFace, currentIndex, RenderFaceNames);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo("Render Face");
|
||||
foreach (var m in materials)
|
||||
{
|
||||
var context = new UniGltfPbrContext(m) { CullMode = RenderFaceCull[nextIndex] };
|
||||
context.Validate();
|
||||
}
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
// Alpha Clipping
|
||||
var alphaClipEnabled = new UniGltfPbrContext(materials[0]).IsAlphaClipEnabled;
|
||||
{
|
||||
EditorGUI.showMixedValue = materials.Any(m => new UniGltfPbrContext(m).IsAlphaClipEnabled != alphaClipEnabled);
|
||||
EditorGUI.BeginChangeCheck();
|
||||
var next = EditorGUILayout.Toggle(Styles.AlphaClip, alphaClipEnabled);
|
||||
if (EditorGUI.EndChangeCheck())
|
||||
{
|
||||
materialEditor.RegisterPropertyChangeUndo("Alpha Clipping");
|
||||
foreach (var m in materials)
|
||||
{
|
||||
var context = new UniGltfPbrContext(m) { IsAlphaClipEnabled = next };
|
||||
context.Validate();
|
||||
}
|
||||
alphaClipEnabled = next;
|
||||
}
|
||||
EditorGUI.showMixedValue = false;
|
||||
}
|
||||
|
||||
// Threshold は Alpha Clipping 有効時のみ表示 (副作用のない単純プロパティ)
|
||||
if (alphaClipEnabled && alphaCutoff != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
materialEditor.ShaderProperty(alphaCutoff, Styles.Threshold);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawSurfaceInputs(
|
||||
MaterialEditor materialEditor,
|
||||
MaterialProperty baseColorTexture, MaterialProperty baseColorFactor,
|
||||
MaterialProperty metallicFactor, MaterialProperty roughnessFactor, MaterialProperty metallicRoughnessTexture,
|
||||
MaterialProperty occlusionTexture, MaterialProperty occlusionStrength,
|
||||
MaterialProperty normalTexture, MaterialProperty normalScale,
|
||||
MaterialProperty emissiveTexture, MaterialProperty emissiveFactor, MaterialProperty emissiveStrength)
|
||||
{
|
||||
// NOTE: シェーダは全テクスチャに Tiling/Offset (ScaleOffset) を持つため、
|
||||
// テクスチャ割当時に各マップの TextureScaleOffsetProperty を表示する。
|
||||
if (baseColorTexture != null && baseColorFactor != null)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.BaseMap, baseColorTexture, baseColorFactor);
|
||||
DrawScaleOffset(materialEditor, baseColorTexture);
|
||||
}
|
||||
|
||||
if (metallicFactor != null) materialEditor.ShaderProperty(metallicFactor, Styles.Metallic);
|
||||
if (roughnessFactor != null) materialEditor.ShaderProperty(roughnessFactor, Styles.Roughness);
|
||||
if (metallicRoughnessTexture != null)
|
||||
{
|
||||
materialEditor.TexturePropertySingleLine(Styles.MetallicRoughnessMap, metallicRoughnessTexture);
|
||||
DrawScaleOffset(materialEditor, metallicRoughnessTexture);
|
||||
}
|
||||
|
||||
if (occlusionTexture != null)
|
||||
{
|
||||
var occExtra = occlusionTexture.textureValue != null ? occlusionStrength : null;
|
||||
materialEditor.TexturePropertySingleLine(Styles.OcclusionMap, occlusionTexture, occExtra);
|
||||
DrawScaleOffset(materialEditor, occlusionTexture);
|
||||
}
|
||||
|
||||
if (normalTexture != null)
|
||||
{
|
||||
var normalExtra = normalTexture.textureValue != null ? normalScale : null;
|
||||
materialEditor.TexturePropertySingleLine(Styles.NormalMap, normalTexture, normalExtra);
|
||||
DrawScaleOffset(materialEditor, normalTexture);
|
||||
}
|
||||
|
||||
if (emissiveTexture != null && emissiveFactor != null)
|
||||
{
|
||||
materialEditor.TexturePropertyWithHDRColor(Styles.Emission, emissiveTexture, emissiveFactor, false);
|
||||
if (emissiveStrength != null)
|
||||
{
|
||||
EditorGUI.indentLevel++;
|
||||
materialEditor.ShaderProperty(emissiveStrength, Styles.EmissiveStrength);
|
||||
EditorGUI.indentLevel--;
|
||||
}
|
||||
DrawScaleOffset(materialEditor, emissiveTexture);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// テクスチャが割り当てられている時のみ Tiling/Offset を表示する。
|
||||
/// </summary>
|
||||
private static void DrawScaleOffset(MaterialEditor materialEditor, MaterialProperty textureProperty)
|
||||
{
|
||||
if (textureProperty.textureValue == null) return;
|
||||
materialEditor.TextureScaleOffsetProperty(textureProperty);
|
||||
GUILayout.Space(8);
|
||||
}
|
||||
|
||||
private static void DrawAdvanced(MaterialEditor materialEditor)
|
||||
{
|
||||
materialEditor.EnableInstancingField();
|
||||
materialEditor.DoubleSidedGIField();
|
||||
materialEditor.RenderQueueField();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 30276155ae5852f43887835dfb0c1c55
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
8
Packages/UniGLTF/UniGltfPbr/Runtime.meta
Normal file
8
Packages/UniGLTF/UniGltfPbr/Runtime.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41730641437d69a4e8988676c461c280
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "UniGLTF.UniGltfPbr",
|
||||
"rootNamespace": "",
|
||||
"references": [],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9fe7352e1c749b94aa9194a537b768e6
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
372
Packages/UniGLTF/UniGltfPbr/Runtime/UniGltfPbrContext.cs
Normal file
372
Packages/UniGLTF/UniGltfPbr/Runtime/UniGltfPbrContext.cs
Normal file
@@ -0,0 +1,372 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace UniGLTF
|
||||
{
|
||||
/// <summary>
|
||||
/// glTF 準拠 PBR ShaderGraph (UniGltfPbr) のマテリアルプロパティを操作するクラス。
|
||||
/// import (書き込み) / export (読み取り) の双方で使う。
|
||||
///
|
||||
/// プロパティ名は glTF 2.0 仕様ネイティブ (baseColorFactor / metallicRoughnessTexture ...)。
|
||||
/// テクスチャは glTF のパッキングをそのまま (roughness 未反転, ORM 未変換) 格納し、
|
||||
/// roughness->smoothness などの変換は ShaderGraph 内の per-fragment 演算で行う。
|
||||
///
|
||||
/// Surface(Opaque/Transparent) / Blend / Cull / AlphaClip は ShaderGraph の
|
||||
/// "Allow Material Override" により露出するプロパティで制御する。
|
||||
/// 1 つの .shadergraph に Built-In / URP の 2 Target を同居させるため、
|
||||
/// URP 系 (_Surface ...) と Built-In 系 (_BUILTIN_* ...) の両方を HasProperty ガード付きで扱う。
|
||||
///
|
||||
/// 参考: UniGLTF.UrpLitContext / UniGLTF.UrpBaseShaderContext
|
||||
/// </summary>
|
||||
public sealed class UniGltfPbrContext
|
||||
{
|
||||
public const string ShaderName = "UniGLTF/UniGltfPbr";
|
||||
public static Shader GetShader() => Shader.Find(ShaderName);
|
||||
|
||||
// --- glTF native pbr properties ---
|
||||
private static readonly int BaseColorFactorProp = Shader.PropertyToID("_baseColorFactor");
|
||||
private static readonly int BaseColorTextureProp = Shader.PropertyToID("_baseColorTexture");
|
||||
private static readonly int MetallicFactorProp = Shader.PropertyToID("_metallicFactor");
|
||||
private static readonly int RoughnessFactorProp = Shader.PropertyToID("_roughnessFactor");
|
||||
private static readonly int MetallicRoughnessTextureProp = Shader.PropertyToID("_metallicRoughnessTexture");
|
||||
private static readonly int OcclusionTextureProp = Shader.PropertyToID("_occlusionTexture");
|
||||
private static readonly int OcclusionStrengthProp = Shader.PropertyToID("_occlusionStrength");
|
||||
private static readonly int NormalTextureProp = Shader.PropertyToID("_normalTexture");
|
||||
private static readonly int NormalScaleProp = Shader.PropertyToID("_normalScale");
|
||||
private static readonly int EmissiveFactorProp = Shader.PropertyToID("_emissiveFactor");
|
||||
private static readonly int EmissiveTextureProp = Shader.PropertyToID("_emissiveTexture");
|
||||
private static readonly int EmissiveStrengthProp = Shader.PropertyToID("_emissiveStrength");
|
||||
private static readonly int AlphaCutoffProp = Shader.PropertyToID("_alphaCutoff");
|
||||
|
||||
// --- surface state (URP ShaderGraph target / stock URP Lit compatible) ---
|
||||
private static readonly int UrpSurfaceProp = Shader.PropertyToID("_Surface");
|
||||
private static readonly int UrpBlendProp = Shader.PropertyToID("_Blend");
|
||||
private static readonly int UrpAlphaClipProp = Shader.PropertyToID("_AlphaClip");
|
||||
private static readonly int UrpCullProp = Shader.PropertyToID("_Cull");
|
||||
private static readonly int UrpZWriteProp = Shader.PropertyToID("_ZWrite");
|
||||
private static readonly int UrpSrcBlendProp = Shader.PropertyToID("_SrcBlend");
|
||||
private static readonly int UrpDstBlendProp = Shader.PropertyToID("_DstBlend");
|
||||
private static readonly int UrpCutoffProp = Shader.PropertyToID("_Cutoff");
|
||||
private const string UrpSurfaceTypeTransparentKeyword = "_SURFACE_TYPE_TRANSPARENT";
|
||||
private const string UrpAlphaTestOnKeyword = "_ALPHATEST_ON";
|
||||
|
||||
// --- surface state (Built-In ShaderGraph target) ---
|
||||
private static readonly int BuiltInSurfaceProp = Shader.PropertyToID("_BUILTIN_Surface");
|
||||
private static readonly int BuiltInBlendProp = Shader.PropertyToID("_BUILTIN_Blend");
|
||||
private static readonly int BuiltInAlphaClipProp = Shader.PropertyToID("_BUILTIN_AlphaClip");
|
||||
private static readonly int BuiltInCullProp = Shader.PropertyToID("_BUILTIN_CullMode");
|
||||
private static readonly int BuiltInZWriteProp = Shader.PropertyToID("_BUILTIN_ZWrite");
|
||||
private static readonly int BuiltInSrcBlendProp = Shader.PropertyToID("_BUILTIN_SrcBlend");
|
||||
private static readonly int BuiltInDstBlendProp = Shader.PropertyToID("_BUILTIN_DstBlend");
|
||||
private const string BuiltInSurfaceTypeTransparentKeyword = "_BUILTIN_SURFACE_TYPE_TRANSPARENT";
|
||||
private const string BuiltInAlphaTestOnKeyword = "_BUILTIN_ALPHATEST_ON";
|
||||
|
||||
public Material Material { get; }
|
||||
|
||||
private readonly HashSet<string> _declaredKeywords;
|
||||
|
||||
public UniGltfPbrContext(Material material)
|
||||
{
|
||||
Material = material;
|
||||
_declaredKeywords = new HashSet<string>();
|
||||
if (material != null && material.shader != null)
|
||||
{
|
||||
foreach (var kw in material.shader.keywordSpace.keywordNames)
|
||||
{
|
||||
_declaredKeywords.Add(kw);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ---- base color ----
|
||||
|
||||
/// <summary>
|
||||
/// _baseColorFactor は ShaderGraph "Default" カラー (sRGB 格納) 想定。
|
||||
/// glTF の linear baseColorFactor は .gamma して格納し、export 時に sRGB->Linear で戻す。
|
||||
/// (UniGLTF.UrpBaseShaderContext.BaseColorSrgb と同じ規約)
|
||||
/// </summary>
|
||||
public Color BaseColorSrgb
|
||||
{
|
||||
get => Material.GetColor(BaseColorFactorProp);
|
||||
set => Material.SetColor(BaseColorFactorProp, value);
|
||||
}
|
||||
|
||||
public Texture BaseColorTexture
|
||||
{
|
||||
get => Material.GetTexture(BaseColorTextureProp);
|
||||
set => Material.SetTexture(BaseColorTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 BaseColorTextureOffset
|
||||
{
|
||||
get => Material.GetTextureOffset(BaseColorTextureProp);
|
||||
set => Material.SetTextureOffset(BaseColorTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 BaseColorTextureScale
|
||||
{
|
||||
get => Material.GetTextureScale(BaseColorTextureProp);
|
||||
set => Material.SetTextureScale(BaseColorTextureProp, value);
|
||||
}
|
||||
|
||||
// ---- metallic roughness (glTF native packing, no conversion) ----
|
||||
|
||||
public float MetallicFactor
|
||||
{
|
||||
get => Material.GetFloat(MetallicFactorProp);
|
||||
set => Material.SetFloat(MetallicFactorProp, value);
|
||||
}
|
||||
|
||||
public float RoughnessFactor
|
||||
{
|
||||
get => Material.GetFloat(RoughnessFactorProp);
|
||||
set => Material.SetFloat(RoughnessFactorProp, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// glTF metallicRoughnessTexture をそのまま (G=roughness, B=metallic) 格納する。
|
||||
/// </summary>
|
||||
public Texture MetallicRoughnessTexture
|
||||
{
|
||||
get => Material.GetTexture(MetallicRoughnessTextureProp);
|
||||
set => Material.SetTexture(MetallicRoughnessTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 MetallicRoughnessTextureOffset
|
||||
{
|
||||
get => Material.GetTextureOffset(MetallicRoughnessTextureProp);
|
||||
set => Material.SetTextureOffset(MetallicRoughnessTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 MetallicRoughnessTextureScale
|
||||
{
|
||||
get => Material.GetTextureScale(MetallicRoughnessTextureProp);
|
||||
set => Material.SetTextureScale(MetallicRoughnessTextureProp, value);
|
||||
}
|
||||
|
||||
// ---- occlusion ----
|
||||
|
||||
public float OcclusionStrength
|
||||
{
|
||||
get => Material.GetFloat(OcclusionStrengthProp);
|
||||
set => Material.SetFloat(OcclusionStrengthProp, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// glTF occlusionTexture をそのまま (R=occlusion) 格納する。
|
||||
/// metallicRoughnessTexture と同一テクスチャ (ORM 1 枚) の場合もある。
|
||||
/// </summary>
|
||||
public Texture OcclusionTexture
|
||||
{
|
||||
get => Material.GetTexture(OcclusionTextureProp);
|
||||
set => Material.SetTexture(OcclusionTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 OcclusionTextureOffset
|
||||
{
|
||||
get => Material.GetTextureOffset(OcclusionTextureProp);
|
||||
set => Material.SetTextureOffset(OcclusionTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 OcclusionTextureScale
|
||||
{
|
||||
get => Material.GetTextureScale(OcclusionTextureProp);
|
||||
set => Material.SetTextureScale(OcclusionTextureProp, value);
|
||||
}
|
||||
|
||||
// ---- normal ----
|
||||
|
||||
public float NormalScale
|
||||
{
|
||||
get => Material.GetFloat(NormalScaleProp);
|
||||
set => Material.SetFloat(NormalScaleProp, value);
|
||||
}
|
||||
|
||||
public Texture NormalTexture
|
||||
{
|
||||
get => Material.GetTexture(NormalTextureProp);
|
||||
set => Material.SetTexture(NormalTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 NormalTextureOffset
|
||||
{
|
||||
get => Material.GetTextureOffset(NormalTextureProp);
|
||||
set => Material.SetTextureOffset(NormalTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 NormalTextureScale
|
||||
{
|
||||
get => Material.GetTextureScale(NormalTextureProp);
|
||||
set => Material.SetTextureScale(NormalTextureProp, value);
|
||||
}
|
||||
|
||||
// ---- emissive ----
|
||||
|
||||
/// <summary>
|
||||
/// _emissiveFactor は HDR カラー (linear 直格納) 想定。
|
||||
/// (UniGLTF.UrpLitContext.EmissionColorLinear と同じ規約)
|
||||
/// </summary>
|
||||
public Color EmissiveFactorLinear
|
||||
{
|
||||
get => Material.GetColor(EmissiveFactorProp);
|
||||
set => Material.SetColor(EmissiveFactorProp, value);
|
||||
}
|
||||
|
||||
public Texture EmissiveTexture
|
||||
{
|
||||
get => Material.GetTexture(EmissiveTextureProp);
|
||||
set => Material.SetTexture(EmissiveTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 EmissiveTextureOffset
|
||||
{
|
||||
get => Material.GetTextureOffset(EmissiveTextureProp);
|
||||
set => Material.SetTextureOffset(EmissiveTextureProp, value);
|
||||
}
|
||||
|
||||
public Vector2 EmissiveTextureScale
|
||||
{
|
||||
get => Material.GetTextureScale(EmissiveTextureProp);
|
||||
set => Material.SetTextureScale(EmissiveTextureProp, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// KHR_materials_emissive_strength の emissiveStrength (default 1)。
|
||||
/// </summary>
|
||||
public float EmissiveStrength
|
||||
{
|
||||
get => Material.HasProperty(EmissiveStrengthProp) ? Material.GetFloat(EmissiveStrengthProp) : 1.0f;
|
||||
set => Material.SetFloat(EmissiveStrengthProp, value);
|
||||
}
|
||||
|
||||
public float AlphaCutoff
|
||||
{
|
||||
get => Material.GetFloat(AlphaCutoffProp);
|
||||
set => Material.SetFloat(AlphaCutoffProp, value);
|
||||
}
|
||||
|
||||
// ---- surface / alpha / cull (material-backed; URP と Built-In の両プロパティを設定) ----
|
||||
|
||||
public UniGltfPbrSurfaceType SurfaceType
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Material.HasProperty(UrpSurfaceProp)) return (UniGltfPbrSurfaceType)(int)Material.GetFloat(UrpSurfaceProp);
|
||||
if (Material.HasProperty(BuiltInSurfaceProp)) return (UniGltfPbrSurfaceType)(int)Material.GetFloat(BuiltInSurfaceProp);
|
||||
return UniGltfPbrSurfaceType.Opaque;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFloatIfExists(UrpSurfaceProp, (float)value);
|
||||
SetFloatIfExists(BuiltInSurfaceProp, (float)value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsAlphaClipEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Material.HasProperty(UrpAlphaClipProp)) return Material.GetFloat(UrpAlphaClipProp) >= 0.5f;
|
||||
if (Material.HasProperty(BuiltInAlphaClipProp)) return Material.GetFloat(BuiltInAlphaClipProp) >= 0.5f;
|
||||
return false;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFloatIfExists(UrpAlphaClipProp, value ? 1.0f : 0.0f);
|
||||
SetFloatIfExists(BuiltInAlphaClipProp, value ? 1.0f : 0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
public CullMode CullMode
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Material.HasProperty(UrpCullProp)) return (CullMode)(int)Material.GetFloat(UrpCullProp);
|
||||
if (Material.HasProperty(BuiltInCullProp)) return (CullMode)(int)Material.GetFloat(BuiltInCullProp);
|
||||
return CullMode.Back;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetFloatIfExists(UrpCullProp, (float)value);
|
||||
SetFloatIfExists(BuiltInCullProp, (float)value);
|
||||
Material.doubleSidedGI = value != CullMode.Back;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 現在の SurfaceType / IsAlphaClipEnabled から、派生するキーワード・ブレンド・renderQueue を反映する。
|
||||
/// (surface/cull の float 自体は setter で設定済み)
|
||||
/// 存在しないプロパティは HasProperty で読み飛ばす。
|
||||
/// </summary>
|
||||
public void Validate()
|
||||
{
|
||||
var isOpaque = SurfaceType == UniGltfPbrSurfaceType.Opaque;
|
||||
var alphaClip = IsAlphaClipEnabled;
|
||||
|
||||
Material.SetOverrideTag("RenderType", (isOpaque, alphaClip) switch
|
||||
{
|
||||
(true, false) => "Opaque",
|
||||
(true, true) => "TransparentCutout",
|
||||
(false, _) => "Transparent",
|
||||
});
|
||||
Material.renderQueue = (isOpaque, alphaClip) switch
|
||||
{
|
||||
(true, false) => (int)RenderQueue.Geometry,
|
||||
(true, true) => (int)RenderQueue.AlphaTest,
|
||||
(false, _) => (int)RenderQueue.Transparent,
|
||||
};
|
||||
|
||||
var srcBlend = isOpaque ? (float)BlendMode.One : (float)BlendMode.SrcAlpha;
|
||||
var dstBlend = isOpaque ? (float)BlendMode.Zero : (float)BlendMode.OneMinusSrcAlpha;
|
||||
var zWrite = isOpaque ? 1.0f : 0.0f;
|
||||
|
||||
// URP target
|
||||
SetFloatIfExists(UrpBlendProp, 0.0f); // 0 == Alpha
|
||||
SetFloatIfExists(UrpZWriteProp, zWrite);
|
||||
SetFloatIfExists(UrpSrcBlendProp, srcBlend);
|
||||
SetFloatIfExists(UrpDstBlendProp, dstBlend);
|
||||
SetKeywordIfDeclared(UrpSurfaceTypeTransparentKeyword, !isOpaque);
|
||||
SetKeywordIfDeclared(UrpAlphaTestOnKeyword, alphaClip);
|
||||
Material.SetShaderPassEnabled("DepthOnly", isOpaque);
|
||||
Material.SetShaderPassEnabled("ShadowCaster", isOpaque);
|
||||
|
||||
// Built-In target
|
||||
SetFloatIfExists(BuiltInBlendProp, 0.0f);
|
||||
SetFloatIfExists(BuiltInZWriteProp, zWrite);
|
||||
SetFloatIfExists(BuiltInSrcBlendProp, srcBlend);
|
||||
SetFloatIfExists(BuiltInDstBlendProp, dstBlend);
|
||||
SetKeywordIfDeclared(BuiltInSurfaceTypeTransparentKeyword, !isOpaque);
|
||||
SetKeywordIfDeclared(BuiltInAlphaTestOnKeyword, alphaClip);
|
||||
|
||||
// cutoff: URP の _Cutoff と本シェーダ独自の _alphaCutoff の両方があれば揃える
|
||||
if (Material.HasProperty(UrpCutoffProp) && Material.HasProperty(AlphaCutoffProp))
|
||||
{
|
||||
Material.SetFloat(UrpCutoffProp, Material.GetFloat(AlphaCutoffProp));
|
||||
}
|
||||
}
|
||||
|
||||
private void SetFloatIfExists(int prop, float value)
|
||||
{
|
||||
if (Material.HasProperty(prop))
|
||||
{
|
||||
Material.SetFloat(prop, value);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetKeywordIfDeclared(string keyword, bool enabled)
|
||||
{
|
||||
if (_declaredKeywords.Contains(keyword))
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
Material.EnableKeyword(keyword);
|
||||
}
|
||||
else
|
||||
{
|
||||
Material.DisableKeyword(keyword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 819191e09406ecb46b8513d6bb471e87
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace UniGLTF
|
||||
{
|
||||
public enum UniGltfPbrSurfaceType
|
||||
{
|
||||
Opaque = 0,
|
||||
Transparent = 1,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d009b34824a54913a3422fd5c1584ff6
|
||||
timeCreated: 1784357213
|
||||
8
Packages/UniGLTF/UniGltfPbr/Shaders.meta
Normal file
8
Packages/UniGLTF/UniGltfPbr/Shaders.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 433bd749d686e5940842f4c432afadcf
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
4870
Packages/UniGLTF/UniGltfPbr/Shaders/UniGltfPbr.shadergraph
Normal file
4870
Packages/UniGLTF/UniGltfPbr/Shaders/UniGltfPbr.shadergraph
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8ba9e3a727ae804aa8aeda83529a9e3
|
||||
ScriptedImporter:
|
||||
internalIDToNameTable: []
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
script: {fileID: 11500000, guid: 625f186215c104763be7675aa2d941aa, type: 3}
|
||||
@@ -15,7 +15,8 @@
|
||||
"com.unity.modules.imgui": "1.0.0",
|
||||
"com.unity.modules.imageconversion": "1.0.0",
|
||||
"com.unity.test-framework": "1.4.6",
|
||||
"com.unity.mathematics": "1.2.6"
|
||||
"com.unity.mathematics": "1.2.6",
|
||||
"com.unity.shadergraph": "12.1.12"
|
||||
},
|
||||
"samples": [
|
||||
{
|
||||
|
||||
@@ -155,7 +155,8 @@
|
||||
"com.unity.modules.imgui": "1.0.0",
|
||||
"com.unity.modules.imageconversion": "1.0.0",
|
||||
"com.unity.test-framework": "1.4.6",
|
||||
"com.unity.mathematics": "1.2.6"
|
||||
"com.unity.mathematics": "1.2.6",
|
||||
"com.unity.shadergraph": "12.1.12"
|
||||
}
|
||||
},
|
||||
"com.vrmc.univrm": {
|
||||
|
||||
Reference in New Issue
Block a user