CG関連

【GLSL(シェーダー)】でよく使う関数とユーザー関数のまとめ【計算編】※随時更新

プログラミングでかっこいい映像をつくりたいと覚え始めた『GLSL(シェーダー)』。

『GLSL(シェーダー)』にはたくさんの組み込み関数と、

よく見るユーザー関数があるなと思いましたので、

それらをまるっとまとめていこうと思います。

アオキ
『HLSL(Unityで使われているシェーダー)』も徐々に織り交ぜてまとめていきます。
Sponsored link

GLSLとHLSLの変数

GLSL HLSL 説明
vec4, vec3, vec2 float4, float3, float2 ベクトル
mat3, mat4, mat3x4 float3x3, float4x4, float3x4 マトリクス(行列)

GLSL(シェーダー)でよく使う関数 三角関数

const float PI = 3.14159;
 
// 度数法[degree]から弧度法[rad]へ
vec4 a = radians(vec4(180)); // => vec4(PI)
// 弧度法[rad]から度数法[degree]へ
vec4 b = degrees(vec4(PI)); // => vec4(180)
 
// サインコサインタンジェント
vec4 c = sin(vec4(PI / 2)); // => vec4(1.0)
vec4 d = cos(vec4(0.0)); // => vec4(1.0)
vec4 e = tan(vec4(PI / 4)); // => vec4(1.0)

//逆三角関数 アークサインアークコサインアークタンジェント
vec4 f = asin(vec4(0.5)); // => vec4(PI / 6)
vec4 g = acos(vec4(0.5)); // => vec4(PI / 3)
vec4 h = atan(vec4(2.0), vec4(2.0)); // => vec4(PI / 4)
vec4 i = atan(vec4(1.0)); // => vec4(PI / 4)

三角関数の関連記事

ラジアンの関連記事

GLSL(シェーダー)でよく使う関数 累乗(るいじょう)

  • 累乗(るいじょう)・・同じ数を順に掛け合わせる
// ネイピア数
const float E = 2.71828;
 
 // 指数 (2の3乗など)
vec4 a = pow(vec4(2.0), vec4(3.0)); // => vec4(8.0) : 2.0^3.0

// ネイピア数 の指数(2乗など)
vec4 b = exp(vec4(2.0)); // => vec4(E * E) : e^2.0

// 2のx乗 (2の3乗)
vec4 d = exp2(vec4(3.0)); // => vec4(8.0) : 2^3.0

// 対数 logarithm の略
vec4 c = log(vec4(E * E * E)); // => vec4(3.0) : ln(e^3)

/ / xの底2の対数を返す
vec4 f = log2(vec4(2.0)); // => vec4(1.0) : log(2, 2.0)


//平方根 (英語でsquare root)
vec4 g = sqrt(vec4(9.0)); // => vec4(3.0) : 平方根

// 1 / 平方根 
vec4 h = inversesqrt(vec4(0.25)); // => vec4(2.0)
// inversesqrt(x) == 1/sqrt(x)

指数(pow)は、小さい数をかけるとより小さくなり、1.0だとなんどかけても1.0になるので、
弱い光を更に弱く、強い光はそのまま残す、といった場合に使われるようです。

反射光によるライティング | wgld.org

参考記事


Sponsored link

GLSL(シェーダー)でよく使う関数 数値をまるめる関数

// 切り捨て
vec4 a1 = floor(vec4(1.5));  // => vec4(1.0)
vec4 a2 = floor(vec4(-1.5)); // => vec4(-2.0)
// 切り上げ
vec4 b1 = ceil(vec4(1.5));  // => vec4(2.0)
vec4 b2 = ceil(vec4(-1.5)); // => vec4(-1.0)
// 0に近づくように端数処理
vec4 c1 = trunc(vec4(1.5));  // => vec4(1.0) : floor
vec4 c2 = trunc(vec4(-1.5)); // => vec4(-1.0): ceil
 
