from2001 / VRM_VisualScriptingNodes

Unity Visual Scripting node library for VRM
MIT License
4 stars 2 forks source link

Vision OS Support (Shader problem) #20

Closed from2001 closed 1 month ago

from2001 commented 6 months ago

The VRM model appears in pink on VisionOS simulator.

【AppleVisionPro】Unity Poly Mesh✖️VRM、スキャンデータ、ライト - トマシープが学ぶ https://bibinbaleo.hatenablog.com/entry/2023/11/29/141546

from2001 commented 6 months ago

v0.112 MToon の URP 対応 - UniVRM Programming documentation https://vrm-c.github.io/UniVRM/en/api/0_112_urp.html

from2001 commented 6 months ago

simplestargame/ShaderGraphsMToonForURPVR: ShaderGraphsMToonForURPVR https://github.com/simplestargame/ShaderGraphsMToonForURPVR

simplestargame/SimpleURPToonLitOutlineExample: SimpleURPToonLitOutlineExample https://github.com/simplestargame/SimpleURPToonLitOutlineExample

from2001 commented 6 months ago

UniversalRPでなんちゃってMToonシェーダーを作ってみた話 – ギャップロ https://gaprot.jp/2020/04/14/universalrp-mtoon/

from2001 commented 6 months ago

simplestargame/VRM-Toon-for-Universal-RP: VRM Toon Shader Graph for Universal RP https://github.com/simplestargame/VRM-Toon-for-Universal-RP

from2001 commented 6 months ago

FFaUniHan/Unity_VRoid_Shader_Graph_Transition: Shaders in games are awesome! In this tutorial, I'll introduce you to the beautiful world of Shader Graph in Unity, even if you have no prior experience in it. https://github.com/FFaUniHan/Unity_VRoid_Shader_Graph_Transition

from2001 commented 6 months ago

simplestargame/SimpleURPToonLitOutlineExample: SimpleURPToonLitOutlineExample https://github.com/simplestargame/SimpleURPToonLitOutlineExample

Tested with VRM10 and VisionOS, but didn't work.

from2001 commented 6 months ago

I couldn't find a good shader for VisionOS, so I will use Lit and Unlit until VRC releases official MToon shader graph for VisionOS.

from2001 commented 6 months ago

I implemented a function to change URP/MToon10 shader to URP/Unlit shader trying to keep the look of the material similar as much as possible.

This is the conversation with ChatGPT to make the function. I made some changes manually, but ChatGPT did a awesome job. https://chat.openai.com/share/5485ced5-2381-4291-a87c-025641d48f82

