0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】SpriteにNormalMapを作って入れてみた

Posted at

はじめに

Unityの2DのURPではLight2Dというものがあり、2Dゲームにいい感じのライティング設定をつけられます。

image.png

いい感じのライティングの例

image.png

公式の雑なスクショですが

  • 光が電柱で遮られてそれっぽい影ができていたり(右上)
  • NormalMapを使っていたりします(右下)

ならそもそもこのNormalMapはどうやって作ってどうやってUnityに取り込んで使用するのか気になったので作ってみました。

NormalMapを作成する

Spriteilluminatorというソフトを使用します。

image.png
こんな感じの画面のソフト

こちらを使用すると取り込んだ画像にNormalMapを調整して入れることができます。
無料版と有料版があり、無料版はおそらく画像の出力ができません。今回は手元でパッと検証を行いたいだけなので無料トライアル版を使用します。これなら出力できました。

ちなみにソフトの使い方は公式サイトの動画を見てください。
なんとなく画面を見ていれば使い方がわかります。

image.png
パラメータを調整してベベルがつけれるのでつけます。

image.png

LitTextureを押すと光源を動かしてどんな光り方がするのか確認できます。
遮蔽されててNormalが効いてていい感じなので出力します。

image.png

ツール上部のExportNormalsで出力できます。

portrait_kohaku_01_n.png

これが完成したNormalMapです。

Unityに入れる

image.png
Unityにドラッグアンドドロップし、Textureの設定を行います。
NormalMapなのでSpriteModeでNormalMapを選択し、Applyします。

image.png
元のカラーテクスチャも入れておきます。
こっちは設定することは無いです。

Unityでライティングする

image.png
2DObjectからSquareを置きます。
SpriteRendererにはさっきのカラーテクスチャを入れます。

image.png
このままだと真っ暗で何も見えないのでライトを置きます

image.png
GlobalLight2Dを置きます。
光過ぎている場所にいくら光源を置いても明るくて変化がわからないのでLight2DIntensityを下げておきます。

image.png
0.3に調整した様子。ちょっと暗い。

image.png
Sprite用の光源を設置します。
QualityをAccurateにし、Distanceを適当な値にします。0.2とかでいいです。

image.png
NormalMapに対応するように設定します。

image.png
顔だけちょっと明るくなっていていい感じです。
ここに作ったNormalMapを設定します。

image.png
元のカラーテクスチャのSpriteEditorを開きます。

image.png
左上からSecondary Texturesを押します。

image.png
右下がSpriteのBorderやPivotを設定するモードからSecondaryTextureを設定する画面に切り替わります。
ここに_NormalMapという名前で作ったNormalMapを入れます。
必ず_NormalMapという命名でないといけないわけではないです。デフォルトのUnityのLight2DのShaderはNormalMapにこの命名でアクセスしているのでデフォルトのShaderを使用するならこの命名でないとアクセスされず、設定されないです。
逆に一からShaderを書く場合は無視して他の命名にしても問題ないです。
設定したらApplyします。

image.png
SpriteにShadowCaster2Dを付けます。(画像はEditor拡張されていて見た目が通常と異なります。)

image.png
EditShapeでSpriteの形を設定します(Editor拡張はポリゴンに沿ってこの形を設定するEditor拡張です)

ここにソースコードがあります。

image.png
今回はこんな感じ(おかしいところ少しあるが…)

この状態でライトを近づけると
image.png
遮られていますね

image.png
NormalMapがOffの時

Shaderを書いてみる

Normalの情報があればいろいろできます。
今回は適当にRimlightの計算を行います。

URPなのでSprite-Lit-DefaultのShaderをコピペし、それを拡張します。

また、Rimlightの計算方法はこれを使います。

inline float CalcRimlight(float3 V, float3 N, float width, float intensity)
{
    float rim = pow(saturate(1. - dot(V, N) + width), intensity);
    rim = saturate(rim);
    return rim;
}

"LightMode" = "Universal2D"のPassの中に

#include "Packages/com.unity.render-pipelines.universal/Shaders/2D/Include/NormalsRenderingShared.hlsl"

を追加
StructにいくつかNormal用の変数が足りないので追加を行い、

half3   normalWS        : TEXCOORD3;
half3   tangentWS       : TEXCOORD4;
half3   bitangentWS     : TEXCOORD5;

Varyings CombinedShapeLightVertex(Attributes v)の中にNormal計算に必要なものが足りなくなるので追加

o.normalWS = -GetViewForwardDir();
o.tangentWS = TransformObjectToWorldDir(v.tangent.xyz);
o.bitangentWS = cross(o.normalWS, o.tangentWS) * v.tangent.w;

CombinedShapeLightFragmentの中に

half3 normal = NormalsRenderingShared(main, normalTS, i.tangentWS.xyz, i.bitangentWS.xyz, i.normalWS.xyz);

half rim = 1.0 - CalcRimlight(float3(0.0, 0.0, 1.0), normal, _Width, _Intensity);

// 適当に赤
color.rgb += rim * half3(1.0, 0.0, 0.0);

を追加
これを行うことでNormalを利用してRimlightの計算ができます。

image.png
こんな感じ。オーラっぽい

おわりに

ノーマルさえ用意できればあとは3Dでの処理とほぼ同じ書き方でいろいろ作れます。
NormalMapを用意するのがソフトを使おうとすると有料ですが簡単にベベルがかけれるのでお勧めです。

Shaderのソースコードはかなり雑ですがここにあります。
https://github.com/ayaha401/Sprite-Rimlight/blob/master/Sprite.shader

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?