// 四捨五入(端数が0.5のときは未定義)
vec4 d1 = round(vec4(1.4)); // => vec4(1.0)
vec4 d2 = round(vec4(1.5)); // => vec4(1.0 or 2.0)
vec4 d3 = round(vec4(1.6)); // => vec4(2.0)
vec4 d4 = round(vec4(2.5)); // => vec4(2.0 or 3.0)
// roundで端数が0.5のときに偶数へ端数処理
vec4 e1 = roundEven(vec4(1.4)); // => vec4(1.0)
vec4 e2 = roundEven(vec4(1.5)); // => vec4(2.0)
vec4 e3 = roundEven(vec4(1.6)); // => vec4(2.0)
vec4 e4 = roundEven(vec4(2.5)); // => vec4(2.0)
 
// 小数点以下を返す fract(x) == x - floor(x) 
vec4 f1 = fract(vec4(1.4));  // => vec4(0.4)
vec4 f2 = fract(vec4(-1.4)); // => vec4(0.6)

//  x-y*floor(x/y)を返す
vec4 g1 = mod(vec4(3.0), vec4(2.0)); // => vec4(1.0)
vec4 g2 = mod(vec4(3.0), 2.0); // => vec4(1.0)
 
アオキ
fractは『HLSL』だとfrac になります。
アオキ
modは『HLSL』だとfmod になります。

GLSL(シェーダー)でよく使う関数 符号、値を制限したり混ぜたり

// 絶対値 (英語でabsolute) (マイナスならプラスに)
vec4 a1 = abs(vec4(2.0));  // => vec4(2.0)
vec4 a2 = abs(vec4(-2.0)); // => vec4(2.0)

// 引数が正なら1.0、0.0なら0.0、負なら-1.0を返す 
vec4 b1 = sign(vec4(2.0));  // => vec4(1.0)
vec4 b2 = sign(vec4(0.0));  // => vec4(0.0)
vec4 b3 = sign(vec4(-2.0)); // => vec4(-1.0)
 
 // 最小値
vec4 c1 = min(vec4(4.0), vec4(3.0)); // => vec4(3.0)
vec4 c2 = min(vec4(4.0), 3.0); // => vec4(3.0)

//最大値
vec4 d1 = max(vec4(3.0), vec4(4.0)); // => vec4(4.0)
vec4 d2 = max(vec4(3.0), 4.0); // => vec4(4.0)
// 引数で与えられた数を、一定の範囲に収める
// xが a と b の間なら xのまま
// xが a より小さいなら aの値
// xが b より大きいなら bの値
// clamp(x, a, b) == min(max(x, a), b)
vec4 e1 = clamp(vec4(0.4), vec4(1.0), vec4(2.0)); // => vec4(1.0)
vec4 e2 = clamp(vec4(1.4), vec4(1.0), vec4(2.0)); // => vec4(1.4)
vec4 e3 = clamp(vec4(2.4), vec4(1.0), vec4(2.0)); // => vec4(2.0)
vec4 e4 = clamp(vec4(0.4), 1.0, 2.0); // => vec4(1.0)
vec4 e5 = clamp(vec4(1.4), 1.0, 2.0); // => vec4(1.4)
vec4 e6 = clamp(vec4(2.4), 1.0, 2.0); // => vec4(2.0)
 
// 線形補間
// 2つのものを混ぜる
// x と y を aの割合で混ぜる
// a が0 (false)に近いほど xが強い
// a が1 (true)に近いほど yが強い
// mix(x, y, a) == x*(1-a) + y*a
vec4 f1 = mix(vec4(1.0), vec4(3.0), vec4(0.25)); // => vec4(1.5)
vec4 f2 = mix(vec4(1.0), vec4(3.0), 0.25); // => vec4(1.5)
vec4 f3 = mix(vec4(1.0), vec4(3.0), bvec4(false)); // => vec4(1.0)
vec4 f4 = mix(vec4(1.0), vec4(3.0), true); // => vec4(3.0)
アオキ
clampとmixはよく見ますな。
アオキ
mixは『HLSL』だとlerp になります。

アオキ
『HLSL』にはclampに似た saturate(x) という関数もあります(0,1でclampする)。

Sponsored link

GLSL(シェーダー)でよく使う関数 ステップ・スムース

