[HoloLens] 3Dモデルの半透明をキレイに表示する
要約
参考情報のブログ記事をもとに StandardDepth.shader を作成し、Unity Asset Store から Unity Technologies 社の Space Robot Kyle アセットをダウンロードしてきて適用した。HoloLens で確認して、違和感のない半透明になっていることを確認した。
動機
HoloLens アプリ上で表示した 3D モデルをを実物に重畳させて表示する場合に役に立つのではないかと考えた。
手順
- [Create] - [Shader] で StandardDepth.shader を作成
- Import した Space Robot Kyle の Material である Robot_Color のコピーを作成 (以下 Robot_Depth)
- Robot_Depth の Shader にShandardDepth を選択
- Robot_Depth の Albedo のα値を 100 くらいに設定
- Source に Albedo Alpha を選択
- Space Robot Kyle の Model である Robot Kyle を Scene に配置
- Hierarchy ツリーで Robot Kyle を展開して、 Robot2 を選択、Material Robot_Depth を適用
- HoloLens アプリとしてビルド
Unity Scene ビューでの表示
(左が通常のStandard Shader、 真ん中が既定の Legacy Shaders/Bumped Diffuse、右が、StandardDepth Shader) Standard Shader では関節部分の半透明に違和感があるが、StandardDepth Shader では無い)
HoloLens 上での表示
動画: www.youtube.com
技術的なポイント
Shader スクリプト内で、デプス書き込みありの透過シェーダーに設定する
Pass{ ZWrite ON ColorMask 0 }
通常 透明シェーダーファミリ (部分的に透過なシェーダー)はデプスバッファに書き込みが、複雑で Convex (非凸)のメッシュの場合、描画順の問題が生まれる可能性があります。今回の例では、Robot Kyle の関節部分に描画順の問題が発生しています。もしそのようなメッシュをフェードイン・フェードアウトした場合、透過をレンダリングする前に、デプスバッファを埋めるシェーダーを使用するのが役立ちます。
Shader スクリプト内で、レンダリングの順番を変更する
Tags{ "RenderType" = "Opaque" "Queue"="Geometry+10" "PerformanceChecks" = "False" }
オブジェクトはすべての不透明のオブジェクトの後にレンダリングされますが、レンダリングキューが 2010 ( Geometry に 10 を加算)のため、透過オブジェクトより先にレンダリングされます。これは、他のオブジェクトのグループの前に描画をさせたい場合に便利です。今回の場合不透明なオブジェクトは Scene に配置していませんが、例えば、多くの場合に透明な水は不透明なオブジェクトの後に、ただし透明なオブジェクトの前に、描画されるようにレンダリング順を変更することが適切です。
補足
パフォーマンスの観点では Legacy Shaders/Bumped Diffuse を使用するのが望ましく、3D モデル作成時の Maya や 3ds Max 上で半透明化した方が良い。動的に Material を変更する要素があれば使用してもいいかもしれない。
参考情報
baba-s.hatenablog.com docs.unity3d.com qiita.com tsubakit1.hateblo.jp assetstore.unity.com matatabi-ux.hateblo.jp docs.unity3d.com docs.unity3d.com
StandardDepth.shader
MIT license で配布していらっしゃるので、【Unity】3Dモデルの半透明をキレイに表示するシェーダを実装する - コガネブログ さんの StandardDepth.shader をこちらに転載させていただきます。
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt) Shader "StandardDepth" { Properties { _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo", 2D) = "white" {} _Cutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5 _Glossiness("Smoothness", Range(0.0, 1.0)) = 0.5 _GlossMapScale("Smoothness Scale", Range(0.0, 1.0)) = 1.0 [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel("Smoothness texture channel", Float) = 0 [Gamma] _Metallic("Metallic", Range(0.0, 1.0)) = 0.0 _MetallicGlossMap("Metallic", 2D) = "white" {} [ToggleOff] _SpecularHighlights("Specular Highlights", Float) = 1.0 [ToggleOff] _GlossyReflections("Glossy Reflections", Float) = 1.0 _BumpScale("Scale", Float) = 1.0 _BumpMap("Normal Map", 2D) = "bump" {} _Parallax("Height Scale", Range(0.005, 0.08)) = 0.02 _ParallaxMap("Height Map", 2D) = "black" {} _OcclusionStrength("Strength", Range(0.0, 1.0)) = 1.0 _OcclusionMap("Occlusion", 2D) = "white" {} _EmissionColor("Color", Color) = (0,0,0) _EmissionMap("Emission", 2D) = "white" {} _DetailMask("Detail Mask", 2D) = "white" {} _DetailAlbedoMap("Detail Albedo x2", 2D) = "grey" {} _DetailNormalMapScale("Scale", Float) = 1.0 _DetailNormalMap("Normal Map", 2D) = "bump" {} [Enum(UV0,0,UV1,1)] _UVSec("UV Set for secondary textures", Float) = 0 // Blending state [HideInInspector] _Mode("__mode", Float) = 0.0 [HideInInspector] _SrcBlend("__src", Float) = 1.0 [HideInInspector] _DstBlend("__dst", Float) = 0.0 [HideInInspector] _ZWrite("__zw", Float) = 1.0 } CGINCLUDE #define UNITY_SETUP_BRDF_INPUT MetallicSetup ENDCG SubShader { Tags{ "RenderType" = "Opaque" "Queue"="Geometry+10" "PerformanceChecks" = "False" } LOD 300 Pass{ ZWrite ON ColorMask 0 } // ------------------------------------------------------------------ // Base forward pass (directional light, emission, lightmaps, ...) Pass { Name "FORWARD" Tags{ "LightMode" = "ForwardBase" } Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] CGPROGRAM #pragma target 3.0 // ------------------------------------- #pragma shader_feature _NORMALMAP #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _EMISSION #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature ___ _DETAIL_MULX2 #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF #pragma shader_feature _PARALLAXMAP #pragma multi_compile_fwdbase #pragma multi_compile_fog #pragma multi_compile_instancing // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. //#pragma multi_compile _ LOD_FADE_CROSSFADE #pragma vertex vertBase #pragma fragment fragBase #include "UnityStandardCoreForward.cginc" ENDCG } // ------------------------------------------------------------------ // Additive forward pass (one light per pass) Pass { Name "FORWARD_DELTA" Tags{ "LightMode" = "ForwardAdd" } Blend[_SrcBlend] One Fog{ Color(0,0,0,0) } // in additive pass fog should be black ZWrite Off ZTest LEqual CGPROGRAM #pragma target 3.0 // ------------------------------------- #pragma shader_feature _NORMALMAP #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF #pragma shader_feature ___ _DETAIL_MULX2 #pragma shader_feature _PARALLAXMAP #pragma multi_compile_fwdadd_fullshadows #pragma multi_compile_fog // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. //#pragma multi_compile _ LOD_FADE_CROSSFADE #pragma vertex vertAdd #pragma fragment fragAdd #include "UnityStandardCoreForward.cginc" ENDCG } // ------------------------------------------------------------------ // Shadow rendering pass Pass{ Name "ShadowCaster" Tags{ "LightMode" = "ShadowCaster" } ZWrite On ZTest LEqual CGPROGRAM #pragma target 3.0 // ------------------------------------- #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _PARALLAXMAP #pragma multi_compile_shadowcaster #pragma multi_compile_instancing // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. //#pragma multi_compile _ LOD_FADE_CROSSFADE #pragma vertex vertShadowCaster #pragma fragment fragShadowCaster #include "UnityStandardShadow.cginc" ENDCG } // ------------------------------------------------------------------ // Deferred pass Pass { Name "DEFERRED" Tags{ "LightMode" = "Deferred" } CGPROGRAM #pragma target 3.0 #pragma exclude_renderers nomrt // ------------------------------------- #pragma shader_feature _NORMALMAP #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _EMISSION #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF #pragma shader_feature ___ _DETAIL_MULX2 #pragma shader_feature _PARALLAXMAP #pragma multi_compile_prepassfinal #pragma multi_compile_instancing // Uncomment the following line to enable dithering LOD crossfade. Note: there are more in the file to uncomment for other passes. //#pragma multi_compile _ LOD_FADE_CROSSFADE #pragma vertex vertDeferred #pragma fragment fragDeferred #include "UnityStandardCore.cginc" ENDCG } // ------------------------------------------------------------------ // Extracts information for lightmapping, GI (emission, albedo, ...) // This pass it not used during regular rendering. Pass { Name "META" Tags{ "LightMode" = "Meta" } Cull Off CGPROGRAM #pragma vertex vert_meta #pragma fragment frag_meta #pragma shader_feature _EMISSION #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature ___ _DETAIL_MULX2 #pragma shader_feature EDITOR_VISUALIZATION #include "UnityStandardMeta.cginc" ENDCG } } SubShader { Tags{ "RenderType" = "Opaque" "PerformanceChecks" = "False" } LOD 150 // ------------------------------------------------------------------ // Base forward pass (directional light, emission, lightmaps, ...) Pass { Name "FORWARD" Tags{ "LightMode" = "ForwardBase" } Blend[_SrcBlend][_DstBlend] ZWrite[_ZWrite] CGPROGRAM #pragma target 2.0 #pragma shader_feature _NORMALMAP #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _EMISSION #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF #pragma shader_feature _ _GLOSSYREFLECTIONS_OFF // SM2.0: NOT SUPPORTED shader_feature ___ _DETAIL_MULX2 // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP #pragma skip_variants SHADOWS_SOFT DIRLIGHTMAP_COMBINED #pragma multi_compile_fwdbase #pragma multi_compile_fog #pragma vertex vertBase #pragma fragment fragBase #include "UnityStandardCoreForward.cginc" ENDCG } // ------------------------------------------------------------------ // Additive forward pass (one light per pass) Pass { Name "FORWARD_DELTA" Tags{ "LightMode" = "ForwardAdd" } Blend[_SrcBlend] One Fog{ Color(0,0,0,0) } // in additive pass fog should be black ZWrite Off ZTest LEqual CGPROGRAM #pragma target 2.0 #pragma shader_feature _NORMALMAP #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature _ _SPECULARHIGHLIGHTS_OFF #pragma shader_feature ___ _DETAIL_MULX2 // SM2.0: NOT SUPPORTED shader_feature _PARALLAXMAP #pragma skip_variants SHADOWS_SOFT #pragma multi_compile_fwdadd_fullshadows #pragma multi_compile_fog #pragma vertex vertAdd #pragma fragment fragAdd #include "UnityStandardCoreForward.cginc" ENDCG } // ------------------------------------------------------------------ // Shadow rendering pass Pass{ Name "ShadowCaster" Tags{ "LightMode" = "ShadowCaster" } ZWrite On ZTest LEqual CGPROGRAM #pragma target 2.0 #pragma shader_feature _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON #pragma shader_feature _METALLICGLOSSMAP #pragma skip_variants SHADOWS_SOFT #pragma multi_compile_shadowcaster #pragma vertex vertShadowCaster #pragma fragment fragShadowCaster #include "UnityStandardShadow.cginc" ENDCG } // ------------------------------------------------------------------ // Extracts information for lightmapping, GI (emission, albedo, ...) // This pass it not used during regular rendering. Pass { Name "META" Tags{ "LightMode" = "Meta" } Cull Off CGPROGRAM #pragma vertex vert_meta #pragma fragment frag_meta #pragma shader_feature _EMISSION #pragma shader_feature _METALLICGLOSSMAP #pragma shader_feature _ _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A #pragma shader_feature ___ _DETAIL_MULX2 #pragma shader_feature EDITOR_VISUALIZATION #include "UnityStandardMeta.cginc" ENDCG } } FallBack "VertexLit" CustomEditor "StandardShaderGUI" }