demo/bump v2.1:小脚丫改成踢起软帐篷,字跟着撑起变形,脚丫弱化不吓人

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-03 16:11:31 +00:00
parent 6f42ee1499
commit cd76d36531

View File

@@ -7,7 +7,7 @@
<!-- 2026-10-03 创意预览(不进正式首页):「整块头图是妈妈的肚皮」v2。
头图去掉了胎儿插画(belly.jpg:原头图渐变拟合 + 一团圆鼓鼓的肚皮柔光,再叠回 LOGO/倒计时/周数/进度条)。
WebGL 把它当一层肉肉的肚皮:
· 宝宝时不时从里面蹬出一只小脚印(脚掌+五个脚趾的高度场),停一会儿、扭一扭、脚趾动一动,再缩回去,隔会儿换个地方;
· 宝宝时不时往外蹬一脚,把肚皮连同上面的字撑成一个软软的小帐篷(顶上隐约一只圆乎乎的小脚丫),扭一扭再缩回去,隔会儿换个地方,常常专挑字踢;
· 手指戳上去 = 肚皮被按下去一个窝,松手后像肉一样 duang duang 回弹(欠阻尼弹簧,过冲时反鼓起来)+ 周围一起晃;
· 戳中小脚印 → 脚印「嗖」地缩回去并往远离手指的方向溜走,过一两秒在别处冒出来。
不再有水波纹。下面的卡片是首页截图(静态),只为给头图一个真实语境。
@@ -77,7 +77,7 @@ float foot(vec2 p){
float sole=sdE(d,vec2(1.,-6.),vec2(11.5,11.));
sole=smin(sole,sdE(d,vec2(-1.5,6.),vec2(8.,11.)),10.);
sole=smin(sole,sdE(d,vec2(-1.,15.),vec2(8.5,9.)),10.);
float hs=smoothstep(6.,-12.,sole);
float hs=smoothstep(8.,-14.,sole);
// 五个脚趾,从大到小;蜷曲时往脚掌收、变矮
float cu=G.y, ht=0.;
vec3 toe[5];
@@ -86,13 +86,21 @@ float foot(vec2 p){
vec3 t=toe[i]; float w=sin(Tm*9.+float(i)*1.3)*.5+.5;
vec2 tc=t.xy+vec2(0.,(3.5+1.5*w)*cu);
float sd=length(d-tc)-t.z;
ht=max(ht,smoothstep(2.5,-3.5,sd)*(.8-.25*cu*w));
ht=max(ht,smoothstep(4.,-5.,sd)*(.62-.18*cu*w));
}
return F.w*max(hs,ht);
}
float dentR=33.;
float dent(vec2 p){vec2 d=p-P.xy;return P.z*exp(-dot(d,d)/(dentR*dentR));}
float hgt(vec2 p){return foot(p)+dent(p);}
// 小帐篷:脚丫往外蹬,把肚皮连同上面的字一起撑成一个尖顶软帐篷
float tent(vec2 p){
if(F.w<.01) return 0.;
vec2 d=p-F.xy; float c=cos(F.z),s=sin(F.z);
d=vec2(c*d.x+s*d.y,-s*d.x+c*d.y); d.y*=.85;
float u=clamp(1.-sqrt(dot(d,d)+64.)/68.,0.,1.)/(1.-8./68.); // 顶上磨圆,不出尖折痕
return F.w*2.3*pow(u,1.7);
}
float hgt(vec2 p){return tent(p)+foot(p)*.3+dent(p);}
void main(){
vec2 p=v*S;
vec3 c0=texture2D(T,v).rgb;
@@ -108,22 +116,24 @@ void main(){
float gw=exp(-dot(dp,dp)/(130.*130.));
vec2 q=p+dp*(-P.z*.03)*gp - J*gw + g*2.2;
float fh=clamp(foot(p)/12.,0.,1.);
q-=(p-F.xy)*.10*fh; // 脚印顶起处微微放大
float th=clamp(tent(p)/16.,0.,1.2);
q-=(p-F.xy)*.36*th; // 帐篷顶把字往外撑开、放大:越靠近顶越被撑大
q=mix(p,q,m);
vec3 c=texture2D(T,clamp(q/S,0.,1.)).rgb;
vec3 n=normalize(vec3(-g*.9,1.));
vec3 n=normalize(vec3(-g*.85,1.));
vec3 L=normalize(vec3(-.45,-.75,.9));
float dif=dot(n,L)-dot(vec3(0.,0.,1.),L);
c+=vec3(1.,.93,.88)*max(dif,0.)*.34;
c*=1.+min(dif,0.)*vec3(.42,.55,.6); // 背光侧偏暖红,像皮肤
c+=vec3(1.,.95,.9)*max(dif,0.)*.30;
c*=1.+min(dif,0.)*vec3(.28,.36,.38); // 背光侧偏暖红,像皮肤
// 脚印四周一圈很淡的凹陷(皮被撑起,边上被拉紧)
float rim=smoothstep(.0,.25,fh)*(1.-smoothstep(.25,.7,fh));
c*=1.-.05*rim*smoothstep(2.,8.,F.w);
// 按下去的窝:窝底暗一点、偏红一点(像压着肉)
// 帐篷往右下投一层淡影,让它「立」起来
vec2 d0=p-F.xy-vec2(7.,11.); c*=1.-.10*exp(-dot(d0,d0)/(48.*48.))*smoothstep(1.,9.,F.w)*(1.-th);
float dn=clamp(-dent(p)/10.,0.,1.)*m;
c*=1.-dn*vec3(.13,.21,.2);
vec3 Hh=normalize(L+vec3(0.,0.,1.));
c+=vec3(1.,.97,.95)*pow(max(dot(n,Hh),0.),36.)*.22*smoothstep(.5,4.,abs(h)); // 皮肤油润的柔高光
c+=vec3(1.,.97,.95)*pow(max(dot(n,Hh),0.),24.)*.12*smoothstep(.5,4.,abs(h)); // 皮肤油润的柔高光
c+=vec3(1.,.88,.8)*smoothstep(2.,12.,h)*.05; // 顶起处微微透亮
gl_FragColor=vec4(c,1.);
}`;
@@ -167,12 +177,14 @@ void main(){
const jg = { x: { v: 0, vel: 0, to: 0, k: 210, c: 4.2 }, y: { v: 0, vel: 0, to: 0, k: 210, c: 4.2 } };
let mode = 'wait', wait = .5, t = 0, count = 0;
const TEXT_SPOTS = [[62, 120], [100, 74], [104, 124], [96, 166], [230, 26], [160, 168]];
function pickSpot() {
for (let i = 0; i < 40; i++) {
// 落在右半边空白肚皮上(原来画宝宝的地方),偶尔窜到左下角;不压在大字和胶囊上
const x = 40 + Math.random() * 300, y = 78 + Math.random() * 108;
if (x < 225 && y < 188) continue;
if (Math.hypot(x - ft.x, y - ft.y) > 70) return { x, y };
// 一半概率专挑字踢(大字「30」、倒计时胶囊、进度条、slogan),字会被撑起来变形;一半落在右边空白肚皮
let x, y;
if (Math.random() < .55) { const s = TEXT_SPOTS[Math.floor(Math.random() * TEXT_SPOTS.length)]; x = s[0] + (Math.random() - .5) * 16; y = s[1] + (Math.random() - .5) * 10; }
else { x = 240 + Math.random() * 100; y = 80 + Math.random() * 100; }
if (Math.hypot(x - ft.x, y - ft.y) > 80) return { x, y };
}
return { x: 300, y: 120 };
}
@@ -195,7 +207,7 @@ void main(){
if (on) {
pk.x = x; pk.y = y; pk.held = true; pk.d.to = -14; pk.d.k = 380; pk.d.c = 22;
const fx = ft.x + ft.ox, fy = ft.y + ft.oy;
if ((mode === 'show' || (mode === 'hide' && ft.h.v > 3)) && Math.hypot(x - fx, y - fy) < 46) {
if ((mode === 'show' || (mode === 'hide' && ft.h.v > 3)) && Math.hypot(x - fx, y - fy) < 58) {
// 戳中小脚丫:嗖地缩回去,往远离手指的方向溜
count++;
let dx = fx - x, dy = fy - y, l = Math.hypot(dx, dy);