Shadertoy: glass and metal hearts
Week #4
大分時間が空いてしまいましたが、前回ブリリアントカットの距離関数が導出できたので、折角ならハートシェイプカットもやってみたいという事で挑戦しました。4月にはすでに導出できてたのですが、いざこのモチーフ使って何作ろうかって段になって全く良いイメージが浮かばず、放置していました。
そんな中、光栄なことにShader of the week に拙作を選出いただきモチベーションが復活。とりあえず何とか形にしてケリをつけて新しい事をやろう、という事でリリースしました。センスのかけらも感じられない残念な仕上がりですが、技術面は見た目以上に進化していたりします。センスが欲しい。
ハートシェイプカットの距離関数
const float vtx[11] = float[11](1.10, 1.39, 1.75, 2.32, 2.68, 2.08, 1.44, 1.12, 0.98, 0.95, 1.00);
const float vcnt = 5.0;
float dfFreeDSBC(in vec3 p, in float r, in float t) {
p = vec3(p.x, abs(p.y)-t, abs(p.z*2.0));
float at = atan(p.z,p.x)/(PI/vcnt);
float a = floor(at+.5)*(PI/vcnt), c = cos(a), s = sin(a);
int i = int(at*2.);
float rf = mix(vtx[i], vtx[i+1], fract(at*2.)) * r;
vec3 q = vec3((c*p.x+s*p.z)/rf, p.y/r, abs(-c*p.z+s*p.x)/rf);
float fcBezel = dot(q, vec3(.544639035, .8386705679, 0)) - .544639035;
float fcUGird = dot(q, vec3(.636291199, .7609957358, .1265661887)) - .636291199;
float fcStar = dot(q, vec3(.332894535, .9328278154, .1378894313)) - .448447409;
float fcTable = q.y - .2727511892 - .05;
float fcCulet = - q.y - .8692867378 * .96;
float fcGirdl = length(q.xz) - .975;
return max(fcGirdl, max(fcCulet, max(fcTable, max(fcBezel, max(fcStar, fcUGird)))));
}
鎖の距離関数
// r=鎖の径、l=鎖一つの長さ、w=太さ
float sdChain(vec3 p, float r, float l, float w){
float a=(l+r-w)*2., x0=mod(p.x, a*2.), x1=mod(p.x+a, a*2.);
return min(length(vec2(length(vec2(max(abs(x0-a)-l,0.),p.z))-r,p.y))-w,
length(vec2(length(vec2(max(abs(x1-a)-l,0.),p.y))-r,p.z))-w);
}
ハートシェイプカットについては、力技でねじ伏せてる感じです。ブリリアントカットを同心円上で拡大縮小することでハート型に加工しています。この方法だと、真ん中で折れてしまうファセットが発生して、厳密なハートシェイプカットより面数が多いのですが、それっぽいのでとりあえず良いかなと思ってます。
それよりも、鎖の距離関数を3行程度で導出できたのが、結構美しくてお気に入りです。
Tips #4
成果物4つ目です。
glass and metal hearts
とりあえずWebGL Advent Calender 2017に1本寄稿予定です。絶賛停止中でしたが、今後も少しづつ書いていこうと思ってます。
- ハートシェイプカット・鎖の距離関数
- 反射物体と透過物体を同時に効率よくレンダリング
- 古典的なレイトレースによる背景描画と模様計算
‐ Shadertoy のフーリエヒストグラム連携