WebGL
GLSL

glsl 色々なハートの描き方

はじめに

glslでハートを描くには沢山のアプローチがあります。
この記事ではglslでの色々なハートの描き方の紹介と、自分で作ったハートの描画方法を紹介したいと思います。

オリジナルハート1

hart.png

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

void main(void){
    vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y);
    p.x-=sign(p.x)*p.y*.4;
    float l = length(p);
    l=step(0.,.8-l);
    gl_FragColor = vec4(vec3(l), 1.0);
}

https://goo.gl/TzbPuQ

glslで遊んでいて偶然発見したハートで式は割とシンプルです。
ちゃんと、座標の中心から等間隔になっています。

dheart.png

ハートのくぼみ部分を調整できないのが難点ですね。

オリジナルハート2

の記事を参考に2Dのハートを描いてみたのがこちらです。

heart2.png

https://goo.gl/LYDJxm

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

float heart(vec2 p){
 return pow(p.x*p.x+p.y*p.y-1.,3.)-p.x*p.x*p.y*p.y*p.y;
}

void main(void){
 vec2 p = (gl_FragCoord.xy * 2.0 - r) / min(r.x, r.y); // 正規化
 float l = 1.-step(0.,heart(p*1.3));
 gl_FragColor = vec4(vec3(.95,.4,.4)*l, 1.0);
}

数式を直接ぶち込んで無理やり作った為、疑似ディスタンスフィールドになります。

(x^2+y^2-1)^3 - x^2*y^3 = 0

として左辺だけを持って来れば作れるので、数式からのコンバートは非常に楽です。

疑似ディスタンスフィールドは距離を変えると大きく図形を歪めます。
ディスタンスフィールドを塗りに使えないのと拡大縮小が出来ないのが難点です。(pによる図形の拡大縮小は出来る)
ただ、疑似ディスタンスフィールドをディスタンスフィールドに変換できそうな気がしています。

dheart2.png

https://goo.gl/TeS2jv

(x^2+y^2-1)^3 - x^2*y^3が作り出すディスタンスフィールドは、ハートとは似てもつかない形に見えるのですが、値が0の境界がハート型になっています。その代わり、通常のディスタンスフィールドと違って0から急激に1に変化していうので、塗りに活用することができません。

色々なハートの描き方

参考