Skip to content

Commit

Permalink
Added Vision OS Suuport (Shader replacement)
Browse files Browse the repository at this point in the history
  • Loading branch information
from2001 committed Dec 5, 2023
1 parent 588ecf8 commit a4a75aa
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ private IEnumerator Enter(Flow flow)
yield return new WaitUntil(() => vrmInstance);
resultValue = vrmInstance.gameObject;

Utils.ReplaceErrorShaders(resultValue, Utils.GetShaderForErrorReplacement());
if (Utils.IsVisionOS()) Utils.ChangeShadersWithTexture(resultValue, "Universal Render Pipeline/Unlit", "_MainTex", "_BaseMap");

yield return outputTrigger;
}
Expand All @@ -66,6 +66,7 @@ private async UniTask<Vrm10Instance> LoadVrm(string URL)
{
VrmBytes = request.downloadHandler.data;
}

Vrm10Instance vrmInstance = await Vrm10.LoadBytesAsync(
VrmBytes,
canLoadVrm0X: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,57 +4,90 @@
using System.Runtime.CompilerServices;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
using Unity.VisualScripting;
using System.Collections.Generic;

namespace VisualScriptingNodes
{
public class Utils : MonoBehaviour
{
static public int addTest(int a, int b)
/// <summary>
/// Return true if current OS is VisionOS.
/// </summary>
/// <returns></returns>
public static bool IsVisionOS()
{
return a + b;
}


//When operatingSystem is "visionOS", return true
if (SystemInfo.operatingSystem.Contains("visionOS")) return true;

public static Shader GetShaderForErrorReplacement(string shaderType = "Unlit")
{
Shader retShader = null;
retShader = shaderType switch
//When VolumeCamera exists in scene, return true
foreach (GameObject obj in GetAllObjectsInScene())
{
"Unlit" => Shader.Find(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset
? "Universal Render Pipeline/Unlit" : "Unlit/Texture"),
"Lit" => Shader.Find(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset
? "Universal Render Pipeline/Lit" : "Standard"),
_ => Shader.Find(GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset
? "Universal Render Pipeline/Unlit" : "Unlit/Texture"),
};
return retShader;
}
Component[] components = obj.GetComponents<Component>();
foreach (Component component in components)
{
if (component.GetType().Name=="VolumeCamera") return true;
}
}

return false;
}

// GameObjectとその子孫のマテリアルのシェーダーを再帰的に置き換えるヘルパーメソッド
public static void ReplaceErrorShaders(GameObject obj, Shader replacementShader)
/// <summary>
/// Return all GameObjects in scene.
/// </summary>
/// <returns></returns>
public static List<GameObject> GetAllObjectsInScene()
{
if (obj.TryGetComponent<Renderer>(out var renderer))
List<GameObject> objectsInScene = new List<GameObject>();
foreach (GameObject obj in UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects())
{
foreach (Material mat in renderer.materials)
{
//if (mat.shader == null || Shader.Find(mat.shader.name) == null)
//{
mat.shader = replacementShader;
//}
}
objectsInScene.Add(obj);
GetChildObjects(obj, ref objectsInScene);
}
return objectsInScene;

// 子GameObjectに対しても同じ処理を行う
foreach (Transform child in obj.transform)
static void GetChildObjects(GameObject obj, ref List<GameObject> objectsInScene)
{
ReplaceErrorShaders(child.gameObject, replacementShader);
foreach (Transform child in obj.transform)
{
objectsInScene.Add(child.gameObject);
GetChildObjects(child.gameObject, ref objectsInScene);
}
}
}



/// <summary>
/// Change all shaders of GameObject to new one.
/// This method is intended to be used for VRM and glTF models on VisionOS.
/// </summary>
/// <param name="targetObject"></param>
/// <param name="newShader">"Universal Render Pipeline/Unlit", "Universal Render Pipeline/Lit", etc.</param>
/// <param name="texturePropertyName_old">Set "_MainTex" for Built-in shader</param>
/// <param name="texturePropertyName_new">Set "_BaseMap" for URP Shader</param>
public static void ChangeShadersWithTexture(GameObject targetObject, string newShader = "Universal Render Pipeline/Unlit", string texturePropertyName_old = "_MainTex", string texturePropertyName_new = "_BaseMap")
{
SkinnedMeshRenderer[] skinedMeshrenderers = targetObject.GetComponentsInChildren<SkinnedMeshRenderer>();
foreach (SkinnedMeshRenderer renderer in skinedMeshrenderers) foreach (Material mat in renderer.materials) ChangeShader(mat, newShader);

MeshRenderer[] meshrenderers = targetObject.GetComponentsInChildren<MeshRenderer>();
foreach (MeshRenderer renderer in meshrenderers) foreach (Material mat in renderer.materials) ChangeShader(mat, newShader);

void ChangeShader(Material mat, string shaderName)
{
if (mat.HasProperty(texturePropertyName_old))
{
Texture texture = mat.GetTexture(texturePropertyName_old);
mat.shader = Shader.Find(shaderName);
mat.SetTexture(texturePropertyName_new, texture);
}
else
{
mat.shader = Shader.Find(newShader);
}
}
}
}
}

0 comments on commit a4a75aa

Please sign in to comment.