[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"guide-nav":3,"doc-\u002Fdocs\u002Fprimitives\u002Fdefine":145},[4,10,16,20,24,28,32,36,40,44,48,52,56,60,64,69,73,78,82,86,90,94,98,102,106,110,114,117,120,124,127,131,134,138,141],{"path":5,"title":6,"description":7,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide","Getting started","Shaders is a library of GPU effect components for Vue, React, Svelte, Solid, JavaScript and Framer, with a design editor for building with them.","code",null,{"path":11,"title":12,"description":13,"category":8,"exclude":14,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fquickstart","Quickstart","Install Shaders, render your first effect, and drive a prop from state.",[15],"js",{"path":17,"title":18,"description":19,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fcomposing-effects","Composing effects","Stack components as layers and nest them to control which layers an effect touches.",{"path":21,"title":22,"description":23,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fblending-masking","Blending and masking","Control how a layer mixes with the layers below it, and reveal one layer through another.",{"path":25,"title":26,"description":27,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fprops-reactivity","Props and reactivity","Bind props to your framework's state so effects update when it changes, and animate props with an animation library.",{"path":29,"title":30,"description":31,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fdynamic-props","Dynamic props","Drive any numeric or position prop from time, the cursor, or another layer, without writing animation code.",{"path":33,"title":34,"description":35,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Flayout-positioning","Layout and positioning","Size and place a shader in your page with CSS, as a background, a fill, or an inline block.",{"path":37,"title":38,"description":39,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Ftransforms","Transforms","Position, size, and rotate any layer inside the canvas with a bounding box, in % or px units.",{"path":41,"title":42,"description":43,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fshape-effects","Shape effects","Pick the 2D, 3D or custom SVG shape that Glass, Neon, Emboss and other shape effects draw inside.",{"path":45,"title":46,"description":47,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fcolor-space","Color space","Match colors to your design tool with the output color space, and keep bright layers from clipping with tone mapping.",{"path":49,"title":50,"description":51,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fhooks-events","Hooks and events","Run code when an effect is ready to show, and show a fallback when the GPU can't run it.",{"path":53,"title":54,"description":55,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fperformance","Performance","Learn what makes an effect expensive on the GPU and how to keep it inside the frame budget.",{"path":57,"title":58,"description":59,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fcustom-shaders","Custom components","Write your own component in TypeScript, use it like any component in the library, and write WGSL by hand when you need to.",{"path":61,"title":62,"description":63,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Ftelemetry","Telemetry","The `\u003CShader>` component occasionally sends an anonymous performance report to help us improve the engine over time.",{"path":65,"title":66,"description":67,"category":68,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fmcp","Shaders MCP","Connect your AI coding agent to Shaders so it can find, install and edit effects in your codebase.","workflows",{"path":70,"title":71,"description":72,"category":68,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fcli","Shaders CLI","Install shaders and presets into your codebase as component files, and keep them in sync with the design editor.",{"path":74,"title":75,"description":76,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fquick-tour-of-the-design-editor","Quick tour of the design editor","A short walkthrough of the full Shaders workflow, from designing on the infinite canvas to exporting code.","editor",{"path":79,"title":80,"description":81,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fintro-to-the-interface","Intro to the interface","A tour of the design editor interface: the canvas, layers, the Properties panel, and the ways to share and export.",{"path":83,"title":84,"description":85,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fcomposing-your-first-shader-effect","Composing your first shader effect","Building a first shader effect in the design editor by stacking and nesting components as layers.",{"path":87,"title":88,"description":89,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fmasking-and-blending","Masking and blending","How blend modes and masks combine components in the design editor.",{"path":91,"title":92,"description":93,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fdynamic-prop-mapping","Dynamic prop mapping","Turning static props into dynamic ones in the design editor: mapping one layer's output into another's prop, following the cursor, or animating automatically.",{"path":95,"title":96,"description":97,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fcustom-media-and-transformations","Custom media and transformations","Uploading images, videos, and SVG files to the media gallery, adding them to a composition, and placing them with transformations.",{"path":99,"title":100,"description":101,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Finstalling-a-shader-via-mcp","Installing a shader via MCP","Installing a shader from the design editor into a hero section with the Shaders MCP.",{"path":103,"title":104,"description":105,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fexploring-shape-effects","Exploring shape effects","Applying shape effects such as liquid glass, liquid metal, and glowing edges to built-in shapes and your own SVG.",{"path":107,"title":108,"description":109,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fglass-component-spotlight","Component spotlight: Glass","A short look at the Glass component and the liquid-glass look it creates.",{"path":111,"title":112,"description":113,"category":77,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fdigital-looks-component-spotlight","Component spotlight: Digital looks","A look at the digital stylization components for glitchy, futuristic, or technical effects.",{"path":115,"title":12,"description":116,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fjs\u002Fquickstart","Install Shaders without a framework, render your first effect on a canvas, and update props at runtime.",{"path":118,"title":12,"description":119,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Freact\u002Fquickstart","Install Shaders in a React app, render your first effect, and drive a prop from state.",{"path":121,"title":122,"description":123,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Freact\u002Fssr","Next.js and SSR","Render Shaders in Next.js and other React SSR apps by keeping each shader on the client.",{"path":125,"title":12,"description":126,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fsolid\u002Fquickstart","Install Shaders in a Solid app, render your first effect, and drive a prop from a signal.",{"path":128,"title":129,"description":130,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fsolid\u002Fssr","SolidStart and SSR","Render Shaders in SolidStart and other Solid SSR apps by keeping each shader on the client.",{"path":132,"title":12,"description":133,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fsvelte\u002Fquickstart","Install Shaders in a Svelte app, render your first effect, and drive a prop from state.",{"path":135,"title":136,"description":137,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fsvelte\u002Fssr","SvelteKit and SSR","Render Shaders in SvelteKit and other Svelte SSR apps, where each shader already waits for the browser.",{"path":139,"title":12,"description":140,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fvue\u002Fquickstart","Install Shaders in a Vue app, render your first effect, and drive a prop from a ref.",{"path":142,"title":143,"description":144,"category":8,"exclude":9,"forceFramework":9},"\u002Fdocs\u002Fguide\u002Fvue\u002Fssr","Nuxt and SSR","Render Shaders in Nuxt and other Vue SSR apps by keeping each shader on the client.",{"id":146,"title":147,"body":148,"categoryId":1679,"categorySlug":1679,"categoryTitle":9,"curated":201,"description":1680,"editUrl":1681,"extension":1682,"group":1679,"groupTitle":1683,"kind":9,"meta":1684,"navigation":201,"path":1685,"seo":1686,"sourceUrl":1687,"stem":1688,"wordCount":282,"__hash__":1689},"primitives\u002Fdocs\u002Fprimitives\u002F1.define\u002Findex.md","defineShader & wgsl",{"type":149,"value":150,"toc":1673},"minimark",[151,155,167,337,344,426,432,524,554,580,605,623,742,758,763,907,911,1202,1206,1580,1584,1669],[152,153,147],"h1",{"id":154},"defineshader-wgsl",[156,157,158,159,166],"p",{},"A shader is a plain object: a name, the props a user can set, and one field that says what it\ndraws. Hand it to ",[160,161,163],"a",{"href":162},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fdefineshader",[8,164,165],{},"defineShader"," and it becomes a component you can mount, nest, blend, mask\nand animate like any shader in the library.",[168,169,174],"pre",{"className":170,"code":171,"language":172,"meta":173,"style":173},"language-ts shiki shiki-themes github-dark","import {defineShader, transformColor, transformPosition, wgsl} from 'shaders\u002Fstd'\n\nexport const Halo = defineShader({\n  name: 'Halo',                      \u002F\u002F what the editor and preset JSON call it\n  props: {                           \u002F\u002F the controls a user can set\n    color: {default: '#ffd166', transform: transformColor},\n    center: {default: {x: 0.5, y: 0.5}, transform: transformPosition},\n    radius: {default: 0.6},\n  },\n  paint: wgsl`                       \u002F\u002F what it draws: a color for every pixel\n    let d = length((uv - center) * vec2f(aspect, 1.0)) \u002F radius;\n    return vec4f(color.rgb, 1.0 - smoothstep(0.8, 1.0, d));\n  `,\n})\n","ts","",[8,175,176,196,203,226,242,251,263,280,292,298,310,316,322,331],{"__ignoreMap":173},[177,178,181,185,189,192],"span",{"class":179,"line":180},"line",1,[177,182,184],{"class":183},"snl16","import",[177,186,188],{"class":187},"s95oV"," {defineShader, transformColor, transformPosition, wgsl} ",[177,190,191],{"class":183},"from",[177,193,195],{"class":194},"sU2Wk"," 'shaders\u002Fstd'\n",[177,197,199],{"class":179,"line":198},2,[177,200,202],{"emptyLinePlaceholder":201},true,"\n",[177,204,206,209,212,216,219,223],{"class":179,"line":205},3,[177,207,208],{"class":183},"export",[177,210,211],{"class":183}," const",[177,213,215],{"class":214},"sDLfK"," Halo",[177,217,218],{"class":183}," =",[177,220,222],{"class":221},"svObZ"," defineShader",[177,224,225],{"class":187},"({\n",[177,227,229,232,235,238],{"class":179,"line":228},4,[177,230,231],{"class":187},"  name: ",[177,233,234],{"class":194},"'Halo'",[177,236,237],{"class":187},",                      ",[177,239,241],{"class":240},"sAwPA","\u002F\u002F what the editor and preset JSON call it\n",[177,243,245,248],{"class":179,"line":244},5,[177,246,247],{"class":187},"  props: {                           ",[177,249,250],{"class":240},"\u002F\u002F the controls a user can set\n",[177,252,254,257,260],{"class":179,"line":253},6,[177,255,256],{"class":187},"    color: {default: ",[177,258,259],{"class":194},"'#ffd166'",[177,261,262],{"class":187},", transform: transformColor},\n",[177,264,266,269,272,275,277],{"class":179,"line":265},7,[177,267,268],{"class":187},"    center: {default: {x: ",[177,270,271],{"class":214},"0.5",[177,273,274],{"class":187},", y: ",[177,276,271],{"class":214},[177,278,279],{"class":187},"}, transform: transformPosition},\n",[177,281,283,286,289],{"class":179,"line":282},8,[177,284,285],{"class":187},"    radius: {default: ",[177,287,288],{"class":214},"0.6",[177,290,291],{"class":187},"},\n",[177,293,295],{"class":179,"line":294},9,[177,296,297],{"class":187},"  },\n",[177,299,301,304,307],{"class":179,"line":300},10,[177,302,303],{"class":187},"  paint: ",[177,305,306],{"class":221},"wgsl",[177,308,309],{"class":194},"`                       \u002F\u002F what it draws: a color for every pixel\n",[177,311,313],{"class":179,"line":312},11,[177,314,315],{"class":194},"    let d = length((uv - center) * vec2f(aspect, 1.0)) \u002F radius;\n",[177,317,319],{"class":179,"line":318},12,[177,320,321],{"class":194},"    return vec4f(color.rgb, 1.0 - smoothstep(0.8, 1.0, d));\n",[177,323,325,328],{"class":179,"line":324},13,[177,326,327],{"class":194},"  `",[177,329,330],{"class":187},",\n",[177,332,334],{"class":179,"line":333},14,[177,335,336],{"class":187},"})\n",[156,338,339,343],{},[340,341,342],"strong",{},"One field says what kind of shader it is."," Give exactly one.",[345,346,347,363],"table",{},[348,349,350],"thead",{},[351,352,353,357,360],"tr",{},[354,355,356],"th",{},"Field",[354,358,359],{},"You get",[354,361,362],{},"What is inside it",[364,365,366,380,400,413],"tbody",{},[351,367,368,374,377],{},[369,370,371],"td",{},[8,372,373],{},"paint:",[369,375,376],{},"a generator that paints from coordinates (gradients, noise, light)",[369,378,379],{},"nothing: it stands on its own",[351,381,382,387,390],{},[369,383,384],{},[8,385,386],{},"effect:",[369,388,389],{},"a filter over the layer nested inside it (tints, blurs, ripples)",[369,391,392,393,396,397],{},"the child layer, read as ",[8,394,395],{},"child"," or sampled as ",[8,398,399],{},"childTexture",[351,401,402,407,410],{},[369,403,404],{},[8,405,406],{},"map:",[369,408,409],{},"a distortion that moves the pixels of the layer inside it",[369,411,412],{},"the child layer",[351,414,415,420,423],{},[369,416,417],{},[8,418,419],{},"shape:",[369,421,422],{},"a 2D shape with fill and stroke",[369,424,425],{},"nothing",[156,427,428,431],{},[340,429,430],{},"Two ways to write what it draws."," Compose it from std words (the rest of this reference)\nand the engine compiles the composition to WGSL. A radial gradient between two color props is\none line:",[168,433,435],{"className":170,"code":434,"language":172,"meta":173,"style":173},"paint: rampOver(dist.radial({center: p('center'), radius: p('radius'), aspect: 1, skew: 0}), pair(p('inner'), p('outer'), p('colorSpace')))\n",[8,436,437],{"__ignoreMap":173},[177,438,439,442,445,448,451,454,457,459,462,465,468,470,472,475,478,481,484,487,490,493,495,497,499,502,505,507,509,512,514,516,518,521],{"class":179,"line":180},[177,440,441],{"class":221},"paint",[177,443,444],{"class":187},": ",[177,446,447],{"class":221},"rampOver",[177,449,450],{"class":187},"(dist.",[177,452,453],{"class":221},"radial",[177,455,456],{"class":187},"({center: ",[177,458,156],{"class":221},[177,460,461],{"class":187},"(",[177,463,464],{"class":194},"'center'",[177,466,467],{"class":187},"), radius: ",[177,469,156],{"class":221},[177,471,461],{"class":187},[177,473,474],{"class":194},"'radius'",[177,476,477],{"class":187},"), aspect: ",[177,479,480],{"class":214},"1",[177,482,483],{"class":187},", skew: ",[177,485,486],{"class":214},"0",[177,488,489],{"class":187},"}), ",[177,491,492],{"class":221},"pair",[177,494,461],{"class":187},[177,496,156],{"class":221},[177,498,461],{"class":187},[177,500,501],{"class":194},"'inner'",[177,503,504],{"class":187},"), ",[177,506,156],{"class":221},[177,508,461],{"class":187},[177,510,511],{"class":194},"'outer'",[177,513,504],{"class":187},[177,515,156],{"class":221},[177,517,461],{"class":187},[177,519,520],{"class":194},"'colorSpace'",[177,522,523],{"class":187},")))\n",[156,525,526,527,532,533,536,537,540,541,540,544,540,547,540,550,553],{},"Or write the math yourself in a ",[160,528,530],{"href":529},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fwgsl",[8,531,306],{}," body: one function that returns a ",[8,534,535],{},"vec4f"," color. Your\nprops, ",[8,538,539],{},"uv",", ",[8,542,543],{},"time",[8,545,546],{},"aspect",[8,548,549],{},"viewport",[8,551,552],{},"pointer"," and the child are bound by name, so there\nis no setup to write. A filter that inverts whatever is inside it:",[168,555,557],{"className":170,"code":556,"language":172,"meta":173,"style":173},"effect: wgsl`\n  return vec4f(1.0 - child.rgb, child.a);\n`\n",[8,558,559,571,576],{"__ignoreMap":173},[177,560,561,564,566,568],{"class":179,"line":180},[177,562,563],{"class":221},"effect",[177,565,444],{"class":187},[177,567,306],{"class":221},[177,569,570],{"class":194},"`\n",[177,572,573],{"class":179,"line":198},[177,574,575],{"class":194},"  return vec4f(1.0 - child.rgb, child.a);\n",[177,577,578],{"class":179,"line":205},[177,579,570],{"class":194},[156,581,582,585,586,589,590,593,594,540,597,600,601,604],{},[340,583,584],{},"Props are the controls."," Each has a ",[8,587,588],{},"default",", usually a ",[8,591,592],{},"transform"," that says what kind of\nvalue it is (",[8,595,596],{},"transformColor",[8,598,599],{},"transformPosition",", …), and optional ",[8,602,603],{},"ui"," metadata that tells\nthe editor how to show it. Blend modes, opacity, masks, transforms, dynamic props and code\nexport come with every shader; you never write them.",[156,606,607,610,611,614,615,618,619,622],{},[340,608,609],{},"Use it like any other shader."," Mount it with ",[8,612,613],{},"\u003CCustomShader src={Halo}>"," in React, Vue,\nSvelte or Solid. Call ",[8,616,617],{},"registerShader(Halo)"," when preset JSON should be able to name it as\n",[8,620,621],{},"type: 'Halo'",".",[168,624,628],{"className":625,"code":626,"language":627,"meta":173,"style":173},"language-tsx shiki shiki-themes github-dark","import {Shader, CustomShader, Blur} from 'shaders\u002Freact' \u002F\u002F or shaders\u002Fvue, shaders\u002Fsvelte, shaders\u002Fsolid\nimport {Halo} from '.\u002Fhalo'\n\n\u003CShader>\n  \u003CBlur intensity={8}>\n    \u003CCustomShader src={Halo} radius={0.8} \u002F>\n  \u003C\u002FBlur>\n\u003C\u002FShader>\n","tsx",[8,629,630,645,657,661,672,695,724,733],{"__ignoreMap":173},[177,631,632,634,637,639,642],{"class":179,"line":180},[177,633,184],{"class":183},[177,635,636],{"class":187}," {Shader, CustomShader, Blur} ",[177,638,191],{"class":183},[177,640,641],{"class":194}," 'shaders\u002Freact'",[177,643,644],{"class":240}," \u002F\u002F or shaders\u002Fvue, shaders\u002Fsvelte, shaders\u002Fsolid\n",[177,646,647,649,652,654],{"class":179,"line":198},[177,648,184],{"class":183},[177,650,651],{"class":187}," {Halo} ",[177,653,191],{"class":183},[177,655,656],{"class":194}," '.\u002Fhalo'\n",[177,658,659],{"class":179,"line":205},[177,660,202],{"emptyLinePlaceholder":201},[177,662,663,666,669],{"class":179,"line":228},[177,664,665],{"class":187},"\u003C",[177,667,668],{"class":214},"Shader",[177,670,671],{"class":187},">\n",[177,673,674,677,680,683,686,689,692],{"class":179,"line":244},[177,675,676],{"class":187},"  \u003C",[177,678,679],{"class":214},"Blur",[177,681,682],{"class":221}," intensity",[177,684,685],{"class":183},"=",[177,687,688],{"class":187},"{",[177,690,691],{"class":214},"8",[177,693,694],{"class":187},"}>\n",[177,696,697,700,703,706,708,711,714,716,718,721],{"class":179,"line":253},[177,698,699],{"class":187},"    \u003C",[177,701,702],{"class":214},"CustomShader",[177,704,705],{"class":221}," src",[177,707,685],{"class":183},[177,709,710],{"class":187},"{Halo} ",[177,712,713],{"class":221},"radius",[177,715,685],{"class":183},[177,717,688],{"class":187},[177,719,720],{"class":214},"0.8",[177,722,723],{"class":187},"} \u002F>\n",[177,725,726,729,731],{"class":179,"line":265},[177,727,728],{"class":187},"  \u003C\u002F",[177,730,679],{"class":214},[177,732,671],{"class":187},[177,734,735,738,740],{"class":179,"line":282},[177,736,737],{"class":187},"\u003C\u002F",[177,739,668],{"class":214},[177,741,671],{"class":187},[168,743,745],{"className":170,"code":744,"language":172,"meta":173,"style":173},"import {defineShader, wgsl, registerShader, …} from 'shaders\u002Fstd'\n",[8,746,747],{"__ignoreMap":173},[177,748,749,751,754,756],{"class":179,"line":180},[177,750,184],{"class":183},[177,752,753],{"class":187}," {defineShader, wgsl, registerShader, …} ",[177,755,191],{"class":183},[177,757,195],{"class":194},[759,760,762],"h2",{"id":761},"reach-for-it-when","Reach for it when",[345,764,765,775],{},[348,766,767],{},[351,768,769,772],{},[354,770,771],{},"When you need",[354,773,774],{},"Use",[364,776,777,788,805,819,842,858,871,888],{},[351,778,779,782],{},[369,780,781],{},"a shader of your own, from a plain object",[369,783,784],{},[160,785,786],{"href":162},[8,787,165],{},[351,789,790,793],{},[369,791,792],{},"per-pixel math you want to write by hand",[369,794,795,799,800,802,803],{},[160,796,797],{"href":529},[8,798,306],{}," in ",[8,801,373],{}," or ",[8,804,386],{},[351,806,807,810],{},[369,808,809],{},"a generator that paints from coordinates",[369,811,812,816,817],{},[160,813,814],{"href":162},[8,815,165],{}," with ",[8,818,373],{},[351,820,821,824],{},[369,822,823],{},"a filter over the layer nested inside",[369,825,826,816,830,832,833,836,837,841],{},[160,827,828],{"href":162},[8,829,165],{},[8,831,386],{}," holding a color word, ",[8,834,835],{},"tintToward",", or a ",[160,838,839],{"href":529},[8,840,306],{}," body that reads child",[351,843,844,847],{},[369,845,846],{},"a filter that reads neighbouring pixels (blur, ripple, mosaic)",[369,848,849,850,854,855],{},"a ",[160,851,852],{"href":529},[8,853,306],{}," body that samples childTexture, or ",[8,856,857],{},"gather",[351,859,860,863],{},[369,861,862],{},"a distortion from one coordinate function",[369,864,865,816,869],{},[160,866,867],{"href":162},[8,868,165],{},[8,870,406],{},[351,872,873,879],{},[369,874,875,876],{},"naming your shader in preset JSON for ",[8,877,878],{},"createShader",[369,880,881,887],{},[160,882,884],{"href":883},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fregistershader",[8,885,886],{},"registerShader",", or the components option",[351,889,890,893],{},[369,891,892],{},"listing the custom shaders an app has registered",[369,894,895,540,901],{},[160,896,898],{"href":897},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fgetregisteredshaders",[8,899,900],{},"getRegisteredShaders",[160,902,904],{"href":903},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fonshaderregistered",[8,905,906],{},"onShaderRegistered",[759,908,910],{"id":909},"example","Example",[168,912,914],{"className":170,"code":913,"language":172,"meta":173,"style":173},"import {defineShader, wgsl, transformColor, transformPosition} from 'shaders\u002Fstd'\n\n\u002F\u002F A generator: concentric color bands radiating from a draggable point, on its own clock.\nexport const Halo = defineShader({\n  name: 'Halo',\n  description: 'Concentric color bands radiating from a point.',\n  animatedTime: {speed: 'speed'},\n  props: {\n    inner: {default: '#ffd166', transform: transformColor, ui: {type: 'color', label: 'Inner'}},\n    outer: {default: '#0b132b', transform: transformColor, ui: {type: 'color', label: 'Outer'}},\n    center: {default: {x: 0.5, y: 0.5}, transform: transformPosition, ui: {type: 'position', label: 'Center'}},\n    radius: {default: 0.6, ui: {type: 'range', min: 0.1, max: 1.5, step: 0.01, label: 'Radius'}},\n    bands: {default: 4, ui: {type: 'range', min: 1, max: 16, step: 1, label: 'Bands'}},\n    speed: {default: 1, ui: {type: 'range', min: 0, max: 4, step: 0.1, label: 'Speed'}},\n  },\n  paint: wgsl`\n    let q = (uv - center) * vec2f(aspect, 1.0);\n    let d = length(q) \u002F radius;\n    let wave = 0.5 + 0.5 * cos(d * bands * 6.2831853 - time * 2.0);\n    let fade = 1.0 - smoothstep(0.7, 1.0, d);\n    return vec4f(mix(outer.rgb, inner.rgb, wave * fade), 1.0);\n  `,\n})\n",[8,915,916,927,931,936,950,958,968,978,983,1005,1024,1047,1084,1116,1146,1151,1160,1166,1172,1178,1184,1190,1197],{"__ignoreMap":173},[177,917,918,920,923,925],{"class":179,"line":180},[177,919,184],{"class":183},[177,921,922],{"class":187}," {defineShader, wgsl, transformColor, transformPosition} ",[177,924,191],{"class":183},[177,926,195],{"class":194},[177,928,929],{"class":179,"line":198},[177,930,202],{"emptyLinePlaceholder":201},[177,932,933],{"class":179,"line":205},[177,934,935],{"class":240},"\u002F\u002F A generator: concentric color bands radiating from a draggable point, on its own clock.\n",[177,937,938,940,942,944,946,948],{"class":179,"line":228},[177,939,208],{"class":183},[177,941,211],{"class":183},[177,943,215],{"class":214},[177,945,218],{"class":183},[177,947,222],{"class":221},[177,949,225],{"class":187},[177,951,952,954,956],{"class":179,"line":244},[177,953,231],{"class":187},[177,955,234],{"class":194},[177,957,330],{"class":187},[177,959,960,963,966],{"class":179,"line":253},[177,961,962],{"class":187},"  description: ",[177,964,965],{"class":194},"'Concentric color bands radiating from a point.'",[177,967,330],{"class":187},[177,969,970,973,976],{"class":179,"line":265},[177,971,972],{"class":187},"  animatedTime: {speed: ",[177,974,975],{"class":194},"'speed'",[177,977,291],{"class":187},[177,979,980],{"class":179,"line":282},[177,981,982],{"class":187},"  props: {\n",[177,984,985,988,990,993,996,999,1002],{"class":179,"line":294},[177,986,987],{"class":187},"    inner: {default: ",[177,989,259],{"class":194},[177,991,992],{"class":187},", transform: transformColor, ui: {type: ",[177,994,995],{"class":194},"'color'",[177,997,998],{"class":187},", label: ",[177,1000,1001],{"class":194},"'Inner'",[177,1003,1004],{"class":187},"}},\n",[177,1006,1007,1010,1013,1015,1017,1019,1022],{"class":179,"line":300},[177,1008,1009],{"class":187},"    outer: {default: ",[177,1011,1012],{"class":194},"'#0b132b'",[177,1014,992],{"class":187},[177,1016,995],{"class":194},[177,1018,998],{"class":187},[177,1020,1021],{"class":194},"'Outer'",[177,1023,1004],{"class":187},[177,1025,1026,1028,1030,1032,1034,1037,1040,1042,1045],{"class":179,"line":312},[177,1027,268],{"class":187},[177,1029,271],{"class":214},[177,1031,274],{"class":187},[177,1033,271],{"class":214},[177,1035,1036],{"class":187},"}, transform: transformPosition, ui: {type: ",[177,1038,1039],{"class":194},"'position'",[177,1041,998],{"class":187},[177,1043,1044],{"class":194},"'Center'",[177,1046,1004],{"class":187},[177,1048,1049,1051,1053,1056,1059,1062,1065,1068,1071,1074,1077,1079,1082],{"class":179,"line":318},[177,1050,285],{"class":187},[177,1052,288],{"class":214},[177,1054,1055],{"class":187},", ui: {type: ",[177,1057,1058],{"class":194},"'range'",[177,1060,1061],{"class":187},", min: ",[177,1063,1064],{"class":214},"0.1",[177,1066,1067],{"class":187},", max: ",[177,1069,1070],{"class":214},"1.5",[177,1072,1073],{"class":187},", step: ",[177,1075,1076],{"class":214},"0.01",[177,1078,998],{"class":187},[177,1080,1081],{"class":194},"'Radius'",[177,1083,1004],{"class":187},[177,1085,1086,1089,1092,1094,1096,1098,1100,1102,1105,1107,1109,1111,1114],{"class":179,"line":324},[177,1087,1088],{"class":187},"    bands: {default: ",[177,1090,1091],{"class":214},"4",[177,1093,1055],{"class":187},[177,1095,1058],{"class":194},[177,1097,1061],{"class":187},[177,1099,480],{"class":214},[177,1101,1067],{"class":187},[177,1103,1104],{"class":214},"16",[177,1106,1073],{"class":187},[177,1108,480],{"class":214},[177,1110,998],{"class":187},[177,1112,1113],{"class":194},"'Bands'",[177,1115,1004],{"class":187},[177,1117,1118,1121,1123,1125,1127,1129,1131,1133,1135,1137,1139,1141,1144],{"class":179,"line":333},[177,1119,1120],{"class":187},"    speed: {default: ",[177,1122,480],{"class":214},[177,1124,1055],{"class":187},[177,1126,1058],{"class":194},[177,1128,1061],{"class":187},[177,1130,486],{"class":214},[177,1132,1067],{"class":187},[177,1134,1091],{"class":214},[177,1136,1073],{"class":187},[177,1138,1064],{"class":214},[177,1140,998],{"class":187},[177,1142,1143],{"class":194},"'Speed'",[177,1145,1004],{"class":187},[177,1147,1149],{"class":179,"line":1148},15,[177,1150,297],{"class":187},[177,1152,1154,1156,1158],{"class":179,"line":1153},16,[177,1155,303],{"class":187},[177,1157,306],{"class":221},[177,1159,570],{"class":194},[177,1161,1163],{"class":179,"line":1162},17,[177,1164,1165],{"class":194},"    let q = (uv - center) * vec2f(aspect, 1.0);\n",[177,1167,1169],{"class":179,"line":1168},18,[177,1170,1171],{"class":194},"    let d = length(q) \u002F radius;\n",[177,1173,1175],{"class":179,"line":1174},19,[177,1176,1177],{"class":194},"    let wave = 0.5 + 0.5 * cos(d * bands * 6.2831853 - time * 2.0);\n",[177,1179,1181],{"class":179,"line":1180},20,[177,1182,1183],{"class":194},"    let fade = 1.0 - smoothstep(0.7, 1.0, d);\n",[177,1185,1187],{"class":179,"line":1186},21,[177,1188,1189],{"class":194},"    return vec4f(mix(outer.rgb, inner.rgb, wave * fade), 1.0);\n",[177,1191,1193,1195],{"class":179,"line":1192},22,[177,1194,327],{"class":194},[177,1196,330],{"class":187},[177,1198,1200],{"class":179,"line":1199},23,[177,1201,336],{"class":187},[759,1203,1205],{"id":1204},"types","Types",[345,1207,1208,1218],{},[348,1209,1210],{},[351,1211,1212,1215],{},[354,1213,1214],{},"Type",[354,1216,1217],{},"What it is",[364,1219,1220,1230,1240,1262,1283,1301,1319,1332,1361,1386,1399,1422,1448,1464,1477,1490,1513,1528,1557,1570],{},[351,1221,1222,1227],{},[369,1223,1224],{},[8,1225,1226],{},"DisplaceByEffectRef",[369,1228,1229],{},"A filter that moves the layer inside by a simulation's vector field.",[351,1231,1232,1237],{},[369,1233,1234],{},[8,1235,1236],{},"GatherEffect",[369,1238,1239],{},"A filter that reads the layer inside anywhere, not just at this pixel: blurs, halftones, displacements.",[351,1241,1242,1247],{},[369,1243,1244],{},[8,1245,1246],{},"IdentityRule",[369,1248,1249,1250,540,1253,540,1256,802,1259,622],{},"When a filter does nothing and can be skipped: built with ",[8,1251,1252],{},"isZero",[8,1254,1255],{},"isValue",[8,1257,1258],{},"allOf",[8,1260,1261],{},"identityWhenever",[351,1263,1264,1269],{},[369,1265,1266],{},[8,1267,1268],{},"PointwiseEffect",[369,1270,1271,1272,540,1275,1278,1279,1282],{},"A filter that edits the layer inside one pixel at a time: what the color words (",[8,1273,1274],{},"saturate",[8,1276,1277],{},"hueRotate",", …) and ",[8,1280,1281],{},"pointwise({build})"," return.",[351,1284,1285,1290],{},[369,1286,1287],{},[8,1288,1289],{},"RecompileRule",[369,1291,1292,1293,1296,1297,1300],{},"When a prop change rebuilds the shader: ",[8,1294,1295],{},"crosses(value)"," at a threshold, or ",[8,1298,1299],{},"recompileWhen(fn)"," by your own test.",[351,1302,1303,1308],{},[369,1304,1305],{},[8,1306,1307],{},"StdCustomDefinition",[369,1309,1310,1311,1314,1315,1318],{},"A raw builder: ",[8,1312,1313],{},"gpu:"," holds a fragment function (and optionally a ",[8,1316,1317],{},"uvRemap",") for effects the words cannot say yet.",[351,1320,1321,1326],{},[369,1322,1323],{},[8,1324,1325],{},"StdDefinition",[369,1327,1328,1329,1331],{},"What ",[8,1330,165],{}," accepts: one of the definition shapes, told apart by which field carries the per-pixel work.",[351,1333,1334,1339],{},[369,1335,1336],{},[8,1337,1338],{},"StdDefinitionBase",[369,1340,1341,1342,540,1345,1348,1349,1352,1353,1356,1357,1360],{},"The fields every definition shares: ",[8,1343,1344],{},"name",[8,1346,1347],{},"props",", optional ",[8,1350,1351],{},"description"," and ",[8,1354,1355],{},"category",", the ",[8,1358,1359],{},"animatedTime"," clock, and engine flags.",[351,1362,1363,1368],{},[369,1364,1365],{},[8,1366,1367],{},"StdGatherFilterDefinition",[369,1369,1370,1371,1373,1374,540,1377,1380,1381,1383,1384,622],{},"A filter that reads the layer inside anywhere: ",[8,1372,386],{}," holds ",[8,1375,1376],{},"gather({…})",[8,1378,1379],{},"displaceBy(…)"," or a ",[8,1382,306],{}," body that samples ",[8,1385,399],{},[351,1387,1388,1393],{},[369,1389,1390],{},[8,1391,1392],{},"StdGeneratorDefinition",[369,1394,1395,1396,1398],{},"A generator: ",[8,1397,373],{}," produces a color from coordinates and needs nothing nested inside.",[351,1400,1401,1406],{},[369,1402,1403],{},[8,1404,1405],{},"StdPointwiseFilterDefinition",[369,1407,1408,1409,1411,1412,540,1414,1380,1417,1419,1420,622],{},"A filter that edits the layer inside one pixel at a time: ",[8,1410,386],{}," holds a color word, ",[8,1413,835],{},[8,1415,1416],{},"pointwise({…})",[8,1418,306],{}," body that reads ",[8,1421,395],{},[351,1423,1424,1429],{},[369,1425,1426],{},[8,1427,1428],{},"StdPropConfig",[369,1430,1431,1432,1348,1434,540,1436,540,1438,540,1440,1443,1444,1447],{},"One prop of a definition: ",[8,1433,588],{},[8,1435,592],{},[8,1437,603],{},[8,1439,1351],{},[8,1441,1442],{},"compileTime",", and a ",[8,1445,1446],{},"recompile:"," rule.",[351,1449,1450,1455],{},[369,1451,1452],{},[8,1453,1454],{},"StdProps",[369,1456,1457,1458,1460,1461,1463],{},"The ",[8,1459,1347],{}," object of a definition: one ",[8,1462,1428],{}," per prop name.",[351,1465,1466,1471],{},[369,1467,1468],{},[8,1469,1470],{},"StdShapeDefinition",[369,1472,1473,1474,1476],{},"A 2D shape: ",[8,1475,419],{}," gives the distance function and the shape's own props; fill, stroke, softness and bounds come for free.",[351,1478,1479,1484],{},[369,1480,1481],{},[8,1482,1483],{},"StdWarpDefinition",[369,1485,1486,1487,1489],{},"A distortion: ",[8,1488,406],{}," is one function from the pixel's coordinate to where in the layer inside to read.",[351,1491,1492,1497],{},[369,1493,1494],{},[8,1495,1496],{},"StdWgslFilterDefinition",[369,1498,1499,1500,1502,1503,1505,1506,1509,1510,1512],{},"A filter whose ",[8,1501,386],{}," is a ",[8,1504,306],{}," body with no ",[8,1507,1508],{},"species"," declared: gather when the body samples ",[8,1511,399],{},", pointwise otherwise.",[351,1514,1515,1520],{},[369,1516,1517],{},[8,1518,1519],{},"WgslHost",[369,1521,1522,1523,1525,1526,622],{},"Where a body runs: a generator's ",[8,1524,373],{},", or a pointwise or gather filter's ",[8,1527,386],{},[351,1529,1530,1535],{},[369,1531,1532],{},[8,1533,1534],{},"WgslInput",[369,1536,1537,1538,1541,1542,1545,1546,1549,1550,1553,1554,622],{},"One entry of ",[8,1539,1540],{},"inputs",": the value to bind under a name — a prop ",[8,1543,1544],{},"p('x')",", a context token ",[8,1547,1548],{},"ctx.time",", a ",[8,1551,1552],{},"Scalar",", or a number — optionally with its WGSL type spelled out as ",[8,1555,1556],{},"{value, type}",[351,1558,1559,1564],{},[369,1560,1561],{},[8,1562,1563],{},"WgslSpec",[369,1565,1566,1567,622],{},"The long form of a body: ",[8,1568,1569],{},"wgsl({body, inputs, alpha, name})",[351,1571,1572,1577],{},[369,1573,1574],{},[8,1575,1576],{},"WgslType",[369,1578,1579],{},"The WGSL types a bound name can have inside a body.",[759,1581,1583],{"id":1582},"words","Words",[1585,1586,1588],"primitive-words",{":words":1587},"[{\"name\":\"defineShader\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fdefineshader\",\"summary\":\"Define a shader component from a plain object: its props, and one field that says what it draws.\"},{\"name\":\"wgsl\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fwgsl\",\"summary\":\"Write the per-pixel math by hand, as one WGSL function body that returns a `vec4f` color.\"},{\"name\":\"registerShader\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fregistershader\",\"summary\":\"Make a user-defined shader findable by its `name`, so preset JSON can reference it as `type: 'Halo'`.\"},{\"name\":\"unregisterShader\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Funregistershader\",\"summary\":\"Forget a user-defined shader by name.\"},{\"name\":\"getRegisteredShader\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fgetregisteredshader\",\"summary\":\"Look up a user-defined shader by name.\"},{\"name\":\"getRegisteredShaders\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fgetregisteredshaders\",\"summary\":\"Every user-defined shader currently registered, oldest first.\"},{\"name\":\"onShaderRegistered\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fonshaderregistered\",\"summary\":\"Be told when a user-defined shader is registered, replaced or removed.\"},{\"name\":\"WgslBody\",\"path\":\"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fwgslbody\",\"summary\":\"What `wgsl` returns: a body ready to sit in `paint:` or `effect:`.\"}]",[1589,1590,1591,1599,1609,1621,1630,1639,1646,1653],"ul",{},[1592,1593,1594,1598],"li",{},[160,1595,1596],{"href":162},[8,1597,165],{}," — Define a shader component from a plain object: its props, and one field that says what it draws.",[1592,1600,1601,1605,1606,1608],{},[160,1602,1603],{"href":529},[8,1604,306],{}," — Write the per-pixel math by hand, as one WGSL function body that returns a ",[8,1607,535],{}," color.",[1592,1610,1611,1615,1616,1618,1619,622],{},[160,1612,1613],{"href":883},[8,1614,886],{}," — Make a user-defined shader findable by its ",[8,1617,1344],{},", so preset JSON can reference it as ",[8,1620,621],{},[1592,1622,1623,1629],{},[160,1624,1626],{"href":1625},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Funregistershader",[8,1627,1628],{},"unregisterShader"," — Forget a user-defined shader by name.",[1592,1631,1632,1638],{},[160,1633,1635],{"href":1634},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fgetregisteredshader",[8,1636,1637],{},"getRegisteredShader"," — Look up a user-defined shader by name.",[1592,1640,1641,1645],{},[160,1642,1643],{"href":897},[8,1644,900],{}," — Every user-defined shader currently registered, oldest first.",[1592,1647,1648,1652],{},[160,1649,1650],{"href":903},[8,1651,906],{}," — Be told when a user-defined shader is registered, replaced or removed.",[1592,1654,1655,1661,1662,1664,1665,802,1667,622],{},[160,1656,1658],{"href":1657},"\u002Fdocs\u002Fprimitives\u002Fdefine\u002Fwgslbody",[8,1659,1660],{},"WgslBody"," — What ",[8,1663,306],{}," returns: a body ready to sit in ",[8,1666,373],{},[8,1668,386],{},[1670,1671,1672],"style",{},"html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":173,"searchDepth":198,"depth":198,"links":1674},[1675,1676,1677,1678],{"id":761,"depth":198,"text":762},{"id":909,"depth":198,"text":910},{"id":1204,"depth":198,"text":1205},{"id":1582,"depth":198,"text":1583},"define","A shader is a plain object: a name, the props a user can set, and one field that says what it draws.","https:\u002F\u002Fgithub.com\u002Fshader-effects-inc\u002Fshaders\u002Fedit\u002Fmain\u002Fpackages\u002Fcore\u002Fdocs\u002Fstd\u002Fdefine.md","md","Defining a shader",{},"\u002Fdocs\u002Fprimitives\u002Fdefine",{"title":147,"description":1680},"https:\u002F\u002Fgithub.com\u002Fshader-effects-inc\u002Fshaders\u002Fblob\u002Fmain\u002Fpackages\u002Fcore\u002Fsrc\u002Fstd\u002Flower.ts","docs\u002Fprimitives\u002F1.define\u002Findex","Aq6qh7PFZqQdXTXtiIql7ANtg2ARKkpMNRdobQH_FNs"]