4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

符号なし距離関数で作る魚眼レンズ効果

Last updated at Posted at 2019-08-14

はじめに

符号なし距離関数シリーズ第3弾です。
今回は、座標pに(1+距離関数)を掛けることによって実現できる魚眼レンズ効果で、色々な距離関数に置き換えてみましょう。

image.png

前回までの内容はこちら

2次元ディスタンスフィールドの一覧はこちら

元の画像

image.png

歪み具合が分かりやすいように、10x10のグリッドを用意し、それぞれのグリッドに左上から左下に掛けて番号を振り、円を描いた画像を用意しました。

魚眼レンズ(fish eye)効果

image.png

p*=(1.+length(p))*.5;

座標pに(1+ユークリッド距離)を掛けると魚眼レンズ効果になります。
ちょっと、コイツを掛けるとカッコよくなるので、結構使われていますね。

マンハッタン

image.png

チェビシェフ

image.png

ミンコフスキー (p=-∞)

image.png

ミンコフスキー (p=0.5)

image.png

ミンコフスキー (p=8)

image.png

六角形

image.png

image.png

逆魚眼

image.png

p*=(1.-length(p)*.25)*1.5;

中央を窪ませたい場合はマイナスすればよいです。

加算バージョンの魚眼

image.png

  p+=sign(p)*length(p)*.05;

加算する場合はsignが必要です。lengthだとマイナスがなくなる為

減算バージョンの魚眼(逆魚眼)

image.png

  p-=sign(p)*length(p)*1.5;

他、バリエーションは色々つくれますが、正直微妙です。

  p-=sign(vec2(p.x,-p.y))*length(p);
  p+=sign(vec2(p.x,-p.y))*length(p);
  p-=length(p);
  p+=length(p);

その他

魚眼レンズ効果と全く同じ距離関数を使うと距離関数の距離1を基点に歪ませることができます。

image.png

  p*=(1.+lStar(p*rot(PI),5.))*.5;
.
.
.
  l+= strokeInner(sd(lStar(p*rot(PI),5.)),.01);

image.png

デフォルトの魚眼レンズ効果でも同じことが起こってますね。

  p*=(1.+length(p))*.5;
.
.
.
  l+= strokeInner(sd(length(p)),.01);

サンプルプログラム

precision mediump float;
uniform vec2  m;       // mouse
uniform float t;       // time
uniform vec2  r;       // resolution
uniform sampler2D smp; // prev scene

const float PI = acos(-1.);
const float TAU = PI * 2.;

#define saturate(x) clamp(x,0.,1.)
#define _tail2x(p,n) (mod(p,2.)-1.)

vec2 tail2x(vec2 p,float n){p*=n;return _tail2x(p,n);}
vec2 tailX2x(vec2 p,float n){p*=n;return vec2(_tail2x(p.x,n),p.y);}
vec2 tailY2x(vec2 p,float n){p*=n;return vec2(p.x,_tail2x(p.y,n));}

float cross(vec2 v1, vec2 v2) {return dot(v1,vec2(v2.y,-v2.x));}
mat2 rot(float a){float c=cos(a),s=sin(a);return mat2(c,-s,s,c);}

// signed distance
float sd(float d,float r){return r-d;} 
float sd(float d){return 1.-d;} 

float fill_na(float d){return step(0.,d);}
float fill(float d){return smoothstep(0.,0.01,d);}
float stroke(float d,float w){return 1.-smoothstep(w,w+0.01,abs(d));}
float strokeInner(float d,float w){return stroke(d-w,w);}
float strokeOuter(float d,float w){return stroke(d+w,w);}

float sumabs(vec2 p){return abs(p.x)+abs(p.y);}
float maxabs(vec2 p){return max(abs(p.x), abs(p.y));}
float minabs(vec2 p){return min(abs(p.x), abs(p.y));}
float lpnorm(vec2 p, float n){vec2 t=pow(abs(p),vec2(n));return pow(t.x+t.y,1./n);}

float lPoly(vec2 p,float n){
  float a = atan(p.x,p.y)+PI;
  float r = TAU/n;
  return cos(floor(.5+a/r)*r-a)*length(p)/cos(r*.5);
}

float lStar(vec2 p,float n){
  return min(lPoly(p,n*.5),lPoly(mod(n,2.)!=0.?vec2(-p.x,p.y):p*rot(TAU/n),n*.5));
}

float lStar(vec2 p,float n,float o){
  return (lPoly(p,n)-lPoly(p*rot(PI/n),n)*o)/(1.-o);
}

float lHeart(vec2 p) {
  p.y += .034;
  p *= 1.1;
  return sqrt(dot(p, p) - abs(p.x)*p.y);
}
float dot2(vec2 p){return dot(p,p);}

float sLocater(vec2 p){
  float l=stroke(sd(maxabs(tailX2x(p,8.))),.016)*stroke(p.y,.03);
  l+=stroke(sd(maxabs(tailY2x(p,8.))),.016)*stroke(p.x,.03);
  l+=stroke(p.x,.001);
  l+=stroke(p.y,.001);
  return l;
}

float pCheckers(vec2 p,float n){vec2 q=p*n;return mod(floor(q.x)+floor(q.y),2.0);}

float seg(vec2 p,float s,float k){p=abs(p*k);return max(s+p.x,s*.5+p.y+p.x);}
float seg7(vec2 p,int n,float s,float k){
    float l=5.,w=s*.5;
    vec2 q=p.yx,h=vec2(s,0.),v=vec2(-w,w);
    l = (n!=1 && n!=4                ?min(seg(q-h,s,k),l):l);
    l = (n!=1 && n!=2 && n!=3 && n!=7?min(seg(p-v,s,k),l):l);
    l = (n!=5 && n!=6                ?min(seg(p-w,s,k),l):l);
    l = (n!=0 && n!=1 && n!=7        ?min(seg(q  ,s,k),l):l);
    l = (n==0 || n==2 || n==6 || n==8?min(seg(p+w,s,k),l):l);
    l = (n!=2                        ?min(seg(p+v,s,k),l):l);
    l = (n!=1 && n!=4 && n!=7        ?min(seg(q+h,s,k),l):l);
    return l;
}
void main(void){
  vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
  vec2 P =p;
  float l=0.;
  //p*=(1.+length(p))*.5;
  //p*=(1.+sumabs(p))*.5;
  //p*=(1.+maxabs(p))*.5;
  //p*=(1.+minabs(p));
  //p*=(1.+lpnorm(p,.5))*.5;
  //p*=(1.+lpnorm(p,8.))*.5;
  //p*=(1.+lPoly(p,6.))*.5;
  p*=(1.+lStar(p*rot(PI),5.))*.5;
  vec2 q=tail2x(p,10.);
  l+= pCheckers(p,5.)*.25+.25;;
  l+= stroke(seg7(q-vec2(.3,0.),int(floor((p.x+1.)*5.)),.4,1.3),.5);
  l+= stroke(seg7(q+vec2(.3,0.),int(floor((1.-p.y)*5.)),.4,1.3),.5);
  l+= strokeInner(sd(length(p)),.01);
  //l+= strokeInner(sd(lStar(p*rot(PI),5.)),.01);
  l*=step(-1.,p.x)*step(p.x,1.)*step(-1.,p.y)*step(p.y,1.);
  l+=sLocater(P);
  gl_FragColor = vec4(vec3(l), 1.0);
}
4
4
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
4
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?