LoginSignup
3
5

More than 3 years have passed since last update.

glsl 2D座標変換 疑似パースペクティブまとめ

Last updated at Posted at 2019-08-14

概要

良く使われている疑似パースペクティブですが、glsl特有の省略によって、良く使われている疑似パースペクティブは座標がひっくり返っていたりして、意味あるテクスチャーを貼る場合に困ったので、自分用の覚書です。岩の模様とか意味がないやつは別に問題ないです。

画像変換前の画像

image.png

Bottom

image.png

Top

image.png

Left

image.png

Right

image.png

水平

image.png

垂直

image.png

水平 + 垂直

image.png

vec2 fakePerspectiveVH(vec2 p){
  float r = 1./abs(abs(p.x)<abs(p.y)?p.y:p.x);
  return abs(p.x)<abs(p.y)?vec2(p.x*r,(-2.*(r-1.)+1.)*sign(p.y)):vec2((-2.*(r-1.)+1.)*sign(p.x),p.y*r);
}

その他

image.png

キューブの中を再現

  l+=mapCheck(fakePerspectiveVH(p));
  l+=mapCheck(p*2.);

サンプルプログラム

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 maxabs(vec2 p){return max(abs(p.x), abs(p.y));}

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;
}

vec2 fakePerspectiveBottom (vec2 p){
  float r = 1./p.y;
  return vec2(-p.x*r, -2.*(r+1.)-1.);
}

vec2 fakePerspectiveTop (vec2 p){
  float r = 1./p.y;
  return vec2(p.x*r, -2.*(r-1.)+1.);
}

vec2 fakePerspectiveLeft(vec2 p){
  float r = 1./p.x;
  return vec2(-2.*(r+1.)-1.,-p.y*r);
}

vec2 fakePerspectiveRight(vec2 p){
  float r = 1./p.x;
  return vec2(-2.*(r-1.)+1.,p.y*r);
}

vec2 fakePerspectiveVertical(vec2 p){
  float r = 1./abs(p.x);
  return vec2((-2.*(r-1.)+1.)*sign(p.x),p.y*r);
}

vec2 fakePerspectiveHorizontal(vec2 p){
  float r = 1./abs(p.y);
  return vec2(p.x*r,(-2.*(r-1.)+1.)*sign(p.y));
}

vec2 fakePerspectiveVH(vec2 p){
  float r = 1./abs(abs(p.x)<abs(p.y)?p.y:p.x);
  return abs(p.x)<abs(p.y)?vec2(p.x*r,(-2.*(r-1.)+1.)*sign(p.y)):vec2((-2.*(r-1.)+1.)*sign(p.x),p.y*r);
}

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;
}

float mapCheck(vec2 p){
  float l=0.;
  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*=step(-1.,p.x)*step(p.x,1.)*step(-1.,p.y)*step(p.y,1.);
  return l;
}

void main(void){
  vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
  vec2 P =p;
  float l=0.;
  l+=mapCheck(fakePerspectiveHorizontal(p));
  //l+=mapCheck(fakePerspectiveVertical(p));
  //l+=mapCheck(fakePerspectiveVH(p));
  //l+=mapCheck(p*2.);

  //l=mapCheck(fakePerspectiveBottom(p));
  //l=mapCheck(fakePerspectiveTop(p));
  //l=mapCheck(fakePerspectiveLeft(p));
  //l=mapCheck(fakePerspectiveRight(p));

  l+=sLocater(p);

  gl_FragColor = vec4(vec3(l), 1.0);
}
3
5
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
3
5