Unityを使った3Dゲームの作り方(かめくめ)ゲーム開発エンジンUnityを使った3Dゲームの制作に参考になる情報を公開しています。2018.10.29今回はUnityのシェーダースクリプトについて見ていこうと思います。シェーダーについて詳しいわけではないので、個人的なメモ書き程度ということにさせて頂きます。(._.)またシェーダースクリプトを書かずともシェーダーグラフを使うとビジュアル操作でシェーダースクリプトを作成出来ますが、そちらはまだ触っていないので出来次第記事にしたいと思います。Graphを触る前に自分で手書きでスクリプトを組んでおくとより理解が深まるかな?という思惑もあります。実際にシェーダーを作成する時はシェーダーグラフで作成し、中身はどうなってんだろ?と言う時にスクリプトの中身を多少理解出来ていると役に立つかもしれません。スポンサーリンクシェーダーって何?シェーダーとはGPU上で動く陰影処理を行うプログラムの事みたいです。Unitの略でリアルタイム画像処理に特化したプロセッサの事です。GPUは膨大な量の並列処理を行う事が出来るので、CPUを使って描画をコントロールするよりも処理が速くなります。シェーダーを使うと3Dオブジェクトの頂点や画面に描画するピクセル等を変化させ3Dモデルに様々なエフェクトを加えることが出来ます。Unityで使うシェーダーシェーダーなんて使っていません!という人がいるかもしれませんが、実は既に使っています(この文句どこかで書いたような記憶があったけれど、C#の勉強カテゴリの継承の記事で使ったかも)。Unity内でCubeやSphereを作成すると、そのオブジェクトにはDefault-Materialという名前のマテリアルが設定されています。そのDefault-MaterialのShaderにはビルトインのStandardシェーダーが設定されています。そんなわけで、マテリアルをゲームオブジェクトに設定するとシェーダーはマテリアルに設定されているということになります。マテリアルはAssetsエリア内で右クリック→Create→Materialで自分で作成出来ますが、シェーダースクリプトも右クリック→Create→Shader→用途に応じて選択で作成出来ます。Shaderを選択します。Shaderはイメージエフェクトを作成する時に使用するといいかもしれません。Shaderはよくわからないので省略します。Shaderは用途に応じて選択しますが、それ用のデフォルトの設定が書かれているだけなので、どれを選択しても中身を理解し書き換えれば同じです。Unityではサーフェスシェーダー(ライティングを考慮した)と頂点シェーダー&フラグメントシェーダー(頂点やピクセルを操作)、固定関数シェーダーで記述出来るようです。シェーダースクリプトの構造サーフェスシェーダースクリプト、頂点シェーダー&フラグメントシェーダーの構造を見ていきましょう。Shaderを選択し、名前をMySurfaceShaderという名前に変更します。関数ENDCG}}サーフェスシェーダーは上のような構造になっています(頂点&フラグメントシェーダーは後で見ていきます)。{}の部分でマテリアルのシェーダー選択時の階層とシェーダー名を自分で設定する事が出来ます。シェーダーのプロパティPropertiesの中にはマテリアルのインスペクタで表示するプロパティを宣言します。1)}_MainTexの部分はスクリプト等から参照する時のプロパティ名で()の中の第1引数のTextureはマテリアルのインスペクタで表示する名前、第2引数が型で=以降が初期値です。Propertiesのスクリプトの記述の最後に;(セミコロン)は要りません。次はSubShaderの部分を見ていきます。{}SubShaderは複数記述する事が出来、ユーザーの環境でサポートされる最初のサブシェーダーが選択されるようになります。どのサブシェーダーもサポートされていない場合はFallBackで指定したシェーダーの使用を試みるようです。次はTagsの部分を見ていきます。}Tagsはレンダリングエンジンがいつどのようにレンダリングするかを設定する部分です。“値”という対で設定します。"Geometry""RenderType"="Opaque"}Queueはレンダリングの順番の設定で、Backgroundは最初にレンダリング、Geometryは不透明な普通のオブジェクト、AlphaTestはGeometryの後、Transparentはこれらの後の透明なオブジェクト等、Overlayは全てのオブジェクトの後にレンダリングするものです。割り当てるための情報が記載されています。docs.unity3d.comを参照してください。RenderTypeはシェーダーを定義済みのいくつかのグループに分ける為に使用します。指示してランタイムに特定のジオメトリを描画するために使用するシェーダを変更できます。これは、エッジ検出などの視覚効果を得るために行う場合があります。次は実際のシェーダーの処理を記述する部分を見ていきます。ENDCG1234CGPROGRAMENDCGCGPROGRAMとENDCGの中に操作したい処理を記述します。次はサーフェスシェーダーコンパイルディレクティブの部分を見ていきます。surfaceでサーフェスシェーダーであることを示し、その後に関数名等を記述します。マニュアルビルトインレンダーパイプラインでは、サーフェスシェーダは、ライティングと連動するシェーダを効率的に記述する方法です。docs.unity3d.comを参照してください。次は構造体の部分を見ていきます。uv_MainTex;};サーフェスシェーダーのInput構造体を作成します。テクスチャ座標を使う場合はuvの後にテクスチャ名を記述します。マニュアルビルトインレンダーパイプラインでは、サーフェスシェーダは、ライティングと連動するシェーダを効率的に記述する方法です。変数宣言部分を見ていきます。_TintColor;2Dのテクスチャプロパティの場合はsampler2D、Colorはfixed4にしています。データの精度として浮動小数点の高精度float、浮動小数点の中精度half、固定小数点の低精度fixed、整数型のint等があります。次は関数部分を見ていきます。{}サーフェス処理関数は上のようになっています。関数名の所にはサーフェスシェーダーコンパイルディレクティブで指定した名前を書きます。Inputは先ほど作ったInput構造体から入力がきます。サーフェスに関する処理はinout(入力出力)でSurfaceOutputStandard構造体に出力されます。SurfaceOutputStandardはサーフェスシェーダーコンパイルディレクティブのライティングモードでStandardを指定した時の構造体で、そこにStandard以外を指定した時は別の構造体を指定する必要があります。StandardSpecularをライティングモードに指定したら構造体はSurfaceOutputStandardSpecular、Lambertを指定したらSurfaceOutputとなります。ここまででサーフェスシェーダーの大まかな構造を見てきました。サーフェスシェーダースクリプトを作ってみる大まかにサーフェスシェーダーの構造を見てきたので、実際にスクリプトを作ってみます。HLSL)learn.microsoft.comに載っているのでそちらを参考にさせて頂きましょう。それでは非常にシンプルなスクリプトを作ってみます。_TintColor.a;}ENDCG}}まずはシェーダースクリプトをマテリアルのShaderの項目のどこに表示されるか?シェーダーの名前を指定します。今回はMySurfaceShaderにMyShaderというシェーダースクリプトを配置します。Propertiesではメインテクスチャの_MainTex、セカンドテクスチャの_SecondTex、色の_TintColorを用意しました。TagsではQueueをGeometryにしてレンダリング順を不透明な通常のオブジェクトとし、RenderTypeをOpaqueにします。addshadowとsurf関数、Standardで物理ベースのシェーダーの宣言をし、addshadowで影ありにします。uv_SecondTex;};と記述し、メインテクスチャとセカンドテクスチャのUVを宣言します。_TintColor;メインテクスチャ、セカンドテクスチャ、カラーの3つの変数を宣言します。最後に実際の処理の部分です。IN.uv_SecondTex).rgb);}o.Albedoはアルベド(表面そのものの色)を設定するので、tex2Dを使って_MainTexをサンプラーステートにし、In.uv_MainTexをテクスチャ座標にし、それに_TintColorを乗算してアルベドに設定しています。何のこっちゃ?って感じですが、tex2Dは_MainTexをIn.uv_MainTexをテクスチャ座標にしてピクセル毎の色を計算してくれるようです。_MainTexにテクスチャを指定すると、そのテクスチャを_MainTexに指定したテクスチャ座標値によって表示する色を決定するので、_MainTexのTilingやOffsetを変更するとテクスチャの貼り付けられ方が変わります。IN.uv_SecondTex).rgb上のようにIN.uv_MainTexの部分をIN.uv_SecondTexに変えた場合は_SecondTexに設定したテクスチャのTilingやOffsetを操作するとメインテクスチャの貼り付けられ方が変わります。基本的に、テクスチャとサンプラーは関連付けられています。スタイルのシェーダー構文を使用する場合のデフォルトの動作です。docs.unity3d.comに詳しい説明があります。サンプリングしたテクスチャの.rgb(RGB値)に_TintColorを乗算するのでインスペクタで_TintColorの色を変更するとテクスチャの色合いが変わります。madを使って今設定したアルベドにセカンドテクスチャを加算して再度アルベドに入れています。madの第1引数が乗算値で、第2引数が1番目の加算値、第3引数が2番目の加算値となります。これで簡単なサーフェスシェーダースクリプトが出来ました。試しにゲームオブジェクトに設定して確認してみましょう。シェーダーを設定するマテリアルが必要になるので、Assetsエリア内で右クリック→Create→Materialを選択し名前をMySurfaceMaterialとします。MySurfaceMaterialのShaderでMySurfaceShaderのMyShaderを設定します。MyShaderを設定したら、MainTex、SecondTexにテクスチャを設定し、TintColorで赤色を設定します。Objects→Cubeを選択し、MySurfaceMaterialマテリアルをCubeにドラッグ&ドロップします。すると、下のようにゲームオブジェクトにマテリアルが設定され、シェーダースクリプトで施した処理が実行されていることがわかります。テクスチャのTilingやOffsetを変更したりTintColorの色を変えるとゲームオブジェクトの変化がわかります。上のような感じになりました。次は頂点シェーダー&フラグメントシェーダーを見ていきます。Shaderを選択し、名前をMyFragmentShaderとします。フラグメント関数ENDCG}}}}上のような構造になっています。ほとんどサーフェスシェーダーと同じですが、CGPROGRAM~ENDCGはPassの中に記述する事になります。CGPROGRAMの中身もほとんどサーフェスシェーダーと同じなのでコンパイラーディレクティブ、構造体や関数の部分だけを見ていきます。コンパイラーディレクティブ部分まずはコンパイラーディレクティブの部分を見ていきます。関数名サーフェスシェーダーの時と同じようにvertex(頂点)、fragment(フラグメント)のディレクティブを書いています。いうプログラミング言語を使用します。docs.unity3d.comを参照してください。次は構造体宣言部分です。Fragmentの略で頂点データからフラグメントへと流し込むデータです。appdataでは頂点データvertexをPOSITIONセマンティック署名を付けて定義し、テクスチャ座標uvをTEXCOORD0を付けて定義しています。セマンティック署名はこのデータがどのようなデータなのかを示すために設定します。POSITIONはオブジェクト空間の頂点位置、TEXCOORD0はテクスチャ座標や位置を表していて最後の数字は何番目かどうかみたいです。SV_POSITIONはピクセル位置(クリップスペース位置)を表しています。次は頂点関数を見ていきます。input){構造体appdataのデータを引数として受け取りそれに処理を加えてv2f構造体を返します。次はフラグメント関数を見ていきます。SV_Target}引数としてvert関数で処理したデータを受け取りそれに処理を加えてフラグメント処理(ピクセル処理)を行います。結果はfixed4型で返しますがそれはSV_Targetで色としてのデータであることをセマンティックで指定しています。頂点シェーダー&フラグメントシェーダースクリプトを作ってみる実際に頂点シェーダー&フラグメントシェーダーのスクリプトを作ってみます。col;}ENDCG}}}MyShaderの中にMyFragmentShaderを作成します。"UnityCG.cginc"という記述がありますが、これは定義済みの変数や関数を呼び出すためのファイルを取り込んでいます。使用できるいくつかのファイルが含まれています。ディレクティブで行われています。docs.unity3d.comを参照してください。今回はUnityCG.cgincを取り込んでいますが、この中で定義されている関数をvert関数内で使用します。_MainTex_ST;メインテクスチャのテクスチャ_MainTex、メインテクスチャのTilingとOffsetを表す_MainTex_STを宣言しています。_MainTexの後に_STと付いていますが、テクスチャの後に_STと付けるとTilingやOffsetの情報を表すようです。vert関数ではUnityCG.cgincで定義されているUnityObjectToClipPos関数を使用して頂点データをオブジェクト空間からカメラのクリップ座標(カメラから見た時の縦横の座標)に変換します。TRANSFORM_TEXで入力のテクスチャを_MainTexをテクスチャ座標としてUVを作成しています。最後にreturnで処理した頂点データをfrag関数に渡します。frag関数ではメインテクスチャを受け取った頂点データinputのテクスチャ座標でサンプリングします。シェーダースクリプトが出来たので、Assetsフォルダ内で右クリック→Create→Materialを選択し、名前をMyFragmentMaterialとしShaderにMyFragmentShaderを設定します。MyFragmentMaterialのMainTexに何かしらのテクスチャを設定します。ヒエラルキー上に新しくCube(サーフェスシェーダー用に作ったCubeを使ってもよし)を作りそれにMyFragmentMaterialをドラッグ&ドロップし設定します。上のようにCubeが表示されました。Cubeにテクスチャが張られているだけのように見えますが・・・・、その通りです!!vert関数ではオブジェクトの位置を3D空間からカメラのクリップ情報に変換しテクスチャのUVの割り当てをし、frag関数ではそのUVデータを元にメインテクスチャを表示しているだけです。vert関数やfrag関数はどこから呼ばれてる?UnityのシェーダースクリプトはHLSLという言語の異形のようです。基本的な事を勉強していないのでシェーダースクリプトは分からない!というままです。そもそもvert関数やfrag関数はどうやっていつ呼び出されてるのか?となんだか処理の流れがわかりません。Unityさんの方から勝手に呼んでくれているようで、オブジェクトの全ての頂点をvert関数で処理し、そのデータをfrag関数の引数として受け取りピクセル処理をしているようです。これらの処理を順番に処理するわけでなくGPUを使って並列に大量処理をしています。これで頂点シェーダー&フラグメントシェーダーのサンプル(実際は何も処理していません)も出来ましたが、本当は頂点を操作したりしてエフェクトを加えたいところですが、手書きで何かエフェクトを加えようと思うと結構難しそうです・・・(^_^;)Unityマニュアルのシェーダー関係のページでサンプルは載っていますが、なんだか難しそうです。頂点データは頂点シェーダー関数への入力で渡されます。入力は頂点法線のデータです。docs.unity3d.comにいくつか載っています。実際のサンプルはシェーダーグラフを使って面白そうなのが出来たら記事にしようと思います。手書きで何もやらないのもあれなんで、頂点を操作してオブジェクトの形状を変化させるサンプルを作成してみましょう。幽霊のようにキャラクターを歪ませるサンプルまずは人型キャラクターの頂点を動かしユラユラと動く幽霊やバーチャル映像の乱れのようなエフェクトを作成していきます。スタンダードアセットのThirdPersonControllerをヒエラルキー上にドラッグ&ドロップします。次はAssetsフォルダ内で右クリック→Create→Materialを選択し、名前をDistortMaterialとします。Shaderを選択し、名前をDistortShaderとします。DistortMaterialのShaderをDistortShaderにします。col;}ENDCG}}}Propertiesで歪ませる量を_Amount、歪みのスピードを_Speedとして定義しました。TagsではQueueとRenderTypeをTransparentにします。OneMinusSrcAlphaで昔ながらの透明のブレンディングをします。マニュアルレンダリング時に深度バッファのコンテンツを更新するかどうかを設定します。有効で、半透明なオブジェクトには無効です。どのようにレンダーターゲットと組み合わせるかを決定します。docs.unity3d.comのUnityマニュアルを参照してください。幽霊感を出すために人型キャラクターを半透明にする為の処理です。変数宣言と関数の部分を見ていきます。col;}vert関数でsinを使って-1~1の値を得ますが、引数でビルトインのシェーダー変数_Timeを使って時間経過でsinで得られる値を変化させます。ビルトインのシェーダー変数に関してはUnityマニュアルを参照してください。ビルトインのインクルードファイルには、シェーダー用のグローバル変数が含まれています。使用中のオブジェクトの変換行列、ライトパラメーター、現在の時間などです。使用しますが、関連するインクルードファイルをインクルードしていれば、宣言する必要はありません。docs.unity3d.com_Timeでステージのロードからの経過時間を取得出来ます。_Timeはfloat4型で倍速?を指定出来ます。_Time[0]は1/20、_Time[1]は1、_Time[2]は2、_Time[3]は3倍のようです。float4型なので0はx、1はy、2はz、3はwに対応していて、_Time.x、_Time.y、_Time.z、_Time.wでも指定出来ます。_Timeにカメラのクリップ空間に変換した頂点のY座標と_Speedとかけてsinの引数に指定しスピードを変化させます。それに_Amountをかけて歪みの量を変化させた位置を頂点のX座標に足してそれを頂点のX座標に入れなおします。カメラのクリップ位置のX座標をsinを使ってY座標に応じて頂点位置をずらしています。ビルトインのシェーダー変数には_SinTimeでも時間に応じたサイン値を取得する事が出来ます。0.5;とアルファ値に0.5を入れています。DistortMaterialのTextureでEthanOcclusionを設定します。ThirdPersonControllerの子要素のEthanBodyとEthanGlassesにDistortMaterialをドラッグ&ドロップします。EthanGlassesにもDistortMaterialを設定しましたが、これはサングラス用に別のマテリアルを作成するのが面倒なのでそのまま適用しました。それでは設定が終わったので確認してみましょう。上のようにキャラクターが歪んで表示されました。マテリアルのインスペクタでSpeedやAmountを変化させると歪みを変化させることが出来るので試してみてください。スクリプトからシェーダーのプロパティを変更する先ほどのシェーダースクリプトでキャラクターに幽霊のようなエフェクトを加えることが出来ますが、SpeedやAmountをインスペクタであらかじめ設定した値から変更できませんでした。そこでC#スクリプトからシェーダーのプロパティ値を変更し、キャラクターの歪みのスピードや大きさを変更出来るようにしてみます。maxAmount));}}インスペクタでキャラクターに使用しているマテリアルを設定します。頂点をズラすスピードと量の最小値と最大値をインスペクタで設定出来るようにし、その範囲でランダムな値を生成し、シェーダーのプロパティに設定します。設定する値);で設定出来ます。プロパティ名はシェーダースクリプトで設定したプロパティ名を指定します。作成したChangeOfDistortionParameterスクリプトをThirdPersonControllerに取り付けます。上のようにMaterialにDistortMaterialをAssetsフォルダからドラッグ&ドロップしておきます。これでランダム値がシェーダースクリプトのプロパティ値に入るので動きがランダムになります。それでは実行してみましょう。上のような感じでランダムに歪みが変わるようになります。終わりにシェーダーを自分で書くのはかなり大変ですね。(^_^;)最初に勉強を始めた時はこの関数はどうやって呼ばれてるんだ?流れはどうなってんの?と通常のC#のプログラム等と似て非なるものなので混乱しました。Unityのマニュアルのシェーダーに関するページはかなり多く、専門的な用語が書いてあったりするので理解をするのは難しいです。いうわけでこの記事は自分用のメモという体にさせて頂きました。シェーダーはレンダリング方式に応じて全方式のシェーダーを全て用意しなければならない為、ここら辺を考えると自分でシェーダースクリプトを作成するよりシェーダーグラフを使った方が良さそうです。シェーダーグラフを使ってないので何とも言えませんが・・・・(^_^;)参考サイトUnityマニュアルーシェーダーリファレンスーのページから色々探せます。コピーかめくめちゃんをフォローする7Unityを使った3Dゲームの作り方(かめくめ)Unityを使った3Dゲームの作り方(かめくめ)関連記事シェーダーUnityのシェーダーグラフについてUnityのシェーダーグラフの使い方と個々のノードについて見ていきます。シェーダーUnityでカメラ前のオブジェクトを半透明にして主人公を見えるようにするUnityでカメラの前のオブジェクトを半透明にして操作キャラクターの主人公を見えるような機能を作成していきます。Unityでパノラマ動画を再生して空を動かすUnityのプロジェクト作成時のテンプレートについてホームシェーダースポンサーリンクサイト内検索が出来ますプロフィール管理人のかめくめちゃんです。(-_-)メールはこちらにお願いします(記事に関する質問は送らないでください、返信は期待しないでください(._.))。kamekumechan@gmail.comいずれはSIRENやバイオハザードみたいなアクションゲームを作りたいと思っています。ゲームシナリオが書けないので面白いゲームはなかなか作れません・・・・。(^_^;)名前の由来はカメが好きだからです。プロフィールになってないな・・・・(-.-)Unityをこれから始める人へこれからUnityを使ってみようという方はUnityを使った3Dゲームの作り方(かめくめ)の歩き方Unityを使った3Dゲームの作り方(かめくめ)で、はじめてUnityの学習をする時の当ブログの記事を読む順番を書きました。機能を積み上げていく形になるので便利かも?gametukurikata.com2019.06.21の記事に記載の順番で見て頂くとUnityの基本的な使い方がわかり、簡単なアクションゲームや、TPSゲームの作成までが出来ます。自作タイピングゲームタイピングゲームを作りました。WebGL形式なのでPCのブラウザで遊べます。以下からプレイ出来ます。FinalTypingUnityを使って作成したローマ字入力のタイピングゲームです。gametukurikata.com2022.01.02お知らせ2023/01/24個人的にUnity2022.2.3f1をインストールしました。2022/10/14UnityのIKを使って足の位置と角度を地面に合わせる機能Unityのゲームでキャラクターの両足が別の高さの地面の上にある時にそれぞれの足をそれぞれの地面につけるようにする機能を作成しますgametukurikata.com2016.04.11機能を少し修正しました。2020/09/19コメント欄は閉鎖しました。今までコメントを投稿してくださった方はありがとうございました。(^^)/2018/08/07わたくしに出来る事は既に記事にしてあるので、ブログ右上の検索窓を活用してください。(._.)またブログの最初の方の機能を積み上げていく記事に関しての疑問点は当ブログ記事のスクリプトの説明と寄せられた質問への回答Unityを使った3Dゲームの作り方(かめくめ)の機能積み上げ形式の記事のスクリプトの説明と寄せられた記事の機能についての質問への回答を掲載しています。gametukurikata.com2019.08.01Unityを使い始めたばかりの人がつまづきやすい点を解消するUnityを使い始めたばかりの人が結構な確率で陥る不具合や疑問点を解消していきます。基本的にはブログに寄せられた質問への回答という感じです。gametukurikata.com2018.12.04も参照してみてください。小・中学生によるデジタルコンテンツ開発の全国大会ですuycc.unity3d.jp2022年大会の先行エントリーが開始されているようです。当ブログはハイスピードプランです。WordPressの編集画面の動作が早くなった。当ブログはハイスピードプランです。WordPressの編集画面の動作が早くなった。記事の内容に質問がある方へUnityを使った3Dゲームの作り方(かめくめ)の歩き方UnityのJavaScriptとC#を読み替えてどちらでも対応出来るようにするホーム検索トップサイドバータイトルとURLをコピーしました。