// 引数でしきい値、値 をとる
// しきい値より少なかったら0
// しきい値より多かったら1
vec4 a1 = step(vec4(0.5), vec4(0.4)); // => vec4(0.0)
vec4 a2 = step(vec4(0.5), vec4(0.6)); // => vec4(1.0)
vec4 a3 = step(0.5, vec4(0.4)); // => vec4(0.0)
vec4 a4 = step(0.5, vec4(0.6)); // => vec4(1.0)

// エルミート補間 引数で範囲1, 範囲2, 値をとる
// 範囲の中で、 0.0から1.0まで滑らかに変化する数値を返す
// smoothstep(a, b, x) : 
vec4 b1 = smoothstep(vec4(1.0), vec4(2.0), vec4(0.4)); // => vec4(0.0)
vec4 b2 = smoothstep(vec4(1.0), vec4(2.0), vec4(1.4)); // => vec4(0.352)
vec4 b3 = smoothstep(vec4(1.0), vec4(2.0), vec4(2.4)); // => vec4(1.0)
vec4 b4 = smoothstep(1.0, 2.0, vec4(0.4)); // => vec4(0.0)
vec4 b5 = smoothstep(1.0, 2.0, vec4(1.4)); // => vec4(0.352)
vec4 b6 = smoothstep(1.0, 2.0, vec4(2.4)); // => vec4(1.0)

GLSL(シェーダー)でよく使う関数 幾何的な関数

// ベクトルと関連
// 始点を(0.0, 0.0)と仮定した時に、引数までどれくらい距離があるか返す
// 参考 https://qiita.com/doxas/items/40898f7ec279b8ab5358
float a = length(vec2(1.0, 1.0)); // => 1.414...

// 引数x と引数y の距離  == length(引数2 - 引数1)
float b = distance(vec2(1.0, 1.0), vec2(-1.0, -1.0)); // => 2.828...

// 正規化 
// 引数 / length(引数)
vec2 e = normalize(vec2(1.0)); // => vec2(0.7071...)
// ベクトル内積 (英語で dot product)
float c = dot(vec2(1.0), vec2(2.0)); // => 4.0

2つのベクトルから1つの値(スカラー)を計算。

3Dでライトを反射させたりする時につかう。

法線ベクトルは内積で計算できます。

参考記事

// 7. 球の法線ベクトル
vec3 sphere_normal(vec3 pos){
    float delta = 0.001;
    return normalize(vec3(
        sphere_d(pos + vec3(delta, 0.0, 0.0)) - sphere_d(pos - vec3(delta, 0.0, 0.0)), //X
        sphere_d(pos + vec3(0.0, delta, 0.0)) - sphere_d(pos - vec3(0.0, delta, 0.0)), //Y
        sphere_d(pos + vec3(0.0, 0.0, delta)) - sphere_d(pos - vec3(0.0, 0.0, delta)) //Z
        ));
}

   vec3 light_dir = vec3(0.0, 0.0, 1.0);
   vec3 normal = sphere_normal(ray.pos);

   float l = dot(normal, - light_dir); //法線ベクトルと光源のベクトルの内積(dot)
// ベクトル外積 (英語で cross product)
vec3 d = cross(vec3(1.0, 2.0, 0.0), vec3(3.0, 4.0, 0.0));
// => vec3(0.0, 0.0, -2.0)

カメラのポジションなどで使う。

上向きベクトルと前向きベクトルを組み合わせると

なぜか横向きベクトルが計算できるという魔法の関数。

参考記事

Sponsored link

GLSL(シェーダー)でよく見るユーザー関数

ノイズ系 random, noize, fbm ユーザー関数

  • ランダム
  • ノイズ(パーリンノイズ)
  • FBM(Fractal Browniam Motion)非整数ブラウン運動
float random (in vec2 _st) {
    return fract(sin(dot(_st.xy,
                         vec2(12.9898,78.233)))*
        43758.5453123);
}

// Based on Morgan McGuire @morgan3d
// https://www.shadertoy.com/view/4dS3Wd
float noise (in vec2 _st) {
    vec2 i = floor(_st);
    vec2 f = fract(_st);

    // Four corners in 2D of a tile
    float a = random(i);
    float b = random(i + vec2(1.0, 0.0));
    float c = random(i + vec2(0.0, 1.0));
    float d = random(i + vec2(1.0, 1.0));

    vec2 u = f * f * (3.0 - 2.0 * f);

    return mix(a, b, u.x) +
            (c - a)* u.y * (1.0 - u.x) +
            (d - b) * u.x * u.y;
}

