169 Views
June 27, 18
スライド概要
2018/6/27に開催されたGTMF2018OSAKAの講演資料です。
講師:黒河 優介(ユニティ・テクノロジーズ・ジャパン合同会社)
リアルタイム3Dコンテンツを制作・運用するための世界的にリードするプラットフォームである「Unity」の日本国内における販売、サポート、コミュニティ活動、研究開発、教育支援を行っています。ゲーム開発者からアーティスト、建築家、自動車デザイナー、映画製作者など、さまざまなクリエイターがUnityを使い想像力を発揮しています。
2018/6/27 ScriptableRenderPipelineでアプリに最適な描画をしよう 講演者名 黒河 優介 所属団体 Unity Technologies Japan 肩書・役職 Developer Relation Engineer
➜荈䊹稱 • 䕵耵 ٝさず⠓爡ػٍآ٥ؤ٦آٗظؙذ٥؍ذصِ • ٦ػحٗكرؚٝ؍ذٕ؟ٝ؝ؤ؎ٓف٦ةؒٝ ،صآٍ٦ؒٝآ٦طوّٝءٖٔ٦ • ➬✲ⰻ㺁 噟ز٦ه؟ךزؙؑآٗف• 㣐鋉垷 ׅꟼחأٝوؓ٦ؿػծדさֲ䕎חزؙؑآٗف • ְג遤䲿周瘝
劤傈ך،ؑآٝت • UnityךزٕؓؿرRenderPipelineךד䲽歗גְאח • ScriptableRenderPipeline(SRP)ך稱➜ • ؛٦؍رةأأ
※劤傈 כForward Rendering ח ꣲ㹀ג׃鑧鹌ׅתְֹג
גְאח䲽歗ךزٕؓؿرUnity גְאחⵖ䖴ך• 䲽歗갫 גְאחְ䪔ךز؎ٓ • גְאחְ䪔ך• Shadow
䲽歗갫ך鑧 㛇劤涸ٕז٦ٕ Opaqueزؙؑآـؔז䩛ַ㤴פ → Depth Testד䲽歗琎幾ׅ Transparentزؙؑآـؔז㤴ַ䩛פ →䲽歗ך灶笼ּ
Opaqueכծ䩛ַ㤴פ
Opaqueכծ䩛ַ㤴פ
Opaqueכծ䩛ַ㤴פ
Opaqueכծ䩛ַ㤴פ Z-Bufferךפ剅ֹ鴥ծZTest剣⸬דךְג׃חծ ⳿勻ꣲ Z-Test剣⸬崞欽ג׃㝢ٕإؙؾ侧幾 חׅ䩛ַ㤴פ䲽歗ְג׃חֲ״ׅ
Transparentכծ㤴ַ䩛פ
Transparentכծ㤴ַ䩛פ
Transparentכծ㤴ַ䩛פ
Transparentכծ㤴ַ䩛פ 㤴ַ䩛פ剅ֻה 姻ֻ׃䲽歗ׁׅתְג 䩛ַ㤴פ剅ֻה ꅾז鿇ⴓך䲽歗ָ灶笼׃ ׅתְג
ֲ㼰׃稢ַֻ䲽歗갫ⵖך䖴ְ׃㜥さ • • • • • 醱侧ךCamera縧ְגDepth⦼ⵖד䖴 RendererךsortingLayerNameⵖד䖴 RendererךsortingOrderⵖד䖴 MeshRendererךsortingOrderⵖד䖴 Material.renderQueueⵖד䖴
ֲ㼰׃䲽歗갫ⵖך䖴ְ׃㜥さ 地面の部分は3つのオブジェクトを描画後に描画して、塗るピクセル数を 減らしてほしいが、一番最初に描画されてしまっています。
ֲ㼰׃䲽歗갫ⵖך䖴ְ׃㜥さ これはRendererのBoundingBoxの中心位置で手前・奥の判定を行っている ため、地面が一番手前と判定されてしまっています。
椚䟝ך䲽歗ך䕎 まず最初に三つのオブジェクトが描画されて…
椚䟝ך䲽歗ך䕎 その後に地面が描画されることが理想形です。
Unityٕך٦ٕ擾濼הְזְג׃ 䲽歗ך갫殢ָⵖ䖴…ְזֹד
גְאחְ䪔ךز؎ٓ պؚٝ؍ذ؎ٓךדأ٦كծչvertexכز؎ٓز؎ٝه ׅתְ遤Ⳣ椚պךד⸇皾さ䧭ךⴓְ鿇չ僇כֻ׃
僇ְ鿇ⴓ⸇ך皾さ䧭 このようにポイントライト3つ あるシーンを描画する場合…
僇ְ鿇ⴓ⸇ך皾さ䧭 まず、ポイントライト適応前の状態を描画します
僇ְ鿇ⴓ⸇ך皾さ䧭 その後、ポイントライト一つ一つ当たった状態のオブ ジェクトを描画して加算合成していきます。 そのため余計な描画負荷を伴います
Point Light....
Shadowך䪔ְגְאח ShadowワⳢך椚כծأؙحنؙحٓـוהק QualitySettingsד鏣㹀䒚כהֿ〳腉
ֲ㼰׃Shadow䒚…ְ
ׅꟼחծ䲽歗כדUnityךדתֿ կ׃ת⳿勻כ鏣㹀ך⦼ דٝⰻ鿇آؒٝכָծ䲽歗Ⳣ椚荈⡤ կ׃דأؙحنؙحٓـֶגׄꟗ
ScriptableRenderPipeline(SRP)ך稱➜ • SRP荈⡤ך堣腉稱➜ • LightWeightRenderPipeline(LWRP)ך稱➜ • ➭ך稱➜
➜堣腉稱ךSRP ؙأ崧ך♴鎸Ⳣ椚ך䲽歗ְג遤דٝآⰻ鿇ؒٝך• Unity ׅד堣腉ָSRPזחֲ״⳿勻ؤ؎وةأؕדزفٔ ؚ• ؕٔٝ ؚٔٝتٖٝךزؙؑآـؔ • Ⳣ椚ך• Shadow ؚٝءحإٗفزأه •
SRPכד䲽歗ך崧דزفؙٔأ剅ֽׅת // 描画時にコールバックされます。引数contextに対して描画命令を発行していきます void OnRender(ScriptableRenderContext context, Camera[] cameras) { foreach (var camera in cameras){ // まず Camera毎のShader のパラメーターセットアップして… SetupShaderParams(camera); // スクリプトで決めたルールでカリングをして… var res = CullResults.Cull(ref cullingParams, context, ref cull); // そしてカリングして得た Rendererを引数で指定したルールで描画します context.DrawRenderers(res.visibleRenderers, ref settings, filterSettings); } }
SRPך㼪Ⰵ倯岀 1.RenderPipelineAsset/RenderPipeline竰䪫أؙٓ׃ 杝荈ח㹀纏ׅת׃ 2. RenderPipelineAsset竰䪫ךأؙٓ׃Asset⡲䧭׃ծ GraphicsSettings.renderPipelineAssetׅת׃زحإח 3.Shader杝荈ךRenderpipelineחさגׇծ LightModeך剅ֹ䳔ִׅת
1.竰䪫أؙٓ׃㹀纏ׅת׃ [ExecuteInEditMode] public class MySRPAsset : RenderPipelineAsset{ protected override IRenderPipeline InternalCreatePipeline(){ return new MyScriptableRenderPipelineInstance(); } } public class MyScriptableRenderPipelineInstance : RenderPipeline{ // 描画のタイミングでコールバックされます public override void Render(ScriptableRenderContext context, Camera[] cameras){ base.Render(context, cameras); foreach (var camera in cameras){ // 描画処理をここに書いていきます } } }
2-1. GraphicsSettingsד鏣㹀
var instance = ScriptableObject.CreateInstance<MySRPAsset>();
AssetDatabase.CreateAsset(instance, "Assets/MyScriptableRenderPipeline.asset");
上記のようなEditor拡張で、独自のRenderPipelineAsset
のアセットを作成します
2-2. GraphicsSettingsד鏣㹀 先ほど作成したRenderPipelineAssetを指定します
3. Shaderך剅ֹ䳔ִ RenderPipeline⩎ דRenderer䲽歗ךֹהׅ鏣㹀חծShaderPassName 床ׅתְג׃կדהֲֿׅծ⟣䠐ך갫殢ךדPass䲽歗ָ〳腉זח ׅתְגկ ךծShader⩎כחPassךせLightModeד僇爙涸ח䭷㹀ׅ䗳銲 ָׅ֮תկ
C#側の処理
var settings = new DrawRendererSettings(camera, new ShaderPassName("BasicPass"));
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true)
{
renderQueueRange = RenderQueueRange.opaque,
layerMask = 1 << LayerDefine.BG
};
context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings);
Shader側
SubShader{
Tags { "Queue"=“Geometry" "RenderType"=“Opaque"}
Pass{
Tags { "LightMode" = "BasicPass"}
....処理等
}
}
C#側の処理
var settings = new DrawRendererSettings(camera, new ShaderPassName("BasicPass"));
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true)
{
renderQueueRange = RenderQueueRange.opaque,
layerMask = 1 << LayerDefine.BG
};
context.DrawRenderers(cull.visibleRenderers, ref settings, filterSettings);
Shader側
SubShader{
Tags { "Queue"=“Geometry" "RenderType"=“Opaque"}
Pass{
Tags { "LightMode" = "BasicPass"}
....処理等
}
}
描画設定で指定したShaderPassNameと
ShaderのLightModeを一致させる必要が
あります。
SRP㼪Ⰵח䔲ךג岣䠐挿
SRPך岣䠐挿 Camera؝ך٦ؙٕحغ禸כㄎׅתזֻזׁ⳿ןկ ךծImageEffect禸ך㹋鄲׃湫ׅ䗳銲ָׅ֮תկ public class MyScriptableRenderPipelineInstance : RenderPipeline{ // 描画のタイミングでコールバックされます public override void Render(ScriptableRenderContext context, Camera[] cameras){ base.Render(context, cameras); foreach (var camera in cameras){ // 描画処理をここに書いていきます } // ImageEffect等の実装はココで実行されるようにする等が必要です } }
SRPך岣䠐挿Ύ Surface Shaderכ㼎䘔ׇתְג׃կ SRPכדծvertex shader / fragment shaderכֻ׃ծ 2018.1ַך倜堣腉ShaderGraphךדShader鎸鶢ח縧ֹ 䳔ִ䗳銲ָׅ֮תկ
Scriptable Render Pipeline״חծ 䲽歗ⵖך䖴דزفؙٔأ稢ַֻ⳿ 勻׃תזחֲ״կ
LightWeightRenderPipeline(LWRP)ך稱➜ ֿֿדתSRPך稱➜ָ׃תֹג׃ծגץׅ0ַ鏣鎘٥圓眠ׅ כך侲㽿ָ넝ְׅדկךծUnity⩎ד欽䠐ذ׃ٖٝف٦ز ָ✳ׅת֮אկ ٥ٌٕ؎غ瘝חぢֽ鯪ꆀٖٝٔتٝ؎ٓف؎ػؚٝ LightWeithRenderPipeline(LWRP) ٥ؒ؎عٝחس暴⻉ٖ׃ٝٔتٝ؎ٓف؎ػؚٝ HDRenderPipeline(HDRP)
LightWeightRenderPipeline(LWRP)ך稱➜ Unityך垥彊(Built-In)ךRenderPipeline׃הزحإـ؟ך ג⡲䧭ׁ׃תկ ♧鿇堣腉䠐㔳涸חꤐ㢩׃䕎ֶגזהծػⴓך ؓؿ٦وٝכأ垥彊״ך葺ְׅתְגזחךկ 垥彊הLWRPך堣腉嫰鯰♴כ鎸URL״ https://blogs.unity3d.com/jp/2018/02/21/the-lightweight-renderpipeline-optimizing-real-time-performance/
LightWeightRenderPipeline(LWRP)ך稱➜ 標準のレンダリングパイプラインで問題だったポイントライトの加算問題も LWRPでは起こりません。ピクセルシェーダー側でキチンとポイントライトを 扱い1パスで描画されます
LWRPך㼪Ⰵגְאח • PackageManager《ד䖤《ג׃鴥 • ٕـٓز㼰ֻז㼪Ⰵְ׃㜥さًأأָؔٓث؝כ • githubַا٦《أ䖤ח♴زؙؑآٗفג׃ꂁ縧 • ؕؤ؎وةأ罋ְִג㜥さًأأָؔٓث؝כ https://github.com/Unity-Technologies/ScriptableRenderPipeline
PackageManagerַLWRPך㼪Ⰵ LightweightRenderPipelineをInstall するだけです
LWRPך㼪Ⰵגְאח • ShaderLWRP㼎䘔חظٌך縧ֹ䳔ִ䗳銲ָ֮ת ׅկ • Unity垥彊ךShader⢪ְגMaterialכגְאח ♧䭍縧䳔ךׅEditor䭁䓸ָず唓ׁדךְגծ ֿⵃ欽ׅת׃կ
LWRPך㼪Ⰵגְאח • 荈魦ךShaderכגְאחծLWRPח㼎䘔ׅ䗳銲ָ֮ ׅת • 㛇劤כLightModeչLightweightForwardպךׅח ׅד • ׃ShadowMapTextureך䪔ְָ㢌דךְגծ Shadow䪔ֲךزؙؑآٗف㜥さכ岣䠐ָ䗳銲ׅד 参考URL https://connect.unity.com/p/lightweightrenderpipelinexiang-kenishaderwoshu-itemita
LWRPך岣䠐挿 • LightWeightRenderPipelineכծ♴鎸؛حػ٦פآ⣛㶷 ְג׃ծ♴鎸؛حػ٦♧آ筰Ⰵח䗳銲ָ ׅ֮ת • PostProcessingStack v2 • ShaderGraph • Core RP
➭ך稱➜ • [ShaderIncludePath]㾩䚍גְאח • Stripping scriptable shader variants(2018.2։)גְאח
[ShaderIncludePath]㾩䚍גְאח • UnityךShaderךincludeٕך٦أػز醱侧䭷㹀ֹד ׃תזחֲ״կ • ֿ״חչAssetsַך窫㼎أػ鿪䏝剅ֻպ or չ湱㼎أػ 孡ָז׃ח剅ֻպ䗳銲ָ׃תזֻז
[ShaderIncludePath]㾩䚍גְאח public class ShaderIncludePathSetting{ [ShaderIncludePath] public static string[] GetPaths(){ return new[]{ "Assets/SRP/Core/", "Assets/SRP/LightWeightPipeline/", }; } Shader内のincludeをコチラからの相対パスで } 指定できるようになります。
[ShaderIncludePath]㾩䚍גְאח • GithubַծLWRP㼪Ⰵ♴חֹה׃鎸חֲ״ך Shaderؒٓ٦ָ㢳涪ׅ㜥さכչShaderIncludePathպ ד姻ָأػְ׃䭷㹀ְׁזְג㜥さָׅ֮תկ
Stripping scriptable shader variants • Shaderךvariants穈さ״חׇծShader荈⡤ך㺁 ꆀָ花㉏ֲת׃ד겗ָ֮׃ת • ٓٝ⟃ؤ؎؟ي؎ة㢩سٕؽח儗ח䝤䕦갟ָ ֮׃ת • ֿח㼎䘔ׅծِ٦ؠ٦⩎ⵃד欽ְז׃穈 さדأإٗفسٕؽׇꤐ㢩תזחֲ״ֹד ׅ 参考URL https://blogs.unity3d.com/2018/05/14/stripping-scriptable-shader-variants/
Stripping scriptable shader variantsה LWRPךꟼ⤘גְאח • LWRPغך٦ّآٝ 2.0 ⟃꣬כדծ Stripping scriptable shader variantsךפ㼎䘔遤ְת ׃կ • ךծLWRP 2.x 禸 כUnity2018.1ⵃכד欽ָ⳿勻ׇת • ➭ךLWRP 2.0禸؎ًכדٝךRenderpipelineⳢח椚꧊⚥ׁ ח׆ׇծٌُآ٦ٕ⻉遤ְ׃ת
؛٦؍رةأأ • 0ַ杝荈ךRenderPipeline荈⡲׃鑧 • LWRPك٦חأRenderPipeline׃يةأؕ鑧
0ַ杝荈ךRenderPipeline荈⡲׃鑧
匢؞ٔهٝד䲽歗ְֽג׃ キャラクターは板ポリゴンに スプライトを貼っただけ
鸐䌢ךRenderPipeline…כד
鸐䌢ךRenderPipeline…כד Transparentは奥から手前を 遵守します
鸐䌢ךRenderPipeline…כד Materialの切り替えを都度しな がら奥から手前へ描画します
鸐䌢ךRenderPipeline…כד そのため、描画するのに非常に多くの Material切り替えが発生しました
Materialⴖ剏ִ䫇ִ…ְ չ㤴ַ䩛պ ֿٕך٦ٕ⡦…ְ׃ַה
Scriptable Render Pipelineז չ㤴ַ䩛պٕ٦ٕ㢌刿 ׅתֹד
䲽歗ךֹהׅ鏣㹀…ד
var pass = new ShaderPassName("BasicPass");
var settings = new DrawRendererSettings(camera, pass);
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true){
renderQueueRange = RenderQueueRange.transparent,
layerMask = 1 << LayerDefine.BG
};
context.DrawRenderers(cull.visibleRenderers,
ref settings,
filterSettings);
䲽歗ךֹהׅ鏣㹀…ד
var pass = new ShaderPassName("BasicPass");
var settings = new DrawRendererSettings(camera, pass);
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true){
renderQueueRange = RenderQueueRange.transparent,
layerMask = 1 <<描画する時のShaderのPass名
LayerDefine.BG
};
を指定できます
context.DrawRenderers(cull.visibleRenderers,
ref settings,
filterSettings);
䲽歗ךֹהׅ鏣㹀…ד
var pass = new ShaderPassName("BasicPass");
var settings = new DrawRendererSettings(camera, pass);
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true){
renderQueueRange = RenderQueueRange.transparent,
layerMask = 1 << LayerDefine.BG
描画する時のソート順を指
};
context.DrawRenderers(cull.visibleRenderers,
定できます
ref settings,
filterSettings);
䲽歗ךֹהׅ鏣㹀…ד
var pass = new ShaderPassName("BasicPass");
var settings = new DrawRendererSettings(camera, pass);
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true){
renderQueueRange = RenderQueueRange.transparent,
layerMask = 1 << LayerDefine.BG
};
描画する対象のオブジェクトの
context.DrawRenderers(cull.visibleRenderers,
ref settings,
Opaque・Transparent等を指定
filterSettings);
できます。
䲽歗ךֹהׅ鏣㹀…ד
var pass = new ShaderPassName("BasicPass");
var settings = new DrawRendererSettings(camera, pass);
settings.sorting.flags = SortFlags.CommonOpaque;
var filterSettings = new FilterRenderersSettings(true){
renderQueueRange = RenderQueueRange.transparent,
layerMask = 1 << LayerDefine.BG
};
context.DrawRenderers(cull.visibleRenderers,
ref settings,
Layer単位で描画するオブジェクト
filterSettings);
を切り替えられます。
֮ הShader חZ Pre-Pass ➬鴥ׅתֶֹד
SubShader{ Tags { "Queue"="Transparent" "RenderType"="Transparent"} // Z Pre-Pass Pass{ Tags { "LightMode" = "ZPrepass"} ZWrite On ColorMask 0 //...実際の処理 } // 実際の描画用のパス Pass{ Tags { "LightMode" = "BasicPass"} ZWrite Off ZTest Equal Blend SrcAlpha OneMinusSrcAlpha //...実際の処理 } }
ֲַ㢌ודSRP ֲ׳׃תְֹג鋅
⯓ חDepth⦼ֽ剅ֹ鴥ׅת αが一定値以下の場合はdiscard して描画を行うShader Pass 「ZPrepass」で一旦キャラク ターを描画します。 ※Z Bufferの様子です
ך䖓䎮䲽ֹׅת その後 床を描画します
ך䖓ةٍؙٓؗ٦䲽ֹׅת キャラクターを通常のShaderPassで描画します。 この時、マテリアル切り替えを最小に抑える順番になるように sorting.flagに「SortFlags.OptimizeStateChanges」を指定します
ך䖓ةٍؙٓؗ٦䲽ֹׅת 最後に影を描画します
Z Pre-Pass㼪Ⰵדך׃ծ ך䖓ך䲽歗儗חչ㤴ַ䩛պ 黼㸚גֻז׃窩ָ灶笼ְז׃ ※α⼱ךד鷲僇ְָז䲿…ׅד
⡦اד٦ز黝䔲ד窩ָ灶笼ַךְז׃ Z BufferのZ値と一致した部分のピクセルでない と、Zテストを通らず、ピクセルが塗られないた め絵が破綻しません
穠卓 Materialⴖ剏ִָ幾 䲽歗頾蚚ָ慧幾׃ת׃
LWRPك٦׃يةأؕחأ鑧 背景からキャラクター。 キャラクターから背景への影 はリアルタイムShadowで、他 は焼いたShadowです。
LWRPك٦׃يةأؕחأ鑧 わかりやすくするため、 リアルタイムのShadowのみ青 くしました。
…תא ⵃ欽Shadowְ搶ח✲Ӎ زؙؑآـؔ → 胜兝زؙؑآـؔ胜兝 Shadowךي؎ةٕӍٔ، ٦ةٍؙٓؗ → زؙؑآـؔ胜兝 زؙؑآـؔ٦ → 胜兝ةٍؙٓؗ ٦ةٍؙٓؗ → ٦ةٍؙٓؗ
LWRP…התתך 焼いたShadowの上からリアル タイムのShadowも描いてしま います
LWRP…התתך それを防ごうとすると、 キャラクターへのShadowが なくなってしまいます
ךְ׃✲ז⡦佦ծ 䲽ך䕦荈⡤ג׃חShadowي؎ةٕٔ،ֽワך٦ةٍؙٓؗ • ׅד،؍ر؎ְֲ،הֲ״ִ䫇׃㼰歗頾蚚 ִ䫇鍑⫷䏝ךShadowדך幥דך٦ワةٍؙٓؗ • ג⥂넝ㅷ颵דךז䕦ְ搶ח✲כ䕦ך• 胜兝
ؕגְאחأػ׃ؤ؎وةأ 始めにキャラクターだけの ShadowMapを生成します
ؕגְאחأػ׃ؤ؎وةأΎ キャラクターだけのShadowMapを 適応して背景を描きます
ؕגְאחأػ׃ؤ؎وةأΏ キャラクターだけのShadowMapに 背景オブジェクトも描き足します。
ؕגְאחأػ׃ؤ؎وةأΐ 最後にキャラクターを描画します。
ׂⳢךֻ椚崧 // 描画時にコールバックされます。引数contextに対して描画命令を発行していきます void OnRender(ScriptableRenderContext context, Camera[] cameras) { foreach (var camera in cameras){ // 「Chara」レイヤーだけ先にShadowを処理します ShadowPass( 1 << Layers.Chara); // 「Chara」レイヤー以外のオブジェクトをレンダリングします DrawObjects( ~( 1<< Layers.Chara) ); // 「Chara」レイヤー以外のShadowを処理します ShadowPass( ~( 1 << Layers.Chara) ); // 「Chara」レイヤーのオブジェクトだけをレンダリングします DrawObjects( 1<< Layers.Chara ); } }
➭ך䘔欽⢽ 通常では、SelfShadowが発 今回の特殊パスを用いれば、 生してしまいます キャラクターのSelfShadowのみオフ に出来ます
SRPך涫㜥״חծShadow Pass 荈歋ⵖח䖴⳿勻ךזחֲ״ דծ倜ְ׃邌植〳腉ח
התScriptableRenderPipeline ַزؙؑآٗفךծ傀㶷דךׅתזֻז侭さ䚍ךה项欵ך• 麓 կׅתְ⠵⸤蕱כִ䳔⛦ך ،ؽءծ䲽歗ワדך׃תזחֲ״稢ַֻⵖ䖴⳿勻 • կׅתָ֮⦼⣣ׅⰅ㼪כדزؙؑآٗفְ䒚ח ծ嫰鯰כדي٦ְזךShadowָ䗳銲ي؎ةٕٔ،װⵖ䖴ز؎ٓ • կׅתְ䙼הְַׅװ׃Ⰵ㼪דךׅת㹋鄲⳿勻חٕفٝء涸 崢欰ַأ٦اךLWRPְג׃䲿⣘ךծUnityכְ㜥さזדֲ • ֲ׳׃דְָ葺ךׅ㹋鄲ד䕎ׅ
Appendix 0ַ⡲䧭؎ٓف؎ػ׃ٝ؟ךٕٝف https://github.com/wotakuro/CustomScriptRenderPipelineTest LWRP何鸡؟׃ٕٝف https://github.com/wotakuro/MixedShadowSample SRPך䒚儗ח饯ֹוזהֿ鎸✲ׅתְג׃ח https://connect.unity.com/u/5768a3b332b306001aaf2d1f