GLSLの関数メモ
関数で何をしてたか忘れちゃうのでメモ
随時更新
build in関数
mix
lerp(線形補完)ができる。
主にカラーの線形補完などに便利。単純に仕組みはベクトルの線形補完なので位置や何にでも別に使える。
0-1に正規化してある、補完の現在のパーセントをmixの3引数目に入れてあげる
引数1
引数2
glslのコード
sign()
符号を判定できる。-, 0, +のいずれかの判定ができる。
クロノス団の説明がシンプルすぎるが、x が 0.0 より小さい場合は -1.0、x が 0.0 に等しい場合は 0.0、x が 0.0 より大きい場合は +1.0 を返す。ということのようだ、それを元に、円を形成することになる上のコードを再分配再結合していく。
build in 初等関数
atan(y,x)
arc tangentの計算
$${\tan(\theta) = \frac{y}{x}}$$としたときの、y,xをatanに入れるとthetaが返ってくる。
floatだけではなく、vec2, 3,4にも対応しているので便利。
基本的に$${-\pi ~ \pi}$$まで帰ってくる。
注意点として、$${x = 0}$$$のときだけ、undefinedになってしまう。単純に0除算になるために、そうなってしまう。
atan2ラッパー関数を作っての回避方法として、以下のような提案があったので便利そう。sign()関数で0の時の処理をごまかす。
atan2の標準的な仕様と同じにして、$${x =0}$$のときは、$${y > 0 \rightarrow \frac{\pi}{2}, y<0 \rightarrow -\frac{\pi}{2}}$$
//https://qiita.com/7CIT/items/ad76cfa6771641951d31
float atan2(float y, float x){
const float PI = 3.141592653589793;
return x == 0.0 ? sign(y)*PI/2 : atan(y, x);
}
vec4版もそのまま流用して
vec4 atan2(vec4 y, vec4 x){
const float PI = 3.141592653589793;
float r = x.x == 0.0 ? sign(y.x)*PI/2 : atan(y.x, x.x);
float g = x.y == 0.0 ? sign(y.y)*PI/2 : atan(y.y, x.y);
float b = x.z == 0.0 ? sign(y.z)*PI/2 : atan(y.z, x.z);
float a = x.w == 0.0 ? sign(y.w)*PI/2 : atan(y.w, x.w);
return vec4(r,g,b,a);
}
texture周り
texture()
texture(sampler2D, uv)でsampler2Dのuv座標に当たる、texelがgetできる。
uvのvec2に関しては、textureOffsetとのoffsetと違い、変数を使って列挙してもエラーにならない。
textureOffsetよりもそのため、こっちの方が、フィルタの実装とかには使える。
TouchDesigner GLSLの場合の例
for(float i = -8; i <= 8; i++){
for(float j = -8; j <= 8; j++){
if(i == -j){
fc += texture(sTD2DInputs[0], vUV.st + vec2(i/u_resolution.x, j/u_resolution.y)) * 1/17;
// fc += textureOffset(sTD2DInputs[0], vUV.st, ivec2(i, j) * 1/17;
}
else{
fc += texture(sTD2DInputs[0], vUV.st + vec2(i/u_resolution.x, j/u_resolution.y)) * 0;
}
}
}
textureOffset()
textureOffset(sampler2D, uv, offset)で、sampler2Dのuv座標の部分から、vec2のoffset分位置をoffsetした、texelをgetできる。
帰ってくるのはrgbaのvec4
注意点として、offsetのivec2(i, j)のi,jの部分は具体的な定数でないといけない。i, jのような変数だとerrorとなってしまう。
ERROR: /project1/glsl8_pixel:28: 'texel offset' : argument must be compile-time constant
って書きたいところです.でも,textureOffset() のマニュアルには「offset は定数でないといけない」って書いてあって,実際コンパイル時にエラーになります.であればと,
ということをやってみました.しかし,ここでまた頭を抱えてしまいます.今日 (2014 年 7 月 26 日) の時点で Windows 7 の Quadro K4000 (ドライバのバージョン 335.23) だとこれで一応動いた気がします.でも,Windows 8.1 の GeForce 840M (337.88) だとなんだかサンプル点がずれてるように見えて,まともに動いているようには思えません.また Mac OS X (marvericks) の MacBook Air だと,やっぱり「offset は定数でないといけない」っていうエラーになります.
たぶん,NVIDIA の GLSL コンパイラの最適化能力が非常に高くて*1,これくらいのループはアンローリングされてインラインに展開されてしまうのだと思います.だから「定数の配列」でも OK なのかもしれません.でも,仕様上それが正しいのかどうかわからなかったので,結局上のように「手でアンローリング」することにしました.もっとエレガントな書き方ないですか.
またほかの注意点として、offsetとして入力できるmax, minが決まっている。具体的にはいくつかなのかは、GL_MIN_PROGRAM_TEXEL_OFFSET, GL_MAX_PROGRAM_TEXEL_OFFSETで決まっているらしく、環境依存。
TouchDesignerのGLSLの場合
vec4 fc = textureOffset(sTD2DInputs[0], vUV.st, ivec2(1, 0))
textureOffset performs a texture lookup at coordinate P from the texture bound to sampler with an additional offset, specified in texels in offset that will be applied to the (u, v, w) texture coordinates before looking up each texel. The offset value must be a constant expression. A limited range of offset values are supported; the minimum and maximum offset values are implementation-dependent and may be determined by querying GL_MIN_PROGRAM_TEXEL_OFFSET and GL_MAX_PROGRAM_TEXEL_OFFSET, respectively.
Note that offset does not apply to the layer coordinate for texture arrays. Also note that offsets are not supported for cube maps.
textureOffsetは、サンプラーにバインドされたテクスチャから座標Pでテクスチャのルックアップを実行し、各テクセルをルックアップする前に、(u, v, w)テクスチャ座標に適用されるオフセットをoffsetでテクセル単位で指定します。オフセット値は定数式でなければなりません。オフセットの最小値と最大値は実装依存であり、それぞれ GL_MIN_PROGRAM_TEXEL_OFFSET と GL_MAX_PROGRAM_TEXEL_OFFSET をクエリすることで決定できます。
オフセットはテクスチャ配列のレイヤー座標には適用されないことに注意。また、オフセットはキューブマップではサポートされていないことに注意してください。
この記事が気に入ったらサポートをしてみませんか?