Zacky's techno memo

sitemap

このサイトのプログラミングは、基本的にArduino/Processing上で動かすものを掲載していく予定です。所詮メモですし、専門性よりも動かしやすさ重視で。

Arduino関連

Processing関連

シェーダ

シェーダとは

コンピュータ上における画像処理のためのソフトウェア処理。

シェーダの種類

Vertex Shader(VS:頂点シェーダ)

モデリングデータ上の座標からスクリーン座標への変換、ラスタライズ(スクリーン座標からピクセル配列への変換)を行ない、以下のシェーダへデータを渡し、実際の描画処理を行なわせる。
このとき、モデリングデータは小図形(ポリゴン)として扱われるため、頂点の集合として扱われている。

Pixel Shader(PS:ピクセルシェーダ)

ピクセル単位で色指定といった処理を行なう。
OpenGLではフラグメント(断片)シェーダという。

Geometry Shader(GS:ジオメトリシェーダ)

ピクセル、ライン、トライアングルといった基本図形(プリミティブ)から、複雑な新しい図形を生成し、ピクセルシェーダへデータを渡す。
OpenGLではプリミティブシェーダという。

参考

GLSL

GLSLとは

“OpenGL Shading Language”の略。C言語ベースの高レベルシェーディング言語。
直接描画をすることはできないが、GLSLファイル(.glsl)を読込むことで、ハードウェア・ソフトウェアの互換性を問わずレンダリングすることができる(描画方法の指定のみをする言語。描画は別ソフトが担当する)。

基本形

//***.glsl

//変数を記述

void main(){

  //処理を記述
	
}

データ型

データ型一覧
データ型 意味 備考
void 戻り値無し 関数専用
bool 論理型 true/false
int 符号付き整数
float 符号付浮動小数点数
vec* *次元浮動小数型ベクトル wikipedia記載は
2≦*≦4 範囲のみ
bvec* *次元論理型ベクトル
ivec* *次元整数型ベクトル
mat* *x*次元浮動小数型行列
sampler*D *次元テクスチャアクセスハンドル wikipedia記載は
1≦*≦3 範囲のみ
samplerCube キューブマップテクスチャアクセスハンドル
sampler*DShadow *次元デプステクスチャアクセスハンドル wikipedia記載は
1≦*≦2 範囲のみ
修飾詞一覧
修飾詞 意味
const 定数
uniform グローバル変数
in 入力変数
out 出力変数
inout 入出力変数

ベクトル型の要素

要素の参照は、座標(x,y,z,w)、色(r,g,b,a)、テクスチャ(s,t,p,q)の用途によって自由に使い分けられる。

// ベクトル型配列の要素参照

  vec4 v = vec4(0.0, 1.0, 2.0, 3.0);

// 1要素のみ参照
  v.x;  // float 0.0
  v.y;  // float 1.0
  v.z;  // float 2.0
  v.w;  // float 3.0
  
  v.r;  // float 0.0
  v.g;  // float 1.0
  v.b;  // float 2.0
  v.a;  // float 3.0

// 複数要素の参照
  v.xy;    // vec2(0.0, 1.0)
  v.yx;    // vec2(1.0, 0.0) … 順序を変えても良い
  v.xz;    // vec2(0.0, 2.0) … 隣同士でなくても良い
  v.rgb;   // vec3(0.0, 1.0, 2.0) … rgbaでも良い
  v.xyzw;  // vec4 v … 全てでも良い
// エラー例
  vec2 v2 = vec2(0.0, 1.0);
  v4.z;  // 第3要素なし→error
  
  vec3 v3 = vec3(0.0, 1.0, 2.0);
  v3.w;  // 第4要素なし→error

行列型の要素

要素の参照は、多次元配列と同様に行なえる。
(GLSLでは、多次元配列使えませんけどね…)

// 行列の使用例

  mat2 m = mat2(0.0, 1.0, 2.0, 3.0);

/*  m = | 0.0  1.0 |
        | 2.0  3.0 |  */

// 各要素
  m[0][0];  // float 0.0
  m[0][1];  // float 1.0
  m[1][0];  // float 2.0
  m[1][1];  // float 3.0

// 行からベクトルを取得
  m[0];  // vec2(0.0, 1.0)

配列

1次元配列のみ使用可能(GLSL4.20まで)。(GLSL4.30よりok)配列の大きさは動的な変更は不可能。

// 配列の宣言例
float f0[5];

const int size = 5;
float f1[size];  // 定数(const)使用可

構造体

struct [構造体型名]{
  // メンバ変数の定義 
  int a;
  float b;
  vec3 c;
} [構造体名]

型変換

C言語風ではあるが、キャストは使用不可なので、型変換の関数を用いる。

// int float boolの相互変換

// int型へ変換
  int(true);     // = 1
  int(false);    // = 0
  int(float);    // 小数以下切捨て

// float型へ変換
  float(true);   // = 1.0
  float(false);  // = 0.0
  float(int);    // 型は変わるが同じ値のまま

// bool型へ変換
  bool(int);     // ==0.0 → false / != 0.0 → true
  bool(float);   // ==0 → false / != 0 → true
