VR4RoboticArm2/VR4RoboticArm/Library/PackageCache/com.meta.xr.sdk.interaction/Editor/PhongPbrMaterialDescriptionPostprocessor.cs
IonutMocanu d7aba243a2 Main
2025-09-08 11:04:02 +03:00

259 lines
12 KiB
C#

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
* All rights reserved.
*
* Licensed under the Oculus SDK License Agreement (the "License");
* you may not use the Oculus SDK except in compliance with the License,
* which is provided at the time of installation or download, or which
* otherwise accompanies this software in either electronic or hard copy form.
*
* You may obtain a copy of the License at
*
* https://developer.oculus.com/licenses/oculussdk/
*
* Unless required by applicable law or agreed to in writing, the Oculus SDK
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if UNITY_2020_2_OR_NEWER
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;
using UnityEditor.AssetImporters; // AssetImporters namespace became non-experimental in 2020.2.0f1
namespace Oculus.Interaction.Editor
{
/**
* Asset processor that will read custom PBR properties from a Phong material description as an asset file is
* imported. These custom properties are applied to standard lit shader properties on the material that is being
* pre processed.
* This is required since the Phong shader is the only one which the unity built-in FBXMaterialDescriptionPreprocessor
* will convert to a "Standard Lit" shader when parsing an FBX file.
* The advantage of performing this processing here, rather than leveraging custom materials in the unity package, is
* that the Asset Import step will create a suitable material for either the URP or Builtin render pipeline.
*/
public class PhongPbrMaterialDescriptionPostprocessor : AssetPostprocessor
{
private const uint Version = 2;
// Required to be executed after every builtin unity processor to ensure the smoothness property is set properly
private const int Order = 11;
// Smoothness source (Albedo or Metallic map alpha)
private static readonly int SmoothnessTextureChannelPropId = Shader.PropertyToID("_SmoothnessTextureChannel");
private static readonly string SmoothnessTextureChannelCustomProp = "ISDK_SmoothnessTextureChannel";
// Smoothness map and scalar properties:
private static readonly int SmoothnessValueBrpPropId = Shader.PropertyToID("_Glossiness");
private static readonly int SmoothnessValueUrpPropId = Shader.PropertyToID("_Smoothness");
private static readonly int SmoothnessScaleValuePropId = Shader.PropertyToID("_GlossMapScale");
private static readonly string SmoothnessFactorCustomProp = "ISDK_SmoothnessFactor";
// Metallic map
private static readonly int MetallicTexturePropId = Shader.PropertyToID("_MetallicGlossMap");
private static readonly int MetallicValuePropId = Shader.PropertyToID("_Metallic");
private static readonly string MetallicFactorPhongProp = "ReflectionFactor";
// Parallax
private static readonly int ParallaxTexturePropId = Shader.PropertyToID("_ParallaxMap");
private static readonly int ParallaxStrengthPropId = Shader.PropertyToID("_Parallax");
private static readonly string ParallaxCustomProp = "ISDK_HeightMap";
private static readonly string ParallaxStrengthCustomProp = "ISDK_HeightFactor";
// Occlusion
private static readonly int OcclusionTexturePropId = Shader.PropertyToID("_OcclusionMap");
private static readonly int OcclusionStrengthPropId = Shader.PropertyToID("_OcclusionStrength");
private static readonly string OcclusionMapCustomProp = "ISDK_OcclusionMap";
private static readonly string OcclusionStrengthCustomProp = "ISDK_OcclusionFactor";
// Detail
private static readonly int DetailTexturePropId = Shader.PropertyToID("_DetailMask");
private static readonly string DetailMapCustomProp = "ISDK_DetailMap";
public override uint GetVersion()
{
return Version;
}
public override int GetPostprocessOrder()
{
return Order;
}
public void OnPreprocessMaterialDescription(MaterialDescription description, Material material,
AnimationClip[] clips)
{
// Asset Processor supports only URP and Builtin standard shaders.
bool isBirpStandardLit = material.shader.name == "Standard";
bool isUrpStandardLit = material.shader.name == "Universal Render Pipeline/Lit";
if (isBirpStandardLit || isUrpStandardLit)
{
var lowerCaseExtension = Path.GetExtension(assetPath).ToLower();
if (lowerCaseExtension == ".fbx" || lowerCaseExtension == ".dae" || lowerCaseExtension == ".obj" ||
lowerCaseExtension == ".blend" || lowerCaseExtension == ".mb" || lowerCaseExtension == ".ma" ||
lowerCaseExtension == ".max")
{
ReadOvrPbrProperties(description, material, isUrpStandardLit);
}
}
}
private void ReadOvrPbrProperties(MaterialDescription description, Material material, bool isUrp)
{
if (!HasISDKProperty(description))
{
// Only overwrite values if an OVR property was detected. This
// should prevent accidental conflicts with any other user defined AssetPostprocessor's
// since we are reading from the Phong Reflection property, not a custom user defined
// property.
return;
}
Vector4 vectorProperty;
float floatProperty;
TexturePropertyDescription textureProperty;
if (description.TryGetProperty(SmoothnessTextureChannelCustomProp, out floatProperty))
{
var isAlbedoAlphaChannel = floatProperty > float.Epsilon;
material.SetFloat(SmoothnessTextureChannelPropId, isAlbedoAlphaChannel ? 1.0f : 0.0f);
var isOpaque = (material.HasProperty("_Mode") && material.GetFloat("_Mode") == 0.0) ||
(material.HasProperty("_Surface") && material.GetFloat("_Surface") == 0.0);
if (isAlbedoAlphaChannel && isOpaque)
{
material.EnableKeyword("_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A");
}
}
if (description.TryGetProperty(SmoothnessFactorCustomProp, out floatProperty))
{
// Note: setting both value and scale value does not seem to cause any problems.
// For smoothness texture channel = metallic alpha
material.SetFloat(SmoothnessValueBrpPropId, floatProperty);
// For smoothness texture channel = albedo alpha
material.SetFloat(SmoothnessScaleValuePropId, floatProperty);
// For smoothness on URP metallic and albedo alpha
material.SetFloat(SmoothnessValueUrpPropId, floatProperty);
}
if (description.TryGetProperty(ParallaxStrengthCustomProp, out floatProperty))
{
material.SetFloat(ParallaxStrengthPropId, floatProperty);
}
if (description.TryGetProperty(OcclusionStrengthCustomProp, out floatProperty))
{
material.SetFloat(OcclusionStrengthPropId, floatProperty);
}
if (description.TryGetProperty("DiffuseColor", out vectorProperty))
{
// URP uses _BaseColor; BIRP uses _Color
var materialColorProp = isUrp ? "_BaseColor" : "_Color";
var diffuseColor = material.GetColor(materialColorProp);
if (!description.TryGetProperty("DiffuseFactor", out float diffuseFactorProperty))
{
diffuseFactorProperty = 1.0f;
}
diffuseColor.r = vectorProperty.x * diffuseFactorProperty;
diffuseColor.g = vectorProperty.y * diffuseFactorProperty;
diffuseColor.b = vectorProperty.z * diffuseFactorProperty;
// Re-assign the diffuse color to work around incorrect color space behavior in the regular FBX importer:
// in gamma mode, it seems to double-apply the gamma correction, so counteract one of the conversions.
if (PlayerSettings.colorSpace == ColorSpace.Gamma)
{
diffuseColor = new Color(
Mathf.GammaToLinearSpace(diffuseColor.r),
Mathf.GammaToLinearSpace(diffuseColor.g),
Mathf.GammaToLinearSpace(diffuseColor.b));
}
material.SetColor(materialColorProp, diffuseColor);
}
if (description.TryGetProperty(MetallicFactorPhongProp, out float metallic))
{
material.SetFloat(MetallicValuePropId, metallic);
}
if (description.TryGetProperty(MetallicFactorPhongProp, out textureProperty))
{
material.SetTexture(MetallicTexturePropId, textureProperty.texture);
material.SetTextureOffset(MetallicTexturePropId, textureProperty.offset);
material.SetTextureScale(MetallicTexturePropId, textureProperty.scale);
// BIRP uses _METALLICGLOSSMAP ; URP uses _METALLICSPECGLOSSMAP
material.EnableKeyword(isUrp ? "_METALLICSPECGLOSSMAP" : "_METALLICGLOSSMAP");
}
if (description.TryGetProperty(ParallaxCustomProp, out textureProperty))
{
material.SetTexture(ParallaxTexturePropId, textureProperty.texture);
material.SetTextureOffset(ParallaxTexturePropId, textureProperty.offset);
material.SetTextureScale(ParallaxTexturePropId, textureProperty.scale);
material.EnableKeyword("_PARALLAXMAP");
}
if (description.TryGetProperty(OcclusionMapCustomProp, out textureProperty))
{
material.SetTexture(OcclusionTexturePropId, textureProperty.texture);
material.SetTextureOffset(OcclusionTexturePropId, textureProperty.offset);
material.SetTextureScale(OcclusionTexturePropId, textureProperty.scale);
}
if (description.TryGetProperty(DetailMapCustomProp, out textureProperty))
{
material.SetTexture(DetailTexturePropId, textureProperty.texture);
material.SetTextureOffset(DetailTexturePropId, textureProperty.offset);
material.SetTextureScale(DetailTexturePropId, textureProperty.scale);
}
// Apply emissive color as well as texture map, which standard doesn't do.
if (
description.TryGetProperty("EmissiveColor", out vectorProperty) &&
vectorProperty.magnitude > vectorProperty.w
|| description.HasAnimationCurve("EmissiveColor.x"))
{
if (description.TryGetProperty("EmissiveFactor", out floatProperty))
vectorProperty *= floatProperty;
Color emissiveColor = vectorProperty;
if (PlayerSettings.colorSpace == ColorSpace.Gamma)
{
// Re-assign the color to work around incorrect color space behavior in the regular FBX importer:
// in gamma mode, it seems to double-apply the gamma correction, so counteract one of the conversions.
emissiveColor = new Color(
Mathf.GammaToLinearSpace(emissiveColor.r),
Mathf.GammaToLinearSpace(emissiveColor.g),
Mathf.GammaToLinearSpace(emissiveColor.b));
}
material.SetColor("_EmissionColor", emissiveColor);
if (floatProperty > 0.0f)
{
material.EnableKeyword("_EMISSION");
material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.RealtimeEmissive;
}
}
}
private static bool HasISDKProperty(MaterialDescription description)
{
var propertyNames = new List<string>();
description.GetFloatPropertyNames(propertyNames);
foreach (var propertyName in propertyNames)
{
if (propertyName.StartsWith("ISDK_"))
{
return true;
}
}
return false;
}
}
}
#endif