energyOrbFragment
constenergyOrbFragment: “const float radius = 0.31;\nconst vec3 violet = vec3(0.55, 0.52, 1.0);\n\nfloat hash(vec3 p) {\n p = fract(p * 0.3183099 + vec3(0.1, 0.2, 0.3));\n p *= 17.0;\n return fract(p.x * p.y * p.z * (p.x + p.y + p.z));\n}\n\nfloat noise(vec3 x) {\n vec3 i = floor(x);\n vec3 f = fract(x);\n f = f * f * (3.0 - 2.0 * f);\n return mix(\n mix(mix(hash(i), hash(i + vec3(1, 0, 0)), f.x),\n mix(hash(i + vec3(0, 1, 0)), hash(i + vec3(1, 1, 0)), f.x), f.y),\n mix(mix(hash(i + vec3(0, 0, 1)), hash(i + vec3(1, 0, 1)), f.x),\n mix(hash(i + vec3(0, 1, 1)), hash(i + vec3(1, 1, 1)), f.x), f.y),\n f.z);\n}\n\nfloat fbm(vec3 p) {\n float v = 0.0;\n float a = 0.5;\n for (int i = 0; i < 5; i++) {\n v += a * noise(p);\n p = p * 2.03 + vec3(1.7);\n a *= 0.5;\n }\n return v;\n}\n\nvoid main() {\n vec2 uv = vUv - 0.5;\n float r = length(uv);\n float t = uTime * uSpeed;\n // Every colour below is ThreeUI’s, scaled by how far uColor is from violet.\n vec3 tint = uColor / violet;\n vec3 colour = vec3(0.0);\n float alpha = 0.0;\n\n if (r < radius) {\n // The sphere’s normal under this pixel, turning slowly about y.\n float z = sqrt(radius * radius - r * r);\n vec3 normal = normalize(vec3(uv, z));\n float angle = t * 0.15;\n mat3 spin = mat3(cos(angle), 0.0, sin(angle), 0.0, 1.0, 0.0, -sin(angle), 0.0, cos(angle));\n vec3 point = spin * normal;\n\n // Two layers of smoke, the second warped by the first.\n float f1 = fbm(point * 2.6 + vec3(0.0, t * 0.12, 0.0));\n float f2 = fbm(point * 4.5 - vec3(t * 0.08, 0.0, t * 0.05) + f1 * 1.8);\n float veil = smoothstep(0.35, 0.75, f2);\n colour = mix(vec3(0.04, 0.02, 0.12), vec3(0.22, 0.16, 0.55), f1 * 1.2);\n colour = mix(colour, vec3(0.62, 0.60, 0.98), veil * 0.65);\n colour *= tint;\n\n // Fresnel at the edge, a highlight on top and a thin bright rim.\n float fresnel = pow(1.0 - z / radius, 2.2);\n float top = pow(max(dot(normal, normalize(vec3(0.0, 0.7, 0.7))), 0.0), 3.0);\n float rim = smoothstep(radius - 0.03, radius, r);\n colour += tint * uIntensity * (vec3(0.55, 0.55, 1.0) * fresnel * 1.1\n + vec3(0.45, 0.42, 0.9) * top * 0.35\n + vec3(0.6, 0.58, 1.0) * rim * 0.6);\n alpha = 1.0;\n } else {\n // The glow outside, faded to nothing before the plane’s edge.\n float glow = clamp(exp(-(r - radius) * 14.0), 0.0, 1.0);\n glow *= 1.0 - smoothstep(0.4, 0.5, r);\n colour = violet * tint * glow * 0.8 * uIntensity;\n // Intensity fades the glow’s cover too, or at 0 it would darken\n // what lies behind the orb.\n alpha = glow * 0.85 * clamp(uIntensity, 0.0, 1.0);\n }\n gl_FragColor = vec4(colour, alpha);\n}\n”
Defined in: packages/engine/src/render/energyOrb.ts:11
The energy orb, for a transparent Shader: a sphere of drifting smoke with
a bright rim and a glow around it, drawn on a plane that faces the camera.
uColor tints it (ThreeUI’s violet is 0.55, 0.52, 1.0), uSpeed scales
the drift and uIntensity the glow.