Skip to main content
UE4.14.0(Preview)で
Forward Shadingを触ってみた
正式版!
自己紹介
● Twitter: com04
● ゲームプログラマー
● 趣味UE4歴: 2年ちょい
● お金貰ってニート中(有給消化)
● スライドは後で公開します
やってみた
● 4.14でForward Shadingが正式採用されたの
で試してみた
– (というのを書いてたら、Epic Games Japanの岡田さんが
Forward Shading+VRのスライドを書かれました)
● UE4.14で広がるVRの可能性
http://www.slideshare.net/EpicGamesJapan/ue414vr
Forward Shadingの有効化
● 「プロジェクト設定」ウィンドウ
→「エンジン」→「Rendering」
→「Forward Shading」チェックボックスをONに
● 再起動を促されるので、エディターを再起動。
有効になったかチェック
● ビューポートの左上にある項目で
「バッファを可視化」→「概要」にする
有効になったかチェック
● Deferred Shading
Gバッファが確認できる
● Forward Shading
Gバッファが見れない
有効になった!
● これだけ!簡単!
で?
● ぼくは何がやりたい?
やりたい!
● Forward Shading出来るのなら、セルシェード(セル
ルック)の実装いい感じに出来るんじゃ?
その前に
● セルシェード(セルルック)に関しては、
おぎまふさん( @ogimafu )が詳しいです。
つよい。いつか倒したい
– 【UE4】セルっぽいルックを頑張ってみる その1(概要)
- 開発日誌
http://ogimafu.blogspot.jp/2015/03/ue4.html
– 【第3回UE4札幌Meetup!!!】 UE4で実装するセル表現
http://www.slideshare.net/TomohiroOgiwara/ue4meet
up-63696087
マテリアル出力追加したい
● マテリアル出力のパラメーターを追加してシェーディン
グ時に使用したい場合、
– Deferred ShadingだとGバッファを拡張してシェー
ディング情報を保存する枠を確保しないといけない
– Forward ShadingだとGバッファが無く、すぐに
シェーディングされるのでそのままの流れで使え
る!Gバッファ追加しなくていい!
そもそものレンダリングフロー
● Deferred Shading
– メッシュの描画命令→
Gバッファにシェーディングに必要な情報をレンダリングして保存
→
(ほぼ)全部のメッシュの描画命令が出た後にGバッファの情報を
使用してスクリーンベースでシェーディング(陰影付)
● Forward Shading
– メッシュの描画命令→
そのままシェーディング
詳しく喋ると1晩かかるのでググって!
やってみた!
● マテリアルのBPで影の色を指定出来るように!
やった事
● マテリアルの出力を拡張。セルシェード用のパラメー
ターを追加。
– マテリアル単位で影色の指定出来るように。
● セルシェード用のパラメーターを、シェーダーの
シェーディング計算部分に流すように←ココ!
● シェーダーをいい感じに弄る
エンジン改造
● UE 4.14.0のエンジンのソースコード落としてきて環境を
整える
– [UE4] エンジンのソースコード取得とビルド手順のまとめ
UE4.6改訂版 – historia
http://historia.co.jp/archives/1327
– エンジン改造 - UE4 Document@com04
http://com04.sakura.ne.jp/unreal/wiki/index.php?
%A5%A8%A5%F3%A5%B8%A5%F3%B2%FE
%C2%A4
事前情報:エンジンコードでのフラグ
● ソースコードでForward ShadingがONかどうか取得
● シェーダーコードでForward Shading時のdefine
● シェーダーコードで、Forward Shadingの時、Gバッ
ファがdisableになってる
static IConsoleVariable* CVarForwardShading =
IConsoleManager::Get().FindConsoleVariable(TEXT("r.ForwardShading"));
const bool bForwardShading =
CVarForwardShading ? (CVarForwardShading->GetInt() != 0) : false;
#define FORWARD_SHADING
#define USES_GBUFFER // これがdisableになってる
事前情報:シェーダーの流れ
● Forward Shading時のシェーダーの流れ
● FPixelShaderInOut_MainPS(BasePassPixelShader.usf)
– GetForwardDirectLighting(ForwardLightingCommon.usf)
● GetDynamicLighting(DeferredLightingCommon.usf)
– SurfaceShading(ShadingModels.usf)
● シェーダーコードは”UnrealEngine/Engine/Shaders”あたり
● ライティング計算はDeferredと同じ物を使ってる。
マテリアル出力に追加~シェーダーで取得
● マテリアル出力に追加~シェーダー内でその値取得まで
● この場で喋ってたら眠くなりそうなので纏めておいた
– UE4でマテリアル出力にピンを追加(UE4.14.0)
http://qiita.com/com04/items/6dc75c647ce97ba72ba4
● 変更箇所多いけど無心で書き加えていくだけ。
シェーダー内での受け渡し枠
● Engine/Shaders/DeferredShadingCommon.usf
– シェーダー内のパラメーター渡し用にFGBufferDataに変数追加
– 初期化しないとエラーが出るので、DecodeGBufferDataに追加
して対処。
// 583行目辺り
#if FORWARD_SHADING
GBuffer.ShadowColor = float3(0,0,0);
#endif
// 350行目辺り
float StoredSpecular;
#if FORWARD_SHADING // ここから
float3 ShadowColor;
#endif // ここまで
シェーダー内での受け渡し
● Engine/Shaders/BasePassPixelShader.usf
– FGBufferData::ShadowColorに、マテリアルから渡されて
きたパラメーターを突っ込む
// 671行目辺り
GBuffer.Depth = MaterialParameters.ScreenPosition.w;
#if FORWARD_SHADING // ここから
GBuffer.ShadowColor = GetMaterialShadowColor(PixelMaterialInputs);
#endif // ここまで
影色の適用
● 色計算部分。LightAccumulator_Add関数を丸々コピー&ペー
ストでLightAccumulator_AddMeetupを作成。
(LightAccumulator.usf)
– 引数にShadowColorを追加
– カラー計算をShadowColorとTotalLightで補間するように
void LightAccumulator_AddMeetup(inout FLightAccumulator In,
float3 TotalLight, float3 ShadowColor, float3 ScatterableLight,
float3 CommonMultiplier,
const bool bNeedsSeparateSubsurfaceLightAccumulation)
// In.TotalLight += TotalLight * CommonMultiplier;
In.TotalLight += lerp(ShadowColor, TotalLight, CommonMultiplier);
影色の適用
● 呼び出し元を差し替える
GetDynamicLighting(DeferredLightingCommon.usf)
// accumulate surface
{
float3 SurfaceLighting =
SurfaceShading(GBuffer, LobeRoughness, LobeEnergy, L, V, N, Random);
#if FORWARD_SHADING
float light = ((NoL * SurfaceAttenuation) > 0.5f) ? 1.0f : 0.0f; // とりあえず2値化
LightAccumulator_AddMeetup(LightAccumulator, SurfaceLighting,
GBuffer.ShadowColor*(1.0/PI), (1.0/PI), light,
bNeedsSeparateSubsurfaceLightAccumulation);
#else
LightAccumulator_Add(LightAccumulator, SurfaceLighting,
(1.0/PI), LightColor * (NoL * SurfaceAttenuation),
bNeedsSeparateSubsurfaceLightAccumulation);
#endif
}
Indirect Lightを消す
● エディター上のPostProcessのSettings
– 「Global Illumination」-「Indirect
Lighting Intensity」を0.0に
● Indirectが有効だと周囲の色味でシェーディングされるのでセ
ルルックっぽくなくなる。左が有効、右が無効。
できた!
● これだけ!
● Gバッファーとか何にも弄らなくていい!
● 多分ぼくが見たセルシェードの中で一番扱いやすいかも。
● 今回弄ってないけど、やるべき項目
– スペキュラも段階付けるとかしないと。
● EngineShadersShadingModels.usf
– StandardShading辺りのハズ…
– ドロップシャドウ周り
● 頑張ればライティング値からテクスチャルックアップの陰影
付も出来るかも。
以上です!
● セルルックとか特殊なシェーディング楽しいよ!
● エンジン改造楽しいよ!(沼