はじめに
glslでハートを描くには沢山のアプローチがあります。
この記事ではglslでの色々なハートの描き方の紹介と、自分で作ったハートの描画方法を紹介したいと思います。
オリジナルハート1
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);
}
glslで遊んでいて偶然発見したハートで式は割とシンプルです。
ちゃんと、座標の中心から等間隔になっています。
ハートのくぼみ部分を調整できないのが難点ですね。
オリジナルハート2
の記事を参考に2Dのハートを描いてみたのがこちらです。
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による図形の拡大縮小は出来る)
ただ、疑似ディスタンスフィールドをディスタンスフィールドに変換できそうな気がしています。
(x^2+y^2-1)^3 - x^2*y^3が作り出すディスタンスフィールドは、ハートとは似てもつかない形に見えるのですが、値が0の境界がハート型になっています。その代わり、通常のディスタンスフィールドと違って0から急激に1に変化していうので、塗りに活用することができません。
色々なハートの描き方
- GLSLレイマーチング研究距離関数について勉強してみた16(Heartの関数を作ってみたその2)
- iqさんの3Dのハート
- http://glslsandbox.com/e#38545.0
- http://glslsandbox.com/e#42120.0