UnityのShaderですがとりあえず今回からコードも合わせて書いていこうとは思います。
といっても、これといってすごいものをやるわけではなく
簡単な内容で感覚を覚えつつ最終的にトゥーンシェーダーとかを自作してみよう的な感じです。
さて、この記事でやるのは基本的にVertex/Fragment Shaderというのは言ってはいますが
UnityでShaderを作成すると基本的にSurface Shaderになっています。
なので、まずはとりあえず必要最低限のコードを書いてしまいましょうか。
Shader "AIChanShader/ColTexture" {
Properties {
_Color ("Color", Color) = (1,1,1,1)
_MainTex ("Albedo (RGB)", 2D) = "white" {}
}
SubShader {
Pass{
Tags { "RenderType"="Opaque" }
CGPROGRAM
#include "UnityCG.cginc"
#pragma vertex vert
#pragma fragment frag
// DECLARATION
sampler2D _MainTex;
float4 _Color;
struct appdata {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
// Vertex Shader
// ----------------------------------------
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
return o;
}
// Fragment Shader
// ----------------------------------------
fixed4 frag(v2f i) : SV_TARGET
{
fixed4 result = tex2D(_MainTex, i.uv) * _Color;
return result;
}
ENDCG
}
}
FallBack "Diffuse"
}
一発書きでうまくいったのでよかったです。
さて、内容に関してはテクスチャを張り付けるだけのシンプルなShaderです。
私がShaderでテスト環境作るときは基本的にここから始まります。
初めのShader "AIChanShader/ColTexture"に関してですが
これはMaterialでShaderを選ぶときに候補として出てくる名前になります。
自信たっぷりのShaderができたらぜひ素敵な名前を付けてあげてください。
Vertex / Fragment Shaderの特徴ですが、
SubShader内にPassを書く必要があります。
ちなみにこのパスというのは覚えておいて損はないです。
複雑なShaderを書いたり似たような画像の計算をするだけのものでしたら
これを使うことになるかもしれないです。
Shaderは必ずCGPROGRAM~ENDCGでひとくくりです。
複雑なShaderになるとCGINCLUDEとか使ったりはしますが今は何も考えないでいいと思います。
本来ならTagなどのお話もしないといけないのですが
これだけで異常なほどの記事を書くことになりそうなので無視します(え。
#pragma vertex vert
#pragma fragment frag
この二つがVeretx / Fragmentを使う名前になります
vertexではvert、fragmentではfragという名前の関数を使って計算してくださいね!って意味です。
struct appdata {
float4 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
};
この二つの構造体がShaderでは計算などに使われるものになります。
書き方に特徴があるわけではありませんが「SV_」から始まるものは
DirectXのシリーズ別などでの互換性を保つもののようです。
もちろんこれより数を増やすこともできますし、
appdataもこれ以外の変数があったりします。
ただ、使っていないのであれば引っ張ってこない方が計算速度が高速になります。
今までの内容でなんとなくShaderの使い方はわかったでしょうか?
多分わからないと思います。
なので実際に動かしてみた方が早いんですよね。まずはここから先に行く前に、
コードを入れて動かしてみてもいいかもしれません。
成功するとこんな感じになります。
さて、ここからはVertex/Fragmentに渡してる関数についてです。
// Vertex Shader
// ----------------------------------------
v2f vert(appdata v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
return o;
}
この関数では座標の計算、そしてfragに渡すuvを取得し、v2fという構造体にわたしています。
前の時に位置を見える位置にといってましたが、
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
と書くだけで簡単にそれが行われます。
頂点をモデル、ビュー、プロジェクション行列にかけているんですね。
なんでこれで描画されるのかなんて私は知らないです。
魔法の言葉としか考えてないです。
uvに渡してるのはテクスチャの位置です。というよりオブジェクトの面を0~1で表現したものです。
これで、Vertex側の準備は整いました。あとはFragmentですね
// Fragment Shader
// ----------------------------------------
fixed4 frag(v2f i) : SV_TARGET
{
fixed4 result = tex2D(_MainTex, i.uv) * _Color;
return result;
}
Fragでは先ほど引っ張ってきたテクスチャ座標をもとに
tex2Dというものを使って「_MainTex」というテクスチャにアクセスし、
uvの場所にある色を引っ張ってきています。
このとき、画像ではなく色という考え方をした方がいいかもしれないです。
テクスチャの指定した位置にある色を引っ張ってくる。
引っ張ってきた色をさらに「_Color」に入ってる色で掛け算しています。
掛け算なので黒にすれば真っ黒になりますし白にすれば画像の色のままになります。
例えばtex2Dで引っ張ってきた色が(1, 0.5, 0.2)で_Colorが(0.5, 0.5, 0.5)なら
最終的な色は(1, 0.5, 0.2) * (0.5, 0.5, 0.5) = (0.5, 0.25, 0.1)となります
(Shaderでは色も256ではなく0~1の間で表現されます)
で、計算してものを戻り値にすることでさっきの画像のような状態になります。
万が一失敗していた場合は紫っぽい色になると思うので
スペルの間違いなどに注意して書いてみてください。
かなり駆け足ですが、これでおしまいです。
わかりにくいかもしれませんが理解できてくると、わかるようでわからないって感じになります。
Shaderは楽しいというのはできる人の言葉です。実際はどう動くか予想のつかない間は
かなり苦痛の作業になると思いますが、表現の幅を広めるのであれば
必須のものとなります。
次回は……法線かな?
PR
COMMENT
カレンダー
最新記事
(02/05)
(01/22)
(06/01)
(12/18)
(12/18)
最新コメント
プロフィール
HN:
あい。
年齢:
31
性別:
非公開
誕生日:
1994/01/09
自己紹介:
仕事でunityしつつ、3Dとかやるので
そろそろどこに向かってるのか分からなくなってきた人
めーるあどれす:
nokutan_aiあっとyahoo.co.jp
このブログはリンクフリーです。
バナーのURL
"https://blog.cnobi.jp/v1/blog/user/ffb3f4a3a70931da92ac361f9c87596b/1408110435"
になってると思います。
@AI_nohito からのツイート
そろそろどこに向かってるのか分からなくなってきた人
めーるあどれす:
nokutan_aiあっとyahoo.co.jp
このブログはリンクフリーです。
バナーのURL
"https://blog.cnobi.jp/v1/blog/user/ffb3f4a3a70931da92ac361f9c87596b/1408110435"
になってると思います。
@AI_nohito からのツイート
カウンター