// ベクトル型の変換

  vec*(float);        // 全成分が同じ値
  vec*(ivec*);        // int型→float型
  bvec*(int, float, …);  // bool型変換に従いtrue/false
  vec2(vec3);         // 3成分目切捨て→2次元ベクトル
  vec3(vec4);         // 4成分目切捨て→3次元ベクトル
  vec3(vec2, float);  // (vec2.x, vec2.y, float)
  vec3(float, vec2);  // (float, vec2.x, vec2.y)
  vec4(vec2, vec2);   // (vec2.x, vec2.y, vec2.x, vec2.y)
// 行列型の変換

  mat*(a);               // 対角要素 = a; 他要素 = 0.0 の対角行列
  mat*(vec*, vec*, …);  // "列"ベクトルを並べた行列
// キャストは使用不可
  int a = 1 ;
  float b = (float) a ;  // error

組み込み変数

とりあえず、よく使いそうなところだけ。
組み込み変数一覧
シェーダ 入出力 データ型 クラス・変数 属性 意味 備考
PS 入力 vec4 gl_FragCoord .x
.y
.z
.w
ウィンドウ座標
出力 vec4 gl_FragColor .r
.g
.b
.a
色取得・指定 (r,g,b,a):赤、緑、青、不透明度(各0~1)
(例) vec4(1.0):白色

参考

GLSL on Processing

GLSL自体には処理を実行する機能はない。
GLSLで記述された処理を、Processing(P5)で出力する例を紹介する。

ファイル配置

スケッチフォルダ
├─***.pde
└─data
  └─shader.glsl

P5スケッチ・GLSLデータ

// P5スケッチ:***.pde

PShader sd;  // シェーダクラス

void setup() {
  size([width], [height], P2D);
  
  // GLSLファイル読込
  sd = loadShader("shader.glsl");
}
 
void draw() {
  
  // シェーダへ値を渡す
  sd.set("[GLSL内uniform変数名]",[値],…);

  // シェーダ描画
  shader(sd);  // ※これだけでは何も描画されない
  
  // 描画エリア指定
  rect(0, 0, width, height);  // ここで描画する図形は、stroke,fillと無関係
  
  resetShader();  // これ以降は、通常の描画が行なわれる

  // 通常の描画処理を記述
  
}
// GLSLデータ:shader.glsl
// ***.pdeのあるフォルダ内にある"data"フォルダ内に配置

void main(){

  // 処理を記述

}

備考:GLSLファイルの文字エンコード

悪いこと言わん、コメントに日本語使うなら、“UTF-8 without BOM”にしとけ。

備考:shader(); と filter();

テクスチャハンドル … filter
エリア指定がなくとも、全体に処理

座標系
レンダラ 座標系 デフォルト原点 備考
Processing 左手(z軸:手前正方向) 左上 resetMatrix();の実行で原点中央
(軸方向はそのまま)
GLSL 左手 左下 Processing上での座標変換は無関係
  rect(10, 10, 100, 100);
  filter(sd);  // 四角形:filter有効
  
  filter(sd);
  rect(10, 10, 100, 100);  // 四角形:filter無効

備考

変数の型

GLSLは、かなり厳密に変数型を見ています。
レンダラに使用するソフトによってはエラーを吐いてくれないと思います(P5は状況によりけり?)ので、注意してコーディングしましょう。

float a = 1   ;  // error( a = 0.0 ; となる)
float a = 1.0 ;  // ok

ピクセル処理

ピクセルシェーダは、その名の通り、各ピクセルごとに対して処理を行なっている。
すなわちmain()関数は次のようになっているため、自分で総当たりさせる繰返し文を書く必要はない。
(正確にはループではなくGPU上での分散処理なので、座標順に処理をする訳ではない(…たぶんそのはず…))

for(int y = 0 ; y < height ; y++){
  for(int x = 0 ; x < width ; x++){
    main();
  }
}

また、「何も書かない処理」を避ける。
「GPUの描画処理自体をしない」ということになり、「上書きしない」という意味にはならない。
処理しないピクセルには、透明を指定すればよい。

if( *** )  gl_FragColor = vec4(1.0);
  // これだけでは、条件falseのピクセルは黒になる(暗黙的に以下の処理が追加される)。
else  gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);  // 黒


if( *** )  gl_FragColor = vec4(1.0);
else  gl_FragColor = vec4(0.0);  // 透明

参考

CGテクニック

画面サイズ

画面サイズ一覧
規格 アス比 備考
QVGA 320 240 4:3
VGA 640 480 4:3
XGA 1024 768 4:3
SXGA 1280 1024 4:3
HDTV720 1280 720 16:9
HDTV1080 1920 1080 16:9
WVGA 800 480 5:3 Galaxy SⅡ(縦横逆比)

ビルボード


RGB・HSV

http://hooktail.org/computer/index.php?RGB%A4%AB%A4%E9HSV%A4%D8%A4%CE%CA%D1%B4%B9%A4%C8%C9%FC%B8%B5

プログラミングテクニック

ソートアルゴリズム

http://www.ics.kagoshima-u.ac.jp/~fuchida/edu/algorithm/sort-algorithm/index.html