Weitere ähnliche Inhalte
Ähnlich wie 【Unity道場 2月】シェーダを書けるプログラマになろう (20)
Mehr von Unity Technologies Japan K.K. (20)
Kürzlich hochgeladen (12)
【Unity道場 2月】シェーダを書けるプログラマになろう
- 44. 半透明はBlend で設定可能
ステップ8に対する設定
Shader "Custom/minimum" {
SubShader {
Tags { "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
…
プログラマブルではない 演算は書けない
ピクセルごとに変えられない
- 50. 最小のシェーダ
Shader "Custom/minimum" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
return fixed4(1,0,0,1);
}
ENDCG
}
}
}
- 51. 最小のシェーダ
ほぼ一般的な
シェーダコード
Shader "Custom/minimum" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
return fixed4(1,0,0,1);
}
ENDCG
}
}
}
頂点シェーダ
フラグメント
シェーダ
- 52. 最小のシェーダ
Unityが用意している
便利な記述
Shader "Custom/minimum" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
return fixed4(1,0,0,1);
}
ENDCG
}
}
}
様々な設定が可能
- 54. 最小のシェーダ
Shader "Custom/minimum" {
SubShader {
Tags { "RenderType"="Opaque" }
Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata {
float4 vertex : POSITION;
};
struct v2f {
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag(v2f i) : SV_Target {
return fixed4(1,0,0,1);
}
ENDCG
}
}
}
頂点シェーダ
フラグメント
シェーダ
セマンティクス付き構造体
- 58. v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
テクスチャマッピングのシェーダ
uvを渡す
テクセルを拾う
- 59. struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
uvはテクスチャ座標
uvはテクスチャ座標
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
uvを渡す
テクセルを拾う
- 62. struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
- 63. v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}補間されたUV座標で
テクスチャから色を得る
struct appdata {
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f {
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
- 65. v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
頂点シェーダ
フラグメントシェーダ
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
- 66. v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
たいてい
同じことを書く 省略しても
生成してくれる
頂点シェーダ
フラグメントシェーダ
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
- 67. v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
たいてい
同じことを書く
たいてい
フクザツになる
省略しても
生成してくれる
楽な記述で
生成してくれる
頂点シェーダ
フラグメントシェーダ
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
- 68. サーフェスシェーダ(surface shader)は
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
たいてい
同じことを書く
たいてい
フクザツになる
省略しても
生成してくれる
楽な記述で
生成してくれる
頂点シェーダ
フラグメントシェーダ
Unityからのプレゼント
fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
- 72. fixed4 frag(v2f i) : SV_Target {
return tex2D(_MainTex, i.uv);
}
tex2Dでテクセルをゲット
tex2DはGPUに直結
ここにシェーダの神秘がある
- 87. (0, 2)
(0, 0)
(2, 2)
(2, 0)
テクスチャ座標が[0, 1]の範囲外の場合
2.0
? ?
?
(0, 1)
(0, 0)
(1, 1)
(1, 0)
- 89. (0, 2)
(0, 0)
(2, 2)
(2, 0)
2.0
? ?
?
tex2D(1.5, 1.5)
は何を返すのか?
tex2D(0.5, 0.5)
の値を返す
- 90. (0, 1)
(0, 0)
(1, 1)
(1, 0)
(0, 2)
(0, 0)
(2, 2)
(2, 0)
テクスチャ座標が[0, 1]の範囲外の場合
2.0
- 105. fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
コード例
※hash4fastは別に定義
- 113. fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
本当に同時に実行される
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
- 114. 隣の3つも
同じ場所を実行
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
- 115. fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
tex2Dは
隣の3つの情報も使う!
- 121. 対処:適切なuvを指定
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
float2 dx = ddx(i.uv) * off.zw;
float2 dy = ddy(i.uv) * off.zw;
fixed4 col = tex2Dgrad(_MainTex, uv, dx, dy);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ddx, ddy で適切な傾きを得て tex2Dgradで指定
- 123. ddx, ddy の神秘
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
float2 dx = ddx(i.uv) * off.zw;
float2 dy = ddy(i.uv) * off.zw;
fixed4 col = tex2Dgrad(_MainTex, uv, dx, dy);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
- 124. ddx, ddy の神秘
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
float2 dx = ddx(i.uv) * off.zw;
float2 dy = ddy(i.uv) * off.zw;
fixed4 col = tex2Dgrad(_MainTex, uv, dx, dy);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
- 125. ddx, ddy の神秘
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
float2 dx = ddx(i.uv) * off.zw;
float2 dy = ddy(i.uv) * off.zw;
fixed4 col = tex2Dgrad(_MainTex, uv, dx, dy);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
横の隣との差
- 126. ddx, ddy の神秘
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = off.zw >= float2(0.5, 0.5) ?
float2(1, 1) : float2(-1, -1);
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
float2 dx = ddx(i.uv) * off.zw;
float2 dy = ddy(i.uv) * off.zw;
fixed4 col = tex2Dgrad(_MainTex, uv, dx, dy);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
縦の隣との差
- 127. fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return fwidth(col);
}
fwidth(v)=abs(ddx(v)) + abs(ddy(v))
- 128. fixed4 frag(v2f i) : SV_Target
{
fixed4 col = tex2D(_MainTex, i.uv);
return lerp(col, fixed4(0,0,0,1), fwidth(col.a));
}
fwidth(v)=abs(ddx(v)) + abs(ddy(v))
- 131. fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
同時に実行されることに想いを馳せる
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
fixed4 frag(v2f i) : SV_Target
{
float4 off = hash4fast(floor(i.uv));
off.zw = ((step(0.5, off.zw)) - 0.5) * 2;
float2 fuv = frac(i.uv);
float2 uv = fuv * off.zw + off.xy;
fixed4 col = tex2D(_MainTex, uv);
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
GPUを扱うときの心構え
- 135. M =
(
a b
c d)
I =
(
1 0
0 1)
=
(
a b
c d)
−1
=
1
ad − bc (
d −b
−c a )M−1
行列単位行列 行列 の逆行列M−1
M MI
- 143. struct appdata {
float4 vertex : POSITION;
float4 normal: NORMAL;
float4 uv: TEXCOORD;
};
struct v2f {
float4 vertex : SV_POSITION;
};
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
appdata に頂点情報
法線が異なれば頂点も別に必要
- 148. v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
return o;
}
inline float4 UnityObjectToClipPos(in float3 pos)
{
return mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(pos, 1.0)));
}
UnityObjectToClipPosの中身:
これを自分で書いても良いが、この1.0を0.0にしたらアウト
- 149. 1 0 0 a
0 1 0 b
0 0 1 c
0 0 0 1
px
py
pz
1
=
px + a
py + b
pz + c
1
1 0 0 a
0 1 0 b
0 0 1 c
0 0 0 1
px
py
pz
0
=
px
py
pz
0
掛けるベクトルのw要素による結果の違い
Positionが加算されない
Positionが加算される
頂点ベクトルはw=1で計算
法線ベクトルはw=0で計算
- 151. 法線を渡すときは注意
v2f vert(appdata v) {
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.normal = UnityObjectToWorldNormal(v.normal);
return o;
}
normalizeが必要
fixed4 frag(v2f i) : SV_Target {
float3 n = normalize(i.normal);
…
線形補間なので
短くなってしまう