1:"$Sreact.fragment" 2:I[9273,["9042","static/chunks/493ff4cd-cc5cbbaffe73cc0c.js","6450","static/chunks/6450-8b251d603c8dfe44.js","717","static/chunks/717-4e13104f6bbae0ae.js","255","static/chunks/255-054b9adadd55d731.js","7177","static/chunks/app/layout-3191237df71f64ed.js"],"Providers"] 3:I[3982,["9042","static/chunks/493ff4cd-cc5cbbaffe73cc0c.js","6450","static/chunks/6450-8b251d603c8dfe44.js","717","static/chunks/717-4e13104f6bbae0ae.js","255","static/chunks/255-054b9adadd55d731.js","7177","static/chunks/app/layout-3191237df71f64ed.js"],"Header"] 4:I[8188,[],""] 5:I[3674,[],""] 6:I[717,["6450","static/chunks/6450-8b251d603c8dfe44.js","1209","static/chunks/1209-941c09327a85bbba.js","717","static/chunks/717-4e13104f6bbae0ae.js","4806","static/chunks/4806-d0fa85f187c1b9d5.js","2190","static/chunks/2190-acbe3d263489f38e.js","3831","static/chunks/app/blog/page-523c64caa839e746.js"],""] 7:I[149,["6450","static/chunks/6450-8b251d603c8dfe44.js","1209","static/chunks/1209-941c09327a85bbba.js","1956","static/chunks/app/blog/combining-vector-and-shaders-for-2d-art/page-a4f8ed5c049f8a99.js"],"SolandraStacked"] 8:I[700,[],"OutletBoundary"] b:I[1860,[],"AsyncMetadataOutlet"] d:I[700,[],"ViewportBoundary"] f:I[700,[],"MetadataBoundary"] 11:I[1267,[],""] :HL["/_next/static/css/2bd7017f0e4e6b03.css","style"] 0:{"P":null,"b":"2xfioPjcSU6dFxG8R7K5z","p":"","c":["","blog","combining-vector-and-shaders-for-2d-art"],"i":false,"f":[[["",{"children":["blog",{"children":["combining-vector-and-shaders-for-2d-art",{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/2bd7017f0e4e6b03.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"h-full antialiased","suppressHydrationWarning":true,"children":["$","body",null,{"className":"flex h-full bg-zinc-200 dark:bg-black","children":["$","$L2",null,{"children":["$","div",null,{"className":"flex w-full","children":[["$","div",null,{"className":"fixed inset-0 flex justify-center sm:px-8","children":["$","div",null,{"className":"flex w-full max-w-7xl lg:px-8","children":["$","div",null,{"className":"w-full bg-white ring-1 ring-zinc-100 dark:bg-zinc-900 dark:ring-zinc-300/20"}]}]}],["$","div",null,{"className":"relative flex w-full flex-col","children":[["$","$L3",null,{}],["$","main",null,{"className":"flex-auto","children":["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","div",null,{"ref":"$undefined","className":"sm:px-8 flex h-full items-center pt-16 sm:pt-32","children":["$","div",null,{"className":"mx-auto w-full max-w-7xl lg:px-8","children":["$","div",null,{"ref":"$undefined","className":"relative px-4 sm:px-8 lg:px-12","children":["$","div",null,{"className":"mx-auto max-w-2xl lg:max-w-5xl","children":["$","div",null,{"className":"flex flex-col items-center","children":[["$","p",null,{"className":"text-base font-semibold text-zinc-400 dark:text-zinc-500","children":"404"}],["$","h1",null,{"className":"mt-4 text-4xl font-bold tracking-tight text-rose-800 sm:text-5xl dark:text-rose-100","children":"Page not found"}],["$","p",null,{"className":"mt-4 text-base text-zinc-600 dark:text-zinc-400","children":"Sorry, we couldn’t find the page you’re looking for."}],["$","p",null,{"className":"mt-4 text-base text-zinc-600 dark:text-zinc-400","children":["You may want to try"," ",["$","a",null,{"href":"https://archive.amimetic.co.uk","className":"font-semibold text-rose-600 hover:text-rose-500","children":"the old version of this website"}]," ","as not everything was included here."]}],["$","$L6",null,{"className":"inline-flex items-center gap-2 justify-center rounded-md py-2 px-3 text-sm outline-offset-2 transition active:transition-none bg-zinc-50 font-medium text-zinc-900 hover:bg-zinc-100 active:bg-zinc-100 active:text-zinc-900/60 dark:bg-zinc-800/50 dark:text-zinc-300 dark:hover:bg-zinc-800 dark:hover:text-zinc-50 dark:active:bg-zinc-800/50 dark:active:text-zinc-50/70 mt-4","href":"/","children":"Go back home"}]]}]}]}]}]}],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}],["$","footer",null,{"className":"mt-32 flex-none","children":["$","div",null,{"ref":"$undefined","className":"sm:px-8","children":["$","div",null,{"className":"mx-auto w-full max-w-7xl lg:px-8","children":["$","div",null,{"className":"border-t border-zinc-100 pb-16 pt-10 dark:border-zinc-700/40","children":["$","div",null,{"ref":"$undefined","className":"relative px-4 sm:px-8 lg:px-12","children":["$","div",null,{"className":"mx-auto max-w-2xl lg:max-w-5xl","children":["$","div",null,{"className":"flex flex-col items-center justify-between gap-6 sm:flex-row","children":[["$","div",null,{"className":"flex flex-wrap justify-center gap-x-6 gap-y-1 text-sm font-medium text-zinc-800 dark:text-zinc-200","children":[["$","$L6",null,{"href":"/about","className":"transition hover:text-sky-500 dark:hover:text-sky-400","children":"About"}],["$","$L6",null,{"href":"/blog","className":"transition hover:text-sky-500 dark:hover:text-sky-400","children":"Writing"}],["$","$L6",null,{"href":"/projects","className":"transition hover:text-sky-500 dark:hover:text-sky-400","children":"Projects"}]]}],["$","p",null,{"className":"text-sm text-zinc-400 dark:text-zinc-500","children":["© ",2025," James Porter"]}]]}]}]}]}]}]}]}]]}]]}]}]}]}]]}],{"children":["blog",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["combining-vector-and-shaders-for-2d-art",["$","$1","c",{"children":[null,["$","$L4",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":["__PAGE__",["$","$1","c",{"children":[["$","div",null,{"ref":"$undefined","className":"sm:px-8 mt-16 lg:mt-32","children":["$","div",null,{"className":"mx-auto w-full max-w-7xl lg:px-8","children":["$","div",null,{"ref":"$undefined","className":"relative px-4 sm:px-8 lg:px-12","children":["$","div",null,{"className":"mx-auto max-w-2xl lg:max-w-5xl","children":["$","div",null,{"className":"xl:relative","children":["$","div",null,{"className":"mx-auto max-w-2xl","children":["$","article",null,{"children":[["$","header",null,{"className":"flex flex-col","children":[["$","h1",null,{"className":"mt-6 text-4xl font-bold tracking-tight text-zinc-800 sm:text-5xl dark:text-zinc-100","children":"Combining Vector Graphics and Shaders with Solandra"}],["$","time",null,{"dateTime":"2024-06-15T17:17:58.655Z","className":"order-first flex items-center text-base text-zinc-400 dark:text-zinc-500","children":[["$","span",null,{"className":"h-4 w-0.5 rounded-full bg-zinc-200 dark:bg-zinc-500"}],["$","span",null,{"className":"ml-3","children":"15 June 2024"}]]}]]}],["$","div",null,{"className":"mt-8 prose dark:prose-invert","data-mdx-content":true,"children":[["$","p",null,{"children":["Solandra 0.19 has APIs for rendering both fragment shaders (GLSL) and ",["$","em",null,{"children":"Solandra Sketches"}]," to offscreen canvases in order to create images. These images can be combined within a Solandra sketch. Let's see how this works with a simple example."]}],"\n",["$","$L7",null,{}],"\n",["$","p",null,{"children":"How was this done? First, let's render a fragment shader. Fragment shaders render per pixel. So we don't describe shapes and lines; instead, we must give a colour value for every single pixel. These values are calculated in a very low-level way in C-like GLSL. We have to figure out a 4d vector for each pixel where the first three values are the RGB values and the last is the alpha value. We can't even use values from our other code directly; we have to pass them in as uniforms."}],"\n",["$","p",null,{"children":["Solandra takes care of setting up the context and wiring up the ",["$","code",null,{"children":"u_resolution"}]," uniform. To render something all you need to do is pass in a ",["$","code",null,{"children":"shader"}]," which contains a ",["$","code",null,{"children":"main"}]," function that writes to ",["$","code",null,{"children":"gl_FragColor"}],". This creates a simple gradient where the red and green values are the relative x and y coordinates of the pixel."]}],"\n",["$","pre",null,{"className":"language-ts","children":["$","code",null,{"className":"language-ts","children":[["$","span",null,{"className":"token keyword","children":"const"}]," shaderImage ",["$","span",null,{"className":"token operator","children":"="}]," ",["$","span",null,{"className":"token function","children":"renderShader"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}],"\n shader",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token comment","children":"/* glsl */"}]," ",["$","span",null,{"className":"token template-string","children":[["$","span",null,{"className":"token template-punctuation string","children":"`"}],["$","span",null,{"className":"token string","children":"\n void main() { \n vec2 r_pos = gl_FragCoord.xy / u_resolution; \n gl_FragColor = vec4(r_pos.x, r_pos.y, 0.4, 1.0); \n }\n "}],["$","span",null,{"className":"token template-punctuation string","children":"`"}]]}],["$","span",null,{"className":"token punctuation","children":","}],"\n",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n"]}]}],"\n",["$","p",null,{"children":["Now let's render something with Solandra offscreen. With Solandra, we have access to much more powerful APIs, and we don't typically care about individual pixels; we draw the entire scene. We will iterate over a set of ",["$","code",null,{"children":"PoissonDiskPoints"}],", generating a hue from the index and drawing a circle."]}],"\n",["$","pre",null,{"className":"language-ts","children":["$","code",null,{"className":"language-ts","children":[["$","span",null,{"className":"token keyword","children":"const"}]," solImage ",["$","span",null,{"className":"token operator","children":"="}]," ",["$","span",null,{"className":"token function","children":"render"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}],"\n w",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"1024"}],["$","span",null,{"className":"token punctuation","children":","}],"\n h",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"1024"}],["$","span",null,{"className":"token punctuation","children":","}],"\n ",["$","span",null,{"className":"token function-variable function","children":"sketch"}],["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token punctuation","children":"("}],"s",["$","span",null,{"className":"token punctuation","children":")"}]," ",["$","span",null,{"className":"token arrow operator","children":"=>"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"forPoissonDiskPoints"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," minDist",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"0.05"}]," ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token punctuation","children":"("}],"pt",["$","span",null,{"className":"token punctuation","children":","}]," i",["$","span",null,{"className":"token punctuation","children":")"}]," ",["$","span",null,{"className":"token arrow operator","children":"=>"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"setFillColor"}],["$","span",null,{"className":"token punctuation","children":"("}],"i ",["$","span",null,{"className":"token operator","children":"%"}]," ",["$","span",null,{"className":"token number","children":"360"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"80"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"70"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"0.7"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"fill"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token keyword","children":"new"}]," ",["$","span",null,{"className":"token class-name","children":["$","span",null,{"className":"token maybe-class-name","children":"Circle"}]}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," at",["$","span",null,{"className":"token operator","children":":"}]," pt",["$","span",null,{"className":"token punctuation","children":","}]," r",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"0.025"}]," ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":","}],"\n",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n"]}]}],"\n",["$","p",null,{"children":["Now let's combine these. We use ",["$","code",null,{"children":"withClipping"}]," to clip the shader to a circle and ",["$","code",null,{"children":"withBlendMode"}]," to overlay the Solandra image on top of the shader in an interesting way."]}],"\n",["$","pre",null,{"className":"language-ts","children":["$","code",null,{"className":"language-ts","children":["s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"background"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token number","children":"20"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"40"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"40"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n\ns",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"withClipping"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token keyword","children":"new"}]," ",["$","span",null,{"className":"token class-name","children":["$","span",null,{"className":"token maybe-class-name","children":"Circle"}]}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," at",["$","span",null,{"className":"token operator","children":":"}]," s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"meta"}],["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"center"}],["$","span",null,{"className":"token punctuation","children":","}]," r",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"0.4"}]," ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":")"}]," ",["$","span",null,{"className":"token arrow operator","children":"=>"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"drawImage"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," image",["$","span",null,{"className":"token operator","children":":"}]," shaderImage ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n\ns",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"withBlendMode"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token string","children":"'overlay'"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":")"}]," ",["$","span",null,{"className":"token arrow operator","children":"=>"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"drawImage"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," image",["$","span",null,{"className":"token operator","children":":"}]," solImage ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n"]}]}],"\n",["$","h2",null,{"children":"Using Images from Shaders"}],"\n",["$","p",null,{"children":"We can also pass images into Solandra shader rendering. Let's first create a simple image of 'snowfall'. A black background with some white circles."}],"\n",["$","pre",null,{"className":"language-ts","children":["$","code",null,{"className":"language-ts","children":[["$","span",null,{"className":"token keyword","children":"const"}]," solImage ",["$","span",null,{"className":"token operator","children":"="}]," ",["$","span",null,{"className":"token function","children":"render"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}],"\n w",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"1024"}],["$","span",null,{"className":"token punctuation","children":","}],"\n h",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"1024"}],["$","span",null,{"className":"token punctuation","children":","}],"\n ",["$","span",null,{"className":"token function-variable function","children":"sketch"}],["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token punctuation","children":"("}],"s",["$","span",null,{"className":"token punctuation","children":")"}]," ",["$","span",null,{"className":"token arrow operator","children":"=>"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"background"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token number","children":"0"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"0"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"0"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"setFillColor"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token number","children":"0"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"0"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token number","children":"100"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"forPoissonDiskPoints"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," minDist",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"0.05"}]," ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":","}]," ",["$","span",null,{"className":"token punctuation","children":"("}],"pt",["$","span",null,{"className":"token punctuation","children":")"}]," ",["$","span",null,{"className":"token arrow operator","children":"=>"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n s",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"fill"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token keyword","children":"new"}]," ",["$","span",null,{"className":"token class-name","children":["$","span",null,{"className":"token maybe-class-name","children":"Circle"}]}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," at",["$","span",null,{"className":"token operator","children":":"}]," pt",["$","span",null,{"className":"token punctuation","children":","}]," r",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token number","children":"0.01"}]," ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":","}],"\n",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n"]}]}],"\n",["$","p",null,{"children":["Okay, how do we pass this into a shader? That is very simple, the ",["$","code",null,{"children":"renderShader"}]," function takes an optional object of images."]}],"\n",["$","pre",null,{"className":"language-ts","children":["$","code",null,{"className":"language-ts","children":["images",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}],"\n solImage\n",["$","span",null,{"className":"token punctuation","children":"}"}],"\n"]}]}],"\n",["$","p",null,{"children":["How do we use these images? With ",["$","code",null,{"children":"texture2D"}]," we can sample the image at a given coordinate. We can now do fancy per-pixel effects on the original images, so for example here we are taking the red, green and blue values from slightly offset locations to create an effect. The ",["$","code",null,{"children":".r"}]," and so on just means take the first colour from this pixel, i.e., red."]}],"\n",["$","pre",null,{"className":"language-ts","children":["$","code",null,{"className":"language-ts","children":[["$","span",null,{"className":"token keyword","children":"const"}]," shaderImage ",["$","span",null,{"className":"token operator","children":"="}]," ",["$","span",null,{"className":"token function","children":"renderShader"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}],"\n shader",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token comment","children":"/* glsl */"}]," ",["$","span",null,{"className":"token template-string","children":[["$","span",null,{"className":"token template-punctuation string","children":"`"}],["$","span",null,{"className":"token string","children":"\n void main() { \n vec2 r_pos = gl_FragCoord.xy / u_resolution; \n\n vec2 r_pos_r = r_pos - vec2(0.01, 0.0);\n vec2 r_pos_g = r_pos - vec2(0.0, 0.01);\n vec2 r_pos_b = r_pos - vec2(0.01, 0.01);\n\n float r = texture2D(solImage, r_pos_r).r;\n float g = texture2D(solImage, r_pos_g).g;\n float b = texture2D(solImage, r_pos_b).b;\n\n gl_FragColor = vec4(r, g, b, 1.0);\n }\n "}],["$","span",null,{"className":"token template-punctuation string","children":"`"}]]}],["$","span",null,{"className":"token punctuation","children":","}],"\n images",["$","span",null,{"className":"token operator","children":":"}]," ",["$","span",null,{"className":"token punctuation","children":"{"}]," solImage ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":","}],"\n",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n\n",["$","span",null,{"className":"token comment","children":"// Actually render it:"}],"\ns",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token method function property-access","children":"drawImage"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":"{"}]," image",["$","span",null,{"className":"token operator","children":":"}]," shaderImage ",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token punctuation","children":")"}],"\n"]}]}],"\n",["$","$L7",null,{"index":1}]]}]]}]}]}]}]}]}]}],null,["$","$L8",null,{"children":["$L9","$La",["$","$Lb",null,{"promise":"$@c"}]]}]]}],{},null,false]},null,false]},null,false]},null,false],["$","$1","h",{"children":[null,["$","$1","x4IXTJ6yo4EMDY4Z79-Iqv",{"children":[["$","$Ld",null,{"children":"$Le"}],null]}],["$","$Lf",null,{"children":"$L10"}]]}],false]],"m":"$undefined","G":["$11","$undefined"],"s":false,"S":true} 12:"$Sreact.suspense" 13:I[1860,[],"AsyncMetadata"] 10:["$","div",null,{"hidden":true,"children":["$","$12",null,{"fallback":null,"children":["$","$L13",null,{"promise":"$@14"}]}]}] a:null e:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] 9:null c:{"metadata":[["$","title","0",{"children":"Combining Vector Graphics and Shaders with Solandra - James Porter"}],["$","meta","1",{"name":"description","content":"Projects and thoughts from James Porter"}]],"error":null,"digest":"$undefined"} 14:{"metadata":"$c:metadata","error":null,"digest":"$undefined"}