返回精选
AI 精选动态 智能评分 60

Ethan Mollick 对比 GPT-5.2 与 GLM-5.2 Deep Think Max Shader 生成

来源: twitter关注列表
作者: Ethan Mollick (@emollick)
发布于: 2026-06-16
收录于: 2026-06-16
AI 推荐理由
提供了可直接运行的对比代码,可直观评估两模型在复杂几何与程序化生成任务上的代码质量差异。
核心解读
Ethan Mollick 对比了 7 个月前的 GPT-5.2 与 GLM-5.2 Deep Think Max 在单次生成 Twigl 着色器任务上的表现,任务为创建部分淹没在风暴海洋中的无限新哥特式塔楼城市,GLM-5.2 出现几处错误。
全文
Compare GPT-5.2 from 7 months ago with the new GLM-5.2 Deep Think Max's: "create a visually interesting shader that can run in twigl with an infinite city of neo-gothic towers partially drowned in a stormy ocean with large waves" "Make it better" GLM-5.2 also had a couple errors https://t.co/335KN2j1Jy https://video.twimg.com/amplify_video/2066963414887329792/vid/avc1/1888x668/KIoSH8XKr4Ev_sps.mp4?tag=28 > **引用原帖 Ethan Mollick (@emollick):** > Had early access to GPT-5.2. Its an impressive model. > Here is GPT 5.2 Pro's version of "create a visually interesting shader that can run in twigl-dot-app make it like an infinite city of neo-gothic towers partially drowned in a stormy ocean with large waves," single shot. https://t.co/ZLeXZ7OIIn > https://x.com/emollick/status/1999185085719887978 Ethan Mollick (@emollick): precision highp float; uniform vec2 resolution; uniform float time; // --- Hash & Noise Functions --- float hash(vec2 p) { p = fract(p * vec2(123.34, 456.21)); p += dot(p, p + 45.32); return fract(p.x * p.y); } float noise(vec2 p) { vec2 i = floor(p); vec2 f = fract(p); f = f * f * (3.0 - 2.0 * f); return mix(mix(hash(i), hash(i + vec2(1.0, 0.0)), f.x), mix(hash(i + vec2(0.0, 1.0)), hash(i + vec2(1.0, 1.0)), f.x), f.y); } float fbm(vec2 p) { float v = 0.0; float a = 0.5; mat2 m = mat2(1.6, 1.2, -1.2, 1.6); for(int i = 0; i < 5; i++) { v += a * noise(p); p = m * p; a *= 0.5; } return v; } // --- SDFs --- float sdOctagon(vec2 p, float r) { p = abs(p); float d = max(p.x, p.y) - r; d = max(d, dot(p, vec2(0.70710678)) - r * 1.12); return d; } float sdCone(vec3 p, vec2 dim) { vec2 q = vec2(length(p.xz), p.y); return max(dot(q, vec2(dim.y, -dim.x)), -q.y - dim.x); } // --- Ocean (Gerstner-inspired waves) --- float waveHeight(vec2 p) { float t = time * 1.5; float h = 0.0; h += sin(p.x * 0.15 + t) * 3.0; h += sin(p.y * 0.25 - t * 1.3) * 2.0; h += sin((p.x + p.y) * 0.3 + t * 1.7) * 1.5; h += fbm(p * 0.4 + vec2(t * 0.2, -t * 0.3)) * 5.0; return h; } // --- Scene Map --- vec2 map(vec3 p) { float oceanBase = -1.5; float ocean = p.y - (oceanBase + waveHeight(p.xz)); float city = 1000.0; float cellSize = 18.0; vec2 id = floor(p.xz / cellSize); vec2 q = mod(p.xz, cellSize) - cellSize * 0.5; float rnd = hash(id); float rnd2 = hash(id + 1.0); if (rnd > 0.15) { float w = 2.5 + rnd * 1.5; float h = 35.0 + rnd2 * 70.0; float baseY = -25.0; // Tapered Main Body float taperY = clamp((p.y - baseY) / max(0.1, h - baseY), 0.0, 1.0); float taper = mix(1.3, 0.5, taperY); float dOct = sdOctagon(q / taper, w) * taper; // Gothic Vertical Ribs float angle = atan(q.x, q.y); float ribs = cos(angle * 8.0) * 0.15; dOct += ribs * smoothstep(h, h - 15.0, p.y) * smoothstep(baseY, baseY + 10.0, p.y); float body = max(dOct, max(p.y - h, baseY - p.y)); city = min(city, body); // Central Spire if (p.y > h - 2.0) { float spireH = 20.0 + rnd2 * 15.0; float spire = sdCone(vec3(q.x, p.y - h, q.y), vec2(w * 0.8, spireH)); city = min(city, spire); } // Corner Spires (Buttresses) vec2 cornerOffset = vec2(w + 1.5); for(int i = 0; i < 4; i++) { vec2 c = cornerOffset; if(i == 1) c.x = -c.x; if(i == 2) c.y = -c.y; if(i == 3) c = -c; vec2 cq = q - c; float c_h = h * 0.75 + rnd2 * 10.0; float c_taperY = clamp((p.y - baseY) / max(0.1, c_h - baseY), 0.0, 1.0); float c_taper = mix(1.2, 0.4, c_taperY); float c_dOct = sdOctagon(cq / c_taper, 0.8) * c_taper; float cBody = max(c_dOct, max(p.y - c_h, baseY - p.y)); city = min(city, cBody); // Small spires on corners if (p.y > c_h - 1.0) { float c_spireH = 10.0 + rnd2 * 5.0; float c_spire = sdCone(vec3(cq.x, p.y - c_h, cq.y), vec2(0.7, c_spireH)); city = min(city, c_spire); } // Flying Buttresses connecting to main tower if (p.y > baseY && p.y < c_h) { vec2 dir = normalize(-c); vec2 perp = vec2(-dir.y, dir.x); float dist = dot(q - c, dir); float rad = abs(dot(q - c, perp)); float arch = sin(clamp(dist / length(cornerOffset), 0.0, 3.14) * 0.5) * 2.0; float buttress = max(rad - 0.4, max(p.y - (c_h * 0.6 + arch), dist - length(cornerOffset))); city = min(city, buttress); } } } if (city < ocean) return vec2(city, 1.0); return vec2(ocean, 0.0); } vec3 calcNormal(vec3 p) { vec2 e = vec2(1.0, -1.0) * 0.02; return normalize( e.xyy * map(p + e.xyy).x + e.yyx * map(p + e.yyx).x + e.yxy * map(p + e.yxy).x + https://t.co/6lZjGExq0y * map(p + https://t.co/6lZjGExq0y).x ); } // --- Lightning System --- float getLightningFlash() { float flashTime = floor(time * 1.5); float flashRnd = hash(vec2(flashTime, 1.0)); if (flashRnd > 0.92) { float flashFrac = fract(time * 1.5); return pow(1.0 - flashFrac, 6.0) + step(0.8, flashRnd) * step(flashFrac, 0.2); } return 0.0; } float lightningBolt(vec3 ro, vec3 rd, float seed) { vec3 p = vec3(hash(vec2(seed, 1.0)) * 40.0 - 20.0, 30.0, 50.0); vec3 dir = normalize(vec3(hash(vec2(seed, 2.0)) * 2.0 - 1.0, -1.0, -0.2)); float dist = 1000.0; for(int i = 0; i < 8; i++) { vec3 toP = p - ro; float t = dot(toP, rd); vec3 closest = ro + rd * t; dist = min(dist, length(closest - p)); // Move bolt point down p += dir * 5.0; // Jitter direction dir.x += (hash(vec2(seed, float(i))) - 0.5) * 0.8; dir = normalize(dir); } return 0.005 / (dist * dist + 0.01); } // --- ACES Tonemapping --- vec3 ACESFilm(vec3 x) { float a = 2.51; float b = 0.03; float c = 2.43; float d = 0.59; float e = 0.14; return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0.0, 1.0); } void main() { vec2 uv = (gl_FragCoord.xy - resolution.xy * 0.5) / resolution.y; // Cinematic High Altitude Camera (Sweeping over the city) // Starts at Z=40.0 so we are immediately over the city, not empty ocean vec3 ro = vec3(sin(time * 0.08) * 25.0, 55.0 + sin(time * 0.2) * 8.0, time * 5.0 + 40.0); vec3 ta = vec3(sin(time * 0.08 + 0.5) * 12.0, 10.0 + sin(time * 0.4) * 3.0, ro.z + 50.0); vec3 ww = normalize(ta - ro); vec3 uu = normalize(cross(ww, vec3(0.0, 1.0, 0.0))); vec3 vv = normalize(cross(uu, ww)); // Chromatic Aberration float ca = 0.003; vec3 rd = normalize(uv.x * uu + uv.y * vv + 1.4 * ww); vec3 rdR = normalize((uv.x - ca) * uu + uv.y * vv + 1.4 * ww); vec3 rdB = normalize((uv.x + ca) * uu + uv.y * vv + 1.4 * ww); // Raymarch float t = 0.0, tR = 0.0, tB = 0.0; float matID = -1.0; for(int i = 0; i < 120; i++) { vec3 p = ro + rd * t; vec2 res = map(p); if(res.x < 0.01) { matID = res.y; break; } t += res.x * 0.8; // slow down near surfaces for precision if(t > 250.0) break; } // Accurate Chromatic Aberration Depth if(matID > -1.0) { tR = t; tB = t; for(int i = 0; i < 6; i++) { float dR = map(ro + rdR * tR).x; if(dR < 0.01) break; tR += dR * 0.5; } for(int i = 0; i < 6; i++) { float dB = map(ro + rdB * tB).x; if(dB < 0.01) break; tB += dB * 0.5; } } float lightning = getLightningFlash(); vec3 moonColor = vec3(0.3, 0.4, 0.6); vec3 lightningColor = vec3(0.9, 0.95, 1.0); vec3 col = vec3(0.0); if(matID >= 0.0) { vec3 p = ro + rd * t; vec3 pR = ro + rdR * tR; vec3 pB = ro + rdB * tB; vec3 n = calcNormal(p); vec3 lightDir = normalize(vec3(0.5, 0.6, 0.3)); if(matID < 0.5) { // Ocean float spec = pow(max(0.0, dot(reflect(-lightDir, n), -rd)), 80.0); vec3 baseCol = mix(vec3(0.01, 0.02, 0.03), vec3(0.05, 0.1, 0.12), n.y); float foam = smoothstep(2.0, 5.0, waveHeight(p.xz)); baseCol = mix(baseCol, vec3(0.6, 0.7, 0.75), foam); col = baseCol * (n.y * 0.5 + 0.5); col += spec * moonColor * 1.2; col += spec * lightningColor * lightning * 10.0; // Foam color separation col.r += smoothstep(2.0, 5.0, waveHeight(pR.xz)) * 0.2; col.b += smoothstep(2.0, 5.0, waveHeight(pB.xz)) * 0.2; } else { // Gothic City float diff = max(0.0, dot(n, lightDir)); // Slightly brightened ambient so towers aren't invisible between lightning strikes vec3 baseCol = vec3(0.07, 0.08, 0.09) * (diff * 0.6 + 0.4); float spec = pow(max(0.0, dot(reflect(-lightDir, n), -rd)), 24.0); baseCol += spec * moonColor * 0.3; baseCol += spec * lightningColor * lightning * 5.0; // Glowing Windows (Simplified and robust logic) vec2 id = floor(p.xz / 18.0); vec2 lq = mod(p.xz, 18.0) - 9.0; float wr = 2.5 + hash(id) * 1.5; // Window strips float winX = abs(mod(lq.x, 1.5) - 0.75); float winShape = step(winX, 0.2); float winY = abs(fract(p.y * 0.25) - 0.5); winShape *= step(winY, 0.35); float winId = hash(id + floor(p.y * 0.25)); float winMask = winShape * step(0.6, winId); vec3 winCol = vec3(1.0, 0.6, 0.2) * winMask * 2.0; // Brighter glow winCol *= 0.7 + 0.3 * sin(time * 8.0 + winId * 100.0); baseCol += winCol; col = baseCol; // Window CA float winShapeR = step(abs(mod(lq.x, 1.5) - 0.75), 0.2) * step(abs(fract(pR.y * 0.25) - 0.5), 0.35); col.r += winShapeR * step(0.6, hash(id + floor(pR.y * 0.25))) * 1.0; float winShapeB = step(abs(mod(lq.x, 1.5) - 0.75), 0.2) * step(abs(fract(pB.y * 0.25) - 0.5), 0.35); col.b += winShapeB * step(0.6, hash(id + floor(pB.y * 0.25))) * 1.0; } // Volumetric Height Fog vec3 fogCol = mix(vec3(0.01, 0.02, 0.03), vec3(0.05, 0.07, 0.09), clamp(rd.y * 0.5 + 0.5, 0.0, 1.0)); fogCol += lightningColor * lightning * 0.4; float fogDensity = exp(-p.y * 0.05) * 0.04; float fog = 1.0 - exp(-t * fogDensity); col = mix(col, fogCol, clamp(fog, 0.0, 0.9)); } else { // Sky vec3 skyCol = mix(vec3(0.005, 0.01, 0.02), vec3(0.04, 0.05, 0.07), clamp(rd.y * 0.5 + 0.5, 0.0, 1.0)); // Volumetric Clouds if(rd.y > 0.0) { vec2 skyUV = rd.xz / rd.y; float clouds = fbm(skyUV * 1.5 + vec2(time * 0.05, 0.0)); clouds = smoothstep(0.4, 0.8, clouds) * rd.y; skyCol = mix(skyCol, vec3(0.02, 0.03, 0.04), clouds); skyCol += lightningColor * lightning * (1.0 - rd.y) * 0.5; } // Lightning Bolts float boltSeed = floor(time * 1.5); if(hash(vec2(boltSeed, 1.0)) > 0.92) { skyCol += lightningColor * lightningBolt(ro, rd, boltSeed) * 50.0; if(hash(vec2(boltSeed, 2.0)) > 0.5) { skyCol += lightningColor * lightningBolt(ro, rd, boltSeed + 1.0) * 50.0; } } col = skyCol; } // Driving Rain (Parallax layers) for(float i = 1.0; i <= 4.0; i++) { vec2 rUV = uv * (5.0 + i * 3.0); rUV.y += time * (15.0 + i * 5.0); // Speed rUV.x += sin(time * 1.0 + i) * 2.0 - ro.z * 0.1; // Wind + Camera Z movement float d = abs(rUV.x - floor(rUV.x + 0.5)); float rain = smoothstep(0.06, 0.0, d) * smoothstep(0.5, 0.4, fract(rUV.y)); col += rain * vec3(0.5, 0.6, 0.7) * (0.2 / i); } // Color Grading & Vignette col = ACESFilm(col * 1.1); col = pow(col, vec3(0.9, 0.95, 1.0)); // Slight color shift float vignette = smoothstep(1.4, 0.3, length(uv)); col *= vignette; // Film Grain col += (hash(gl_FragCoord.xy + time) - 0.5) * 0.03; gl_FragColor = vec4(col, 1.0); }
#模型#比较#分析