はじめに
今回はStandardShaderを置き換えて軽量化しようという記事になります!
まずStandardShader
は様々な機能を持つ万能なシェーダです。
公式にあるお堅い言葉にするとこんな感じ。
Unity の Standard Shader は、包括的な機能を持つビルトインシェーダーです。
Standard Shader によって、すべてのマテリアルタイプで使用できるよう、様々なシェーダータイプ(Diffuse、Specular、Bumped Specular、Reflective など)が 1 つのシェーダーに結合されます。
普段シェーダーを触ったことがない方は基本的にはこちらを無意識に利用しているはずです。(デフォルトがこれのため)
ただし万能が故に、使わない機能も多く無駄な処理がなされている可能性も大いにあります。
特にモバイルゲームではここを改善することでパフォーマンスが向上したりするかもしれません。
そこで今回は実際にStandardShader
を置き換えてみましょう。
自作シェーダー
まずはStandardShader
でいうAlbedo
(テクスチャではなく色)のみを持つシェーダーを書いて、置き換えてみます。
その前に、StandardShader
のプロパティがどのように実装されているかをみてみましょう。
Properties { _Color ("Color", Color) = (1.000000,1.000000,1.000000,1.000000) _MainTex ("Albedo", 2D) = "white" { } _Cutoff ("Alpha Cutoff", Range(0.000000,1.000000)) = 0.500000 _Glossiness ("Smoothness", Range(0.000000,1.000000)) = 0.500000 _GlossMapScale ("Smoothness Scale", Range(0.000000,1.000000)) = 1.000000 [Enum(Metallic Alpha,0,Albedo Alpha,1)] _SmoothnessTextureChannel ("Smoothness texture channel", Float) = 0.000000 [Gamma] _Metallic ("Metallic", Range(0.000000,1.000000)) = 0.000000 _MetallicGlossMap ("Metallic", 2D) = "white" { } [ToggleOff] _SpecularHighlights ("Specular Highlights", Float) = 1.000000 [ToggleOff] _GlossyReflections ("Glossy Reflections", Float) = 1.000000 _BumpScale ("Scale", Float) = 1.000000 [Normal] _BumpMap ("Normal Map", 2D) = "bump" { } _Parallax ("Height Scale", Range(0.005000,0.080000)) = 0.020000 _ParallaxMap ("Height Map", 2D) = "black" { } _OcclusionStrength ("Strength", Range(0.000000,1.000000)) = 1.000000 _OcclusionMap ("Occlusion", 2D) = "white" { } _EmissionColor ("Color", Color) = (0.000000,0.000000,0.000000,1.000000) _EmissionMap ("Emission", 2D) = "white" { } _DetailMask ("Detail Mask", 2D) = "white" { } _DetailAlbedoMap ("Detail Albedo x2", 2D) = "grey" { } _DetailNormalMapScale ("Scale", Float) = 1.000000 [Normal] _DetailNormalMap ("Normal Map", 2D) = "bump" { } [Enum(UV0,0,UV1,1)] _UVSec ("UV Set for secondary textures", Float) = 0.000000 [HideInInspector] _Mode ("__mode", Float) = 0.000000 [HideInInspector] _SrcBlend ("__src", Float) = 1.000000 [HideInInspector] _DstBlend ("__dst", Float) = 0.000000 [HideInInspector] _ZWrite ("__zw", Float) = 1.000000 }
この一番上にある_Color
が今回の目的のAlbedo
という文字の右にある色のことです。
ちなみになんですが、StandartShader
は50871
行もコードがあるみたいでした。
行が長いから重いとは限りませんが、想像以上にすごくてビックリです。
追記)このようなご指摘をいただきました。
モバイルだとシェーダ言語はGLSLになる(スクショの言語は別)ため、
— SpearSoft@個人ゲーム開発者 (@SpearSoftGames) March 4, 2020
このシェーダプログラムは変換されて全てが使われるわけではないとは思います。
本当に50000行なら現行のモバイル端末では全く動かない気がします
これをSurface Shader
で書いてみましょう。
Shader "Custom/Simple" { Properties{ _Color ("Albedo", Color) = (1,1,1,1) } SubShader { Tags { "RenderType"="Opaque" } LOD 200 CGPROGRAM #pragma surface surf Standard fullforwardshadows #pragma target 3.0 struct Input { float2 uv_MainTex; }; fixed4 _Color; void surf (Input IN, inout SurfaceOutputStandard o) { o.Albedo = _Color.rgb; } ENDCG } FallBack "Diffuse" }
あとはマテリアルのシェーダーをCustom -> Simple
に置き換えれば、自動的に色も引き継がれます。
モバイル用シェーダーに置き換える
実はUnityはモバイル用にシンプルなシェーダーを事前に用意してくれています。
docs.unity3d.com
場所はMobile
カテゴリ以下にある奴です。
これらはたとえモバイルでなくとも用いることができ、よりパフォーマンスを出すことができます。
しかし機能に制限がつくことだけは注意してください。
- シェーダーに色合いを加えるマテリアルの色や主要な色はありません
- シェーダーが法線マップを取得するために、ベーステクスチャからタイリングとオフセットが使用されます
- パーティクルシェーダーは AlphaTest と ColorMask をサポートしません
- 制限された特性とライティングのサポート - 例えば、シェーダーの中には 1 つのディレクショナルライトしかサポートしないものがある、など
さいごに
今回自作のシェーダーも作りましたが、実際にどれくらいのパフォーマンスの改善があったかは計測していないのでわかっていません。
ただしモバイルシェーダーは確実に効果があるはずなので、まずはそちらを利用してみると良いかもしれないですね。
ではまた。