LoginSignup
19
18

More than 3 years have passed since last update.

【随時更新】shaderでよく使う計算

Last updated at Posted at 2020-01-07

自分用にまとめてます
思いついたら更新していく

よく使う計算

テクスチャカラーの値から小数点第一位のみ取得

テクスチャカラーの値なので 0 ~ 1 の幅という想定

float color.r = TextureColor.r;
color.r = floor(color.r * 10) / 10;

一度10倍してから整数のみを返すfloor関数を呼び出す
その後、10で割る
ゴリ押しなのでもっといい方法を知りたい

「0 ~ 1」 → 「-1 ~ 1」 に変換

x = y * 2 - 1
  • y = 0 の時
    • 0 * 2 - 1 = -1
  • y = 0.5の時
    • 0.5 * 2 - 1 = 0
  • y = 1の時
    • 1 * 2 - 1 = 1

他の値でも同じように置換したい場合は
x = y * 2 - yの最大値
と考える

「-1 ~ 1」 → 「0 ~ 1」に変換

x = y * 0.5 + 0.5
  • y = -1の時
    • -1 * 0.5 + 0.5 = 0
  • y = 0 の時
    • 0 * 0.5 + 0.5 = 0.5
  • y = 1の時
    • 1 * 0.5 + 0.5 = 1

他の値でも同じように置換したい場合は
x = y * 0.5 + (yの最大値 * 0.5)
と考える

「 1 」に変換

x = y * 0 + 1.0f

全てのカラーを白にしたい場合

「 0 」に変換

x = y * 0

カラーを黒にしたい場合

頂点から入力されたUV座標を 「移動」 「拡大縮小」 する

uv = float2(
  (inputUV.x - uvPosition.x) * 0.5f / uvSize + 0.5f,
  (inputUV.y - uvPosition.y) * 0.5f / uvSize + 0.5f
);

色の平均値を求める

ただの平均の求め方
平均を求めてくれる関数があった気がするけど思い出せない

averageColor = (R + B + G) / 3

Flip処理

uv.x = abs(input.uv.x * 2 - 1);

UV座標を -1 ~ 1 に変換して絶対値を求める
するとUV座標が 1 ~ 0 ~ 1 に変換されていく

テクスチャの着色

fixed lum = Luminance(outColor.rgb); 
outColor.rgb = lerp(_BlackColor.rgb, _WhiteColor.rgb, lum);

lumはグレースケール化しているだけなので
以下の計算方法でも同じカラーを取得できる

outColor.rgb = dot(outColor.rgb, fixed3(0.3, 0.6, 0.1));

よく使う関数

abs

絶対値を返す
割と使いやすい

y = abs(x)

sqrt

平方根を返す
極座標計算などで使える

y = sqrt(x)

sin

sin波を返す
cosの方が使いやすい

y = sin(x)

cos

cos波を返す
アルファフェードはこっちの方が使いやすい

y = cos(x)

wrapのrepeatを使わずにrepatする

入力された値に対して 1.0 で割った結果のうりあまりを返す

uv = frac(uv);

wrapのrepeatを使わずにrepatしながら間隔を一定に開けたい

x = 入れたい値
fmodでxの値で割ったあまりを返してくれる

uv = fmod(uv, x);

ブレンドモード

加算

OutColor = A + B

減算

OutColor = A - B

乗算

OutColor = A * B

スクリーン

OutColor = 1 - ((1 - A) * ( 1 - B))

マスク画像を元にAとBの画像をブレンド

OutColor = lerp(A, B, Mask);

マスク画像の特定のカラーチャンネルのみにスクリーン合成をベースに画像を合成

OutColor = lerp(A, 1 - ((1 - A) * ( 1 - B)), maskChannel)

アニメーション

uvスクロール

uv.x += _Time.y * uvScroll.x * uvVector.x
uv.y += _Time.y * uvScroll.y * uvVector.y

波形を利用したフェードインフェードアウト

sin波かcos波を利用してフェードアニメーションを行う
sin波だと0スタートの[-1 ~ 1]
cos波だと1スタートの[-1 ~ 1]
y = x * 0.5f + 0.5f の計算式を利用して[0 ~ 1]に変換する

alpha *= cos(_Time.y * fadeTime) * 0.5f + 0.5f

簡易的にグラデーションをつくる

右へのグラデーション

color.rgb = uv.x;

左へのグラデーション

color.rgb = 1 - uv.x;

上へのグラデーション

color.rgb = uv.y;

下へのグラデーション

color.rgb = 1 - uv.y;
19
18
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
19
18