It turns out that this method doesn't work on VisionOS simulator since MToon shader will not set and trigger errors when VRM is loaded.

        /// <summary>
        /// Change all URP/MToon10 shaders of GameObject to URP/Unlit.
        /// This method is intended to be used for VRM models on VisionOS.
        /// </summary>
        /// <param name="targetObject"></param>
        public static void ChangeMtoon10ShaderToUnlitOfGameobject(GameObject targetObject)
        {
            ChangeToUnlitMaterialsRecursive(targetObject.transform);
            static void ChangeToUnlitMaterialsRecursive(Transform target)
            {
                if (target.TryGetComponent<Renderer>(out var renderer))
                {
                    var materialsCopy = renderer.materials;
                    for (int i = 0; i < materialsCopy.Length; i++)
                    {
                        materialsCopy[i] = GetUnlitMaterialMadeByMToon10Shader(materialsCopy[i]);
                    }
                    renderer.materials = materialsCopy;
                }
                foreach (Transform child in target)
                {
                    ChangeToUnlitMaterialsRecursive(child);
                }
            }
        }

        /// <summary>
        /// Change URP/MToon10 shader to URP/Unlit shader.
        /// </summary>
        /// <param name="mat_original"></param>
        static Material GetUnlitMaterialMadeByMToon10Shader(Material mat_original)
        {
            if (mat_original.shader.name != "VRM10/Universal Render Pipeline/MToon10")
            {
                return mat_original; // Exit if the shader is not MToon10
            }

            // Create a temporary copy of the material to extract properties
            Material tempMat = new(mat_original);

            // Create a new material with the Unlit shader
            Material newMat = new(Shader.Find("Universal Render Pipeline/Unlit"));

            // Handle Surface Type (Opaque/Transparent)
            bool isTransparent = tempMat.GetFloat("_AlphaMode") > 0 || tempMat.GetFloat("_TransparentWithZWrite") > 0;

            if (isTransparent)
            {
                // Set surface type to Transparent and enable Alpha Clipping
                newMat.SetFloat("_Surface", 1.0f); // Set to Transparent
                newMat.SetFloat("_AlphaClip", 1.0f); // Enable Alpha Clipping

                // Set blend modes for transparent materials
                newMat.SetFloat("_SrcBlend", (float)UnityEngine.Rendering.BlendMode.SrcAlpha);
                newMat.SetFloat("_DstBlend", (float)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                newMat.SetFloat("_ZWrite", 0.0f); // Typically, ZWrite is off for transparent materials
            }
            else
            {
                // Set surface type to Opaque and disable Alpha Clipping
                newMat.SetFloat("_Surface", 0.0f); // Set to Opaque
                newMat.SetFloat("_AlphaClip", 0.0f); // Disable Alpha Clipping
            }

            // Transfer texture and color properties
            if (tempMat.HasProperty("_MainTex") && newMat.HasProperty("_BaseMap"))
            {
                newMat.SetTexture("_BaseMap", tempMat.GetTexture("_MainTex"));
            }
            if (tempMat.HasProperty("_Color") && newMat.HasProperty("_BaseColor"))
            {
                newMat.SetColor("_BaseColor", tempMat.GetColor("_Color"));
            }

            // Transfer alpha cutoff property
            if (tempMat.HasProperty("_Cutoff"))
            {
                newMat.SetFloat("_Cutoff", tempMat.GetFloat("_Cutoff"));
            }

            //Dispose of the temporary material
            DestroyImmediate(tempMat);

            // Additional blend mode settings can be adjusted here if needed

            // Set shader again (I don't know why this is necessary, but it doesn't work without it)
            newMat.shader = Shader.Find("Universal Render Pipeline/Unlit");

            return newMat;
        }
from2001 commented 6 months ago

MaterialDescriptorGenerator can be made for the VRM importer in editor mode to use specific shaders https://github.com/vrm-c/UniVRM/pull/2116

MaterialDescriptorGenerator and MaterialDescriptor can be made for runtime load to use specific shaders UrpVrmMaterialDescriptorGenerator.cs BuiltInVrmMaterialDescriptorGenerator.cs

from2001 commented 6 months ago

Shader replace code didn't work on the simulator. It seems that Script graph code crashed before VRM scale change in the next node

Screenshot 2023-12-18 at 0 07 00 Screenshot 2023-12-18 at 0 03 02
from2001 commented 6 months ago

I think we could make our own UrpVrm10MaterialDescriptorGenerator to create materials with Unlit shader

Library/PackageCache/com.vrmc.vrm@0.115.0/Runtime/IO/Material/URP/Import/UrpVrm10MaterialDescriptorGenerator.cs

Then, use it for loading VRMs

            Vrm10Instance vrmInstance = await Vrm10.LoadBytesAsync(
                VrmBytes,
                canLoadVrm0X: true,
                materialGenerator: GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset
                    ? new UrpVrm10MaterialDescriptorGenerator() : null
            );
from2001 commented 6 months ago

It turns out that "Universal Render Pipeline/Unlit" shader will be code stripped on VisionOS if you don' t include any materials with Unlit material in the project...........

I put Unlit Material into /Packages/com.from2001.vrm-visualscripting-nodes/Runtime/Resources to avoid code strip, and it worked.

from2001 commented 6 months ago

I made an original MaterialDescriptorGenerator for Unlit shader for . https://github.com/from2001/VRM_VisualScriptingNodes/commit/81d9059b2601919940211a651b27d5d468aac7de

UrpUnlitMaterialDescriptorGenerator.cs

UnlitValidator.cs

On VisionOS, use UrpUnlitMaterialDescriptorGenerator in stead of UrpVrm10MaterialDescriptorGenerator

Vrm10Instance vrmInstance = await Vrm10.LoadBytesAsync(
    VrmBytes,
    canLoadVrm0X: true,
    materialGenerator: GraphicsSettings.currentRenderPipeline is UniversalRenderPipelineAsset
        ? new UrpUnlitMaterialDescriptorGenerator() : null
);
from2001 commented 6 months ago

Fixed shader problem on VisionOS and released compatible version. https://github.com/from2001/VRM_VisualScriptingNodes/releases/tag/v0.1.6

Screenshot 2023-12-18 at 17 49 00

from2001 commented 6 months ago

This parameter of STYLY-chan should be Opaque, but it is Transparent now

Screenshot 2023-12-20 at 9 05 20
from2001 commented 1 month ago

I’ll integrate the PolySpatialEnvironmentDiffuseShader to this package.

https://github.com/segurvita/PolySpatialEnvironmentDiffuseShader

from2001 commented 1 month ago

Materials are now replaced with PolySpatialEnvironmentDiffuseShader shader materials on visionOS

https://github.com/from2001/VRM_VisualScriptingNodes/releases/tag/v0.1.11