[{"data":1,"prerenderedAt":2839},["ShallowReactive",2],{"navigation":3,"\u002Fapi\u002Fadvanced\u002Ftsl-composables":265,"\u002Fapi\u002Fadvanced\u002Ftsl-composables-surround":2834},[4,29,78,181,199,231,241,245,249,253,257,261],{"title":5,"path":6,"stem":7,"children":8,"icon":27,"titleTemplate":28},"Getting Started","\u002Fgetting-started","1.getting-started\u002F1.index",[9,12,17,22],{"title":10,"path":6,"stem":7,"icon":11},"Introduction","i-lucide-house",{"title":13,"path":14,"stem":15,"icon":16},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F2.installation","i-lucide-download",{"title":18,"path":19,"stem":20,"icon":21},"Your First Scene","\u002Fgetting-started\u002Fyour-first-scene","1.getting-started\u002F3.your-first-scene","i-lucide-donut",{"title":23,"path":24,"stem":25,"icon":26},"Upgrade Guide","\u002Fgetting-started\u002Fupgrade-guide","1.getting-started\u002F4.upgrade-guide","i-lucide-circle-arrow-up","i-lucide-rocket","%s · Get Started with TresJS",{"title":30,"path":31,"stem":32,"children":33},"Essentials","\u002Fessentials","2.essentials",[34,36,48],{"title":30,"path":31,"stem":35},"2.essentials\u002Findex",{"title":37,"icon":38,"open":39,"path":40,"stem":41,"children":42,"page":47},"Core Architecture","i-lucide-cpu",true,"\u002Fessentials\u002Fcore-architecture","2.essentials\u002F1.core-architecture",[43],{"title":44,"path":45,"stem":46},"Custom Vue Renderer","\u002Fessentials\u002Fcore-architecture\u002Fcustom-vue-renderer","2.essentials\u002F1.core-architecture\u002F2.custom-vue-renderer",false,{"title":49,"icon":50,"open":39,"path":51,"stem":52,"children":53,"page":47},"Key Concepts","i-lucide-medal","\u002Fessentials\u002Fconcepts","2.essentials\u002F2.concepts",[54,58,62,66,70,74],{"title":55,"path":56,"stem":57},"Declarative vs Imperative","\u002Fessentials\u002Fconcepts\u002Fdeclarative-vs-imperative","2.essentials\u002F2.concepts\u002F1.declarative-vs-imperative",{"title":59,"path":60,"stem":61},"Reactivity","\u002Fessentials\u002Fconcepts\u002Freactivity","2.essentials\u002F2.concepts\u002F2.reactivity",{"title":63,"path":64,"stem":65},"Constructor Arguments","\u002Fessentials\u002Fconcepts\u002Fconstructor-arguments","2.essentials\u002F2.concepts\u002F3.constructor-arguments",{"title":67,"path":68,"stem":69},"Declarative Properties","\u002Fessentials\u002Fconcepts\u002Fdeclarative-properties","2.essentials\u002F2.concepts\u002F4.declarative-properties",{"title":71,"path":72,"stem":73},"Extending the Catalogue","\u002Fessentials\u002Fconcepts\u002Fextending-catalogue","2.essentials\u002F2.concepts\u002F5.extending-catalogue",{"title":75,"path":76,"stem":77},"Child Attachments","\u002Fessentials\u002Fconcepts\u002Fchild-attachments","2.essentials\u002F2.concepts\u002F6.child-attachments",{"title":79,"path":80,"stem":81,"children":82},"API","\u002Fapi","3.api",[83,86,108,135,145,159],{"title":84,"path":80,"stem":85},"TresJS API Reference","3.api\u002F1.index",{"title":87,"icon":88,"open":39,"path":89,"stem":90,"children":91,"page":47},"Components","i-lucide-box","\u002Fapi\u002Fcomponents","3.api\u002F1.components",[92,96,100,104],{"title":93,"path":94,"stem":95},"\u003CTresCanvas \u002F>","\u002Fapi\u002Fcomponents\u002Ftres-canvas","3.api\u002F1.components\u002Ftres-canvas",{"title":97,"path":98,"stem":99},"\u003CTresCanvasContext \u002F>","\u002Fapi\u002Fcomponents\u002Ftres-context","3.api\u002F1.components\u002Ftres-context",{"title":101,"path":102,"stem":103},"Tres Components","\u002Fapi\u002Fcomponents\u002Ftres-objects","3.api\u002F1.components\u002Ftres-objects",{"title":105,"path":106,"stem":107},"TresPortal","\u002Fapi\u002Fcomponents\u002Ftres-portal","3.api\u002F1.components\u002Ftres-portal",{"title":109,"titleTemplate":110,"icon":111,"path":112,"stem":113,"children":114,"page":47},"Composables","%s · TresJS Composables","i-lucide-arrow-right-left","\u002Fapi\u002Fcomposables","3.api\u002F2.composables",[115,119,123,127,131],{"title":116,"path":117,"stem":118},"useTres","\u002Fapi\u002Fcomposables\u002Fuse-tres","3.api\u002F2.composables\u002F1.use-tres",{"title":120,"path":121,"stem":122},"useTresContext","\u002Fapi\u002Fcomposables\u002Fuse-tres-context","3.api\u002F2.composables\u002F2.use-tres-context",{"title":124,"path":125,"stem":126},"useLoop","\u002Fapi\u002Fcomposables\u002Fuse-loop","3.api\u002F2.composables\u002F3.use-loop",{"title":128,"path":129,"stem":130},"useGraph","\u002Fapi\u002Fcomposables\u002Fuse-graph","3.api\u002F2.composables\u002F4.use-graph",{"title":132,"path":133,"stem":134},"useLoader","\u002Fapi\u002Fcomposables\u002Fuse-loader","3.api\u002F2.composables\u002F5.use-loader",{"title":136,"icon":137,"path":138,"stem":139,"children":140,"page":47},"Event handling","i-lucide-mouse-pointer-2","\u002Fapi\u002Fevents","3.api\u002F3.events",[141],{"title":142,"path":143,"stem":144},"Pointer Events","\u002Fapi\u002Fevents\u002Fpointer-events","3.api\u002F3.events\u002F1.pointer-events",{"title":146,"icon":147,"path":148,"stem":149,"children":150,"page":47},"Utils","i-lucide-wrench","\u002Fapi\u002Futils","3.api\u002F4.utils",[151,155],{"title":152,"path":153,"stem":154},"Type Guards","\u002Fapi\u002Futils\u002Ftype-guards","3.api\u002F4.utils\u002F1.type-guards",{"title":156,"path":157,"stem":158},"Directives","\u002Fapi\u002Futils\u002Fdirectives","3.api\u002F4.utils\u002F2.directives",{"title":160,"icon":161,"path":162,"stem":163,"children":164,"page":47},"Advanced","i-lucide-brain-circuit","\u002Fapi\u002Fadvanced","3.api\u002F5.advanced",[165,169,173,177],{"title":166,"path":167,"stem":168},"Scaling Performance 🚀","\u002Fapi\u002Fadvanced\u002Fperformance","3.api\u002F5.advanced\u002Fperformance",{"title":170,"path":171,"stem":172},"Primitives","\u002Fapi\u002Fadvanced\u002Fprimitives","3.api\u002F5.advanced\u002Fprimitives",{"title":174,"path":175,"stem":176},"TSL composables","\u002Fapi\u002Fadvanced\u002Ftsl-composables","3.api\u002F5.advanced\u002Ftsl-composables",{"title":178,"path":179,"stem":180},"WebGPU","\u002Fapi\u002Fadvanced\u002Fweb-gpu","3.api\u002F5.advanced\u002Fweb-gpu",{"title":182,"path":183,"stem":184,"children":185,"icon":188,"titleTemplate":198},"CLI","\u002Fcli","4.cli\u002F1.index",[186,189,194],{"title":187,"path":183,"stem":184,"icon":188},"TresJS CLI","i-lucide-terminal",{"title":190,"path":191,"stem":192,"icon":193},"From model to component","\u002Fcli\u002Ffrom-model-to-component","4.cli\u002F2.from-model-to-component","i-lucide-route",{"title":195,"path":196,"stem":197,"icon":88},"tres gltf","\u002Fcli\u002Fgltf","4.cli\u002F3.gltf","%s · TresJS CLI",{"title":200,"path":201,"stem":202,"children":203},"Cookbook","\u002Fcookbook","5.cookbook",[204,207,211,215,219,223,227],{"title":205,"path":201,"stem":206},"Cookbook 🍳🧑‍🍳","5.cookbook\u002Findex",{"title":208,"path":209,"stem":210},"OrbitControls","\u002Fcookbook\u002Forbit-controls","5.cookbook\u002F1.orbit-controls",{"title":212,"path":213,"stem":214},"Basic Animations","\u002Fcookbook\u002Fbasic-animations","5.cookbook\u002F2.basic-animations",{"title":216,"path":217,"stem":218},"Model Animation","\u002Fcookbook\u002Fmodel-animation","5.cookbook\u002F3.model-animation",{"title":220,"path":221,"stem":222},"Advanced GSAP Animations","\u002Fcookbook\u002Fadvanced-gsap-animations","5.cookbook\u002F4.advanced-gsap-animations",{"title":224,"path":225,"stem":226},"Tweakpane","\u002Fcookbook\u002Ftweakpane","5.cookbook\u002F5.tweakpane",{"title":228,"path":229,"stem":230},"Dynamic components","\u002Fcookbook\u002Ftransition-dynamic","5.cookbook\u002F6.transition-dynamic",{"title":232,"path":233,"stem":234,"children":235},"Community","\u002Fcommunity","6.community\u002F1.index",[236,237],{"title":232,"path":233,"stem":234},{"title":238,"path":239,"stem":240},"Awesome Resources","\u002Fcommunity\u002Fawesome-resources","6.community\u002Fawesome-resources",{"title":242,"path":243,"stem":244},"German Translation","\u002Fde","de",{"title":246,"path":247,"stem":248},"Spanish Translation","\u002Fes","es",{"title":250,"path":251,"stem":252},"French Translation","\u002Ffr","fr",{"title":254,"path":255,"stem":256},"Italian Translation","\u002Fit","it",{"title":258,"path":259,"stem":260},"Japanese Translation","\u002Fjp","jp",{"title":262,"path":263,"stem":264},"Chinese Translation","\u002Fzh","zh",{"id":266,"title":174,"body":267,"description":2828,"extension":2829,"links":2830,"meta":2831,"navigation":39,"path":175,"seo":2832,"stem":176,"__hash__":2833},"docs\u002F3.api\u002F5.advanced\u002Ftsl-composables.md",{"type":268,"value":269,"toc":2808},"minimark",[270,286,299,367,376,381,384,404,407,411,426,471,474,659,662,665,683,686,739,742,839,842,952,966,1064,1067,1078,1083,1131,1137,1140,1198,1201,1220,1223,1416,1419,1466,1489,1493,1500,1515,1522,1535,1540,1543,1642,1676,1683,1687,1701,1716,1719,1890,1893,1990,1994,2004,2239,2242,2245,2442,2445,2468,2471,2510,2514,2601,2608,2614,2695,2699,2744,2747,2779,2782,2804],[271,272,273],"warning",{},[274,275,276,280,281,285],"p",{},[277,278,279],"strong",{},"Experimental",": these composables are in ",[282,283,284],"code",{},"@tresjs\u002Fcore\u002Fwebgpu"," since v5.11. Their API can change in a minor release.",[274,287,288,290,291,298],{},[282,289,284],{}," has four composables for ",[292,293,297],"a",{"href":294,"rel":295},"https:\u002F\u002Fgithub.com\u002Fmrdoob\u002Fthree.js\u002Fwiki\u002FThree.js-Shading-Language",[296],"nofollow","TSL"," work:",[300,301,302,315],"table",{},[303,304,305],"thead",{},[306,307,308,312],"tr",{},[309,310,311],"th",{},"Composable",[309,313,314],{},"Use it for",[316,317,318,333,343,353],"tbody",{},[306,319,320,330],{},[321,322,323,326,327],"td",{},[282,324,325],{},"useUniforms"," \u002F ",[282,328,329],{},"useUniform",[321,331,332],{},"Values. Bind refs, getters or Leches controls to uniforms.",[306,334,335,340],{},[321,336,337],{},[282,338,339],{},"useNodes",[321,341,342],{},"Shared graphs that many components read (noise, functions, varyings). Built once.",[306,344,345,350],{},[321,346,347],{},[282,348,349],{},"useLocalNodes",[321,351,352],{},"The graph of one component, built from shared uniforms and nodes.",[306,354,355,360],{},[321,356,357],{},[282,358,359],{},"useRenderPipeline",[321,361,362,363,366],{},"Post-processing with three's ",[282,364,365],{},"RenderPipeline",".",[274,368,369,370,373,374,366],{},"They work only in components inside a ",[282,371,372],{},"TresCanvas"," from ",[282,375,284],{},[377,378,380],"h2",{"id":379},"values-and-structure","Values and structure",[274,382,383],{},"Keep this rule in mind:",[385,386,387,398],"ul",{},[388,389,390,393,394,397],"li",{},[277,391,392],{},"A value goes in a uniform."," A uniform change writes ",[282,395,396],{},"uniform.value",". Three sends it to the GPU, with no graph rebuild and no shader recompile.",[388,399,400,403],{},[277,401,402],{},"A structure change goes through a rebuild."," A new graph recompiles every material that uses it.",[274,405,406],{},"If a prop changes the color, the strength or the speed, put it in a uniform. Rebuild the graph only when a prop changes its shape: which node to use, or how many times a JavaScript loop runs.",[377,408,410],{"id":409},"the-canvas-store","The canvas store",[274,412,413,414,417,418,421,422,425],{},"Each canvas has one store with three collections: ",[282,415,416],{},"uniforms",", ",[282,419,420],{},"nodes"," and ",[282,423,424],{},"passes",". The store is created when a component first uses a TSL composable.",[385,427,428,434,452,465],{},[388,429,430,433],{},[277,431,432],{},"First registration wins."," When two components register the same name, the second one gets the entry of the first.",[388,435,436,439,440,443,444,447,448,451],{},[277,437,438],{},"Entries live as long as the canvas."," They stay when the component that registered them unmounts, so a uniform or node you register in a ",[282,441,442],{},"v-if"," component stays in the store after it hides. Remove entries with ",[282,445,446],{},"remove*"," or ",[282,449,450],{},"clear*",". Everything is freed when the canvas unmounts.",[388,453,454,457,458,461,462,366],{},[277,455,456],{},"Scopes."," Pass a scope name to keep entries apart (",[282,459,460],{},"useUniforms({ uHealth: 100 }, 'player')","). Read a scoped entry with ",[282,463,464],{},"uniforms.player.uHealth",[388,466,467,470],{},[277,468,469],{},"Raw nodes."," The store never wraps a node in a Vue proxy.",[377,472,325],{"id":473},"useuniforms",[475,476,481],"pre",{"className":477,"code":478,"language":479,"meta":480,"style":480},"language-ts shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","import { useUniforms } from '@tresjs\u002Fcore\u002Fwebgpu'\n\nconst props = defineProps\u003C{ density: number }>()\nconst color = ref('#82dbc5')\n\nconst { uColor, uDensity } = useUniforms({ uColor: color, uDensity: () => props.density }, 'fog')\n","ts","",[282,482,483,515,521,558,585,590],{"__ignoreMap":480},[484,485,488,492,496,500,503,506,509,512],"span",{"class":486,"line":487},"line",1,[484,489,491],{"class":490},"s7zQu","import",[484,493,495],{"class":494},"sMK4o"," {",[484,497,499],{"class":498},"sTEyZ"," useUniforms",[484,501,502],{"class":494}," }",[484,504,505],{"class":490}," from",[484,507,508],{"class":494}," '",[484,510,284],{"class":511},"sfazB",[484,513,514],{"class":494},"'\n",[484,516,518],{"class":486,"line":517},2,[484,519,520],{"emptyLinePlaceholder":39},"\n",[484,522,524,528,531,534,538,541,545,548,552,555],{"class":486,"line":523},3,[484,525,527],{"class":526},"spNyl","const",[484,529,530],{"class":498}," props ",[484,532,533],{"class":494},"=",[484,535,537],{"class":536},"s2Zo4"," defineProps",[484,539,540],{"class":494},"\u003C{",[484,542,544],{"class":543},"swJcz"," density",[484,546,547],{"class":494},":",[484,549,551],{"class":550},"sBMFI"," number",[484,553,554],{"class":494}," }>",[484,556,557],{"class":498},"()\n",[484,559,561,563,566,568,571,574,577,580,582],{"class":486,"line":560},4,[484,562,527],{"class":526},[484,564,565],{"class":498}," color ",[484,567,533],{"class":494},[484,569,570],{"class":536}," ref",[484,572,573],{"class":498},"(",[484,575,576],{"class":494},"'",[484,578,579],{"class":511},"#82dbc5",[484,581,576],{"class":494},[484,583,584],{"class":498},")\n",[484,586,588],{"class":486,"line":587},5,[484,589,520],{"emptyLinePlaceholder":39},[484,591,593,595,597,600,603,606,609,612,614,616,619,621,623,626,628,631,633,636,639,642,644,647,650,652,655,657],{"class":486,"line":592},6,[484,594,527],{"class":526},[484,596,495],{"class":494},[484,598,599],{"class":498}," uColor",[484,601,602],{"class":494},",",[484,604,605],{"class":498}," uDensity ",[484,607,608],{"class":494},"}",[484,610,611],{"class":494}," =",[484,613,499],{"class":536},[484,615,573],{"class":498},[484,617,618],{"class":494},"{",[484,620,599],{"class":543},[484,622,547],{"class":494},[484,624,625],{"class":498}," color",[484,627,602],{"class":494},[484,629,630],{"class":536}," uDensity",[484,632,547],{"class":494},[484,634,635],{"class":494}," ()",[484,637,638],{"class":526}," =>",[484,640,641],{"class":498}," props",[484,643,366],{"class":494},[484,645,646],{"class":498},"density ",[484,648,649],{"class":494},"},",[484,651,508],{"class":494},[484,653,654],{"class":511},"fog",[484,656,576],{"class":494},[484,658,584],{"class":498},[274,660,661],{},"Each value can be a plain value, a ref or a getter. When a ref or getter changes, the uniform value changes. The uniform node stays the same object.",[274,663,664],{},"If the uniform already exists, the call reuses the same node. Who changes its value:",[385,666,667,673],{},[388,668,669,672],{},[277,670,671],{},"The call that created the uniform owns its value."," When that component mounts again (and no other instance of it is mounted), or after a hot update, its new values apply. If a value changes type (a number becomes a color), the uniform gets a new node.",[388,674,675,678,679,682],{},[277,676,677],{},"Other callers do not reset the value."," This includes another component that reuses the name, and a second instance of the same component (for example in a ",[282,680,681],{},"v-for","). A ref or getter they pass still writes its later changes.",[274,684,685],{},"To give each instance its own value, use one scope per instance:",[475,687,689],{"className":477,"code":688,"language":479,"meta":480,"style":480},"useUniforms({ uFlicker: () => props.flicker }, `torch-${props.id}`)\n",[282,690,691],{"__ignoreMap":480},[484,692,693,695,697,699,702,704,706,708,710,712,715,717,720,723,726,729,731,734,737],{"class":486,"line":487},[484,694,325],{"class":536},[484,696,573],{"class":498},[484,698,618],{"class":494},[484,700,701],{"class":536}," uFlicker",[484,703,547],{"class":494},[484,705,635],{"class":494},[484,707,638],{"class":526},[484,709,641],{"class":498},[484,711,366],{"class":494},[484,713,714],{"class":498},"flicker ",[484,716,649],{"class":494},[484,718,719],{"class":494}," `",[484,721,722],{"class":511},"torch-",[484,724,725],{"class":494},"${",[484,727,728],{"class":498},"props",[484,730,366],{"class":494},[484,732,733],{"class":498},"id",[484,735,736],{"class":494},"}`",[484,738,584],{"class":498},[274,740,741],{},"The input is converted to a uniform value:",[300,743,744,754],{},[303,745,746],{},[306,747,748,751],{},[309,749,750],{},"Input",[309,752,753],{},"Uniform value",[316,755,756,769,788,812,824],{},[306,757,758,766],{},[321,759,760,417,763],{},[282,761,762],{},"number",[282,764,765],{},"boolean",[321,767,768],{},"the same",[306,770,771,784],{},[321,772,773,774,417,777,780,781],{},"color string (",[282,775,776],{},"'#ff0000'",[282,778,779],{},"'red'","), ",[282,782,783],{},"Color",[321,785,786],{},[282,787,783],{},[306,789,790,801],{},[321,791,792,417,795,417,798],{},[282,793,794],{},"{ x, y }",[282,796,797],{},"{ x, y, z }",[282,799,800],{},"{ x, y, z, w }",[321,802,803,417,806,417,809],{},[282,804,805],{},"Vector2",[282,807,808],{},"Vector3",[282,810,811],{},"Vector4",[306,813,814,822],{},[321,815,816,417,819],{},[282,817,818],{},"Vector2\u002F3\u002F4",[282,820,821],{},"Matrix3\u002F4",[321,823,768],{},[306,825,826,836],{},[321,827,828,829,417,832,835],{},"TSL node (",[282,830,831],{},"color('#f00')",[282,833,834],{},"vec3(0, 1, 0)",")",[321,837,838],{},"a typed uniform with the node's value",[274,840,841],{},"Leches controls are refs, so they work directly:",[475,843,845],{"className":477,"code":844,"language":479,"meta":480,"style":480},"const { color, amplitude } = useControls({ color: '#82dbc5', amplitude: { value: 0.2, min: 0, max: 1 } })\nuseUniforms({ uColor: color, uAmplitude: amplitude })\n",[282,846,847,925],{"__ignoreMap":480},[484,848,849,851,853,855,857,860,862,864,867,869,871,873,875,877,879,881,883,886,888,890,893,895,899,901,904,906,909,911,914,916,919,921,923],{"class":486,"line":487},[484,850,527],{"class":526},[484,852,495],{"class":494},[484,854,625],{"class":498},[484,856,602],{"class":494},[484,858,859],{"class":498}," amplitude ",[484,861,608],{"class":494},[484,863,611],{"class":494},[484,865,866],{"class":536}," useControls",[484,868,573],{"class":498},[484,870,618],{"class":494},[484,872,625],{"class":543},[484,874,547],{"class":494},[484,876,508],{"class":494},[484,878,579],{"class":511},[484,880,576],{"class":494},[484,882,602],{"class":494},[484,884,885],{"class":543}," amplitude",[484,887,547],{"class":494},[484,889,495],{"class":494},[484,891,892],{"class":543}," value",[484,894,547],{"class":494},[484,896,898],{"class":897},"sbssI"," 0.2",[484,900,602],{"class":494},[484,902,903],{"class":543}," min",[484,905,547],{"class":494},[484,907,908],{"class":897}," 0",[484,910,602],{"class":494},[484,912,913],{"class":543}," max",[484,915,547],{"class":494},[484,917,918],{"class":897}," 1",[484,920,502],{"class":494},[484,922,502],{"class":494},[484,924,584],{"class":498},[484,926,927,929,931,933,935,937,939,941,944,946,948,950],{"class":486,"line":517},[484,928,325],{"class":536},[484,930,573],{"class":498},[484,932,618],{"class":494},[484,934,599],{"class":543},[484,936,547],{"class":494},[484,938,625],{"class":498},[484,940,602],{"class":494},[484,942,943],{"class":543}," uAmplitude",[484,945,547],{"class":494},[484,947,859],{"class":498},[484,949,608],{"class":494},[484,951,584],{"class":498},[274,953,954,955,958,959,962,963,366],{},"A Leches control is a ",[282,956,957],{},"Ref\u003Cany>",", so the uniform bound to it is typed loosely (",[282,960,961],{},"LooseUniformNode","). TSL accepts it as any node. To get the exact type, cast it once: ",[282,964,965],{},"uColor as UniformNode\u003C'color', Color>",[967,968,969,976],"tip",{},[274,970,971,972,975],{},"For a value that changes every frame, write it in ",[282,973,974],{},"onBeforeRender",", not through a ref. This needs no watcher:",[475,977,979],{"className":477,"code":978,"language":479,"meta":480,"style":480},"const { uTime } = useUniforms({ uTime: 0 })\nconst { onBeforeRender } = useLoop()\nonBeforeRender(({ elapsed }) => { uTime.value = elapsed })\n",[282,980,981,1011,1029],{"__ignoreMap":480},[484,982,983,985,987,990,992,994,996,998,1000,1003,1005,1007,1009],{"class":486,"line":487},[484,984,527],{"class":526},[484,986,495],{"class":494},[484,988,989],{"class":498}," uTime ",[484,991,608],{"class":494},[484,993,611],{"class":494},[484,995,499],{"class":536},[484,997,573],{"class":498},[484,999,618],{"class":494},[484,1001,1002],{"class":543}," uTime",[484,1004,547],{"class":494},[484,1006,908],{"class":897},[484,1008,502],{"class":494},[484,1010,584],{"class":498},[484,1012,1013,1015,1017,1020,1022,1024,1027],{"class":486,"line":517},[484,1014,527],{"class":526},[484,1016,495],{"class":494},[484,1018,1019],{"class":498}," onBeforeRender ",[484,1021,608],{"class":494},[484,1023,611],{"class":494},[484,1025,1026],{"class":536}," useLoop",[484,1028,557],{"class":498},[484,1030,1031,1033,1035,1038,1042,1045,1047,1049,1051,1053,1056,1058,1060,1062],{"class":486,"line":523},[484,1032,974],{"class":536},[484,1034,573],{"class":498},[484,1036,1037],{"class":494},"({",[484,1039,1041],{"class":1040},"sHdIc"," elapsed",[484,1043,1044],{"class":494}," })",[484,1046,638],{"class":526},[484,1048,495],{"class":494},[484,1050,1002],{"class":498},[484,1052,366],{"class":494},[484,1054,1055],{"class":498},"value",[484,1057,611],{"class":494},[484,1059,1041],{"class":498},[484,1061,502],{"class":494},[484,1063,584],{"class":498},[274,1065,1066],{},"Destructure the uniforms you use every frame. A read through the returned object goes through two proxies and costs about 200 times more than a read from a variable (about 65 ns).",[274,1068,1069,1070,1073,1074,1077],{},"In ",[282,1071,1072],{},"on-demand"," ",[292,1075,1076],{"href":94},"render mode",", a change from a ref or getter requests a new frame.",[1079,1080,1082],"h3",{"id":1081},"read-uniforms","Read uniforms",[475,1084,1086],{"className":477,"code":1085,"language":479,"meta":480,"style":480},"const fog = useUniforms('fog') \u002F\u002F one scope\nconst all = useUniforms() \u002F\u002F the root entries and every scope\n",[282,1087,1088,1114],{"__ignoreMap":480},[484,1089,1090,1092,1095,1097,1099,1101,1103,1105,1107,1110],{"class":486,"line":487},[484,1091,527],{"class":526},[484,1093,1094],{"class":498}," fog ",[484,1096,533],{"class":494},[484,1098,499],{"class":536},[484,1100,573],{"class":498},[484,1102,576],{"class":494},[484,1104,654],{"class":511},[484,1106,576],{"class":494},[484,1108,1109],{"class":498},") ",[484,1111,1113],{"class":1112},"sHwdD","\u002F\u002F one scope\n",[484,1115,1116,1118,1121,1123,1125,1128],{"class":486,"line":517},[484,1117,527],{"class":526},[484,1119,1120],{"class":498}," all ",[484,1122,533],{"class":494},[484,1124,499],{"class":536},[484,1126,1127],{"class":498},"() ",[484,1129,1130],{"class":1112},"\u002F\u002F the root entries and every scope\n",[274,1132,1133,1134,366],{},"The result is live: it reads the store each time. It is also reactive to entries that are added, replaced or removed, so you can use it in templates and ",[282,1135,1136],{},"computed",[1079,1138,329],{"id":1139},"useuniform",[475,1141,1143],{"className":477,"code":1142,"language":479,"meta":480,"style":480},"const uTime = useUniform('uTime', 0) \u002F\u002F create or reuse a root uniform\nconst same = useUniform('uTime') \u002F\u002F read it. Throws if it does not exist\n",[282,1144,1145,1174],{"__ignoreMap":480},[484,1146,1147,1149,1151,1153,1156,1158,1160,1163,1165,1167,1169,1171],{"class":486,"line":487},[484,1148,527],{"class":526},[484,1150,989],{"class":498},[484,1152,533],{"class":494},[484,1154,1155],{"class":536}," useUniform",[484,1157,573],{"class":498},[484,1159,576],{"class":494},[484,1161,1162],{"class":511},"uTime",[484,1164,576],{"class":494},[484,1166,602],{"class":494},[484,1168,908],{"class":897},[484,1170,1109],{"class":498},[484,1172,1173],{"class":1112},"\u002F\u002F create or reuse a root uniform\n",[484,1175,1176,1178,1181,1183,1185,1187,1189,1191,1193,1195],{"class":486,"line":517},[484,1177,527],{"class":526},[484,1179,1180],{"class":498}," same ",[484,1182,533],{"class":494},[484,1184,1155],{"class":536},[484,1186,573],{"class":498},[484,1188,576],{"class":494},[484,1190,1162],{"class":511},[484,1192,576],{"class":494},[484,1194,1109],{"class":498},[484,1196,1197],{"class":1112},"\u002F\u002F read it. Throws if it does not exist\n",[1079,1199,146],{"id":1200},"utils",[274,1202,1203,1205,1206,417,1209,421,1212,1215,1216,1219],{},[282,1204,325],{}," also returns ",[282,1207,1208],{},"removeUniforms(names, scope?)",[282,1210,1211],{},"clearUniforms(scope?)",[282,1213,1214],{},"rebuildUniforms(scope?)",". ",[282,1217,1218],{},"clearUniforms('root')"," clears only the root entries. With no argument, it clears everything.",[377,1221,339],{"id":1222},"usenodes",[475,1224,1226],{"className":477,"code":1225,"language":479,"meta":480,"style":480},"import { useNodes } from '@tresjs\u002Fcore\u002Fwebgpu'\nimport { Fn, normalLocal, positionLocal, sin } from 'three\u002Ftsl'\n\nuseNodes(({ uniforms }) => {\n  const { uAmplitude, uFrequency } = uniforms.wave\n  return {\n    wave: positionLocal.add(normalLocal.mul(sin(positionLocal.y.mul(uFrequency)).mul(uAmplitude))),\n  }\n})\n",[282,1227,1228,1247,1282,1286,1304,1329,1336,1403,1409],{"__ignoreMap":480},[484,1229,1230,1232,1234,1237,1239,1241,1243,1245],{"class":486,"line":487},[484,1231,491],{"class":490},[484,1233,495],{"class":494},[484,1235,1236],{"class":498}," useNodes",[484,1238,502],{"class":494},[484,1240,505],{"class":490},[484,1242,508],{"class":494},[484,1244,284],{"class":511},[484,1246,514],{"class":494},[484,1248,1249,1251,1253,1256,1258,1261,1263,1266,1268,1271,1273,1275,1277,1280],{"class":486,"line":517},[484,1250,491],{"class":490},[484,1252,495],{"class":494},[484,1254,1255],{"class":498}," Fn",[484,1257,602],{"class":494},[484,1259,1260],{"class":498}," normalLocal",[484,1262,602],{"class":494},[484,1264,1265],{"class":498}," positionLocal",[484,1267,602],{"class":494},[484,1269,1270],{"class":498}," sin",[484,1272,502],{"class":494},[484,1274,505],{"class":490},[484,1276,508],{"class":494},[484,1278,1279],{"class":511},"three\u002Ftsl",[484,1281,514],{"class":494},[484,1283,1284],{"class":486,"line":523},[484,1285,520],{"emptyLinePlaceholder":39},[484,1287,1288,1290,1292,1294,1297,1299,1301],{"class":486,"line":560},[484,1289,339],{"class":536},[484,1291,573],{"class":498},[484,1293,1037],{"class":494},[484,1295,1296],{"class":1040}," uniforms",[484,1298,1044],{"class":494},[484,1300,638],{"class":526},[484,1302,1303],{"class":494}," {\n",[484,1305,1306,1309,1311,1313,1315,1318,1320,1322,1324,1326],{"class":486,"line":587},[484,1307,1308],{"class":526},"  const",[484,1310,495],{"class":494},[484,1312,943],{"class":498},[484,1314,602],{"class":494},[484,1316,1317],{"class":498}," uFrequency",[484,1319,502],{"class":494},[484,1321,611],{"class":494},[484,1323,1296],{"class":498},[484,1325,366],{"class":494},[484,1327,1328],{"class":498},"wave\n",[484,1330,1331,1334],{"class":486,"line":592},[484,1332,1333],{"class":490},"  return",[484,1335,1303],{"class":494},[484,1337,1339,1342,1344,1346,1348,1351,1353,1356,1358,1361,1363,1366,1368,1371,1373,1376,1378,1380,1382,1385,1388,1390,1392,1394,1397,1400],{"class":486,"line":1338},7,[484,1340,1341],{"class":543},"    wave",[484,1343,547],{"class":494},[484,1345,1265],{"class":498},[484,1347,366],{"class":494},[484,1349,1350],{"class":536},"add",[484,1352,573],{"class":543},[484,1354,1355],{"class":498},"normalLocal",[484,1357,366],{"class":494},[484,1359,1360],{"class":536},"mul",[484,1362,573],{"class":543},[484,1364,1365],{"class":536},"sin",[484,1367,573],{"class":543},[484,1369,1370],{"class":498},"positionLocal",[484,1372,366],{"class":494},[484,1374,1375],{"class":498},"y",[484,1377,366],{"class":494},[484,1379,1360],{"class":536},[484,1381,573],{"class":543},[484,1383,1384],{"class":498},"uFrequency",[484,1386,1387],{"class":543},"))",[484,1389,366],{"class":494},[484,1391,1360],{"class":536},[484,1393,573],{"class":543},[484,1395,1396],{"class":498},"uAmplitude",[484,1398,1399],{"class":543},")))",[484,1401,1402],{"class":494},",\n",[484,1404,1406],{"class":486,"line":1405},8,[484,1407,1408],{"class":494},"  }\n",[484,1410,1412,1414],{"class":486,"line":1411},9,[484,1413,608],{"class":494},[484,1415,584],{"class":498},[274,1417,1418],{},"Other components read the same node object:",[475,1420,1422],{"className":477,"code":1421,"language":479,"meta":480,"style":480},"const { wave } = useNodes()\nconst fx = useNodes('player') \u002F\u002F a scope\n",[282,1423,1424,1441],{"__ignoreMap":480},[484,1425,1426,1428,1430,1433,1435,1437,1439],{"class":486,"line":487},[484,1427,527],{"class":526},[484,1429,495],{"class":494},[484,1431,1432],{"class":498}," wave ",[484,1434,608],{"class":494},[484,1436,611],{"class":494},[484,1438,1236],{"class":536},[484,1440,557],{"class":498},[484,1442,1443,1445,1448,1450,1452,1454,1456,1459,1461,1463],{"class":486,"line":517},[484,1444,527],{"class":526},[484,1446,1447],{"class":498}," fx ",[484,1449,533],{"class":494},[484,1451,1236],{"class":536},[484,1453,573],{"class":498},[484,1455,576],{"class":494},[484,1457,1458],{"class":511},"player",[484,1460,576],{"class":494},[484,1462,1109],{"class":498},[484,1464,1465],{"class":1112},"\u002F\u002F a scope\n",[274,1467,1468,1469,417,1471,417,1473,1475,1476,417,1479,417,1482,417,1485,1488],{},"The creator gets the store (",[282,1470,416],{},[282,1472,420],{},[282,1474,424],{},") and the canvas objects (",[282,1477,1478],{},"scene",[282,1480,1481],{},"camera",[282,1483,1484],{},"renderer",[282,1486,1487],{},"sizes",").",[1079,1490,1492],{"id":1491},"when-the-creator-runs","When the creator runs",[274,1494,1495,1496,1499],{},"Once per generation. It does ",[277,1497,1498],{},"not"," run again when a value it read from a prop changes. A new node would not reach the components that already built their graphs from the old one, and every material that uses it would recompile. So:",[385,1501,1502,1505],{},[388,1503,1504],{},"A value that changes goes in a uniform, and the node reads the uniform.",[388,1506,1507,1508,1511,1512,1514],{},"A structure change goes through ",[282,1509,1510],{},"rebuildNodes(scope?)",". All creators run again, and ",[282,1513,349],{}," consumers that read a replaced node rebuild.",[274,1516,1517,1518,1521],{},"A creator that reads an entry before it exists gets ",[282,1519,1520],{},"undefined"," until the next rebuild. A warning in development names the entry. Register entries higher in the tree, or earlier in the same component.",[274,1523,1524,1205,1526,417,1529,421,1532,366],{},[282,1525,339],{},[282,1527,1528],{},"removeNodes",[282,1530,1531],{},"clearNodes",[282,1533,1534],{},"rebuildNodes",[274,1536,1537,1538,1488],{},"Good candidates: complex functions, multi-octave noise, reusable effects, shared varyings. Poor candidates: short expressions and math for one component (use ",[282,1539,349],{},[377,1541,349],{"id":1542},"uselocalnodes",[475,1544,1546],{"className":477,"code":1545,"language":479,"meta":480,"style":480},"import { useLocalNodes } from '@tresjs\u002Fcore\u002Fwebgpu'\n\nconst { colorNode } = useLocalNodes(({ uniforms, nodes }) => ({\n  colorNode: nodes.wave.mul(uniforms.uStrength),\n}))\n",[282,1547,1548,1567,1571,1607,1635],{"__ignoreMap":480},[484,1549,1550,1552,1554,1557,1559,1561,1563,1565],{"class":486,"line":487},[484,1551,491],{"class":490},[484,1553,495],{"class":494},[484,1555,1556],{"class":498}," useLocalNodes",[484,1558,502],{"class":494},[484,1560,505],{"class":490},[484,1562,508],{"class":494},[484,1564,284],{"class":511},[484,1566,514],{"class":494},[484,1568,1569],{"class":486,"line":517},[484,1570,520],{"emptyLinePlaceholder":39},[484,1572,1573,1575,1577,1580,1582,1584,1586,1588,1590,1592,1594,1597,1599,1601,1604],{"class":486,"line":523},[484,1574,527],{"class":526},[484,1576,495],{"class":494},[484,1578,1579],{"class":498}," colorNode ",[484,1581,608],{"class":494},[484,1583,611],{"class":494},[484,1585,1556],{"class":536},[484,1587,573],{"class":498},[484,1589,1037],{"class":494},[484,1591,1296],{"class":1040},[484,1593,602],{"class":494},[484,1595,1596],{"class":1040}," nodes",[484,1598,1044],{"class":494},[484,1600,638],{"class":526},[484,1602,1603],{"class":498}," (",[484,1605,1606],{"class":494},"{\n",[484,1608,1609,1612,1614,1616,1618,1621,1623,1625,1628,1630,1633],{"class":486,"line":560},[484,1610,1611],{"class":543},"  colorNode",[484,1613,547],{"class":494},[484,1615,1596],{"class":498},[484,1617,366],{"class":494},[484,1619,1620],{"class":498},"wave",[484,1622,366],{"class":494},[484,1624,1360],{"class":536},[484,1626,1627],{"class":498},"(uniforms",[484,1629,366],{"class":494},[484,1631,1632],{"class":498},"uStrength)",[484,1634,1402],{"class":494},[484,1636,1637,1639],{"class":486,"line":587},[484,1638,608],{"class":494},[484,1640,1641],{"class":498},"))\n",[475,1643,1647],{"className":1644,"code":1645,"language":1646,"meta":480,"style":480},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003CTresMeshStandardNodeMaterial :color-node=\"colorNode\" \u002F>\n","vue",[282,1648,1649],{"__ignoreMap":480},[484,1650,1651,1654,1657,1660,1663,1665,1668,1671,1673],{"class":486,"line":487},[484,1652,1653],{"class":494},"\u003C",[484,1655,1656],{"class":543},"TresMeshStandardNodeMaterial",[484,1658,1659],{"class":494}," :",[484,1661,1662],{"class":526},"color-node",[484,1664,533],{"class":494},[484,1666,1667],{"class":494},"\"",[484,1669,1670],{"class":498},"colorNode",[484,1672,1667],{"class":494},[484,1674,1675],{"class":494}," \u002F>\n",[274,1677,1678,1679,1682],{},"It returns a record of ",[282,1680,1681],{},"shallowRef","s. After a rebuild, the refs hold the new nodes and Tres puts them on the material.",[1079,1684,1686],{"id":1685},"when-it-rebuilds","When it rebuilds",[274,1688,1689,1690,1693,1694,1697,1698,1700],{},"The creator runs ",[277,1691,1692],{},"untracked",". Reading ",[282,1695,1696],{},"props.color"," in it does not make the graph rebuild when ",[282,1699,1696],{}," changes. It rebuilds only when:",[1702,1703,1704,1707,1710],"ol",{},[388,1705,1706],{},"a source in the second argument changes,",[388,1708,1709],{},"a store entry that the creator read is replaced, removed or added,",[388,1711,1712,1715],{},[282,1713,1714],{},"rebuild*"," starts a new generation, or a hot update replaces the component.",[274,1717,1718],{},"Declare a source only for an input that decides the structure of the graph:",[475,1720,1722],{"className":477,"code":1721,"language":479,"meta":480,"style":480},"const props = defineProps\u003C{ octaves: number, strength: number }>()\n\nuseUniforms({ uStrength: () => props.strength }) \u002F\u002F a value: no rebuild\n\nconst { colorNode } = useLocalNodes(\n  ({ uniforms }) => ({ colorNode: fbm(positionWorld, props.octaves).mul(uniforms.uStrength) }),\n  [() => props.octaves], \u002F\u002F structure: a JS loop runs `octaves` times\n)\n",[282,1723,1724,1756,1760,1791,1795,1812,1864,1886],{"__ignoreMap":480},[484,1725,1726,1728,1730,1732,1734,1736,1739,1741,1743,1745,1748,1750,1752,1754],{"class":486,"line":487},[484,1727,527],{"class":526},[484,1729,530],{"class":498},[484,1731,533],{"class":494},[484,1733,537],{"class":536},[484,1735,540],{"class":494},[484,1737,1738],{"class":543}," octaves",[484,1740,547],{"class":494},[484,1742,551],{"class":550},[484,1744,602],{"class":494},[484,1746,1747],{"class":543}," strength",[484,1749,547],{"class":494},[484,1751,551],{"class":550},[484,1753,554],{"class":494},[484,1755,557],{"class":498},[484,1757,1758],{"class":486,"line":517},[484,1759,520],{"emptyLinePlaceholder":39},[484,1761,1762,1764,1766,1768,1771,1773,1775,1777,1779,1781,1784,1786,1788],{"class":486,"line":523},[484,1763,325],{"class":536},[484,1765,573],{"class":498},[484,1767,618],{"class":494},[484,1769,1770],{"class":536}," uStrength",[484,1772,547],{"class":494},[484,1774,635],{"class":494},[484,1776,638],{"class":526},[484,1778,641],{"class":498},[484,1780,366],{"class":494},[484,1782,1783],{"class":498},"strength ",[484,1785,608],{"class":494},[484,1787,1109],{"class":498},[484,1789,1790],{"class":1112},"\u002F\u002F a value: no rebuild\n",[484,1792,1793],{"class":486,"line":560},[484,1794,520],{"emptyLinePlaceholder":39},[484,1796,1797,1799,1801,1803,1805,1807,1809],{"class":486,"line":587},[484,1798,527],{"class":526},[484,1800,495],{"class":494},[484,1802,1579],{"class":498},[484,1804,608],{"class":494},[484,1806,611],{"class":494},[484,1808,1556],{"class":536},[484,1810,1811],{"class":498},"(\n",[484,1813,1814,1817,1819,1821,1823,1825,1827,1830,1832,1835,1838,1840,1842,1844,1847,1849,1851,1853,1855,1858,1860,1862],{"class":486,"line":592},[484,1815,1816],{"class":494},"  ({",[484,1818,1296],{"class":1040},[484,1820,1044],{"class":494},[484,1822,638],{"class":526},[484,1824,1603],{"class":498},[484,1826,618],{"class":494},[484,1828,1829],{"class":543}," colorNode",[484,1831,547],{"class":494},[484,1833,1834],{"class":536}," fbm",[484,1836,1837],{"class":498},"(positionWorld",[484,1839,602],{"class":494},[484,1841,641],{"class":498},[484,1843,366],{"class":494},[484,1845,1846],{"class":498},"octaves)",[484,1848,366],{"class":494},[484,1850,1360],{"class":536},[484,1852,1627],{"class":498},[484,1854,366],{"class":494},[484,1856,1857],{"class":498},"uStrength) ",[484,1859,608],{"class":494},[484,1861,835],{"class":498},[484,1863,1402],{"class":494},[484,1865,1866,1869,1872,1874,1876,1878,1881,1883],{"class":486,"line":1338},[484,1867,1868],{"class":498},"  [",[484,1870,1871],{"class":494},"()",[484,1873,638],{"class":526},[484,1875,641],{"class":498},[484,1877,366],{"class":494},[484,1879,1880],{"class":498},"octaves]",[484,1882,602],{"class":494},[484,1884,1885],{"class":1112}," \u002F\u002F structure: a JS loop runs `octaves` times\n",[484,1887,1888],{"class":486,"line":1405},[484,1889,584],{"class":498},[274,1891,1892],{},"If the graph rebuilds many times per second, a warning in development tells you to move the input into a uniform.",[271,1894,1895,1909],{},[274,1896,1897,1898,1901,1902,1905,1906,547],{},"Only reads made ",[277,1899,1900],{},"before the creator returns"," are tracked. The body of ",[282,1903,1904],{},"Fn(() => ...)"," runs later, when three builds the shader. Read the entry in the creator and use the variable in ",[282,1907,1908],{},"Fn",[475,1910,1912],{"className":477,"code":1911,"language":479,"meta":480,"style":480},"useLocalNodes(({ uniforms }) => {\n  const strength = uniforms.uStrength \u002F\u002F tracked\n  return { effect: Fn(() => strength.mul(2))() }\n})\n",[282,1913,1914,1930,1948,1984],{"__ignoreMap":480},[484,1915,1916,1918,1920,1922,1924,1926,1928],{"class":486,"line":487},[484,1917,349],{"class":536},[484,1919,573],{"class":498},[484,1921,1037],{"class":494},[484,1923,1296],{"class":1040},[484,1925,1044],{"class":494},[484,1927,638],{"class":526},[484,1929,1303],{"class":494},[484,1931,1932,1934,1936,1938,1940,1942,1945],{"class":486,"line":517},[484,1933,1308],{"class":526},[484,1935,1747],{"class":498},[484,1937,611],{"class":494},[484,1939,1296],{"class":498},[484,1941,366],{"class":494},[484,1943,1944],{"class":498},"uStrength",[484,1946,1947],{"class":1112}," \u002F\u002F tracked\n",[484,1949,1950,1952,1954,1957,1959,1961,1963,1965,1967,1969,1971,1973,1975,1978,1981],{"class":486,"line":523},[484,1951,1333],{"class":490},[484,1953,495],{"class":494},[484,1955,1956],{"class":543}," effect",[484,1958,547],{"class":494},[484,1960,1255],{"class":536},[484,1962,573],{"class":543},[484,1964,1871],{"class":494},[484,1966,638],{"class":526},[484,1968,1747],{"class":498},[484,1970,366],{"class":494},[484,1972,1360],{"class":536},[484,1974,573],{"class":543},[484,1976,1977],{"class":897},"2",[484,1979,1980],{"class":543},"))() ",[484,1982,1983],{"class":494},"}\n",[484,1985,1986,1988],{"class":486,"line":560},[484,1987,608],{"class":494},[484,1989,584],{"class":498},[1079,1991,1993],{"id":1992},"install-nodes-on-an-object","Install nodes on an object",[274,1995,1996,1997,447,2000,2003],{},"Some nodes go on an object, such as ",[282,1998,1999],{},"scene.fogNode",[282,2001,2002],{},"scene.backgroundNode",". Return a function instead of a record. It runs after the build. The function it returns undoes the install:",[475,2005,2007],{"className":477,"code":2006,"language":479,"meta":480,"style":480},"import { fog, rangeFogFactor } from 'three\u002Ftsl'\n\nuseUniforms({ uFogColor: '#1a1a2e', uNear: 3, uFar: 10 }, 'fog')\n\nuseLocalNodes(({ scene, uniforms }) => {\n  const { uFogColor, uNear, uFar } = uniforms.fog\n  const fogNode = fog(uFogColor, rangeFogFactor(uNear, uFar))\n\n  return () => {\n    scene.fogNode = fogNode\n    return () => { scene.fogNode = null }\n  }\n})\n",[282,2008,2009,2033,2037,2088,2092,2113,2140,2171,2175,2185,2201,2227,2232],{"__ignoreMap":480},[484,2010,2011,2013,2015,2018,2020,2023,2025,2027,2029,2031],{"class":486,"line":487},[484,2012,491],{"class":490},[484,2014,495],{"class":494},[484,2016,2017],{"class":498}," fog",[484,2019,602],{"class":494},[484,2021,2022],{"class":498}," rangeFogFactor",[484,2024,502],{"class":494},[484,2026,505],{"class":490},[484,2028,508],{"class":494},[484,2030,1279],{"class":511},[484,2032,514],{"class":494},[484,2034,2035],{"class":486,"line":517},[484,2036,520],{"emptyLinePlaceholder":39},[484,2038,2039,2041,2043,2045,2048,2050,2052,2055,2057,2059,2062,2064,2067,2069,2072,2074,2077,2080,2082,2084,2086],{"class":486,"line":523},[484,2040,325],{"class":536},[484,2042,573],{"class":498},[484,2044,618],{"class":494},[484,2046,2047],{"class":543}," uFogColor",[484,2049,547],{"class":494},[484,2051,508],{"class":494},[484,2053,2054],{"class":511},"#1a1a2e",[484,2056,576],{"class":494},[484,2058,602],{"class":494},[484,2060,2061],{"class":543}," uNear",[484,2063,547],{"class":494},[484,2065,2066],{"class":897}," 3",[484,2068,602],{"class":494},[484,2070,2071],{"class":543}," uFar",[484,2073,547],{"class":494},[484,2075,2076],{"class":897}," 10",[484,2078,2079],{"class":494}," },",[484,2081,508],{"class":494},[484,2083,654],{"class":511},[484,2085,576],{"class":494},[484,2087,584],{"class":498},[484,2089,2090],{"class":486,"line":560},[484,2091,520],{"emptyLinePlaceholder":39},[484,2093,2094,2096,2098,2100,2103,2105,2107,2109,2111],{"class":486,"line":587},[484,2095,349],{"class":536},[484,2097,573],{"class":498},[484,2099,1037],{"class":494},[484,2101,2102],{"class":1040}," scene",[484,2104,602],{"class":494},[484,2106,1296],{"class":1040},[484,2108,1044],{"class":494},[484,2110,638],{"class":526},[484,2112,1303],{"class":494},[484,2114,2115,2117,2119,2121,2123,2125,2127,2129,2131,2133,2135,2137],{"class":486,"line":592},[484,2116,1308],{"class":526},[484,2118,495],{"class":494},[484,2120,2047],{"class":498},[484,2122,602],{"class":494},[484,2124,2061],{"class":498},[484,2126,602],{"class":494},[484,2128,2071],{"class":498},[484,2130,502],{"class":494},[484,2132,611],{"class":494},[484,2134,1296],{"class":498},[484,2136,366],{"class":494},[484,2138,2139],{"class":498},"fog\n",[484,2141,2142,2144,2147,2149,2151,2153,2156,2158,2160,2162,2165,2167,2169],{"class":486,"line":1338},[484,2143,1308],{"class":526},[484,2145,2146],{"class":498}," fogNode",[484,2148,611],{"class":494},[484,2150,2017],{"class":536},[484,2152,573],{"class":543},[484,2154,2155],{"class":498},"uFogColor",[484,2157,602],{"class":494},[484,2159,2022],{"class":536},[484,2161,573],{"class":543},[484,2163,2164],{"class":498},"uNear",[484,2166,602],{"class":494},[484,2168,2071],{"class":498},[484,2170,1641],{"class":543},[484,2172,2173],{"class":486,"line":1405},[484,2174,520],{"emptyLinePlaceholder":39},[484,2176,2177,2179,2181,2183],{"class":486,"line":1411},[484,2178,1333],{"class":490},[484,2180,635],{"class":494},[484,2182,638],{"class":526},[484,2184,1303],{"class":494},[484,2186,2188,2191,2193,2196,2198],{"class":486,"line":2187},10,[484,2189,2190],{"class":498},"    scene",[484,2192,366],{"class":494},[484,2194,2195],{"class":498},"fogNode",[484,2197,611],{"class":494},[484,2199,2200],{"class":498}," fogNode\n",[484,2202,2204,2207,2209,2211,2213,2215,2217,2219,2221,2224],{"class":486,"line":2203},11,[484,2205,2206],{"class":490},"    return",[484,2208,635],{"class":494},[484,2210,638],{"class":526},[484,2212,495],{"class":494},[484,2214,2102],{"class":498},[484,2216,366],{"class":494},[484,2218,2195],{"class":498},[484,2220,611],{"class":494},[484,2222,2223],{"class":494}," null",[484,2225,2226],{"class":494}," }\n",[484,2228,2230],{"class":486,"line":2229},12,[484,2231,1408],{"class":494},[484,2233,2235,2237],{"class":486,"line":2234},13,[484,2236,608],{"class":494},[484,2238,584],{"class":498},[274,2240,2241],{},"On a rebuild, the old cleanup runs before the new install. On unmount, the cleanup runs.",[377,2243,359],{"id":2244},"userenderpipeline",[475,2246,2248],{"className":477,"code":2247,"language":479,"meta":480,"style":480},"import { useRenderPipeline, useUniforms } from '@tresjs\u002Fcore\u002Fwebgpu'\nimport { bloom } from 'three\u002Faddons\u002Ftsl\u002Fdisplay\u002FBloomNode.js'\n\nconst props = defineProps\u003C{ strength: number }>()\nuseUniforms({ uStrength: () => props.strength })\n\nuseRenderPipeline(({ renderPipeline, passes, uniforms }) => {\n  const sceneColor = passes.scenePass.getTextureNode()\n  renderPipeline.outputNode = sceneColor.add(bloom(sceneColor, uniforms.uStrength))\n})\n",[282,2249,2250,2273,2293,2297,2319,2345,2349,2375,2398,2436],{"__ignoreMap":480},[484,2251,2252,2254,2256,2259,2261,2263,2265,2267,2269,2271],{"class":486,"line":487},[484,2253,491],{"class":490},[484,2255,495],{"class":494},[484,2257,2258],{"class":498}," useRenderPipeline",[484,2260,602],{"class":494},[484,2262,499],{"class":498},[484,2264,502],{"class":494},[484,2266,505],{"class":490},[484,2268,508],{"class":494},[484,2270,284],{"class":511},[484,2272,514],{"class":494},[484,2274,2275,2277,2279,2282,2284,2286,2288,2291],{"class":486,"line":517},[484,2276,491],{"class":490},[484,2278,495],{"class":494},[484,2280,2281],{"class":498}," bloom",[484,2283,502],{"class":494},[484,2285,505],{"class":490},[484,2287,508],{"class":494},[484,2289,2290],{"class":511},"three\u002Faddons\u002Ftsl\u002Fdisplay\u002FBloomNode.js",[484,2292,514],{"class":494},[484,2294,2295],{"class":486,"line":523},[484,2296,520],{"emptyLinePlaceholder":39},[484,2298,2299,2301,2303,2305,2307,2309,2311,2313,2315,2317],{"class":486,"line":560},[484,2300,527],{"class":526},[484,2302,530],{"class":498},[484,2304,533],{"class":494},[484,2306,537],{"class":536},[484,2308,540],{"class":494},[484,2310,1747],{"class":543},[484,2312,547],{"class":494},[484,2314,551],{"class":550},[484,2316,554],{"class":494},[484,2318,557],{"class":498},[484,2320,2321,2323,2325,2327,2329,2331,2333,2335,2337,2339,2341,2343],{"class":486,"line":587},[484,2322,325],{"class":536},[484,2324,573],{"class":498},[484,2326,618],{"class":494},[484,2328,1770],{"class":536},[484,2330,547],{"class":494},[484,2332,635],{"class":494},[484,2334,638],{"class":526},[484,2336,641],{"class":498},[484,2338,366],{"class":494},[484,2340,1783],{"class":498},[484,2342,608],{"class":494},[484,2344,584],{"class":498},[484,2346,2347],{"class":486,"line":592},[484,2348,520],{"emptyLinePlaceholder":39},[484,2350,2351,2353,2355,2357,2360,2362,2365,2367,2369,2371,2373],{"class":486,"line":1338},[484,2352,359],{"class":536},[484,2354,573],{"class":498},[484,2356,1037],{"class":494},[484,2358,2359],{"class":1040}," renderPipeline",[484,2361,602],{"class":494},[484,2363,2364],{"class":1040}," passes",[484,2366,602],{"class":494},[484,2368,1296],{"class":1040},[484,2370,1044],{"class":494},[484,2372,638],{"class":526},[484,2374,1303],{"class":494},[484,2376,2377,2379,2382,2384,2386,2388,2391,2393,2396],{"class":486,"line":1405},[484,2378,1308],{"class":526},[484,2380,2381],{"class":498}," sceneColor",[484,2383,611],{"class":494},[484,2385,2364],{"class":498},[484,2387,366],{"class":494},[484,2389,2390],{"class":498},"scenePass",[484,2392,366],{"class":494},[484,2394,2395],{"class":536},"getTextureNode",[484,2397,557],{"class":543},[484,2399,2400,2403,2405,2408,2410,2412,2414,2416,2418,2421,2423,2426,2428,2430,2432,2434],{"class":486,"line":1411},[484,2401,2402],{"class":498},"  renderPipeline",[484,2404,366],{"class":494},[484,2406,2407],{"class":498},"outputNode",[484,2409,611],{"class":494},[484,2411,2381],{"class":498},[484,2413,366],{"class":494},[484,2415,1350],{"class":536},[484,2417,573],{"class":543},[484,2419,2420],{"class":536},"bloom",[484,2422,573],{"class":543},[484,2424,2425],{"class":498},"sceneColor",[484,2427,602],{"class":494},[484,2429,1296],{"class":498},[484,2431,366],{"class":494},[484,2433,1944],{"class":498},[484,2435,1641],{"class":543},[484,2437,2438,2440],{"class":486,"line":2187},[484,2439,608],{"class":494},[484,2441,584],{"class":498},[274,2443,2444],{},"With a callback, it:",[1702,2446,2447,2456,2462,2465],{},[388,2448,2449,2450,2452,2453,2455],{},"creates three's ",[282,2451,365],{}," and a ",[282,2454,2390],{}," (the scene with the active camera),",[388,2457,2458,2459,2461],{},"sets ",[282,2460,2407],{}," to the scene pass, then runs your callbacks,",[388,2463,2464],{},"renders the canvas through the pipeline,",[388,2466,2467],{},"frees the pipeline and restores normal rendering when the component unmounts.",[274,2469,2470],{},"Mount the effect component to turn the effect on, and unmount it to turn it off:",[475,2472,2474],{"className":1644,"code":2473,"language":1646,"meta":480,"style":480},"\u003CBloomEffect v-if=\"bloomEnabled\" :strength=\"strength\" \u002F>\n",[282,2475,2476],{"__ignoreMap":480},[484,2477,2478,2480,2483,2486,2488,2490,2493,2495,2497,2500,2502,2504,2506,2508],{"class":486,"line":487},[484,2479,1653],{"class":494},[484,2481,2482],{"class":543},"BloomEffect",[484,2484,2485],{"class":490}," v-if",[484,2487,533],{"class":494},[484,2489,1667],{"class":494},[484,2491,2492],{"class":498},"bloomEnabled",[484,2494,1667],{"class":494},[484,2496,1659],{"class":494},[484,2498,2499],{"class":526},"strength",[484,2501,533],{"class":494},[484,2503,1667],{"class":494},[484,2505,2499],{"class":498},[484,2507,1667],{"class":494},[484,2509,1675],{"class":494},[1079,2511,2513],{"id":2512},"callbacks","Callbacks",[475,2515,2517],{"className":477,"code":2516,"language":479,"meta":480,"style":480},"useRenderPipeline(\n  ({ renderPipeline, passes }) => { \u002F* main: set outputNode *\u002F },\n  ({ passes }) => { passes.scenePass.setMRT(mrt({ output, velocity })) }, \u002F\u002F setup: runs first\n)\n",[282,2518,2519,2525,2547,2597],{"__ignoreMap":480},[484,2520,2521,2523],{"class":486,"line":487},[484,2522,359],{"class":536},[484,2524,1811],{"class":498},[484,2526,2527,2529,2531,2533,2535,2537,2539,2541,2544],{"class":486,"line":517},[484,2528,1816],{"class":494},[484,2530,2359],{"class":1040},[484,2532,602],{"class":494},[484,2534,2364],{"class":1040},[484,2536,1044],{"class":494},[484,2538,638],{"class":526},[484,2540,495],{"class":494},[484,2542,2543],{"class":1112}," \u002F* main: set outputNode *\u002F",[484,2545,2546],{"class":494}," },\n",[484,2548,2549,2551,2553,2555,2557,2559,2561,2563,2565,2567,2570,2572,2575,2577,2579,2582,2584,2587,2589,2592,2594],{"class":486,"line":523},[484,2550,1816],{"class":494},[484,2552,2364],{"class":1040},[484,2554,1044],{"class":494},[484,2556,638],{"class":526},[484,2558,495],{"class":494},[484,2560,2364],{"class":498},[484,2562,366],{"class":494},[484,2564,2390],{"class":498},[484,2566,366],{"class":494},[484,2568,2569],{"class":536},"setMRT",[484,2571,573],{"class":543},[484,2573,2574],{"class":536},"mrt",[484,2576,573],{"class":543},[484,2578,618],{"class":494},[484,2580,2581],{"class":498}," output",[484,2583,602],{"class":494},[484,2585,2586],{"class":498}," velocity",[484,2588,502],{"class":494},[484,2590,2591],{"class":543},")) ",[484,2593,649],{"class":494},[484,2595,2596],{"class":1112}," \u002F\u002F setup: runs first\n",[484,2598,2599],{"class":486,"line":560},[484,2600,584],{"class":498},[274,2602,2603,2604,2607],{},"The callbacks run when the pipeline is created, when the scene or the active camera changes (with a new scene pass), when a store entry they read changes, and on ",[282,2605,2606],{},"rebuild()",". They do not run on re-render. Put dynamic values in uniforms.",[274,2609,2610,2611,2613],{},"Return a record from a callback to register more passes. ",[282,2612,2390],{}," is reserved.",[475,2615,2617],{"className":477,"code":2616,"language":479,"meta":480,"style":480},"useRenderPipeline(({ renderPipeline, scene, camera }) => {\n  const depthPass = pass(scene, camera)\n  renderPipeline.outputNode = depthPass\n  return { depthPass }\n})\n",[282,2618,2619,2644,2666,2679,2689],{"__ignoreMap":480},[484,2620,2621,2623,2625,2627,2629,2631,2633,2635,2638,2640,2642],{"class":486,"line":487},[484,2622,359],{"class":536},[484,2624,573],{"class":498},[484,2626,1037],{"class":494},[484,2628,2359],{"class":1040},[484,2630,602],{"class":494},[484,2632,2102],{"class":1040},[484,2634,602],{"class":494},[484,2636,2637],{"class":1040}," camera",[484,2639,1044],{"class":494},[484,2641,638],{"class":526},[484,2643,1303],{"class":494},[484,2645,2646,2648,2651,2653,2656,2658,2660,2662,2664],{"class":486,"line":517},[484,2647,1308],{"class":526},[484,2649,2650],{"class":498}," depthPass",[484,2652,611],{"class":494},[484,2654,2655],{"class":536}," pass",[484,2657,573],{"class":543},[484,2659,1478],{"class":498},[484,2661,602],{"class":494},[484,2663,2637],{"class":498},[484,2665,584],{"class":543},[484,2667,2668,2670,2672,2674,2676],{"class":486,"line":523},[484,2669,2402],{"class":498},[484,2671,366],{"class":494},[484,2673,2407],{"class":498},[484,2675,611],{"class":494},[484,2677,2678],{"class":498}," depthPass\n",[484,2680,2681,2683,2685,2687],{"class":486,"line":560},[484,2682,1333],{"class":490},[484,2684,495],{"class":494},[484,2686,2650],{"class":498},[484,2688,2226],{"class":494},[484,2690,2691,2693],{"class":486,"line":587},[484,2692,608],{"class":494},[484,2694,584],{"class":498},[1079,2696,2698],{"id":2697},"read-the-pipeline","Read the pipeline",[475,2700,2702],{"className":477,"code":2701,"language":479,"meta":480,"style":480},"const { renderPipeline, passes, isReady, rebuild, reset, clearPasses } = useRenderPipeline()\n",[282,2703,2704],{"__ignoreMap":480},[484,2705,2706,2708,2710,2712,2714,2716,2718,2721,2723,2726,2728,2731,2733,2736,2738,2740,2742],{"class":486,"line":487},[484,2707,527],{"class":526},[484,2709,495],{"class":494},[484,2711,2359],{"class":498},[484,2713,602],{"class":494},[484,2715,2364],{"class":498},[484,2717,602],{"class":494},[484,2719,2720],{"class":498}," isReady",[484,2722,602],{"class":494},[484,2724,2725],{"class":498}," rebuild",[484,2727,602],{"class":494},[484,2729,2730],{"class":498}," reset",[484,2732,602],{"class":494},[484,2734,2735],{"class":498}," clearPasses ",[484,2737,608],{"class":494},[484,2739,611],{"class":494},[484,2741,2258],{"class":536},[484,2743,557],{"class":498},[274,2745,2746],{},"Without callbacks, it only reads. It never creates the pipeline and does not keep one alive.",[385,2748,2749,2759,2764,2770],{},[388,2750,2751,2754,2755,2758],{},[282,2752,2753],{},"renderPipeline"," is a ref: the pipeline, or ",[282,2756,2757],{},"null"," when no component configures one.",[388,2760,2761,2763],{},[282,2762,2606],{}," runs the callbacks again with a new scene pass.",[388,2765,2766,2769],{},[282,2767,2768],{},"reset()"," frees the pipeline now. The canvas renders without it until the next rebuild.",[388,2771,2772,2775,2776,2778],{},[282,2773,2774],{},"clearPasses()"," removes and disposes the passes that callbacks registered. ",[282,2777,2390],{}," stays, so the pipeline keeps drawing.",[274,2780,2781],{},"One pipeline renders per canvas. If two components configure it, a warning shows and the one mounted last renders. When it unmounts, the other one configures the pipeline again.",[274,2783,2784,2786,2787,2790,2791,2794,2795,417,2798,421,2800,2803],{},[282,2785,359],{}," throws under a ",[282,2788,2789],{},"WebGLRenderer",". It uses the ",[292,2792,2793],{"href":125},"render function"," of the loop, so it works with the ",[282,2796,2797],{},"always",[282,2799,1072],{},[282,2801,2802],{},"manual"," render modes.",[2805,2806,2807],"style",{},"html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":480,"searchDepth":487,"depth":517,"links":2809},[2810,2811,2812,2817,2820,2824],{"id":379,"depth":517,"text":380},{"id":409,"depth":517,"text":410},{"id":473,"depth":517,"text":325,"children":2813},[2814,2815,2816],{"id":1081,"depth":523,"text":1082},{"id":1139,"depth":523,"text":329},{"id":1200,"depth":523,"text":146},{"id":1222,"depth":517,"text":339,"children":2818},[2819],{"id":1491,"depth":523,"text":1492},{"id":1542,"depth":517,"text":349,"children":2821},[2822,2823],{"id":1685,"depth":523,"text":1686},{"id":1992,"depth":523,"text":1993},{"id":2244,"depth":517,"text":359,"children":2825},[2826,2827],{"id":2512,"depth":523,"text":2513},{"id":2697,"depth":523,"text":2698},"Manage TSL uniforms, shared nodes and the WebGPU render pipeline with Vue composables.","md",null,{},{"title":174,"description":2828},"Atto2GFtTgge-KYx5x5CwFbS9VLmJ7dfffSyFYADh8o",[2835,2837],{"title":170,"path":171,"stem":172,"description":2836,"children":-1},"Use the primitive component to directly integrate any Three.js object within your Vue application.",{"title":178,"path":179,"stem":180,"description":2838,"children":-1},"Render TresJS scenes with WebGPU, node materials and TSL.",1793348715066]