特に意味はないですが…
レムニスケートを書きたい。
レイマーチングで、書いてみました。
ふと、レイマーチングで、レムニスケート曲線を描きたくなったので書きたくなったので、書いてみました。
距離関数はこんな感じ
float dLemniscate(vec3 p){
return (p.x*p.x+p.y*p.y+p.z*p.z)*(p.x*p.x+p.y*p.y+p.z*p.z) - 1.15 * (p.x*p.x-p.y*p.y-p.z*p.z);
}
すると、ヌーブラっぽくなったので、これは、なんかつくれるのではないか?
とだらだら、お絵かきをつづけたところ以下のような動画が作れました。
なんか「エロい!」そういう所感をしかない…
precision mediump float;
uniform vec2 resolution;
uniform vec2 mouse;
uniform float time;
uniform sampler2D prevScene;
float dLemniscate(vec3 p){
return (p.x*p.x+p.y*p.y+p.z*p.z)*(p.x*p.x+p.y*p.y+p.z*p.z) - 1.15 * (p.x*p.x-p.y*p.y-p.z*p.z);
}
float dWall(vec3 p){
return dot(p, vec3(0.0, 0.0, 0.3*abs(sin(time)))) + 1.0;
}
float distanceHub(vec3 p){
return min(dLemniscate(p), dWall(p));
}
vec3 genNormal(vec3 p){
float d = 0.001;
return normalize(vec3(
distanceHub(p + vec3( d, 0.0, 0.0)) - distanceHub(p + vec3( -d, 0.0, 0.0)),
distanceHub(p + vec3(0.0, d, 0.0)) - distanceHub(p + vec3(0.0, -d, 0.0)),
distanceHub(p + vec3(0.0, 0.0, d)) - distanceHub(p + vec3(0.0, 0.0, -d))
));
}
void main(){
vec2 p = (gl_FragCoord.xy * 2.0 - resolution) / min(resolution.x, resolution.y);
vec3 cPos = vec3(0.0, 0.0, 3.0);
vec3 cDir = vec3(0.0, 0.0, -1.0);
vec3 cUp = vec3(0.0, 1.0, 0.0);
vec3 cSide = cross(cDir, cUp);
float targetDepth = 1.0;
vec3 ray = normalize(cSide * p.x + cUp * p.y + cDir * targetDepth);
float dist = 0.0;
float rLen = 0.0;
vec3 rPos = cPos;
for(int i = 0; i < 32; ++i){
dist = distanceHub(rPos);
rLen += dist;
rPos = cPos + ray * rLen;
}
if(abs(dist) < 0.001){
vec3 normal = genNormal(rPos);
vec3 light = normalize(vec3(mouse + 1.0, 1.0));
float diff = max(dot(normal, light), 0.1);
gl_FragColor = vec4(vec3(diff,diff*0.71,diff*0.75), 1.0);
}else{
gl_FragColor = vec4(vec3(0.0), 1.0);
}
}