見出し画像

「つぶやきGLSLと形で覚えるfract」 - テルメモ


はじめに

GLSL初学者のfract関数のメモです。
関数の情報を集めて勉強しています、書きかけのメモです。
(調べたらアップデートします: 20230402 updated)

fractの基本

GLSLの組み込み関数を読む時に
いつも参考にさせていただいている記事のfractと「リアルタイムグラフィックスの数学」を参考にしました。

fractの引数に値を入れると、xからx以下の最大の整数を引いた値を返してくれる。

fractに正の値を入れた時は、整数と小数に分け、少数だけを返す。負の値を入れた場合は、整数と小数に分け、fract(x) = x - [x]で計算した値を返す。

fract関数に正の値を入れた場合は、整数部分と小数部分に分けて小数部分だけを返します。

負の値を入れた場合は、整数部分と小数部分に分けて、fract(x) = x - [x]の式を使って計算した値を返します。ここで、[x]はxの床値(floor value)を表しています。

例:
fract(2.3) = 2.3 - ⌊2.3⌋ = 2.3 - 2 = 0.3
fract(-2.3) = -2.3 - ⌊-2.3⌋ = -2.3 - (-3) = 0.7

> fract(x)
 x-floor(x)を返す
参考:
GLSLについてのメモ
リアルタイムグラフィックスの数学―GLSLではじめるシェーダプログラミング


fract - fractionalは日本語で分数で。では分数とは。

分数(ぶんすう、英: fraction)とは 2 つの数の比を用いた数の表現方法のひとつである。
参考: Wikipedia 分数

The Book of Shaders の図解

The Book of Shaders  - fract
https://thebookofshaders.com/glossary/?search=fract

実際の数値を入れた時の返ってくる値

fract(x)関数は、数値xの小数部分を返す関数です。整数部分を取り除いた値が結果となります。

fract(2.3)の場合、2.3は、整数部分2と小数部分0.3に分けられます。fract関数は小数部分のみを取り出すため、0.3が取り出されます。

従って、fract(2.3)の結果は0.3となります。

fract(-2.3)の場合、-2.3は、整数部分-2と小数部分-0.3に分けられます。fract関数は小数部分のみを取り出すため、-0.3が取り出されます。

ただし、fract関数の結果は常に正の値であるべきです。そのため、-0.3を正の値に変換する必要があります。これは、1に-0.3を加えることで実現できます。

1 + (-0.3) = 0.7

従って、fract(-2.3)の結果は0.7となります。

つぶやきGLSLで試す

つぶやきGLSLのデフォルト表示のループ内、最初のabs箇所をfractに変えると分割されて表示される。(geekerモードです)

void main(){
 vec2 p=(gl_FragCoord.xy*2.-r)/min(r.y,r.x);
 
 for(int i=0;i<8;++i){
   p.xy=fract(p)/abs(dot(p,p))-vec2(.9+cos(t*.2)*.4);
 }
 gl_FragColor=vec4(p.xxy,1);
}

もっと単純にしてみる

スクリーンショット 2020-04-24 4.16.31
void main(){
 vec2 p=(gl_FragCoord.xy*2.-r)/min(r.y,r.x);
 
 gl_FragColor=vec4(fract(p.x),fract(p.y),1,1);
}

単純にしたものにTimeを掛けてみる

void main(){
 vec2 p=(gl_FragCoord.xy*2.-r)/min(r.y,r.x);
 
 gl_FragColor=vec4(fract(p.x*t),fract(p.y*t),1,1);
}

その他メモ

すぐの発展はないけど、ここから発見がありそうなのでメモ。

Question about Frac() in GLSL shader

fract(x)を使った時に、分数のxを返しますよね。
これは 0から0.99999999を無限に返します、これはあっていますか?

中のソースで試してみる。

 #define  F(x) floor(x) - ceil(x) + min(ceil(x),1.) + fract(x)
void main(){
 vec2 p=(gl_FragCoord.xy*2.)/min(r.y,r.x);
 
 gl_FragColor=vec4(F(p.x*t),F(p.y*t),1,1);
}

ズームブラーフィルタ

ランダム内でも使われていたりする。

precision mediump float;
uniform sampler2D texture;
uniform float     strength;
varying vec2      vTexCoord;
const float tFrag = 1.0 / 512.0;
const float nFrag = 1.0 / 30.0;
const vec2  centerOffset = vec2(256.0, 256.0);
float rnd(vec3 scale, float seed){
   return fract(sin(dot(gl_FragCoord.stp + seed, scale)) * 43758.5453 + seed);
}
void main(void){
   vec3  destColor = vec3(0.0);
   float random = rnd(vec3(12.9898, 78.233, 151.7182), 0.0);
   vec2  fc = vec2(gl_FragCoord.s, 512.0 - gl_FragCoord.t);
   vec2  fcc = fc - centerOffset;
   float totalWeight = 0.0;
   
   for(float i = 0.0; i <= 30.0; i++){
       float percent = (i + random) * nFrag;
       float weight = percent - percent * percent;
       vec2  t = fc - fcc * percent * strength * nFrag;
       destColor += texture2D(texture, t * tFrag).rgb * weight;
       totalWeight += weight;
   }
   gl_FragColor = vec4(destColor / totalWeight, 1.0);
}

ズームブラーフィルタ - wgld.org
https://wgld.org/d/webgl/w067.html

Soundとfract

 #define  n(n) fract(sin(n)*4.)
void main(){
 vec2 p=(gl_FragCoord.xy*2.-r)/max(r.y,r.x);
 gl_FragColor=vec4(1.-fract(n(s)+p.x*p.x), 1.-fract(n(s)+p.y*p.y), 1., 1.);
}
vec2 mainSound(float t){
 return vec2(sin(.2831*256.*t*3.)+pow(fract(5.2831*2.*t*.5),.4));
}

分からないことだらけやで。

この記事が気に入ったらサポートをしてみませんか?