Unityシェーダースニペット集
シェーダー定義マクロ及び定数
docs.unity3d.com
定義済みシェーダープリプロセッサーマクロ - Unity マニュアル
Unity は、シェーダープログラム をコンパイルするときに、プリプロセッサーマクロをいくつか定義します。
docs.unity3d.com
ビルトインのシェーダー変数 - Unity マニュアル
Unity のビルトインのインクルードファイルには、シェーダー用のグローバル変数が含まれています。使用中のオブジェクトの変換行列、ライトパラメーター、現在の時間などです。これらは他の変数と同様に シェーダープログラム で使用しますが、関連するインクルードファイルをインクルードしていれば、宣言する必要はありません。
ビルドインでよくつかうやつ
Name
type
説明
_Time
float4
ステージのロードからの時間 (t/20, t, t2, t 3)。
unity_DeltaTime
float4
デルタ時間: (dt, 1/dt, smoothDt, 1/smoothDt)
_ScreenParams
float4
x はカメラのターゲットテクスチャの幅(単位:ピクセル)、y はカメラのターゲットテクスチャの高さ(単位:ピクセル)、 z は 1.0 + 1.0/幅、 w は 1.0 + 1.0/高さです。
_ProjectionParams
float4
x は 1.0 または -1.0、反転した射影行列で現在レンダリングしている場合は負の値。y は カメラのNear Plane、z はカメラのFar Plane、w は 1/Far Plane。
よく使う定数
// 円周率
#define PI 3.14159265
static const PI = 3.14159265f ;
// 角度→ラジアン
#define DEG2RAD PI / 180.0f
static const float DEG2RAD = PI / 180.0f ;
// 使い方
float rad = degree * DEG2RAD ;
全部入りStandardSurfaceShader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 Properties
{
// アルベド
_Color ( "Color" , Color ) = ( 1 , 1 , 1 , 1 )
_MainTex ( "Albedo (RGB)" , 2 D ) = "white" {}
// 法線
_BumpScale ( "Scale" , Float ) = 1.0
_BumpMap ( "Normal" , 2 D ) = "bump" {}
// ラフネス
_Glossiness ( "Roughness" , Range ( 0.0 , 1.0 )) = 0.5 // Standard準拠だがRoughnessを_Glossinessという名前で受けてるのムカつく
_SpecGlossMap ( "Roughness Map" , 2 D ) = "white" {}
// メタリック
_Metallic ( "Metallic" , Range ( 0.0 , 1.0 )) = 0.0
_MetallicGlossMap ( "Metallic" , 2 D ) = "white" {}
// オクルージョン
_OcclusionStrength ( "Strength" , Range ( 0.0 , 1.0 )) = 1.0
_OcclusionMap ( "Occlusion" , 2 D ) = "white" {}
}
void surf ( Input IN , inout SurfaceOutputStandard o )
{
fixed4 c = tex2D ( _MainTex , IN . uv_MainTex );
o . Albedo = c . rgb ;
o . Alpha = c . a ;
o . Normal = UnpackScaleNormal ( tex2D ( _BumpMap , IN . uv_BumpMap ), _BumpScale );
o . Metallic = tex2D ( _MetallicGlossMap , IN . uv_MainTex );
o . Metallic *= _Metallic ;
o . Smoothness = 1.0f - tex2D ( _SpecGlossMap , IN . uv_MainTex );
o . Smoothness *= ( 1.0f - _Glossiness );
}
スクリーン座標を取得する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 struct v2f
{
float2 uv : TEXCOORD0 ;
}
v2f vert (
float4 vertex : POSITION ,
float2 uv : TEXCOORD0 ,
out float4 outpos : SV_POSITION // VPOSとSV_POSITIONを両方同時にフラグメントシェーダーに渡せないので、SV_POSITIONにout修飾子を付ける
)
{
v2f o ;
o . uv = uv ;
outpos = UnityObjectToClipPos ( vertex );
return o ;
}
fixed4 frag ( v2f i , UNITY_VPOS_TYPE screenPos : VPOS ) : SV_Target
{
// screnPosは解像度の値(ex. 1920x1280)のような整数値なので0-1に変換する
float2 screenPosNorm = screenPos . xy / _ScreenParam . xy ;
}
アルファブレンディング
float4 src ; // 前景
float4 dst ; // 背景
float outA = src . a + dst . a * ( 1 - src . a );
float3 outRGB = lerp ( dst . rgb , src . rgb , src . a );
float4 out = float4 ( outRGB , outA );
コントラスト調整
float3 c = color ;
c = 1.0f / ( 1.0f + exp ( - _Contrast * ( c - 0.5f )));
軽いコントラスト
dst = src - ( src - src * src ) * - x ;
Remap01
float remap01 ( float x , float min_value , float max_value )
{
return ( x - min_value ) / ( max_value - min_value );
}
Remap
float remap ( float value , float inputMin , float inputMax , float outputMin , float outputMax )
{
return ( value - inputMin ) * (( outputMax - outputMin ) / ( inputMax - inputMin )) + outputMin ;
}
ガンマ補正
inline float3 srgbToLinear ( float3 c )
{
return lerp ( c / 12 . 92 , pow (( c + 0 . 055 ) / 1 . 055 , 2 . 4 ), step ( 0 . 04045 , c ));
}
inline float3 linearToSrgb ( float3 c )
{
return lerp ( c * 12 . 92 , 1 . 055 * pow ( c , 1 . 0 / 2 . 4 ) - 0 . 055 , step ( 0 . 0031308 , c ));
}
LinearStep
閾値aから閾値bで0~1で線形に遷移する関数
float linearstep ( float a , float b , float x )
{
return saturate (( x - a ) / ( b - a ));
}
SmoothStep
閾値aから閾値bで0~1で緩やかに遷移する関数
float smoothstep ( float a , float b , float x )
{
float t = saturate (( x - a ) / ( b - a ));
return t * t * ( 3.0 - ( 2.0 * t ));
}
グレースケールからノーマルを作る
事前に_TexelSize
を宣言しておく必要がある。
SurfaceShader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 // テクスチャ宣言時に_HightMap_TexelSizeを宣言
sampler2D _HightMap ;
float4 _HightMap_TexelSize ;
// 【中略】
float center = tex2Dlod ( _HightMap , float4 ( IN . uv_HightMap , 0 , 0 )). r ;
float right = tex2Dlod ( _HightMap , float4 ( IN . uv_HightMap + float2 ( _HightMap_TexelSize . x , 0 ), 0 , 0 )). r ;
float up = tex2Dlod ( _HightMap , float4 ( IN . uv_HightMap + float2 ( 0 , _HightMap_TexelSize . y ), 0 , 0 )). r ;
float sampleDeltaRight = right - center ;
float sampleDeltaUp = up - center ;
float3 grayNorm = cross (
float3 ( 1 , 0 , sampleDeltaRight * _NormalStrength ),
float3 ( 0 , 1 , sampleDeltaUp * _NormalStrength ));
o . Normal = normalize ( grayNorm );
Alpha to Coverage有効
SubShader
{
// ここで指定
AlphaToMask On
Pass
{}
}
ScreenPosの正規化
SurfaceShader
解説
xy: 0 ~ w を 0 ~ 1
z: -w ~ w を -1 ~ 1
に正規化する
float4 screenPos = float4 ( IN . screenPos . xyz , IN . screenPos . w + 0.00000000001 );
float4 screenPosNorm = screenPos / screenPos . w ;
プラットフォームによる差を吸収し、Zが必ず0から1になるようにする
screenPosNorm.z = (UNITY_NEAR_CLIP_VALUE >= 0) ? screenPosNorm.z : screenPosNorm.z * 0.5 + 0.5;
ScreenPosからGrabTextrueの位置、UV値を求める
SurfaceShader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 inline float4 ComputeGrabScreenPos ( float4 pos )
{
#if UNITY_UV_STARTS_AT_TOP
float scale = - 1.0 ;
#else
float scale = 1.0 ;
#endif
float4 o = pos ;
o . y = pos . w * 0.5f ;
o . y = ( pos . y - o . y ) * _ProjectionParams . x * scale + o . y ;
return o ;
}
// 使用方法
float4 grabPos = ComputeGrabScreenPos ( IN . screenPos );
float2 grabUV = grabPos . xy / grabPos . w ;
fixed4 grabColor = tex2D ( _GrabTextrue , grabUV );
デプステクスチャの取得
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 // 宣言が必要
sampler2D _CameraDepthTexture ; // カメラからのデプステクスチャ
// 【中略】
// 正規化されたScreenPosを使用する必要がる
float4 screenPos = float4 ( IN . screenPos . xyz , IN . screenPos . w + 0.00000000001 );
float4 screenPosNorm = screenPos / screenPos . w ;
screenPosNorm . z = ( UNITY_NEAR_CLIP_VALUE >= 0 ) ? screenPosNorm . z : screenPosNorm . z * 0.5 + 0.5 ;
// この段階では非線形
float depth = SAMPLE_DEPTH_TEXTURE ( _CameraDepthTexture , screenPosNorm . xy );
// カメラからの距離 (ワールド座標系のスケール)
float linearEyeDepth = LinearEyeDepth ( depth );
// カメラからの距離(Near - Far -> 0 - 1)
float linear01 = Linear01Depth ( depth );
// 取得できたdepthと同じ単位系のモデルのデプスの求め方
float surfaceDepth = UNITY_Z_0_FAR_FROM_CLIPSPACE ( IN . screenPos . z );
HSV RGB変換
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 float3 hsv2rgb ( float3 c )
{
float4 K = float4 ( 1.0 , 2.0 / 3.0 , 1.0 / 3.0 , 3.0 );
float3 p = abs ( frac ( c . xxx + K . xyz ) * 6.0 - K . www );
return c . z * lerp ( K . xxx , clamp ( p - K . xxx , 0.0 , 1.0 ), c . y );
}
float3 hsv2rgb ( float3 c )
{
return (( clamp ( abs ( frac ( c . x + float3 ( 0 , 2 , 1 ) / 3. ) * 6. - 3. ) - 1. , 0. , 1. ) - 1. ) * c . y + 1. ) * c . z ;
}
float3 rgb2hsv ( float3 c )
{
float4 K = float4 ( 0.0 , - 1.0 / 3.0 , 2.0 / 3.0 , - 1.0 );
float4 p = lerp ( float4 ( c . bg , K . wz ), float4 ( c . gb , K . xy ), step ( c . b , c . g ));
float4 q = lerp ( float4 ( p . xyw , c . r ), float4 ( c . r , p . yzx ), step ( p . x , c . r ));
float d = q . x - min ( q . w , q . y );
float e = 1.0e-10 ;
return float3 ( abs ( q . z + ( q . w - q . y ) / ( 6.0 * d + e )), d / ( q . x + e ), q . x );
}
強制的にポイントサンプリングする
テクスチャの設定で変えられるので。正直使いどころはあまりない。
1つのデータを複数のサンプリング方法で取得するときに便利?
// 無理やりポイントサンプリングする
{
float2 pixelPos = floor ( i . uv * _MainTex_TexelSize . zw ) + float2 ( 0.5f , 0.5f );
i . uv = ( float2 ) pixelPos * _MainTex_TexelSize . xy ;
}
視界に張り付くシェーダー
// なるべく最後に描画されるように設定する。
Tags { "RenderType" = "Transparent" "Queue" = "Overlay+3000" "IgnoreProjector" = "True" }
v2f vert ( appdata v )
{
v2f o ;
// uv座標をポジションにする。
o . pos = float4 ( 2 * v . uv . x + 1 - 2 , 1 - 2 * v . uv . y , 1 , 1 );
o . uv = TRANSFORM_TEX ( v . uv , _MainTex );
return o ;
}
ワールド座標
// 頂点シェーダー
o . worldPos = mul ( unity_ObjectToWorld , v . vertex ). xyz ;
オブジェクトの原点座標
// モデル原点
float4 objectOrigin = mul ( unity_ObjectToWorld , float4 ( 0.0 , 0.0 , 0.0 , 1.0 ));
ビュー方向
float3 viewDir = normalize ( UnityWorldSpaceViewDir ( worldPos ));
ベクトル回転
軸回転
float sinX = sin ( _Time . x * 0.1 * 2 * PI );
float cosX = cos ( _Time . x * 0.1 * 2 * PI );
// X軸回転
float3x3 rotateX = float3x3 (
1 , 0 , 0 ,
0 , cosX , - sinX ,
0 , sinX , cosX
);
ノイズ系