#define NUM_OCTAVES 5

float fbm ( in vec2 _st) {
    float v = 0.0;
    float a = 0.5;
    vec2 shift = vec2(100.0);
    // Rotate to reduce axial bias
    mat2 rot = mat2(cos(0.5), sin(0.5),
                    -sin(0.5), cos(0.50));
    for (int i = 0; i < NUM_OCTAVES; ++i) {
        v += a * noise(_st);
        _st = rot * _st * 2.0 + shift;
        a *= 0.5;
    }
    return v;
}

参考記事

TheBookOfShaders

ランダム関数は他の作り方もあるようです。

ランダムな値を返す関数 on GLSL

X軸回転(3D) ユーザー関数

mat3 x_axis_rot(float angle){
    float c = cos(angle);
    float s = sin(angle);
    return mat3(1.0, 0.0, 0.0, 0.0, c, -s, 0.0, s, c); 
 
}

Y軸回転(3D) ユーザー関数

mat3 y_axis_rot(float angle){
    float c = cos(angle);
    float s = sin(angle);
    return mat3(c, 0.0, s, 0.0, 1.0, 0.0, -s, 0.0,  c);
}

スムース(距離関数をスムーズに合成) レイマーチングで使用

float smin(float d1, float d2, float k ){
    float res = exp(-k * d1) + exp(-k * d2);
    return -log(res) / k;
}

関連記事

参考記事

GLSLの関数

GLSLについてのメモ

『GLSL(シェーディング)』関係ではこんな記事も読まれています。

1. 【GLSL】プログラムでかっこいい映像をつくりたい! 〜『TouchDesigner』を見据えて

2. 【WebGL】入門 わかりやすく【図解】してみた

3. 【OpenGL】と【DirectX】のバージョンをまとめてみた【シェーダーメイン】【初心者向け】

4. 【GLSL(シェーディング)】でよく使う関数とユーザー関数のまとめ※随時更新

5. 【GLSL】プログラムでかっこいい映像をつくるには『レイマーチング』なるものを覚えればいいらしい

6. 【GLSL】『レイマーチング』入門その1 距離関数とレイとカメラの設定

7. 【GLSL】『レイマーチング』入門(2) 立体的に見せる方法〜光の反射は『内積』で〜

8. 【GLSL】『レイマーチング』入門(3) 距離関数を使ってみる・回転・合成・量産

9. 【TouchDesigner】で『GLSL』を使う方法まとめ【画像あり】

10. 【TouchDesigner】『GLSL MAT』の使い方 3次元でぐりぐり動かしてみる

11. 【GLSL】波のつくり方簡易まとめ。波もプログラムでつくれます【コピペスタイル】

アオキ
ツイッターでも記事ネタ含めちょろちょろ書いていくので、よろしければぜひフォローお願いしますm(_ _ )m

アオキのツイッターアカウント


関連記事一覧 (一部広告あり)

コメント

  1. この記事へのコメントはありません。

  1. この記事へのトラックバックはありません。

CAPTCHA


最近の記事

アーカイブ

  1. バックエンド

    【Laravel第4弾】Vue.js3(CompositionAPI+Scrip…
  2. オンライン教材

    【ChatGPT】エンジニア編をリリースしました
  3. オンライン教材

    【AWS】【初心者向け】インフラの基礎からわかる講座をリリースしました【Udem…
  4. オンライン教材

    【React】初心者向け講座をリリースしました【MUI】【Udemy】
  5. オンライン教材

    ChatGPTをビジネス活用する講座をリリースしました【Udemy】
PAGE TOP
Ads Blocker Image Powered by Code Help Pro

広告ブロックを摘出しました!!

ブラウザ拡張を使用して広告をブロックしていることが摘出されました。

ブラウザの広告ブロッカーの機能を無効にするか、
当サイトのドメインをホワイトリストに追加し、「更新」をクリックして下さい。

あなたが広告をブロックする権利があるように、
当方も広告をブロックしている人にコンテンツを提供しない権利と自由があります。

Powered By
100% Free SEO Tools - Tool Kits PRO