{"componentChunkName":"component---node-modules-narative-gatsby-theme-novela-src-templates-author-template-tsx","path":"/authors/rick/page/6","result":{"pageContext":{"author":{"authorsPage":true,"bio":"I am a creative frontend developer, I specialise in React, GLSL, postprocessing and R3F. I love to experiment with code and deal with complex topics.\n","id":"a2f54938-ce4a-58e3-a14f-42c21df2482a","name":"Rick","featured":true,"social":[{"url":"https://twitter.com/TheFrontDev"},{"url":"https://github.com/Richard-Thompson"}],"slug":"/authors/rick","avatar":{"small":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABRlsKyA51mANxhD//xAAcEAACAgIDAAAAAAAAAAAAAAABAgMSAAQREyD/2gAIAQEAAQUCCLCqVkRYwROt5aDCak7DFn2Dx3+P/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAgMAAwEAAAAAAAAAAAAAAAECESEQIDEy/9oACAEBAAY/AnuH1fEU/KIuMUtQ0WyoYedP/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBUSD/2gAIAQEAAT8hv6qbzGnBGvZesblRLKajqgyHnSZETPIHoo4SmR6uJW1r7fx//9oADAMBAAIAAwAAABCQyAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAeEAEAAgICAwEAAAAAAAAAAAABABEhMUFhIFGRsf/aAAgBAQABPxDOQFt9a7gbWsLru1ycRUEAjJbBWGActkvYxwhbwlRCKSwoC5sGwsd/kpeSkMZPRL0ptbPzw//Z","aspectRatio":0.7647058823529411,"src":"/static/80e6d82107a1db055d4e32d8c709c04c/fa1ea/Rick.jpg","srcSet":"/static/80e6d82107a1db055d4e32d8c709c04c/afb2b/Rick.jpg 13w,\n/static/80e6d82107a1db055d4e32d8c709c04c/7c20e/Rick.jpg 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/fa1ea/Rick.jpg 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/03612/Rick.jpg 75w,\n/static/80e6d82107a1db055d4e32d8c709c04c/61cdf/Rick.jpg 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/0ff54/Rick.jpg 1200w","srcWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/e7b2c/Rick.webp","srcSetWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/58718/Rick.webp 13w,\n/static/80e6d82107a1db055d4e32d8c709c04c/74aad/Rick.webp 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/e7b2c/Rick.webp 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/ed320/Rick.webp 75w,\n/static/80e6d82107a1db055d4e32d8c709c04c/66016/Rick.webp 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/9000d/Rick.webp 1200w","sizes":"(max-width: 50px) 100vw, 50px"},"medium":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABRlsKyA51mANxhD//xAAcEAACAgIDAAAAAAAAAAAAAAABAgMSAAQREyD/2gAIAQEAAQUCCLCqVkRYwROt5aDCak7DFn2Dx3+P/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAgMAAwEAAAAAAAAAAAAAAAECESEQIDEy/9oACAEBAAY/AnuH1fEU/KIuMUtQ0WyoYedP/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBUSD/2gAIAQEAAT8hv6qbzGnBGvZesblRLKajqgyHnSZETPIHoo4SmR6uJW1r7fx//9oADAMBAAIAAwAAABCQyAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAeEAEAAgICAwEAAAAAAAAAAAABABEhMUFhIFGRsf/aAAgBAQABPxDOQFt9a7gbWsLru1ycRUEAjJbBWGActkvYxwhbwlRCKSwoC5sGwsd/kpeSkMZPRL0ptbPzw//Z","aspectRatio":0.7575757575757576,"src":"/static/80e6d82107a1db055d4e32d8c709c04c/61cdf/Rick.jpg","srcSet":"/static/80e6d82107a1db055d4e32d8c709c04c/7c20e/Rick.jpg 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/fa1ea/Rick.jpg 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/61cdf/Rick.jpg 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/59538/Rick.jpg 150w,\n/static/80e6d82107a1db055d4e32d8c709c04c/fd013/Rick.jpg 200w,\n/static/80e6d82107a1db055d4e32d8c709c04c/0ff54/Rick.jpg 1200w","srcWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/66016/Rick.webp","srcSetWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/74aad/Rick.webp 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/e7b2c/Rick.webp 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/66016/Rick.webp 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/d9b14/Rick.webp 150w,\n/static/80e6d82107a1db055d4e32d8c709c04c/6b183/Rick.webp 200w,\n/static/80e6d82107a1db055d4e32d8c709c04c/9000d/Rick.webp 1200w","sizes":"(max-width: 100px) 100vw, 100px"},"large":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAECAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABg1aVCDnTzVmwxB//xAAcEAACAgMBAQAAAAAAAAAAAAABAgADBBESEzH/2gAIAQEAAQUCCLSqFbEWsEXr3aUEJ5JyGLPkHXvKxsn7P//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAAICAwEAAAAAAAAAAAAAAAABAiEQETEy/9oACAEBAAY/AndHreIp8IuKStDRtmoUcLz/AP/EABwQAQACAgMBAAAAAAAAAAAAAAEAESFBEFFhMf/aAAgBAQABPyG/qJvMalEGO5aivuyVEsi17FYkyHWyJlDOoGoo0Sks2uN21r3cGsTBHvH/2gAMAwEAAgADAAAAEOAFMP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8QH//EAB4QAQACAwACAwAAAAAAAAAAAAEAESExQRBhUXGR/9oACAEBAAE/EOgIHnWvcZWNF17tdORkgCmxgpDIO2JkNMCFprBCQ1LCqA/mCCCO4l8SkMZPgh3MbW7+TJQfdQg2hB4//9k=","aspectRatio":0.7522935779816514,"src":"/static/80e6d82107a1db055d4e32d8c709c04c/ec46e/Rick.jpg","srcSet":"/static/80e6d82107a1db055d4e32d8c709c04c/a2637/Rick.jpg 82w,\n/static/80e6d82107a1db055d4e32d8c709c04c/15203/Rick.jpg 164w,\n/static/80e6d82107a1db055d4e32d8c709c04c/ec46e/Rick.jpg 328w,\n/static/80e6d82107a1db055d4e32d8c709c04c/b69a5/Rick.jpg 492w,\n/static/80e6d82107a1db055d4e32d8c709c04c/23a36/Rick.jpg 656w,\n/static/80e6d82107a1db055d4e32d8c709c04c/0ff54/Rick.jpg 1200w","srcWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/5a48e/Rick.webp","srcSetWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/2d087/Rick.webp 82w,\n/static/80e6d82107a1db055d4e32d8c709c04c/29d87/Rick.webp 164w,\n/static/80e6d82107a1db055d4e32d8c709c04c/5a48e/Rick.webp 328w,\n/static/80e6d82107a1db055d4e32d8c709c04c/42f2e/Rick.webp 492w,\n/static/80e6d82107a1db055d4e32d8c709c04c/dec03/Rick.webp 656w,\n/static/80e6d82107a1db055d4e32d8c709c04c/9000d/Rick.webp 1200w","sizes":"(max-width: 328px) 100vw, 328px"}}},"originalPath":"/authors/authors-rick","skip":6,"limit":6,"group":[{"id":"d23ba61d-85d1-54d9-9e3a-a76bc980252f","slug":"/how-to-build-environments-in-unity","secret":false,"title":"How to build environments in unity","author":"Rick","date":"April 1st, 2023","dateForSEO":"2023-04-01T00:00:00.000Z","timeToRead":6,"excerpt":"A complete guide to getting started with unity to create amazing environments. Along with how to get assets from the unity asset store. Covering post processing, terrain tools and using materials inside of unity.","canonical_url":null,"subscription":true,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"How to build environments in unity\",\n  \"author\": \"Rick\",\n  \"date\": \"2023-04-01T00:00:00.000Z\",\n  \"hero\": \"./images/unity-environment-hero.png\",\n  \"excerpt\": \"A complete guide to getting started with unity to create amazing environments. Along with how to get assets from the unity asset store. Covering post processing, terrain tools and using materials inside of unity.\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Quite a while ago now I was inspired by a piece of work which Lusion worked on \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.operanorth.co.uk/turn-of-the-screw-immersive-trailer/\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"Turn of the Screw\"), \". I thought to myself along time ago how can this be done?\"), mdx(\"p\", null, \"Recently I thought of unity again. Originally I didn\\u2019t really consider this seriously as I was under the impression shaders wouldnt work on webgl builds.\"), mdx(\"p\", null, \"I do stand corrected though! the URP (universal render pipeline) actually has really good support for webgl builds. The only downside is that you cant do unity on mobile and if you do sort out the memory issues on mobile, the webgl builds will only work on the top tier hardware.\"), mdx(\"p\", null, \"So what can be made with something like unity?\"), mdx(\"h2\", {\n    \"id\": \"the-project\"\n  }, \"The project\"), mdx(\"p\", null, \"I have been doing some studying for a while now and looked at quite a few of the settings on unity. This gave me a good grounding in what to do. Here is a timelapse of what im about to describe.\"), mdx(\"iframe\", {\n    src: \"https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7047320869450174464\",\n    height: \"551\",\n    width: \"504\",\n    frameBorder: \"0\",\n    allowFullScreen: \"\",\n    title: \"Embedded post\"\n  }), mdx(\"p\", null, \"The project will consist of creating a terrain, texturing it and then using terrain tools to place trees and details.\"), mdx(\"p\", null, \"And finally, do a small camera animation on load of the scene.\"), mdx(\"h2\", {\n    \"id\": \"terrain\"\n  }, \"Terrain\"), mdx(\"p\", null, \"You can create a terrain by going to Game Object \\u2014> 3D Object \\u2014> terrain.\"), mdx(\"p\", null, \"I created a folder in the project window at the bottom of the screen to store all my materials. I then right clicked in this folder on the project pane window, which gives you the option to create a material. I then set this material to a browny color.\"), mdx(\"p\", null, \"If we go back to the inspector window on the left with the terrain selected you will find the terrain settings on the far tab. You can then set the material here like so.\"), mdx(\"p\", null, \"Then when you select the terrain you will get several options on the right inspector window. One of which being - Paint Terrain. This will have a raise or lower terrain option we will be using. Mouse click on the terrain to increase height and ctrl + left mouse click click lowers the terrain under the brush.\"), mdx(\"p\", null, \"If you see the video in this post on linkedIn then you will see I played around with something until I was happy with it. Keeping in mind I wanted to try and have the terrain higher at the edges of my world map.\"), mdx(\"iframe\", {\n    src: \"https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7047320869450174464\",\n    height: \"543\",\n    width: \"504\",\n    frameBorder: \"0\",\n    allowFullScreen: \"\",\n    title: \"Embedded post\"\n  }), mdx(\"h2\", {\n    \"id\": \"packages-we-are-going-to-use\"\n  }, \"Packages we are going to use\"), mdx(\"p\", null, \"\\u2018Cartoon & Stylized HDRI sky Pack 02\\u2019 and \\u2018Stylized Nature Pack\\u2019 are the two packages I am going to use. The first which will provide the background and some of the lighting to the scene and the final one for the grass textures and trees.\"), mdx(\"p\", null, \"You can go to the packages via the window tab at the top and then install and import each of the above packages. Once they are imported you should see them in the project window at the bottom.\"), mdx(\"p\", null, \"One thing you will probably see is that the assets or prefabs are purple, this will be because you will need to set them up if they were built in a different pipeline to the one you are in.\"), mdx(\"p\", null, \"This is relatively straight forward. Click on the prefab and then in the inspector window on the right you can go to the shader material and go nature \\u2014> and then what ever shader we need, wether that be bark or leaves.\"), mdx(\"h2\", {\n    \"id\": \"hdri-background-image\"\n  }, \"HDRI background image\"), mdx(\"p\", null, \"The background image I chose was this one\"), mdx(\"p\", null, \"The way I used it is dragged onto the background of the window\"), mdx(\"h2\", {\n    \"id\": \"placing-trees-onto-the-terrain\"\n  }, \"Placing trees onto the terrain\"), mdx(\"p\", null, \"The terrain tools has a scattering tool, there are better paid versions of this but for now as Im learning this will do. Click on the terrain, go to the last tab which is for the settings and reduce the width and height to 100 x 100. Then go to this tab - Paint Trees.\"), mdx(\"p\", null, \"While here \\u2018edit trees\\u2019 and then add the prefab we just setup for the tree. This is a little confusing as we can use other prefabs which aren\\u2019t trees here, rocks for example or anything we want to scatter.\"), mdx(\"p\", null, \"Select the tree we just added in the list, after we could either mass place or select a brush and start painting onto the terrain.\"), mdx(\"p\", null, \"For now all we will do is mass place and use ctrl + left click to deselect trees on lower parts to create a sort of opening.\"), mdx(\"p\", null, \"By this time you should have a terrain which we have modelled and textured, along with a spread of trees mass placed and selectively removed in areas.\"), mdx(\"p\", null, \"You can change the color of the leafs and bark on this nature pack\\u2019s trees. This will allow you to coordinate the color scheme in the project. To do this just select the tree and go to the shaders at the bottom of the inspector window.\"), mdx(\"p\", null, \"One thing to bare in mind is with the terrain selected you will have to go to the last tab, which is terrain settings and then you will probably need to increase detail distance from 80 to something like 150 and then change when we start the billboard effect. To save system usage, unity can start to use billboards at a certain distance from the camera, we want this to be quite far away.\"), mdx(\"p\", null, \"Also make sure when you add trees to the pallete that there is no bend and that randow rotation is selected on the tree.\"), mdx(\"h2\", {\n    \"id\": \"placing-grass-textures-onto-the-terrain\"\n  }, \"Placing grass textures onto the terrain\"), mdx(\"p\", null, \"The next step I want to try and accomplish is spreading the grass onto the terrain, to do this go to the terrain details section and add a new grass texture like the one below. I used grass_4.png from the nature pack. It should be a white texture with opacity around the solid white.\"), mdx(\"p\", null, \"With the cursor over the terrain, you can start clicking and placing the grass. I tried to keep the grass solid in the opening and then patchy under the trees.\"), mdx(\"p\", null, \"The colors are entirely your decission but try and make it so the HDRI sky and tree colors are similar to maximise the effect of the scene.\"), mdx(\"p\", null, \"Remember you can always do crt + left click to remove grass or do ctrl + z to undo.\"), mdx(\"h2\", {\n    \"id\": \"particle-effects-from-nature-asset-pack\"\n  }, \"Particle effects from Nature asset pack\"), mdx(\"p\", null, \"If you go to the Nature asset pack in the project window you can see that there will be 2 effects we will want to use. These are particle effects. Light shafts and dust particles, with either one of these selected you can drag onto the scene and position + rotate them for maximum effect.\"), mdx(\"p\", null, \"This part of the work is very simple as we are using a commercial asset pack from the asset store, if we were to model or use graphs in unity it would get more complicated!\"), mdx(\"h2\", {\n    \"id\": \"post-processing-in-the-unity-scene\"\n  }, \"Post processing in the unity scene\"), mdx(\"p\", null, \"There is a package called post processing. This is the package we will use for vinigarrete and bloom. There are several steps we need to complete before the effects can be applied.\"), mdx(\"p\", null, \"First of all go to the package manager and install/import post processing. Once complete, if you right click in the root of your project in the project window, you should see the postprocessing volume profile option.\"), mdx(\"p\", null, \"So we need to do a few things before we can use bloom, create a postprocessing volume in the scene (top menu \\u2014> GameObject \\u2014> 3D Object \\u2014> Post -process Volume), create a Post processing Profile (project window \\u2014> right click \\u2014> create \\u2014> Post-processing Profile), drag the profile on the camera, and with the camera selected create a post processing layer component, select a postprocessing layer or create and select the layer, ensure the layer is selected on the volume we created earlier and there ya go, we should be able to go onto the volume and select bloom etc.\"), mdx(\"h2\", {\n    \"id\": \"camera-animation\"\n  }, \"Camera animation\"), mdx(\"p\", null, \"For the camera animation we need to create a camera animation controller and animation clip. To do this go to the project window and ricght click \\u2014> create \\u2014> Animation Controller and Animation.\"), mdx(\"p\", null, \"Drag the animation onto the controller and then drag the controller onto the camera in the hierarchy window. Having done this we can now select the camera and animate! First off, double click on the animation clip.\"), mdx(\"p\", null, \"The first key frame is done for us, but we can add a property with the camera selected, I did position.\"), mdx(\"p\", null, \"We can then move the frames forward slightly and put a new key frame in, this way the camera will animate when we play the animation clip.\"), mdx(\"h2\", {\n    \"id\": \"netlify-and-webgl-builds\"\n  }, \"Netlify and webgl builds\"), mdx(\"p\", null, \"The key thing I wanted to do is to get this on a website. The critical information you need to know is this does not work on mobile devices, there are memory problems which cause the unity project not to load on mobile. And unity even officially says it doesnt support mobile devices for webgl builds.\"), mdx(\"p\", null, \"With this in mind we can do a webgl build and compress the build files. Once we have the build files, we can place them in the public folder of our react project (mine is built with nextjs, but in general any react project would have them here). Here is my webgl build component.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"\\\"client\\\";\\nimport { useState, useRef, useEffect } from \\\"react\\\";\\nimport { Unity, useUnityContext } from \\\"react-unity-webgl\\\";\\n\\nconst WebglBuild = () => {\\n  const { unityProvider } = useUnityContext({\\n    loaderUrl: \\\"/build/test2.loader.js\\\",\\n    dataUrl: \\\"/build/test2.data\\\",\\n    frameworkUrl: \\\"/build/test2.framework.js\\\",\\n    codeUrl: \\\"/build/test2.wasm\\\",\\n  });\\n\\n  return (\\n    <Unity\\n      unityProvider={unityProvider}\\n      style={{ width: \\\"100%\\\", height: \\\"100%\\\" }}\\n    />\\n  );\\n};\\n\\nexport default WebglBuild;\\n\")), mdx(\"p\", null, \"And to serve the compressed files you have to tell netlify to give certain files a header when you request specific files, which will cause the compressed one to be donwloaded and un compressed. Here is my netlify.yml file.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-yml\"\n  }, \"# Define the headers to be used on all paths\\nheaders:\\n  - for: \\\"/*.js\\\"\\n    headers:\\n      Content-Encoding: \\\"br\\\"\\n  - for: \\\"/*.data\\\"\\n    headers:\\n      Content-Encoding: \\\"br\\\"\\n  - for: \\\"/*.wasm\\\"\\n    headers:\\n      Content-Encoding: \\\"br\\\"\\n\")), mdx(\"p\", null, \"Essentially if we request a js, data or wasm then we want to serve the br compressed file format. The browser will automatically unwrap this compressed file.\"));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABmUlEQVQoz22Ra28SQRSG+QUtlK6gbVXYnWV39mZZLGxIjVs13oIfWkiRUAPl0tIq2sQP/gT/9ePMBgyafngyZ3LO+545c3Kj0YjBYMBwOGQ6nfPt9ie313crfnAzX7Jc3LGYf2c++cpMcTVbZvnrqxu0XjMej5V+Ss73fRzHwbQskrjB5FOfSafPtDPg8v1nZm96XL465eKkSzft0Uu7nKZn9N/2VX1C1awihMBSek0uCAKiKCIIQ5L6IZ2kwYck5vXzmFSGpMKlbUleWi4v/IiTOOZdq0GnfaQMDzNdpAhX5DzPQ5vqi7BsSsYexu4jKvldPhoGZ3v7/G4fc3Gwz1G+SKlQorhT5kGxjDBFptNTag9NZiilNvWpPLXY3ipjFB5yLhwWvuSL6/IrOabrBAjjgJ3tMgVFfqtEtXKPYaxGaDabxPU6z9TIYRTg1GrUVaPQldTsGo+rJk9M9UfCxlZ3sTrX0/1jmCRJ1kVKmRV4voerXmWrRdUUOvZUTkoXqWJ3g03DNblWq5Vt+X/+CnV8T16z+bI1fwDPZgMa+3PeCgAAAABJRU5ErkJggg==","aspectRatio":2.5376344086021505,"src":"/static/635ef334ba7b4760aaab430ed15ee147/a1946/unity-environment-hero.png","srcSet":"/static/635ef334ba7b4760aaab430ed15ee147/5b37e/unity-environment-hero.png 236w,\n/static/635ef334ba7b4760aaab430ed15ee147/49058/unity-environment-hero.png 472w,\n/static/635ef334ba7b4760aaab430ed15ee147/a1946/unity-environment-hero.png 944w,\n/static/635ef334ba7b4760aaab430ed15ee147/030f1/unity-environment-hero.png 1416w,\n/static/635ef334ba7b4760aaab430ed15ee147/75927/unity-environment-hero.png 1888w,\n/static/635ef334ba7b4760aaab430ed15ee147/b99c0/unity-environment-hero.png 3440w","srcWebp":"/static/635ef334ba7b4760aaab430ed15ee147/99fbb/unity-environment-hero.webp","srcSetWebp":"/static/635ef334ba7b4760aaab430ed15ee147/77392/unity-environment-hero.webp 236w,\n/static/635ef334ba7b4760aaab430ed15ee147/1f177/unity-environment-hero.webp 472w,\n/static/635ef334ba7b4760aaab430ed15ee147/99fbb/unity-environment-hero.webp 944w,\n/static/635ef334ba7b4760aaab430ed15ee147/4a492/unity-environment-hero.webp 1416w,\n/static/635ef334ba7b4760aaab430ed15ee147/b0b8f/unity-environment-hero.webp 1888w,\n/static/635ef334ba7b4760aaab430ed15ee147/f0969/unity-environment-hero.webp 3440w","sizes":"(max-width: 944px) 100vw, 944px"},"regular":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABmUlEQVQoz22Ra28SQRSG+QUtlK6gbVXYnWV39mZZLGxIjVs13oIfWkiRUAPl0tIq2sQP/gT/9ePMBgyafngyZ3LO+545c3Kj0YjBYMBwOGQ6nfPt9ie313crfnAzX7Jc3LGYf2c++cpMcTVbZvnrqxu0XjMej5V+Ss73fRzHwbQskrjB5FOfSafPtDPg8v1nZm96XL465eKkSzft0Uu7nKZn9N/2VX1C1awihMBSek0uCAKiKCIIQ5L6IZ2kwYck5vXzmFSGpMKlbUleWi4v/IiTOOZdq0GnfaQMDzNdpAhX5DzPQ5vqi7BsSsYexu4jKvldPhoGZ3v7/G4fc3Gwz1G+SKlQorhT5kGxjDBFptNTag9NZiilNvWpPLXY3ipjFB5yLhwWvuSL6/IrOabrBAjjgJ3tMgVFfqtEtXKPYaxGaDabxPU6z9TIYRTg1GrUVaPQldTsGo+rJk9M9UfCxlZ3sTrX0/1jmCRJ1kVKmRV4voerXmWrRdUUOvZUTkoXqWJ3g03DNblWq5Vt+X/+CnV8T16z+bI1fwDPZgMa+3PeCgAAAABJRU5ErkJggg==","aspectRatio":2.546875,"src":"/static/635ef334ba7b4760aaab430ed15ee147/3ddd4/unity-environment-hero.png","srcSet":"/static/635ef334ba7b4760aaab430ed15ee147/078a8/unity-environment-hero.png 163w,\n/static/635ef334ba7b4760aaab430ed15ee147/e56da/unity-environment-hero.png 327w,\n/static/635ef334ba7b4760aaab430ed15ee147/3ddd4/unity-environment-hero.png 653w,\n/static/635ef334ba7b4760aaab430ed15ee147/c5cc7/unity-environment-hero.png 980w,\n/static/635ef334ba7b4760aaab430ed15ee147/eebd2/unity-environment-hero.png 1306w,\n/static/635ef334ba7b4760aaab430ed15ee147/b99c0/unity-environment-hero.png 3440w","srcWebp":"/static/635ef334ba7b4760aaab430ed15ee147/0acdf/unity-environment-hero.webp","srcSetWebp":"/static/635ef334ba7b4760aaab430ed15ee147/ac59e/unity-environment-hero.webp 163w,\n/static/635ef334ba7b4760aaab430ed15ee147/7660b/unity-environment-hero.webp 327w,\n/static/635ef334ba7b4760aaab430ed15ee147/0acdf/unity-environment-hero.webp 653w,\n/static/635ef334ba7b4760aaab430ed15ee147/75470/unity-environment-hero.webp 980w,\n/static/635ef334ba7b4760aaab430ed15ee147/68d47/unity-environment-hero.webp 1306w,\n/static/635ef334ba7b4760aaab430ed15ee147/f0969/unity-environment-hero.webp 3440w","sizes":"(max-width: 653px) 100vw, 653px"},"narrow":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAYAAAD5nd/tAAAACXBIWXMAAAsTAAALEwEAmpwYAAABmUlEQVQoz22Ra28SQRSG+QUtlK6gbVXYnWV39mZZLGxIjVs13oIfWkiRUAPl0tIq2sQP/gT/9ePMBgyafngyZ3LO+545c3Kj0YjBYMBwOGQ6nfPt9ie313crfnAzX7Jc3LGYf2c++cpMcTVbZvnrqxu0XjMej5V+Ss73fRzHwbQskrjB5FOfSafPtDPg8v1nZm96XL465eKkSzft0Uu7nKZn9N/2VX1C1awihMBSek0uCAKiKCIIQ5L6IZ2kwYck5vXzmFSGpMKlbUleWi4v/IiTOOZdq0GnfaQMDzNdpAhX5DzPQ5vqi7BsSsYexu4jKvldPhoGZ3v7/G4fc3Gwz1G+SKlQorhT5kGxjDBFptNTag9NZiilNvWpPLXY3ipjFB5yLhwWvuSL6/IrOabrBAjjgJ3tMgVFfqtEtXKPYaxGaDabxPU6z9TIYRTg1GrUVaPQldTsGo+rJk9M9UfCxlZ3sTrX0/1jmCRJ1kVKmRV4voerXmWrRdUUOvZUTkoXqWJ3g03DNblWq5Vt+X/+CnV8T16z+bI1fwDPZgMa+3PeCgAAAABJRU5ErkJggg==","aspectRatio":2.533333333333333,"src":"/static/635ef334ba7b4760aaab430ed15ee147/502b1/unity-environment-hero.png","srcSet":"/static/635ef334ba7b4760aaab430ed15ee147/f2e6d/unity-environment-hero.png 114w,\n/static/635ef334ba7b4760aaab430ed15ee147/4ddba/unity-environment-hero.png 229w,\n/static/635ef334ba7b4760aaab430ed15ee147/502b1/unity-environment-hero.png 457w,\n/static/635ef334ba7b4760aaab430ed15ee147/7ddc2/unity-environment-hero.png 686w,\n/static/635ef334ba7b4760aaab430ed15ee147/435bf/unity-environment-hero.png 914w,\n/static/635ef334ba7b4760aaab430ed15ee147/b99c0/unity-environment-hero.png 3440w","srcWebp":"/static/635ef334ba7b4760aaab430ed15ee147/15384/unity-environment-hero.webp","srcSetWebp":"/static/635ef334ba7b4760aaab430ed15ee147/31fce/unity-environment-hero.webp 114w,\n/static/635ef334ba7b4760aaab430ed15ee147/e3e25/unity-environment-hero.webp 229w,\n/static/635ef334ba7b4760aaab430ed15ee147/15384/unity-environment-hero.webp 457w,\n/static/635ef334ba7b4760aaab430ed15ee147/0258d/unity-environment-hero.webp 686w,\n/static/635ef334ba7b4760aaab430ed15ee147/64ea2/unity-environment-hero.webp 914w,\n/static/635ef334ba7b4760aaab430ed15ee147/f0969/unity-environment-hero.webp 3440w","sizes":"(max-width: 457px) 100vw, 457px"},"seo":{"src":"/static/635ef334ba7b4760aaab430ed15ee147/6050d/unity-environment-hero.png"}}},{"id":"4f579eb0-5864-585a-ac16-8b96fa1b4cfe","slug":"/how-to-animate-grass-and-alpha-clipped-grass-in-react-three-fiber-using-glsl","secret":false,"title":"How to animate grass and alpha clipped grass in react three fiber using GLSL","author":"Rick","date":"March 31st, 2023","dateForSEO":"2023-03-31T00:00:00.000Z","timeToRead":2,"excerpt":"This is the perfect way to animate grass which is created using alpha clipped planes using alpha maps. This can easily be adapted to follow an origin or empty, which would signify the wind in a scene. Follow previous tutorials to instance grass onto a plane from blender. This would be the precursor to animating this grass!","canonical_url":null,"subscription":true,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"How to animate grass and alpha clipped grass in react three fiber using GLSL\",\n  \"author\": \"Rick\",\n  \"date\": \"2023-03-31T00:00:00.000Z\",\n  \"hero\": \"./images/wavy-grass-hero.png\",\n  \"excerpt\": \"This is the perfect way to animate grass which is created using alpha clipped planes using alpha maps. This can easily be adapted to follow an origin or empty, which would signify the wind in a scene. Follow previous tutorials to instance grass onto a plane from blender. This would be the precursor to animating this grass!\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"This is going to be a really quick look at a really cool way to animate grass. Which I got inspiration from a great tutorial on how to create stylized grass from \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://m.youtube.com/watch?v=RjDyR_lIWm4\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"Pierrick Picaut\"), \".\"), mdx(\"p\", null, \"This tutorial goes in depth on how to accomplish the effect of stylized grass in blender and looks at animating the grass! I wont be going into loads of details on how to export grass from blender as this has been covered in previous tutorials on thefrontdev, but I will be explaining how I create animated grass in a similar way.\"), mdx(\"iframe\", {\n    src: \"https://codesandbox.io/embed/jolly-solomon-fcizk9?fontsize=14&hidenavigation=1&theme=dark&view=preview\",\n    style: {\n      \"width\": \"100%\",\n      \"height\": \"500px\",\n      \"border\": \"0\",\n      \"borderRadius\": \"4px\",\n      \"overflow\": \"hidden\",\n      \"maxWidth\": \"500px\"\n    },\n    title: \"jolly-solomon-fcizk9\",\n    allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\",\n    sandbox: \"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n  }), mdx(\"h2\", {\n    \"id\": \"the-tutorial\"\n  }, \"The tutorial\"), mdx(\"p\", null, \"Pierrick Picaut does some truly inspirational tutorials and you can learn a lot about shaders and how to accomplish lots of different effects by watching his YouTube videos.\"), mdx(\"p\", null, \"This one really struck me as a really good example of porting to raw GLSL and @react-three/fiber. In particular the part about using noise to animate the alpha clipped grass.\"), mdx(\"h2\", {\n    \"id\": \"alpha-clipping-and-alpha-maps\"\n  }, \"Alpha clipping and alpha maps\"), mdx(\"p\", null, \"The alpha map is just a image which has a object in it where parts of the image have an opacity lower than 1. \"), mdx(\"p\", null, \"opacity = 1 === fully opaque \"), mdx(\"p\", null, \"opacity = 0 === effectively invisible \"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1024px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"100%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAAsSAAALEgHS3X78AAAB8klEQVQ4y52TzUtUURiHZ8YPKkmtDFIXBmoZuJjKwtI0IYpMJRNURgIlyUooREnQbGkEgm5cGq4scOeuf26m5xe/MxyuV3G88HDee8573u+TyZzxK5VKxygWi/+p+GIKl+FC+D+TQXk+wVgNvIz3zhthzk6ewrDlXCUGlVJdiJQ16/0N6LCcrSRlKfcmUr8Bu8nGnPrZQIjmVRSNGIaflqtSa5j0FurltQ/eRmffYT6OOtm8kxoQIrwNP6L9Q3gI3XAl7W7aeARjt+A6/IJL2kf3L+tVyEN/IptjEcYH12DEzn5DO7TCkQ3qfyFq3sU0g43QbHkAnlv+w6W7rPdYD0BNugNLUAtN0Bayi4vboKH1+5T3LpChfY2PB3oPnnEux1+gBfmxDIbSJdOd1TDDqsdFT2wbnsA4bME7687DILxxdtqrLjfBHmZZNSqf4D5MwJoawP6cHS15BnU2x/57ByT9XDAYhvc1Ch9YZ+QdWZc+Qg98hkUbUFMKyCs2OuCZLacs6w84eMS6CWOqlV9KwSO0alnkXedvzmbRo1U2WI2CDoZgxzUbdKcnPEZf4QVMKiP0N2AZ1p1RJqRc5RpOuuCbjrjXEY5aWRGqo9Pqrpu1IMPS93Rk45fR7o5NwU1H0e/nl3FknaCy1LumymAkfob/AC/zO+ba+q7KAAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/0c19430c129832b18280475d2fa03f0f/53334/grass_4.webp 1024w\"],\n    \"sizes\": \"(max-width: 1024px) 100vw, 1024px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/0c19430c129832b18280475d2fa03f0f/658fc/grass_4.png 1024w\"],\n    \"sizes\": \"(max-width: 1024px) 100vw, 1024px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/0c19430c129832b18280475d2fa03f0f/658fc/grass_4.png\",\n    \"alt\": \"Wavy grass base alpha map\",\n    \"title\": \"Wavy grass base alpha map\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"So how can we leverage this in a fragment shader?\"), mdx(\"p\", null, \"In the fragment shader, you would sample the alpha map and get the r channel like below:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"float alpha = texture2D(grassTexture, uvs).r;\\n//If transparent, don't draw\\nif (alpha < 0.005) discard;\\n\")), mdx(\"p\", null, \"This bit of code in the main function of a fragment shader will do the following, check if the alpha is below 0.005. So basically is this fragment of the material invisible and if so we use the GLSL key word - discard. This will tell the fragment shader to discard this fragment for every run of the shader where the fragments opacity is below 0.005.\"), mdx(\"p\", null, \"and thats it, its that simple!\"), mdx(\"p\", null, \"I bet you can imagine why this would be useful in situations like these or when using points and you want a custom shape on each point.\"), mdx(\"h2\", {\n    \"id\": \"vertex-and-fragment-shaders\"\n  }, \"Vertex and Fragment shaders\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"export const vertexShader = `\\nvarying vec2 vUv;\\nvarying vec3 pos;\\nvoid main () {\\n  vUv = uv;\\n  pos = position;\\n  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\\n}\\n`;\\n\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"import { noise3D } from \\\"./noise\\\";\\n\\nexport const fragmentShader = `\\nuniform float time;\\nuniform sampler2D grassTexture;\\n\\nvarying vec3 pos;\\nvarying vec2 vUv;\\n\\n${noise3D}\\n\\nvoid main () {\\n  float scaledNoise = .0190;\\n  float noise = noise(pos);\\n\\n  float wavyStrength = sin(time + pos.y)* 0.04;\\n  vec2 uvs = vec2(mix(vUv.x, noise * scaledNoise , wavyStrength ), vUv.y);\\n\\n  float alpha = texture2D(grassTexture, uvs).r;\\n  //If transparent, don't draw\\n  if (alpha < 0.005) discard;\\n\\n  vec4 color = texture2D(grassTexture, uvs.xy);\\n  gl_FragColor = color;\\n}\\n`;\\n\")), mdx(\"p\", null, \"The vertex shader is pretty bog standard and the only special thing is we pass 2 varyings to the fragment shader, pos and vUv.\"), mdx(\"p\", null, \"The fragment shader is where it all happens.\"), mdx(\"p\", null, \"First off we get the noise using \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \" gist which has kindly collated it from various places.\"), mdx(\"p\", null, \"Then we use a sine modulator to get the sway back and forth.\"), mdx(\"p\", null, \"During which we use the y positional coordinate which will apply a sin wave in the y axis. We slow this down to 4% (0.04) of its speed as we don\\u2019t want a super fast animation, sometimes its all about the subtle animations which would make a scene.\"), mdx(\"p\", null, \"The code below is how we control the speed of the waviness.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"vec2 uvs = vec2(mix(vUv.x, noise * scaledNoise , wavyStrength ), vUv.y);\\n\")), mdx(\"p\", null, \"We mix noise we created earlier with the x coordinate from the uvs and use the oscillating wavyStrength to control how much noise is applied to the x axis of the uvs.\"), mdx(\"p\", null, \"Giving the overall effect of wavy grass in the wind! Obviously this is still quite strong so you could slow it down further or decrease the applied noise by decreasing the scale even further.\"), mdx(\"p\", null, \"The final part is the color, or which you can put any color here you like. If you has loads of grass planes you could use the positional values of each vertex to get a noise value and then apply this to the grass color. And as each plane would have a different position you could have patchy grass. \"));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABQUlEQVQoz41TuYoCQRRsD7ww00BBQQMDMy9QA1GMRDwxWI0UEQxM9CP86e3tqn1zuMyo42xQzGteV9H16o2iUvwEuKDn+1x7ocLEnmsUCkQ0GiiqwsQssk9sOHTqSOS9IDy2fHAJKBaJfN6p12uiXPb3n6DCZshSiWy3yVyOPJ0Ydl/9iCUdj79CXqATCepul3owoJ7NqMdj6mqVWoh2z3P/W2CEY1u2ij9Y51TKQa1GM53SzOc0+z1Np0PTbNJkMn6Oi2DL0qQQaQUgQtxuyfOZbLXIyYTMZoMtvwzWSjWZJJZLJ4Tdjth+EYcDMRoRxyNRqTAoTPV2get14nYjxCpkbthsiMWCWK2I+93uP1bn4x4+LkCSxfVKNBqE2ESvR/T7zqsvF8JK/F+C3mWWwUOSg6SJWMwZgwSFdPrtr/jAL2zF+nP0e0GAAAAAAElFTkSuQmCC","aspectRatio":1.6054421768707483,"src":"/static/8d941d57ab7928d7bba929f67fd56109/95d9d/wavy-grass-hero.png","srcSet":"/static/8d941d57ab7928d7bba929f67fd56109/5b37e/wavy-grass-hero.png 236w,\n/static/8d941d57ab7928d7bba929f67fd56109/49058/wavy-grass-hero.png 472w,\n/static/8d941d57ab7928d7bba929f67fd56109/95d9d/wavy-grass-hero.png 634w","srcWebp":"/static/8d941d57ab7928d7bba929f67fd56109/d18ea/wavy-grass-hero.webp","srcSetWebp":"/static/8d941d57ab7928d7bba929f67fd56109/77392/wavy-grass-hero.webp 236w,\n/static/8d941d57ab7928d7bba929f67fd56109/1f177/wavy-grass-hero.webp 472w,\n/static/8d941d57ab7928d7bba929f67fd56109/d18ea/wavy-grass-hero.webp 634w","sizes":"(max-width: 634px) 100vw, 634px"},"regular":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAYAAACpUE5eAAAACXBIWXMAAAsTAAALEwEAmpwYAAABQElEQVQ4y42TSYsCMRCFo6gH9eTyA0RRkZ6LnhQREVxABNeLC4h48Kz45+P0e1OxYeju6Yx9eFQRki9VrxJFpfhJ8EWE1sJScWBhEHI5K1TFqeydJxJebDaJajWwFgAiVMUfpdNEsejlySSx3xOZjHW/iuMhez0vdrvkdOrlAo/00FBdKf1frdd0SyW6lwtdx6ErFbqWc+pbbtKpFF9+SZsm6myW+suhXq2oJxNqAetOh7pc5kugr9A5w4lu2ZhdKJCtFjkakbsdeb2S4zHZ75P1OimHrS0HZIw3sdEgFgtisyHOZ0KAEP8wmxECfQ/r01B+31o+T0hlOJ2I+ZyQVnE4EMslsd0StxshdkS9RTvw8SCOR2Iw8ODSNoZD4vkk7nfrj1HWb2babbeJWo2oVAgZxtsGY4HJ4wCjNsXJ/foBnxIkhDZYDOgAAAAASUVORK5CYII=","aspectRatio":1.5980392156862746,"src":"/static/8d941d57ab7928d7bba929f67fd56109/95d9d/wavy-grass-hero.png","srcSet":"/static/8d941d57ab7928d7bba929f67fd56109/078a8/wavy-grass-hero.png 163w,\n/static/8d941d57ab7928d7bba929f67fd56109/e56da/wavy-grass-hero.png 327w,\n/static/8d941d57ab7928d7bba929f67fd56109/95d9d/wavy-grass-hero.png 634w","srcWebp":"/static/8d941d57ab7928d7bba929f67fd56109/d18ea/wavy-grass-hero.webp","srcSetWebp":"/static/8d941d57ab7928d7bba929f67fd56109/ac59e/wavy-grass-hero.webp 163w,\n/static/8d941d57ab7928d7bba929f67fd56109/7660b/wavy-grass-hero.webp 327w,\n/static/8d941d57ab7928d7bba929f67fd56109/d18ea/wavy-grass-hero.webp 634w","sizes":"(max-width: 634px) 100vw, 634px"},"narrow":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAACXBIWXMAAAsTAAALEwEAmpwYAAABQUlEQVQoz41TuYoCQRRsD7ww00BBQQMDMy9QA1GMRDwxWI0UEQxM9CP86e3tqn1zuMyo42xQzGteV9H16o2iUvwEuKDn+1x7ocLEnmsUCkQ0GiiqwsQssk9sOHTqSOS9IDy2fHAJKBaJfN6p12uiXPb3n6DCZshSiWy3yVyOPJ0Ydl/9iCUdj79CXqATCepul3owoJ7NqMdj6mqVWoh2z3P/W2CEY1u2ij9Y51TKQa1GM53SzOc0+z1Np0PTbNJkMn6Oi2DL0qQQaQUgQtxuyfOZbLXIyYTMZoMtvwzWSjWZJJZLJ4Tdjth+EYcDMRoRxyNRqTAoTPV2get14nYjxCpkbthsiMWCWK2I+93uP1bn4x4+LkCSxfVKNBqE2ESvR/T7zqsvF8JK/F+C3mWWwUOSg6SJWMwZgwSFdPrtr/jAL2zF+nP0e0GAAAAAAElFTkSuQmCC","aspectRatio":1.6056338028169015,"src":"/static/8d941d57ab7928d7bba929f67fd56109/502b1/wavy-grass-hero.png","srcSet":"/static/8d941d57ab7928d7bba929f67fd56109/f2e6d/wavy-grass-hero.png 114w,\n/static/8d941d57ab7928d7bba929f67fd56109/4ddba/wavy-grass-hero.png 229w,\n/static/8d941d57ab7928d7bba929f67fd56109/502b1/wavy-grass-hero.png 457w,\n/static/8d941d57ab7928d7bba929f67fd56109/95d9d/wavy-grass-hero.png 634w","srcWebp":"/static/8d941d57ab7928d7bba929f67fd56109/15384/wavy-grass-hero.webp","srcSetWebp":"/static/8d941d57ab7928d7bba929f67fd56109/31fce/wavy-grass-hero.webp 114w,\n/static/8d941d57ab7928d7bba929f67fd56109/e3e25/wavy-grass-hero.webp 229w,\n/static/8d941d57ab7928d7bba929f67fd56109/15384/wavy-grass-hero.webp 457w,\n/static/8d941d57ab7928d7bba929f67fd56109/d18ea/wavy-grass-hero.webp 634w","sizes":"(max-width: 457px) 100vw, 457px"},"seo":{"src":"/static/8d941d57ab7928d7bba929f67fd56109/95d9d/wavy-grass-hero.png"}}},{"id":"b6f26ab6-9a0a-531b-a3e3-d871951a6e23","slug":"/want-to-make-a-cool-shader-in-three-then-come-read-on!","secret":false,"title":"Want to make a cool shader in three ? then come read on!","author":"Rick","date":"March 27th, 2023","dateForSEO":"2023-03-27T00:00:00.000Z","timeToRead":1,"excerpt":"Really cool tutorial on how to use custom shaders to make abstract visuals and integrate with threejs and USING GLSL. Look at the code example for some indepth detail on how to create something like this!","canonical_url":null,"subscription":true,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Want to make a cool shader in three ? then come read on!\",\n  \"author\": \"Rick\",\n  \"date\": \"2023-03-27T00:00:00.000Z\",\n  \"hero\": \"./images/mysterious-cube-hero.png\",\n  \"excerpt\": \"Really cool tutorial on how to use custom shaders to make abstract visuals and integrate with threejs and USING GLSL. Look at the code example for some indepth detail on how to create something like this!\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"iframe\", {\n    src: \"https://codesandbox.io/embed/gracious-nightingale-wxqze1?fontsize=14&hidenavigation=1&theme=dark&view=preview\",\n    style: {\n      \"width\": \"100%\",\n      \"height\": \"500px\",\n      \"border\": \"0\",\n      \"borderRadius\": \"4px\",\n      \"overflow\": \"hidden\",\n      \"maxWidth\": \"500px\"\n    },\n    title: \"gracious-nightingale-wxqze1\",\n    allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\",\n    sandbox: \"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n  }), mdx(\"p\", null, \"I\\u2019m a big advacate of learning by doing something. In my spare time around my day job I practice shaders quite often; I find it very useful to play around with node graphs in software like blender, unity or unreal. The benefit being you get a deep understanding of the code behind the nodes, which allow you to do more complex and exciting shaders.\"), mdx(\"p\", null, \"This was a project which was really fun to do! and I did around christmass \\uD83D\\uDE42\"), mdx(\"p\", null, \"It involved playing around with noise and applying this to on hover or onEnter event in @react-three/fiber.\"), mdx(\"h2\", {\n    \"id\": \"the-shaders\"\n  }, \"The Shaders\"), mdx(\"p\", null, \"Please find the code below, this involved a pretty basic vertex and fragment shader.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"varying vec2 vUv;\\nvarying vec3 pos;\\nvarying vec3 norm;\\n\\nvoid main() {\\n  vUv = uv;\\n  norm = normal;\\n  pos = (vec4(position, 1.0)).xyz;\\n  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\\n}\\n\")), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"uniform float time;\\nuniform vec2 resolution;\\nuniform vec3 origin;\\nuniform float radius;\\nvarying vec2 vUv;\\nvarying vec3 pos;\\n\\n\\n#pragma glslify: random = require(glsl-random)\\n#define iterations 25\\n#define mod3 vec3(.1031, .11369, .13787)\\n\\nvec3 hash3_3(vec3 p3) {\\np3 = fract(p3 * mod3);\\n  p3 += dot(p3, p3.yxz + 19.19);\\n  return -1. + 2. * fract(vec3((p3.x + p3.y) * p3.z, (p3.x+p3.z) * p3.y, (p3.y+p3.z) * p3.x));\\n}\\n\\nfloat perlin_noise3(vec3 p) {\\n  vec3 pi = floor(p);\\n  vec3 pf = p - pi;\\n\\n  vec3 w = pf * pf * (3. - 2. * pf);\\n\\n  return    mix(\\n    mix(\\n          mix(\\n              dot(pf - vec3(0, 0, 0), hash3_3(pi + vec3(0, 0, 0))),\\n              dot(pf - vec3(1, 0, 0), hash3_3(pi + vec3(1, 0, 0))),\\n              w.x),\\n          mix(\\n              dot(pf - vec3(0, 0, 1), hash3_3(pi + vec3(0, 0, 1))),\\n              dot(pf - vec3(1, 0, 1), hash3_3(pi + vec3(1, 0, 1))),\\n              w.x),\\n    w.z),\\n      mix(\\n          mix(\\n              dot(pf - vec3(0, 1, 0), hash3_3(pi + vec3(0, 1, 0))),\\n              dot(pf - vec3(1, 1, 0), hash3_3(pi + vec3(1, 1, 0))),\\n              w.x),\\n          mix(\\n              dot(pf - vec3(0, 1, 1), hash3_3(pi + vec3(0, 1, 1))),\\n              dot(pf - vec3(1, 1, 1), hash3_3(pi + vec3(1, 1, 1))),\\n              w.x),\\n     w.z),\\nw.y);\\n}\\n\\n\\nfloat noise_sum_abs3(vec3 p) {\\n  float f = 0.;\\n  p = p * 3.;\\n  f += 1.0000 * abs(perlin_noise3(p)); p = 2. * p;\\n  f += 0.5000 * abs(perlin_noise3(p)); p = 3. * p;\\n  f += 0.2500 * abs(perlin_noise3(p)); p = 4. * p;\\n  f += 0.1250 * abs(perlin_noise3(p)); p = 5. * p;\\n  f += 0.0625 * abs(perlin_noise3(p)); p = 6. * p;\\n\\n  return f;\\n}\\n\\n\\n\\nvoid main() {\\n  vec2 temp = vUv;\\n  float noise = noise_sum_abs3(pos * 20.2 / radius * 0.1);\\n  vec3 mixed = mix(pos, origin, noise);\\n\\n  vec3 color = vec3(0.01* (noise), 0.01*  (noise), 0.02 *  (noise));\\n\\n  float noisyRadius = radius * (noise);\\n  if (noisyRadius - length(pos - origin) > 0.0) {\\n    if (noisyRadius - length(pos - origin) < pow(noise, 9.0) * 50.0) {\\n      color = vec3(0.0021 * noise * length(mixed) * 40.0 / length(pos - origin) ,0.0021 * noise * length(mixed) * 40.0 / length(pos - origin),0.05 * noise * length(mixed) * 40.0 / length(pos - origin));\\n    }\\n  }\\n  gl_FragColor.rgba = vec4(color, 1.0);\\n}\\n\")), mdx(\"p\", null, \"The vertex shader is just bog standard with nothing special but several varyings we pass to the fragment shader.\"), mdx(\"p\", null, \"The fragment shader is where the magic happens and is where the visuals come from.\"), mdx(\"p\", null, \"The uniforms then varyings go first as usual in the fragment shader.We have some noise functions at the top of the file which we use to shape the surface effect on this cube.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"// Get noise value using expanding or contracting radius\\nfloat noise = noise_sum_abs3(pos * 20.2 / radius * 0.1);\\n\\n// We get a point between the position of the fragment and the origin\\n// of the hover effect. This essentially maps the shape of the noise // onto the color below.\\nvec3 mixed = mix(pos, origin, noise);\\n\\n// This is the whiter color which gives the greyed out effect.\\nvec3 color = vec3(0.01* (noise), 0.01*  (noise), 0.02 *  (noise));\\n\\nfloat noisyRadius = radius * (noise);\\nif (noisyRadius - length(pos - origin) > 0.0) {\\n  if (noisyRadius - length(pos - origin) < pow(noise, 9.0) * 50.0) {\\n    // This is the part of the code which gives the white and blue colors\\n    color = vec3(0.0021 * noise * length(mixed) * 40.0 / length(pos - origin) ,0.0021 * noise * length(mixed) * 40.0 / length(pos - origin),0.05 * noise * length(mixed) * 40.0 / length(pos - origin));\\n  }\\n}\\n\\n// So we either have the greayed out colours or the whitey blue colors.\\ngl_FragColor.rgba = vec4(color, 1.0);\\n\")), mdx(\"p\", null, \"Above is a brief explanation of what the code does, alot of this was me playing around with gradiented noise and SDF\\u2019s/noise radi.\"), mdx(\"p\", null, \"Hope you like playing around with it.\"), mdx(\"p\", null, \"Pretty short article but have a play with the code and add or remove things!\"));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAChElEQVQ4y2VUu24TURDd1929j33Z3jhObMckEQlEiYJASNCliRIJpFSIFoGEREVBxVfwH+lp6WmR4E+oD2dmHSfBxbXvzp0598yZsxslSYIoinQZY+C9132SRCgKi6Oj7zg+/gFrA5rmBcryKZzLkJkCUhvH8apelwRk5XmuYHEcYTx+i8nkDYtnCGGPwBs8TzCbfcDh4TUvLvFwZjDpAkH+A5SfoihQVZUG8rzGfP6RzK7RjZ6jGbQYjjfgXcecKap6F2UYYXtYwFtDtl47WwFaayFLbiqKkvuG/4Hstli4hcliiN2TSi+Sc+da5rQwfE5Ty5UxZnUpoLDrwWq2PERdT9G20uoQedagm5dYnAYEv8FYx5wRwStkmdUaBacExuQ896JhwgfPJAkGLRB2wiY3FZpugGbbK1hZdswLCiadeN9pntQLOx1QmlILPyZ1o1NL05QJhRYWRaVskiRfySFx7wdLtgN29Jg15f2hiD553mJ//zMODr6y5VMCNEsZBgpijFtqOGCswc7OOw7um9pobcoibl0/w/n5L1xd/eWUPxHEsrBifKLMpBMB7aWxtNYrTKfvCZCuA/amdmT2El13ruyc28fm5mtaZVsnK+c9oIezwnKybuq7gL25hUWqbVxe/sHZ2U/u52Q51vZFU+eGKOkEk93odgva2+8eeqK+6rpLXFz8pqZfVK+yHOskxQV19Qi2O0Y0ekCL3LYrb5pzrn/17oImSawaWTvnGqnPxErStugnA5SLo8EOovkJIkqQEMOH0GMEbsQqPViCm4+FMBWgEBZsedEbPQ/39aIU0d4ThNEmQZcxARBQeR/X2RoyHFK7VtnGcbY2BNeyi6pdPf8DGVBZGwRKrEAAAAAASUVORK5CYII=","aspectRatio":1.3485714285714285,"src":"/static/73bc9846b7e4187f67eda8934f88e8d0/c4e3b/mysterious-cube-hero.png","srcSet":"/static/73bc9846b7e4187f67eda8934f88e8d0/5b37e/mysterious-cube-hero.png 236w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/49058/mysterious-cube-hero.png 472w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/c4e3b/mysterious-cube-hero.png 622w","srcWebp":"/static/73bc9846b7e4187f67eda8934f88e8d0/c32a3/mysterious-cube-hero.webp","srcSetWebp":"/static/73bc9846b7e4187f67eda8934f88e8d0/77392/mysterious-cube-hero.webp 236w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/1f177/mysterious-cube-hero.webp 472w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/c32a3/mysterious-cube-hero.webp 622w","sizes":"(max-width: 622px) 100vw, 622px"},"regular":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAChElEQVQ4y2VUu24TURDd1929j33Z3jhObMckEQlEiYJASNCliRIJpFSIFoGEREVBxVfwH+lp6WmR4E+oD2dmHSfBxbXvzp0598yZsxslSYIoinQZY+C9132SRCgKi6Oj7zg+/gFrA5rmBcryKZzLkJkCUhvH8apelwRk5XmuYHEcYTx+i8nkDYtnCGGPwBs8TzCbfcDh4TUvLvFwZjDpAkH+A5SfoihQVZUG8rzGfP6RzK7RjZ6jGbQYjjfgXcecKap6F2UYYXtYwFtDtl47WwFaayFLbiqKkvuG/4Hstli4hcliiN2TSi+Sc+da5rQwfE5Ty5UxZnUpoLDrwWq2PERdT9G20uoQedagm5dYnAYEv8FYx5wRwStkmdUaBacExuQ896JhwgfPJAkGLRB2wiY3FZpugGbbK1hZdswLCiadeN9pntQLOx1QmlILPyZ1o1NL05QJhRYWRaVskiRfySFx7wdLtgN29Jg15f2hiD553mJ//zMODr6y5VMCNEsZBgpijFtqOGCswc7OOw7um9pobcoibl0/w/n5L1xd/eWUPxHEsrBifKLMpBMB7aWxtNYrTKfvCZCuA/amdmT2El13ruyc28fm5mtaZVsnK+c9oIezwnKybuq7gL25hUWqbVxe/sHZ2U/u52Q51vZFU+eGKOkEk93odgva2+8eeqK+6rpLXFz8pqZfVK+yHOskxQV19Qi2O0Y0ekCL3LYrb5pzrn/17oImSawaWTvnGqnPxErStugnA5SLo8EOovkJIkqQEMOH0GMEbsQqPViCm4+FMBWgEBZsedEbPQ/39aIU0d4ThNEmQZcxARBQeR/X2RoyHFK7VtnGcbY2BNeyi6pdPf8DGVBZGwRKrEAAAAAASUVORK5CYII=","aspectRatio":1.3471074380165289,"src":"/static/73bc9846b7e4187f67eda8934f88e8d0/c4e3b/mysterious-cube-hero.png","srcSet":"/static/73bc9846b7e4187f67eda8934f88e8d0/078a8/mysterious-cube-hero.png 163w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/e56da/mysterious-cube-hero.png 327w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/c4e3b/mysterious-cube-hero.png 622w","srcWebp":"/static/73bc9846b7e4187f67eda8934f88e8d0/c32a3/mysterious-cube-hero.webp","srcSetWebp":"/static/73bc9846b7e4187f67eda8934f88e8d0/ac59e/mysterious-cube-hero.webp 163w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/7660b/mysterious-cube-hero.webp 327w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/c32a3/mysterious-cube-hero.webp 622w","sizes":"(max-width: 622px) 100vw, 622px"},"narrow":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAACXBIWXMAABYlAAAWJQFJUiTwAAAChElEQVQ4y2VUu24TURDd1929j33Z3jhObMckEQlEiYJASNCliRIJpFSIFoGEREVBxVfwH+lp6WmR4E+oD2dmHSfBxbXvzp0598yZsxslSYIoinQZY+C9132SRCgKi6Oj7zg+/gFrA5rmBcryKZzLkJkCUhvH8apelwRk5XmuYHEcYTx+i8nkDYtnCGGPwBs8TzCbfcDh4TUvLvFwZjDpAkH+A5SfoihQVZUG8rzGfP6RzK7RjZ6jGbQYjjfgXcecKap6F2UYYXtYwFtDtl47WwFaayFLbiqKkvuG/4Hstli4hcliiN2TSi+Sc+da5rQwfE5Ty5UxZnUpoLDrwWq2PERdT9G20uoQedagm5dYnAYEv8FYx5wRwStkmdUaBacExuQ896JhwgfPJAkGLRB2wiY3FZpugGbbK1hZdswLCiadeN9pntQLOx1QmlILPyZ1o1NL05QJhRYWRaVskiRfySFx7wdLtgN29Jg15f2hiD553mJ//zMODr6y5VMCNEsZBgpijFtqOGCswc7OOw7um9pobcoibl0/w/n5L1xd/eWUPxHEsrBifKLMpBMB7aWxtNYrTKfvCZCuA/amdmT2El13ruyc28fm5mtaZVsnK+c9oIezwnKybuq7gL25hUWqbVxe/sHZ2U/u52Q51vZFU+eGKOkEk93odgva2+8eeqK+6rpLXFz8pqZfVK+yHOskxQV19Qi2O0Y0ekCL3LYrb5pzrn/17oImSawaWTvnGqnPxErStugnA5SLo8EOovkJIkqQEMOH0GMEbsQqPViCm4+FMBWgEBZsedEbPQ/39aIU0d4ThNEmQZcxARBQeR/X2RoyHFK7VtnGcbY2BNeyi6pdPf8DGVBZGwRKrEAAAAAASUVORK5CYII=","aspectRatio":1.3411764705882352,"src":"/static/73bc9846b7e4187f67eda8934f88e8d0/502b1/mysterious-cube-hero.png","srcSet":"/static/73bc9846b7e4187f67eda8934f88e8d0/f2e6d/mysterious-cube-hero.png 114w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/4ddba/mysterious-cube-hero.png 229w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/502b1/mysterious-cube-hero.png 457w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/c4e3b/mysterious-cube-hero.png 622w","srcWebp":"/static/73bc9846b7e4187f67eda8934f88e8d0/15384/mysterious-cube-hero.webp","srcSetWebp":"/static/73bc9846b7e4187f67eda8934f88e8d0/31fce/mysterious-cube-hero.webp 114w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/e3e25/mysterious-cube-hero.webp 229w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/15384/mysterious-cube-hero.webp 457w,\n/static/73bc9846b7e4187f67eda8934f88e8d0/c32a3/mysterious-cube-hero.webp 622w","sizes":"(max-width: 457px) 100vw, 457px"},"seo":{"src":"/static/73bc9846b7e4187f67eda8934f88e8d0/c4e3b/mysterious-cube-hero.png"}}},{"id":"04e59628-9091-5a2e-a376-1e6928726fce","slug":"/how-to-create-a-immersive-3d-environment-for-the-web","secret":false,"title":"How to create a immersive 3D environment for the web","author":"Rick","date":"January 14th, 2023","dateForSEO":"2023-01-14T00:00:00.000Z","timeToRead":7,"excerpt":"The number 1 walk-through for creating an immersive environment for the web. A in depth look on converting a blender project into a optimized web project. Including amazing fireflies, grass, and HDRI image creation.","canonical_url":null,"subscription":true,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"How to create a immersive 3D environment for the web\",\n  \"author\": \"Rick\",\n  \"date\": \"2023-01-14T00:00:00.000Z\",\n  \"hero\": \"./images/floating-island-hero.png\",\n  \"excerpt\": \"The number 1 walk-through for creating an immersive environment for the web. A in depth look on converting a blender project into a optimized web project. Including amazing fireflies, grass, and HDRI image creation.\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"Hello from 2023!\"), mdx(\"p\", null, \"This is my latest project of converting a blender project to an optimized web project - from grass, to particle simulations to sourcing trees from cg trader. Im going to walk through this showcase\"), mdx(\"p\", null, \"Below are a couple of versions of this project.\"), mdx(\"iframe\", {\n    src: \"https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7017801733540048896\",\n    height: \"614\",\n    width: \"504\",\n    frameBorder: \"0\",\n    allowFullScreen: \"\",\n    title: \"Embedded post\"\n  }), mdx(\"iframe\", {\n    src: \"https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7017864388673945601\",\n    height: \"593\",\n    width: \"504\",\n    frameBorder: \"0\",\n    allowFullScreen: \"\",\n    title: \"Embedded post\"\n  }), mdx(\"p\", null, \"And here is the final \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://rick3d.com/3d-world/\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"link\"), \".\"), mdx(\"h2\", {\n    \"id\": \"modelling-geometry\"\n  }, \"Modelling Geometry\"), mdx(\"p\", null, \"This model consists of two main parts a rough decimated layer and a inflated and scaled UV sphere.\"), mdx(\"p\", null, \"This is a great tutorial on how to create a rocky like exterior to a mesh, you can either use the addon or follow the tutorial to get the same effect i have on my outer sphere. Create what basic shape you want and then apply the effect or create it via the modifiers.\"), mdx(\"p\", null, \"Once we have the rocky layer, the premise would be to use the sculpting tools - in particular the inflation tool, with low detail - to inflate parts of the flatter inner sphere over the top of the rocky sphere.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"3436px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"39.76%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABcklEQVQY00WQ2W6CUBCGfZgmJq0iaJG9lLqkNo1JRcBoFRcu7F3VqERUlKp1wQ1v6tt2OHb5LiYn888/ywmU9bqmqbIsqz5aoVAwDKPVbg8GA9M0O532W7NZLBZzOVlRlXJFL5Ve84r6kpPlvBK4JcloNBpDxONko17zTp67dbe7/cZ1d/vDx2zW7XVVVSEIXJIkmmZDkdhVMBy8xgM0TTEMw/EcSZKG0fg6n8FzOHr7o7c7HFdr15nNP5cryxomHqRUOiWKd+FwKBS6gQhmmmUZnuMYhs5mn8e2DaWb7fbgnZbrtT11rOGob5p6pSyKAs9zsCCGRRB4wB+LEAQB3lW9Ml8sJlPHnkyt0bjb67fanVpVTyYklmV5nscJAsMwHPFvBgH8EDUlD6MmjjMaj99brXq9+phOsr81eAT3zQQyUxQFm0MLaOzLaH/pXnzKZFLJhMBDxpcABoEhfibDDSQijrj0gnjJUBeQdMnAX/2ZvwEPtJL/4UhqiQAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/fe9fdd73a11c92590f01e686b34b8446/a3bc4/modelling-the-base.webp 2500w\", \"/static/fe9fdd73a11c92590f01e686b34b8446/2f1f8/modelling-the-base.webp 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/fe9fdd73a11c92590f01e686b34b8446/412e4/modelling-the-base.png 2500w\", \"/static/fe9fdd73a11c92590f01e686b34b8446/09388/modelling-the-base.png 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/fe9fdd73a11c92590f01e686b34b8446/09388/modelling-the-base.png\",\n    \"alt\": \"Modelling the rocky base of our island\",\n    \"title\": \"Modelling the rocky base of our island\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"The trick here is to inflate the parts between the main rocky slabs, this way it looks more natural having the soil mesh areas overlay the rocky areas mesh.\"), mdx(\"p\", null, \"Very importantly if we want to have this optimized for the web as best we can the we want low detail on dynotoplogy while using the inflate tool, this way we can still shape the soil mesh overlay in such a way that it can be shaped but doesn\\u2019t add 30k vertices, which would be a bit of a waste of performance on the web. One setting to make sure you have relatively high is the number of undo\\u2019s in blenders system settings in preferences. I find myself more times than I can count going back and reverting things so I can try again.\"), mdx(\"h2\", {\n    \"id\": \"grass\"\n  }, \"Grass\"), mdx(\"p\", null, \"Grass is very hard to optimize for the web, it can involve many many vertices, or 10\\u2019s of thousands of instances.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"3436px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"39.76%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABNElEQVQY022OXW+CMBSG+zscxYlaVzAgCLRBqEZvjLsysBV1QRcSr6ZuI27J/PM7aDRz8WnTnJ73fLwoW+ZpmibJk3yWs9lsPp9LKVer1/V6ned5lmWgSjiphDdbrhaLlySJp9NpHMfIZ9w/wzn3PHfyOPksit37x/7r++dwGI1Gvu+Vku8Nh0POmGHo9UaDEIKCIAjDMIoiIaJ+iRiPx5vtttjvN5s32DcYDMqs6IdhDyQhhGVZ7XbbNC1kH+mcgRg013VFJBzH7ljWRYU842CTMcZt22G8h6qAWsUYK4oCoUaadypW4KuqGO4xf6JSqZim2e26MMgpB3cQvqDgWk1rPVC1rmktAle9r+I/QD+lFAyDhZMXhK9pNAmhuqbVYS+U/2vWKTUMA/bfbr7U3UzS6+ZfA+Rgtss7AHsAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/7276a03a68b65924ffcf30eab3c69671/a3bc4/mesh-view-grass.webp 2500w\", \"/static/7276a03a68b65924ffcf30eab3c69671/2f1f8/mesh-view-grass.webp 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/7276a03a68b65924ffcf30eab3c69671/412e4/mesh-view-grass.png 2500w\", \"/static/7276a03a68b65924ffcf30eab3c69671/09388/mesh-view-grass.png 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/7276a03a68b65924ffcf30eab3c69671/09388/mesh-view-grass.png\",\n    \"alt\": \"Modelling view for the grass\",\n    \"title\": \"Modelling view for the grass\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"The way I chose to do this and which I find gives the best results is alpha clipping a 2D grass tuft, here is one I found on the web for free.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"355px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"95.49295774647887%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAATCAYAAACQjC21AAAACXBIWXMAAAsTAAALEwEAmpwYAAAFh0lEQVQ4yy1UCUyURxR+y//Pe7NqNW2iJsZq0qYeFVHEM4DGC1cUFOVYwcVlWXbBhV12ATnkhgWF9QBl0V0WQbEgKuKBFygaK97aRqutqdVemmqsGm3VpnE7JJ3kZTKZmW++N9/3HmTuI/D+BWB2IahKOYSVfASWFhzQ/QQUQZYBMDxcKfU8Aubpg+EiwHlOAeEVHBbPA0jeiQrFZAZRdoTZZoSgVATIaOeQ2c5HZu3jPnPMjKx7EWyt9GVeB4417SIISlcOLeiUxu+4AqGemwDlpyRpZRXB2mYig5sGR24gyDrAYdJqBn4ixAbvD7/kRj5iXgaOKj/BoOgoqrP3M3VKI0JoEfdN3Y025xXFKkevArxegOkm4tp68i8/r2TjIhnOtaE0RctgWqIANDQQ6F302domPjWslMIBBtHGHinZsgez8w9JsHID9xVnTthPydojrxDU23hwlIOnGzx8ckgOfhqYiqMCRbqTNEzpFysAtU4CTS19ktbC56gdZAoy8wlVZ6VifQO1Jdbx8YluPivZQ951rax8Rgr5aep4g9FF5rVNFBhZiYsW5wmweBw6MY6N8O0HTN/LFTtuKyFtDw/Tbac10ZW0qviY3ClYOU0NFCXmrcad9HeyE+uT3LxFV0fP0pspKbqKmtZsp3HBFgQ/DfpPiMWh/johimUPKVLE52e0kcrSxFdoHCxzfSd7sqaWtGkeMpp3UWOqC6/nH6Btmhq6mNWCL9a6sDvCTvbsDuVCYwMfMiYag0NLSA4vpcFQ0cUUuYe4EIIHqjeSRl3BNmW34/NIO4UnOalGrNcJdn+YG+lYnIOuprrxfFwVq9Q5ub2wS6nFaWyYfyKqknfzscE2YrDaOZBV9nAoPc6niXTdy4uwz+zBh2GFaBSpnluaI+utTditrsTvI8vweWItvoqpYGXWvbw3/zBXCTFC9fVk3PvmY9l6UAmw6bQ8ytRE43M7lBNXVWNfZAk+NrnoeEg2FsVU4EljjZyR5sazK4rYm7gN+NKwnT2Pd7ADCbV0P6yYEo317FLHPUXAwbs+sLlHYv2+kiq7ZGtGK6k1W6g1uhS9mc14WZXDvgsrQHegXk5d48Ce+RbmXVmMv68oxj8jSvGKeOzh0kK6nOzCE+4r0ujqM9LI7H1C5bYbAPtvwnDHKfkrw07qWpLD3qvL2TVRTv+E5uDZiHxmDstjd1WZ7F1ECd7TbcW3S/PxtSoLb8dupgvGHWj33PTxqz6uwElaLsO2Xkl29flA81VFbEYLekNz8XVwivxYsxkf6WqwM6acnY8pw5dhOez18kL81tZEb2camHe2ib3QbqOvyw7LZVF2OWB6Is533WQSbD+jgAf/AvQ+hIGFHezH8AL0BsTLjxNq8KX9KHMLxnciCph3npm9F/97KauFngbEsw/zbfhTmgevp7pZ1gQNqoVDBoWuFz7MbZNBX0eSZTeH7DZqWF2N3uk6udfaTL+YG7A7JJNdWJzFPixbz7wJW3CXuYF+mxrP+paV4LVUNx0JNFPpVD0bMcuEEGxGHwEiussekgo7OeS080KDk7wLrOyk8N3PEcX4LLIUv4kux/uGGnynq6Ha5Hp6OkPP2qMr8EHoevIIdot8EwiC08lHlU8ABQcRostQUlcgJNVhnq6WvAtt7LJ4/YYQ5dcluWxnjB3rrY10P3YjPozfhK+CUlh3tJ1ui1JL8zdwCClUwhcRQuH+UXKMw9w0Js3UyyDSLdM40BuSia2CzYkFVjwdU4kpiTWotTXTHWHuHwTo9fnp7ORsC3YNU+GQ0SsQpuhQMT7m/36Yu59gTISsgM99QLsVE8Sli6psrI6rxvqleWiLqsRJoqYXmdx0Z1EW3hJsT89Nx1sBBlSJkoOAJJT6m8JkLYJvHMJ//nMCS+HmpV4AAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/94cd7355b609b51ff7bd9750e85b85c6/32fba/grass-1.1-alpha.webp 355w\"],\n    \"sizes\": \"(max-width: 355px) 100vw, 355px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/94cd7355b609b51ff7bd9750e85b85c6/0facb/grass-1.1-alpha.png 355w\"],\n    \"sizes\": \"(max-width: 355px) 100vw, 355px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/94cd7355b609b51ff7bd9750e85b85c6/0facb/grass-1.1-alpha.png\",\n    \"alt\": \"Grass tuft I found on the internet for free\",\n    \"title\": \"Grass tuft I found on the internet for free\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"We consume this in the shader and use the discard key word for removing the parts with opacity less than 0.1. This way the grass actually looks like a 2d grass tuft. We then apply the positions json to update the instances matrix, which will store rotation and position in.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"3436px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"39.76%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABNUlEQVQY022Oz26CQBDGeYyGsgsssLqgwKJdUBDEXrhaJezWv4l9g9577KUv3altjDb+MofJN/PNfNrheFJKtm3bdZ1Sr5vNVip13G3f9uq0k/uNAjopoaSS+8MRNtbr9XK5XK1WmkgzIUT6hxDZpMmTj4Z+teHnS/De+NXkKc0AmInF8yJL0yDwHdellGrTfFrMZiVUVVbzqq7ralaM+tbYfYhdPeXDej6vzhRF0TRNWZZRFA0GgzCMtCRJOOfxBR6DMoxi03Zsx+Pn8Y/KOXggwjllFvMkzXLNNE2MMULIeDSgJ56nIwNhbBNiWpZxha7rYRiORmN4ATfhoIYuGMi2Sa/PsENIj9rUQ5aJrgA/YwwCQ4TflBq6xfUoZT4hDkYY1v+ZfcaCIID/982XvbsiuzV/A2wRW0IlZJCGAAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/cf3419f2dfc6d964419ae84873816b42/a3bc4/shading-view-grass.webp 2500w\", \"/static/cf3419f2dfc6d964419ae84873816b42/2f1f8/shading-view-grass.webp 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/cf3419f2dfc6d964419ae84873816b42/412e4/shading-view-grass.png 2500w\", \"/static/cf3419f2dfc6d964419ae84873816b42/09388/shading-view-grass.png 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/cf3419f2dfc6d964419ae84873816b42/09388/shading-view-grass.png\",\n    \"alt\": \"Shading view of the grass\",\n    \"title\": \"Shading view of the grass\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"The rotations is the key bit here. We want to rotate it in such a way that we don\\u2019t get lines as we pan round the grass. This looks super bad and fake.\"), mdx(\"p\", null, \"The best bit is we provide fake positions to the instances to begin with and then use the instance matrix to transform the original position / rotation, or offset the original position and rotation to each instances position.\"), mdx(\"p\", null, \"There are ways to improve this, by storing data in images and using an index value to generate some uvs to access the pixels in the image, this way we by pass KB/MB\\u2019s of json storing positional data, instead we can have like a 100kb image, which potentially could use some sort of image optimization with minimal signal lose.\"), mdx(\"h2\", {\n    \"id\": \"trees\"\n  }, \"Trees\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1086px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"57.6427255985267%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAAC50lEQVQozwHcAiP9AMpwU6qYj3PZ+Grd/o/j7HLg+WHc/mXc/GTc/GTc/GXc+17c/4zg7/TQhPONKPiwGfajG+hyHNBSF7k7GgC3l1jDtZWH6v+/78Tu4X25x6V03/xv4Pxu3/tv3/tv3/x84fnM2Lr4w1n2lhv0mB78rBvoZhrQRxXCRycAt4M/5pZuy+Lb5OV3xKM/uIxQpODklfL/le38lu78kvD/u+7n/KFO7mkb52Mi2kkb7YAj9o4562YVyzcUAK1/Os5wUeSyas29V696ObSHTsLe0L7//7z7/L38/bv8/9P77e6NUNlAFdNAINtgM++LIPqvI/VmEtorBwCyez3RaF7Pg1W0kD6vdji1j1rV9O7X///W/P3W/f3X/f3g///t39jakITpfkD0ozT2ixf0fhftUQ7aKwYAwIRk4IOMz3lrwXFMxXNmya+N6fr25f//4P794///5vj86O33zs/q69Wl8I1b9qM68HES5FIf7FgX1SMEAMaSitebpt+qn+GYhdhtgObW1+z1+PL//+n2+trd6sS40bOfvpp7n/K5auFeSuaATfeMGuhXHuFEF8wdAwDUrbXRtLzRuqPGoobXd4vXpbzi4dzMwcyumbiafJ6MaZKQaY2LZ4y8b2/QUU/dfGLzhCTYQxXOKBLDFwYAr4+cxKKt0ay+16641Zua07Kx3MzKpYajfFJ9iF+EgFl7kWWEj2iDdk17jlN6xYWRzoFUyEUrxmdKwIMfAKd3aruUg7WQf8qdiMB5X7aQh8etvMWypqeFhpp3hoJdd39Sd5lnfHxSdYxjhM2Wlufda9GzZtLEhMrMTQCabT+/h3PRmofJgnu5cVSnh1Cdg1+0mXDIsXvQxH2XdHWCWHGHWHKYdXfTxnrfr43Vv1DLzhy6tjC4r1oAmocNsJYjyrQztIBErW1Yt3lhu4Zao4FAs5pKu59ZtJBrlXJxmHxxsJ1z6uVqzZx2q4w3npwJhXoGi4MBSRC8XYlfRNIAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/f0522ed05da0a8f74882b6eb8cb8d783/710cb/tree-pack-hero.webp 1086w\"],\n    \"sizes\": \"(max-width: 1086px) 100vw, 1086px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/f0522ed05da0a8f74882b6eb8cb8d783/c92c4/tree-pack-hero.png 1086w\"],\n    \"sizes\": \"(max-width: 1086px) 100vw, 1086px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/f0522ed05da0a8f74882b6eb8cb8d783/c92c4/tree-pack-hero.png\",\n    \"alt\": \"Tree pack from cgtrader\",\n    \"title\": \"Tree pack from cgtrader\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"The trees came from cgtrader. The tree pack is a low poly and can be found \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.cgtrader.com/3d-models/plant/other/story-tree-pack\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"here\"), \".\"), mdx(\"p\", null, \"My thoughts on this is I am trying to do a POC, my time is valuable and I don\\u2019t want to get bogged down in creating 6-10 variations of low poly trees and then UV editing + shading / baking textures.\"), mdx(\"p\", null, \"They are very good quality low poly trees and came with materials.\"), mdx(\"p\", null, \"This way I can focus on the important aspects like making the lighting good and tweaking effects like the fireflies.\"), mdx(\"h2\", {\n    \"id\": \"world-background-and-hdri\"\n  }, \"World Background and HDRI\"), mdx(\"p\", null, \"The best thing which will make your 3D scenes look professional is HDRI maker and the results you can get with rendering a world background as a HDRI.\"), mdx(\"p\", null, \"The HDRI will emit light onto the scene and will become probably the most important part of your environment, setting the mood and allowing you to create atmosphere.\"), mdx(\"p\", null, \"You can follow any tutorials you like or mess around with layered noise to gets stars or anything.. and then essentially bake or render it to hdri 2/4k (usually best for the web - depending on if it has detail of just gradient block colors).\"), mdx(\"p\", null, \"Then its as simple as loading it in using @react-three/drei\\u2019s environment component. You can make this look so so slick on your personal projects.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1394px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"103.44332855093256%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAACzElEQVQ4y1VS2XbbNhAFAcwMNlIULVFc4i225NRxHMuxY6d9S7+i35DHnPSprznpJ/RzOwNSbirdMxqCuMsAUsXf/zDw6ndqH2l4puFJ6vgrjZ/yI+OT9LKSF8fnXOWtsl+/228/cPeZ1g/UPVH3kfqX+iS1f87I/Ytcrgpxh7jFoz22H3B9j5tHbB8E0jzS5iNtHkWre/pPetJiZ1ztcXWHR3fYvJe6up/75i6/2ovi+kHA6u1DlpsVFdY3WL/DBSM31Vusb3H5Hqqb3NzKItfmdpYWRZYTIQXlNaRriL9AeAPxjVR+DJfgzintMO6oumZgdQOsywbLrCgx9wr8ztKFpctcL4AuGRguYvs5Nb+l5jnV9y5uKV6BPxPd8honlfqdsvbMMOC1MaOxHcCW4Dgtb/v9n5ubL/39X+vtH9GvvD8jOqewE7NwBUkCKrAnAnNszSswA0GfwqL0IRFUPi5Ss0irKlZlrB21iK9RMl5at2UJ5ek0uNNAJ1YfO1qVISafyrCoUlOmelE2VaqrtKzi0lNwtLHmjMNaOGcJpVWn1cYUI0FXxjKFKoVUsmXgPgWXPMXgq0z20VdoOeOJNacsoUzRC/Qrh6sUQvSJkUKMPvBuhGg0Ge0cemts8JGwZybvZzB5MKrXanDYeHLBsV0STx+tgRRqAg8WHX/BRecdboSp2HJU8sPJi9HhEVjDH7blzNGzLWYhTiFBplBgWkkqrF7NXTFYvXZEBDRlZnIeO8hBeIlThoRQsuE8acFk1R3QIyQ5opAyWSBCPAry/ISIumjsRM77c2yRGRhatda4QHwnLrCz52vj6yFjdFFYrVYH20HIxaAmmpyB6E2HV2ttrQYwyNBMK6o85HCYcTbLsecD6KZjYHld8OWvc23zhnGyMub4QJ5mngfo5tfFoeFN+iXk9F+YHsdZS/1M/l+k/uU+fmqGQ7pc9fAv2oZQK78EIwwAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/1852912d858ee0dc6dcf22dffcca3e9d/7b980/HDRI-background-V1.webp 1394w\"],\n    \"sizes\": \"(max-width: 1394px) 100vw, 1394px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/1852912d858ee0dc6dcf22dffcca3e9d/6f2aa/HDRI-background-V1.png 1394w\"],\n    \"sizes\": \"(max-width: 1394px) 100vw, 1394px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/1852912d858ee0dc6dcf22dffcca3e9d/6f2aa/HDRI-background-V1.png\",\n    \"alt\": \"Render of earlier hdri background\",\n    \"title\": \"Render of earlier hdri background\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"3440px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"40.040000000000006%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABmUlEQVQY02Pw8fZycXH29PSa3lG1ckrD4t6qxd0Vi/trlkyoW9BXs6CvbnF/PZALRIv6asoLMoODAj09PV1dXX28fRjcHYw9nIxsLQ2vr2z7dXDKl90Tvu6d9HXflO8Hp/04NO3n4enfD0z9tn/yt/2Tvu+fXJUdZ2RirKuro6KqpqOrx+DlYuZkb2pjYXR5Yd2H7b2vNne+3tr7YlPXg2W195bW3FlY/mxt88stXS82db7d2j2tLtvVycHGxsbO0dXa3oXB0EBfS0fXyED/wZrW/4em/tg38feByd929azNcZkfYTQ/wuTRsrq/R2b82DsBKPX/yLTGrAgTC2tXFxdbO1sGPT09bW0dI0PDmZVJq1oyljSkLm1MXd6c1h7vmWml2xDiuLg+ZXlT2rLG1CUNKWvbMpJDvEzMLKytLK2srBiMjY1NwEBaRk5cQlJcUgqCpGRkJaVlgKQEkCsBFRSTkFRSVjYyAtoFAmDNpsZAvoK8vJycLBzBAaqgjLKysr6+gb6+PtDJIM1AANKsoCBHCAB1gzVDAQA/nKrXb0zDngAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/675a0695ea51311095d9082bb75d24fc/a3bc4/HDRI-background-V2.webp 2500w\", \"/static/675a0695ea51311095d9082bb75d24fc/b19ed/HDRI-background-V2.webp 3440w\"],\n    \"sizes\": \"(max-width: 3440px) 100vw, 3440px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/675a0695ea51311095d9082bb75d24fc/412e4/HDRI-background-V2.png 2500w\", \"/static/675a0695ea51311095d9082bb75d24fc/8853a/HDRI-background-V2.png 3440w\"],\n    \"sizes\": \"(max-width: 3440px) 100vw, 3440px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/675a0695ea51311095d9082bb75d24fc/8853a/HDRI-background-V2.png\",\n    \"alt\": \"Render of latest hdri background\",\n    \"title\": \"Render of latest hdri background\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"One small thing to note is that the environment intensity will need to be tweaked as again I found there isn\\u2019t a 121 relationship, it comes close but not exact. Which is to be expected considering blender and threejs/R3F are two completely separate render engines.\"), mdx(\"h2\", {\n    \"id\": \"clouds\"\n  }, \"Clouds\"), mdx(\"p\", null, \"In the same regards for the trees I chose some low poly clouds which looked good and came with materials.\"), mdx(\"p\", null, \"If you don\\u2019t have the spare \\\\$, then there are numerous tutorials on generating low poly clouds. Just follow one of those tutorials and create a few variations of clouds.\"), mdx(\"h2\", {\n    \"id\": \"hosting\"\n  }, \"Hosting\"), mdx(\"p\", null, \"For hosting I have just put it on netlify as I don\\u2019t get high traffic and even if I did I could by more time from netlify.\"), mdx(\"p\", null, \"The key thing here is to get the website behind cloudflare as we can get really good caching then!\"), mdx(\"p\", null, \"This way we can save on the bandwidth for netlify. Again I wont go into too much detail but there will be some infra, but all pretty standard / basic.\"), mdx(\"p\", null, \"And a point for the future I am going to put this on a custom domain, as it always feels more professional if you do this.\"), mdx(\"h2\", {\n    \"id\": \"shading\"\n  }, \"Shading\"), mdx(\"p\", null, \"One thing that will become abundantly clear as you make complex textures/ patterns, is that the shader graphs don\\u2019t export to the GLTF format, and even if it did there would be no end of trouble for the versioning and how blender implements the graph in its own flavour of code and not a 121 with GLSL.\"), mdx(\"p\", null, \"So how can we over come this? Baking. We can use cycles and bake a texture to a set of UV coordinates. So we need relatively clean topology.\"), mdx(\"p\", null, \"It is no good to make a really complex shape with many over lapping random vertices, the mesh of vertices needs to be as clean as possible or in other words have clean topology for uv unwrapping.\"), mdx(\"p\", null, \"UV unwrapping is the task of mapping a 3D mesh to a 2D plane of coordinates, such that every 3D vertex is placed on this 2D coordinate plane. This way we can store the color of each 3D vertex onto the texture at certain 2D coordinates, which represent a 3D spacial coordinate.\"), mdx(\"p\", null, \"Here is an example, it is the base mesh uvs highlighted:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"3440px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"40.040000000000006%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABV0lEQVQY01WRXU/CMBSGi2K8Q4xRE0NEIILG0K5fbF3bdRMhwDY+NuOdF/4S/7qn40J9c9I2b89zenKKdrv9Zg1aFXm+LcuigD3f5HlVf1RVDc62UdlcHQ4VmJu8WCxXRbFFlEmCMQkoCQLYIOBACGbcayZlFIZCSh9CgCPlDFM5fsbTQCLReOLxmg4v9eTKPnXVS48LEUWhNTpzLnUJrBBaa6UUJENtqA8rAlCwQPRO8Q1yD63FANlxhzEex8oa4wFj6/2+XK/maRrHMXREPOx1hKkenOl7lA1Poh6SowvIiCJljHmdz1MdvsXcOZckNrGWMYYx/oU5o/W0/UmQ7bfwLQr6HYDDMPTvWpdb+m4mWZZakDH/YMqEkvR7ef7FT+ygze9aYtT1g5nNoEnAjU10kkIXGooZTSn9+zKXgmtJQk4kO0bQmDCzCCbkS8ReyisCxn9Oox/wBmVV2h+K4wAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/3d36cc7e1d0e0238a51f80f6eb0cdd9a/a3bc4/uvs-selected-base.webp 2500w\", \"/static/3d36cc7e1d0e0238a51f80f6eb0cdd9a/b19ed/uvs-selected-base.webp 3440w\"],\n    \"sizes\": \"(max-width: 3440px) 100vw, 3440px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/3d36cc7e1d0e0238a51f80f6eb0cdd9a/412e4/uvs-selected-base.png 2500w\", \"/static/3d36cc7e1d0e0238a51f80f6eb0cdd9a/8853a/uvs-selected-base.png 3440w\"],\n    \"sizes\": \"(max-width: 3440px) 100vw, 3440px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/3d36cc7e1d0e0238a51f80f6eb0cdd9a/8853a/uvs-selected-base.png\",\n    \"alt\": \"uvs selected of base mesh\",\n    \"title\": \"uvs selected of base mesh\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"And here is the albedo or color of the mesh stored in the texture:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"3436px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"39.76%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABJ0lEQVQY022QW0/CMBiGN3a/hCW7UZHdjBAWd+rB9bCBsjBjYgSkE3CgN/4tf6vfNrIo+qTpKX36fq222+2VUqvlqiiKh4bFopjn+UZtD8f315bttixLpcr9W1VVh41Sy9V6/aK0MMJBELijka7rWkM7ubi8ShIWxzHBmBJMCIwYoZhQGiLqjm/GXqjBDqXU87xer6c3wATkoTPMsoxzLtP0VmZCpkIKLgQlJAyDtmn13YRMJpOz5OuTLO6n8vOJzGey9oXAmEClYcNJ7pI72XGcWZYxLh/v+NfH+DnnTKRgI4T+kQ3D+Jk8GAwgWTRlT1Pw6lgoG87/kuEnfN+3bduyrH6/D71pmq7rSikZY7UjRf1ggLFzGTXgPyQnGAOJsXYRRVEnfwMob1iM9b5rUgAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/52a43c2ce6b220f1d74e385cfab7b059/a3bc4/albedo-base.webp 2500w\", \"/static/52a43c2ce6b220f1d74e385cfab7b059/2f1f8/albedo-base.webp 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/52a43c2ce6b220f1d74e385cfab7b059/412e4/albedo-base.png 2500w\", \"/static/52a43c2ce6b220f1d74e385cfab7b059/09388/albedo-base.png 3436w\"],\n    \"sizes\": \"(max-width: 3436px) 100vw, 3436px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/52a43c2ce6b220f1d74e385cfab7b059/09388/albedo-base.png\",\n    \"alt\": \"uvs selected of base mesh\",\n    \"title\": \"uvs selected of base mesh\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"As you can see the albedo is stored within the plane shape on the UV map.\"), mdx(\"p\", null, \"So again, I wont go into lots of detail on clean topology in blender as theres many tutorials which will describe it better than me.\"), mdx(\"p\", null, \"Once we have clean topology, a set of UVS and the cycles render engine enabled. We can select a image node (disconnected from anything) and the mesh in question and we can bake diffuse, or emit or combined.\"), mdx(\"p\", null, \"Three small points to make: you cannot bake alpha directly, emit tends to be limited to strength 1 afaik and finally the lighting in the scene can drastically affect the diffuse albedo/color of the objects when baked (sounds obvious this last point but has caught me out sometimes).\"), mdx(\"p\", null, \"Baking is where we essentially hardcode the colors for a mesh into a texture to be loaded into the 3D environment when we load the model.\"), mdx(\"p\", null, \"You should be aware that if you bake to an 8k image, if this project is designed for the web then you will still have to download this massive image, so its always balancing the good looks of higher res images/textures with the performance tradeoffs on the web which goes along with high res images / textures. Be prepared to try multiple times to get the best looking baked textures.\"), mdx(\"h2\", {\n    \"id\": \"fire-flies\"\n  }, \"Fire flies\"), mdx(\"p\", null, \"The fire flies were an adaptation of \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.thefrontdev.co.uk/storing-positional-xyz-values-in-a-texture-and-reading-in-a-r3f-shader-material\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \" where by we store the positional data of points in a image from blender, where each pixel represents a positional piece of data about a point. Lucky for us we can use geometry nodes to covert a bounding shape into a volume, distribute points or instances inside the volume and then run the script in the article above to get the positional image.\"), mdx(\"p\", null, \"We can read this or texture sample this and convert back to positions.\"), mdx(\"p\", null, \"Now we have a quick and easy way to do this we can now concentrate on adding movement and the way it looks ie the bloom below.\"), mdx(\"p\", null, \"The movement is influenced by noise and gl_PointSize also oscillates, which means the size of the points will change which helps create a realistic firefly effect.\"), mdx(\"h2\", {\n    \"id\": \"postprocessing-and-bloom\"\n  }, \"Postprocessing and bloom\"), mdx(\"p\", null, \"The postprocessing and bloom is what gives the glowing effect for the 3D text and fireflies. With postprocessing things can get really complicated really quickly. However with some experience I can now try and mitigate the complexities.\"), mdx(\"p\", null, \"Instead of doing some really complicated I lowered the luminesce or brightness threshold in the @react-three/postprocessing library\\u2019s bloom effect. Then increase the vec3() components (x/y/z) for the fireflies points and increase the emission of the text. This was we increase the brightness of these 3D objects and enter above the threshold and there bloom is applied.\"), mdx(\"p\", null, \"This takes a lot of tweaking and for me lights are by far the hardest thing to get right.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1080px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"100%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAIAAAAC64paAAAACXBIWXMAAAsTAAALEwEAmpwYAAADZklEQVQ4y01TO28kRRDunenu6vfM7GN2XrtreW287Nmz9u563z4bAsRJSOgOCUF0Do7ABCBEQHQxIjvpJBJETEpAhPgNiJCMhICAkBSJmlkfutY3rZpRf/V9XVVD5OBa9nato0euWIVnn598/MfxR7+FydJKZrSFfMmLNc9rFDXyFRQbBAYE8rXtP9T9axGf5ttvhk9+bU++1MoZyZEsihUe2J8WxVrcB5v9l4osshUiOv5geP1y/PTP3lvfO9d1RmmjRb5EX6rYyHwj8o0strp3pXpbUVQg+KjBDYvL/Oa7waOfBu/+qNpTp1QYdIyxMi5VtlHJpc7XFS3f7iExXbogmCw4eJvHZbp78eDZ36d3/5xun0fWGKOdi5gpoD2BYAhuIDpnKr6Q8UR2StmdidaY4L1lvla9nUzmye7F6PavTjqzkivFjXEetzw4EtG4U37WuviqOX7WPL0LR7c63UCzIqOfneo/VN2yPXt+8uHvSTYJbdiKEhT3qfaZs9EwPn7cHd/Go6fdB3fp+RdRvjNhn0B1+53IlgqVr16evP9zp5m2W0WaHhkLlAEhRArQwtfgmRpWgJHCKkNYawStN3V6may/Lj/9d/TOD6FRRmutuHWSUVzM1MvawLmWNU2tbPVmHGl43OcOTJZefTt475do9AnyjAuMM9ZZKQVjzDmkRYFrUp96DZ9RhQAuCM8uWTqn3XPIsPvXon/DswVkC54vIZsrraWQrmIHDp3UuRhlFDNQTnhvy3HWelcsmbJOicVHGs/2WGgsmkIy+pTWavRqLZquPmNMIJ5CuuLJjKeLemLXPJlzzBJPAHsWhFpbFwTGCoO0qv+qDlRNbpUinvHOBcQzSBYVUjS8qm6RLqxz2ghtJA4bAjnGiNoCiksC4ZlsTXk042HJwpI3z6E9hc4U4jl0Z1gzpNen0a3CV+tQXJo6HZH2ROgDE56AOrRRye2Y2TEPTjnG0ZnF/oRYdln7rHYsXhVU7ZSE0j4wJxhQmnM4pPyQwpDJN5geMTOq2yvuZauaSa2FlJxzKoATj6ReI/W8DNFo4J5Tv+fTA58fMjE09n9ZtTevNABnQgAAIzXzFe7jzKuyFJQOsC4Ofy+rXaWMTZey4laDh2P7GrmRvGLWgZ/7XgYMJEcNhvA9v9FokNfWf1HFcgEdip0dAAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/53420ea19ce77ab1710d01925eb0eaf7/64908/final-snapshots-floating-island.webp 1080w\"],\n    \"sizes\": \"(max-width: 1080px) 100vw, 1080px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/53420ea19ce77ab1710d01925eb0eaf7/6d80e/final-snapshots-floating-island.png 1080w\"],\n    \"sizes\": \"(max-width: 1080px) 100vw, 1080px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/53420ea19ce77ab1710d01925eb0eaf7/6d80e/final-snapshots-floating-island.png\",\n    \"alt\": \"Floating island snapshots in the browser\",\n    \"title\": \"Floating island snapshots in the browser\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"The transfer of lights from blender to three/r3f is a 100% not 121. So you will have to do some tweaking of the lights, positions and intensities. This includes playing around with the environment map intensity as well.\"), mdx(\"h2\", {\n    \"id\": \"final-thoughts\"\n  }, \"Final Thoughts\"), mdx(\"p\", null, \"You might be asking yourself why would I tell everyone how to do immersive 3D environments, surely this will detract from my opportunities or future prospects.\"), mdx(\"p\", null, \"The only answer i have to this is.. by helping people stream line workflows and drastically reduce time to ship products, I can effectively help my own prospects. The more companies which do this sort of thing the more need for people like me there will be and potentially in the future I can do more of what I love :)\"), mdx(\"p\", null, \"Plus I really like to help people into 3D, this is something I have a deep passion for and anyone who asks for help will receive it (when time permits obvs haha) \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://mailto:rick@thefrontdev.co.uk\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"rick@thefrontdev.co.uk\")), mdx(\"p\", null, \"Hopefully this article was useful and sparked your interest!\"), mdx(\"p\", null, \"Everything I have done on this project was demonstrated in pioneering open source workflows for 3D, blender and three/r3f.\"), mdx(\"p\", null, \"I will hopefully open-source the repository under some sort of license in the near future but for now it needs tidying up and perfecting.\"), mdx(\"p\", null, \"Let me know if you have any issues or improvements for this project via linkedin or email.\"), mdx(\"p\", null, \"For now goodbye!\"));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADIklEQVQ4yz1TS28cRRDunZl+d89zHzPT89iXzWJ5vfZ67X1414mTWFECSSA5c4ELJw5c4AQn+A0ckOAQgYSExCncOCCB+Av8G6rHS6RPpW+666uqqapG1KwbrFixAUvN0pJivQdc2c/NnmeLO5/GrhFpz0gypZ0FDsYyW4bDZ7wzJfGEmQ3NLml6QXtzmi9puqDZhT0BWTpvyBp54sDBkfRzxoRUkdJdwQRhIUtmJD4j4ZT475JgyqITGkOaM9Kek+4FTS9Bj1x3QGmgNVNaAqSgSkmlOOWFxyceHbtk6OIBoX3GU8pGmB9iOcHBMY5mqIV6lPjaZ77mWnOlmITElDqo57QKp5UBaVmkDmo71uZw7uGBxw4R42PH7RGuhR8LFRERYha6xHh04JE+wP3fNqgb9DEbeewABfWNy2KSTGR5jZMjnC1EsWFmzbIFh86btTB2CsysZLHhwHPLdbUjZoOgkw6Wnjaqvke6U7mfyopm59yseLUVxRWE4KAst7y6tp0HFGuWXyLaO3Oxcmkoyi0LRzw9vfNQ1Q5kvLhS1dYW0oydwJyBVFuYE04mID6FzK0WplAz7ziiS23ZK1HuWLMhNqi1V5CZdmcknbNyw8or2j5CvLpHQxiGpp1jh2pPdMDJ/nY252at6/vMVrsDvYTFig9gvbiNtSPxOwjuCOTUuT9+2Vt925l/AR2CgtvnX+rBE20uRb7wutOgXLePP46mn/HimvROZHaO40No2IamSxzUqv909Oqf8Yd/V7c/1e+/mXz07+jJb+bmh/z+d+bhj8XN9/XjX7uLr4tHryFHMvtc5FvEuycyGiidaB1F7VGUDPLho2L6SXn6aW/xVXX78+jFn8Pnf9RPf++/9yZdflPe/jL84C/z4LWqnyOlue+rMAzBBr5WEidhrJjjCwI7qlQU+EaJWPsmak+DZKJkO0iOongkRYyUEqDXvgyCQErw5nbJJaw33AjFmYJt50wyLKkHAK4ZDyCR9JH1uAMXUvDQjyGO4lwJqeGZNedvHfZESslZoEOkG6cGNpWvNNQO4ZOoFwYRMG2934rlHqAX/D9kEm8YM/KJewAAAABJRU5ErkJggg==","aspectRatio":1.102803738317757,"src":"/static/b6d453e388d6dc39dbc445997b08ec29/a1946/floating-island-hero.png","srcSet":"/static/b6d453e388d6dc39dbc445997b08ec29/5b37e/floating-island-hero.png 236w,\n/static/b6d453e388d6dc39dbc445997b08ec29/49058/floating-island-hero.png 472w,\n/static/b6d453e388d6dc39dbc445997b08ec29/a1946/floating-island-hero.png 944w,\n/static/b6d453e388d6dc39dbc445997b08ec29/030f1/floating-island-hero.png 1416w,\n/static/b6d453e388d6dc39dbc445997b08ec29/1ea3a/floating-island-hero.png 1520w","srcWebp":"/static/b6d453e388d6dc39dbc445997b08ec29/99fbb/floating-island-hero.webp","srcSetWebp":"/static/b6d453e388d6dc39dbc445997b08ec29/77392/floating-island-hero.webp 236w,\n/static/b6d453e388d6dc39dbc445997b08ec29/1f177/floating-island-hero.webp 472w,\n/static/b6d453e388d6dc39dbc445997b08ec29/99fbb/floating-island-hero.webp 944w,\n/static/b6d453e388d6dc39dbc445997b08ec29/4a492/floating-island-hero.webp 1416w,\n/static/b6d453e388d6dc39dbc445997b08ec29/9d244/floating-island-hero.webp 1520w","sizes":"(max-width: 944px) 100vw, 944px"},"regular":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADIklEQVQ4yz1TS28cRRDunZl+d89zHzPT89iXzWJ5vfZ67X1414mTWFECSSA5c4ELJw5c4AQn+A0ckOAQgYSExCncOCCB+Av8G6rHS6RPpW+666uqqapG1KwbrFixAUvN0pJivQdc2c/NnmeLO5/GrhFpz0gypZ0FDsYyW4bDZ7wzJfGEmQ3NLml6QXtzmi9puqDZhT0BWTpvyBp54sDBkfRzxoRUkdJdwQRhIUtmJD4j4ZT475JgyqITGkOaM9Kek+4FTS9Bj1x3QGmgNVNaAqSgSkmlOOWFxyceHbtk6OIBoX3GU8pGmB9iOcHBMY5mqIV6lPjaZ77mWnOlmITElDqo57QKp5UBaVmkDmo71uZw7uGBxw4R42PH7RGuhR8LFRERYha6xHh04JE+wP3fNqgb9DEbeewABfWNy2KSTGR5jZMjnC1EsWFmzbIFh86btTB2CsysZLHhwHPLdbUjZoOgkw6Wnjaqvke6U7mfyopm59yseLUVxRWE4KAst7y6tp0HFGuWXyLaO3Oxcmkoyi0LRzw9vfNQ1Q5kvLhS1dYW0oydwJyBVFuYE04mID6FzK0WplAz7ziiS23ZK1HuWLMhNqi1V5CZdmcknbNyw8or2j5CvLpHQxiGpp1jh2pPdMDJ/nY252at6/vMVrsDvYTFig9gvbiNtSPxOwjuCOTUuT9+2Vt925l/AR2CgtvnX+rBE20uRb7wutOgXLePP46mn/HimvROZHaO40No2IamSxzUqv909Oqf8Yd/V7c/1e+/mXz07+jJb+bmh/z+d+bhj8XN9/XjX7uLr4tHryFHMvtc5FvEuycyGiidaB1F7VGUDPLho2L6SXn6aW/xVXX78+jFn8Pnf9RPf++/9yZdflPe/jL84C/z4LWqnyOlue+rMAzBBr5WEidhrJjjCwI7qlQU+EaJWPsmak+DZKJkO0iOongkRYyUEqDXvgyCQErw5nbJJaw33AjFmYJt50wyLKkHAK4ZDyCR9JH1uAMXUvDQjyGO4lwJqeGZNedvHfZESslZoEOkG6cGNpWvNNQO4ZOoFwYRMG2934rlHqAX/D9kEm8YM/KJewAAAABJRU5ErkJggg==","aspectRatio":1.1013513513513513,"src":"/static/b6d453e388d6dc39dbc445997b08ec29/3ddd4/floating-island-hero.png","srcSet":"/static/b6d453e388d6dc39dbc445997b08ec29/078a8/floating-island-hero.png 163w,\n/static/b6d453e388d6dc39dbc445997b08ec29/e56da/floating-island-hero.png 327w,\n/static/b6d453e388d6dc39dbc445997b08ec29/3ddd4/floating-island-hero.png 653w,\n/static/b6d453e388d6dc39dbc445997b08ec29/c5cc7/floating-island-hero.png 980w,\n/static/b6d453e388d6dc39dbc445997b08ec29/eebd2/floating-island-hero.png 1306w,\n/static/b6d453e388d6dc39dbc445997b08ec29/1ea3a/floating-island-hero.png 1520w","srcWebp":"/static/b6d453e388d6dc39dbc445997b08ec29/0acdf/floating-island-hero.webp","srcSetWebp":"/static/b6d453e388d6dc39dbc445997b08ec29/ac59e/floating-island-hero.webp 163w,\n/static/b6d453e388d6dc39dbc445997b08ec29/7660b/floating-island-hero.webp 327w,\n/static/b6d453e388d6dc39dbc445997b08ec29/0acdf/floating-island-hero.webp 653w,\n/static/b6d453e388d6dc39dbc445997b08ec29/75470/floating-island-hero.webp 980w,\n/static/b6d453e388d6dc39dbc445997b08ec29/68d47/floating-island-hero.webp 1306w,\n/static/b6d453e388d6dc39dbc445997b08ec29/9d244/floating-island-hero.webp 1520w","sizes":"(max-width: 653px) 100vw, 653px"},"narrow":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAADIklEQVQ4yz1TS28cRRDunZl+d89zHzPT89iXzWJ5vfZ67X1414mTWFECSSA5c4ELJw5c4AQn+A0ckOAQgYSExCncOCCB+Av8G6rHS6RPpW+666uqqapG1KwbrFixAUvN0pJivQdc2c/NnmeLO5/GrhFpz0gypZ0FDsYyW4bDZ7wzJfGEmQ3NLml6QXtzmi9puqDZhT0BWTpvyBp54sDBkfRzxoRUkdJdwQRhIUtmJD4j4ZT475JgyqITGkOaM9Kek+4FTS9Bj1x3QGmgNVNaAqSgSkmlOOWFxyceHbtk6OIBoX3GU8pGmB9iOcHBMY5mqIV6lPjaZ77mWnOlmITElDqo57QKp5UBaVmkDmo71uZw7uGBxw4R42PH7RGuhR8LFRERYha6xHh04JE+wP3fNqgb9DEbeewABfWNy2KSTGR5jZMjnC1EsWFmzbIFh86btTB2CsysZLHhwHPLdbUjZoOgkw6Wnjaqvke6U7mfyopm59yseLUVxRWE4KAst7y6tp0HFGuWXyLaO3Oxcmkoyi0LRzw9vfNQ1Q5kvLhS1dYW0oydwJyBVFuYE04mID6FzK0WplAz7ziiS23ZK1HuWLMhNqi1V5CZdmcknbNyw8or2j5CvLpHQxiGpp1jh2pPdMDJ/nY252at6/vMVrsDvYTFig9gvbiNtSPxOwjuCOTUuT9+2Vt925l/AR2CgtvnX+rBE20uRb7wutOgXLePP46mn/HimvROZHaO40No2IamSxzUqv909Oqf8Yd/V7c/1e+/mXz07+jJb+bmh/z+d+bhj8XN9/XjX7uLr4tHryFHMvtc5FvEuycyGiidaB1F7VGUDPLho2L6SXn6aW/xVXX78+jFn8Pnf9RPf++/9yZdflPe/jL84C/z4LWqnyOlue+rMAzBBr5WEidhrJjjCwI7qlQU+EaJWPsmak+DZKJkO0iOongkRYyUEqDXvgyCQErw5nbJJaw33AjFmYJt50wyLKkHAK4ZDyCR9JH1uAMXUvDQjyGO4lwJqeGZNedvHfZESslZoEOkG6cGNpWvNNQO4ZOoFwYRMG2934rlHqAX/D9kEm8YM/KJewAAAABJRU5ErkJggg==","aspectRatio":1.1067961165048543,"src":"/static/b6d453e388d6dc39dbc445997b08ec29/502b1/floating-island-hero.png","srcSet":"/static/b6d453e388d6dc39dbc445997b08ec29/f2e6d/floating-island-hero.png 114w,\n/static/b6d453e388d6dc39dbc445997b08ec29/4ddba/floating-island-hero.png 229w,\n/static/b6d453e388d6dc39dbc445997b08ec29/502b1/floating-island-hero.png 457w,\n/static/b6d453e388d6dc39dbc445997b08ec29/7ddc2/floating-island-hero.png 686w,\n/static/b6d453e388d6dc39dbc445997b08ec29/435bf/floating-island-hero.png 914w,\n/static/b6d453e388d6dc39dbc445997b08ec29/1ea3a/floating-island-hero.png 1520w","srcWebp":"/static/b6d453e388d6dc39dbc445997b08ec29/15384/floating-island-hero.webp","srcSetWebp":"/static/b6d453e388d6dc39dbc445997b08ec29/31fce/floating-island-hero.webp 114w,\n/static/b6d453e388d6dc39dbc445997b08ec29/e3e25/floating-island-hero.webp 229w,\n/static/b6d453e388d6dc39dbc445997b08ec29/15384/floating-island-hero.webp 457w,\n/static/b6d453e388d6dc39dbc445997b08ec29/0258d/floating-island-hero.webp 686w,\n/static/b6d453e388d6dc39dbc445997b08ec29/64ea2/floating-island-hero.webp 914w,\n/static/b6d453e388d6dc39dbc445997b08ec29/9d244/floating-island-hero.webp 1520w","sizes":"(max-width: 457px) 100vw, 457px"},"seo":{"src":"/static/b6d453e388d6dc39dbc445997b08ec29/6050d/floating-island-hero.png"}}},{"id":"c6dc81a2-caaa-5866-83ba-9d76216fc326","slug":"/creating-an-amazing-particle-transition-in-blender-and-exporting-to-react-three-fiber","secret":false,"title":"Creating An Amazing Particle Transition In Blender and Exporting to React Three Fiber","author":"Rick","date":"November 27th, 2022","dateForSEO":"2022-11-27T00:00:00.000Z","timeToRead":3,"excerpt":"Highlighting a workflow from blender to React Three Fiber (R3F) for morphing particles from different shapes. Utilizing images for storing data in blender and then consuming in a React Three Fiber / Threejs shader.","canonical_url":null,"subscription":true,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Creating An Amazing Particle Transition In Blender and Exporting to React Three Fiber\",\n  \"author\": \"Rick\",\n  \"date\": \"2022-11-27T00:00:00.000Z\",\n  \"hero\": \"./images/particle-animation-hero.png\",\n  \"excerpt\": \"Highlighting a workflow from blender to React Three Fiber (R3F) for morphing particles from different shapes. Utilizing images for storing data in blender and then consuming in a React Three Fiber / Threejs shader.\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"This article is one way in which you can create particle animations in blender and via a script, export to \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"@react-three/fiber\"), \"!\"), mdx(\"p\", null, \"The premise is as follows:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Using geometry nodes we create particles on the surface of a shape and we morph between shapes \"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Via scripting, we export the data via an image \"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Merge images \"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"In R3F we consume this texture/image\")), mdx(\"iframe\", {\n    src: \"https://codesandbox.io/embed/youthful-feynman-jr24d1?fontsize=14&hidenavigation=1&theme=dark&view=preview\",\n    style: {\n      \"width\": \"100%\",\n      \"height\": \"500px\",\n      \"border\": \"0\",\n      \"borderRadius\": \"4px\",\n      \"overflow\": \"hidden\",\n      \"maxWidth\": \"500px\"\n    },\n    title: \"youthful-feynman-jr24d1\",\n    allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\",\n    sandbox: \"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n  }), mdx(\"h2\", {\n    \"id\": \"using-geometry-nodes-we-create-particles-on-the-surface-of-a-shape\"\n  }, \"Using geometry nodes we create particles on the surface of a shape\"), mdx(\"p\", null, \"The idea came from this youtube \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://m.youtube.com/watch?v=pimbaEE9cjQ\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"tutorial on particle morphing in blender by Robbie Tilton\")), mdx(\"p\", null, \"Here is the node setup in blender:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"2222px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"58.95589558955896%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAABt0lEQVQoz3WS626cMBCF9xn6p4s9voMBG2xzZyGbrHabVv3R93+dDlEUqUpzhEbC8ufxOeOT1jrPc2OMNqb2pbGGMsYExwJAuc31kEBL/Dk+QhnFSoAC6gRvIoRQQmJs49CDUkxJKHRWaL+O07ZSo5CHXFNncZ0GJ82h09FGCGstM2rdti6mvWp9Uakh5nPfzePr/YHXoJK7sY/rbEPTXZY6NDHEd7goCibF/cd9HMdlf6lCi5eBLPOufX6+AfDzd5JCuu5PeJB4s4TlgNHNGbcCjX3jUigqJ6UUfQBtXE1dDWUJITDOGRcH+KETkrlQc+G0VOM0uab5xjJV2mnfhNLjnFLvu6GdloghsX91opRWtrjffuXev/7+uaR+QBNl2YZWSjY9hXaowuDTkuhnGKPG3Oqm4Zx736TSvdSdlgbDB0JTkDGIYzCfyHfPFOg5y6QSZWNxJBkHXFJdy105rdc0rJSSw/FnGA80XOYg8Jms22qsVbkBo6bt4htXeZyaB/hP2wMmlKa6uS1X33f3x2Mo6j9+NhpdV1ppQjLAtl/oCCymmOaLLct933HmSirOxOH5i4Yf+gvZHmXWNh8V5gAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/4021a36bff5c19d9b19d3f54bbb63aee/43654/geometry-node-setup.webp 2222w\"],\n    \"sizes\": \"(max-width: 2222px) 100vw, 2222px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/4021a36bff5c19d9b19d3f54bbb63aee/ef5f3/geometry-node-setup.png 2222w\"],\n    \"sizes\": \"(max-width: 2222px) 100vw, 2222px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/4021a36bff5c19d9b19d3f54bbb63aee/ef5f3/geometry-node-setup.png\",\n    \"alt\": \"Geometry node setup in blender\",\n    \"title\": \"Geometry node setup in blender\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"We start off by distributing the points / instances on the first shape:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"2160px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"38.51851851851852%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAABM0lEQVQY031Ry26DMBDkM/AbzMtgIBAwj4DhkFTlWKXNqbf0//+hdhpFyaWj1Ur2eHZ2vQ55BcbkPyBMXEAA/Ds5zxRlhPmUMVODUGyzLfYIiGAu6NJjVWFqWefJE4si7Oaq7HauT13OIPdw4D8C+kyofbtq2bfI3Pjei3OSJNNh6vop8aN9nGY8JIwiSiAlNjOqDuM6z2mcWLPAv4sxMtNgWeSL1k3bDml5HpatXQhAtMyikxZvKygzQ23be13X2A5CHCFEXVWBSABn3WHUWue5jGWhJt1rzTgPy7xoalntiOcp1Z0/z/M8I4TshwWBEYowigCEx9Pxev2Zxr4Zj9vHt1INoaZjC4wwcEHfD5fL17qud7FpwHI3SCmHYUjTNIljmaWc89ct4iiKmqYxz/Btpb/a3kfdwqu1wAAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/0932a9ecef863033563fc25b5261ed7a/f5d30/initial-flow-GN.webp 2160w\"],\n    \"sizes\": \"(max-width: 2160px) 100vw, 2160px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/0932a9ecef863033563fc25b5261ed7a/eb386/initial-flow-GN.png 2160w\"],\n    \"sizes\": \"(max-width: 2160px) 100vw, 2160px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/0932a9ecef863033563fc25b5261ed7a/eb386/initial-flow-GN.png\",\n    \"alt\": \"Distributing points on first shape\",\n    \"title\": \"Distributing points on first shape\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"Having done this we now want to do the same node setup on two more shapes and then use the mix color node.\"), mdx(\"p\", null, \"To Get it animating we have to keyframe the factor of the mix node. This way it will animate from 0-1 over time. I chose 400 frames as the max / end of the animation.\"), mdx(\"p\", null, \"So we now have 3 shapes and they animate between the factors of the mix nodes.\"), mdx(\"p\", null, \"We will need a way to utilise this inside of a shader in \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"threejs\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"@react-three/fiber\"), \". Welcome the export script to the stage! \\uD83D\\uDC40\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/2d37e5fc2a73f17b6fcd762b79226ff7/particle-morph-1.4.blend\"\n  }, \"Here is\"), \" the blender file.\"), mdx(\"p\", null, \"And \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://github.com/Gerstmann-Bradley/Mograph-Presets-of-Geometry-Nodes\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"here is a link\"), \" to some geometry node presets addon.\"), mdx(\"h2\", {\n    \"id\": \"via-scripting-we-export-the-data-via-an-image\"\n  }, \"Via scripting, we export the data via an image\"), mdx(\"p\", null, \"So here is the export script:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"import bpy\\nimport numpy as np\\nimport os\\n\\n\\nobject = bpy.data.objects[\\\"Sphere\\\"]\\n\\ndef particleSetter(scene, degp):\\n    degp = bpy.context.evaluated_depsgraph_get()\\n    obj = bpy.data.objects['Sphere']\\n    obj_evaluated = obj.evaluated_get(degp)\\n    cFrame = scene.frame_current\\n    location = []\\n\\n    instance_count = 0\\n    for object_instance in degp.object_instances:\\n        # This is an object which is being instanced.\\n        obj = object_instance.object\\n        # `is_instance` denotes whether the object is coming from instances (as an opposite of\\n        # being an emitting object. )\\n  \\n        if object_instance.is_instance and object_instance.parent == obj_evaluated:\\n            # Instanced will additionally have fields like uv, random_id and others which are\\n            # specific for instances. See Python API for DepsgraphObjectInstance for details,\\n            loc, rot, sca = object_instance.matrix_world.decompose()\\n                \\n            location.extend([loc[0] / 150.0 + 0.5,loc[1]/ 150.0 + 0.5, loc[2]/150.0   + 0.5])\\n\\n    print(location)\\n    \\n    size = int(len(location)/ 3), 1\\n\\n    image = bpy.data.images.new(\\\"pos-1.0-frame-%s\\\" % cFrame, width=size[0], height=size[1])\\n    image.colorspace_settings.name = 'Non-Color'\\n    pixels = [None] * size[0] * size[1]\\n    for x in range(size[0]):\\n        r = location[x * 3 -2]\\n        g = location[x * 3 -1]\\n        b = location[x * 3]\\n        a = 1.0\\n        pixels[x] = [r, g, b, a]\\n    pixels = [chan for px in pixels for chan in px]\\n    image.pixels = pixels\\n    image.file_format = \\\"PNG\\\"\\n    image.filepath_raw = \\\"/tmp/position-frame-%s.png\\\" % cFrame\\n   \\n    image.save()    \\n\\n#clear the post frame handler\\nbpy.app.handlers.frame_change_post.clear() \\n\\n#run the function on each frame\\nbpy.app.handlers.frame_change_post.append(particleSetter)\\n\")), mdx(\"p\", null, \"This is all based around running a function every frame. A small point is that you have to use some inbuilt functions from the blender python API. I found \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://blender.stackexchange.com/questions/168122/handler-frame-change-pre-doesnt-work-in-render\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this stackoverflow\"), \" post very useful.\"), mdx(\"p\", null, \"In essense we:\"), mdx(\"ul\", null, mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"grab the sphere\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"evaluate the data\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Manipulate the coordinates into 0-1 range \"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Determine the number of pixels we will create \"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"Set \", mdx(\"inlineCode\", {\n    parentName: \"li\"\n  }, \"image.colorspace_settings.name = 'Non-Color'\"), \" to avoid gama correction done on the images in sRGB color space <\\u2014 very important\"), mdx(\"li\", {\n    parentName: \"ul\"\n  }, \"run this function every frame change \")), mdx(\"p\", null, \"One important point is I used my desktop to run this as its quite intensive on my laptop.\"), mdx(\"p\", null, \"Another couple of important points from my studying or learning is that if the number is too high we divide the position by we lose signal strength or precision.. but conversely if too low then we will get solid colors and we dont want this and this is a way to tell us that we have values which have clamped to 0.0 or 1.0 which means we need to increase the number we divide by.\"), mdx(\"p\", null, \"Solid colors are 0.0 or 1.0 in values for vec3()\\u2018s or vec4\\u2019s.\"), mdx(\"p\", null, \"Theres a good example of explaining this calculation \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.thefrontdev.co.uk/exporting-particle-animations-from-blender-via-images-for-use-in-r3f-and-three.js\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"in a previous article\"), \".\"), mdx(\"p\", null, \"The last point is that we dont want \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://stackoverflow.com/questions/29806039/gamma-correction-doesnt-look-properly-corrected-is-this-linear\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"gamma correction\")), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1248px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"70.03205128205127%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAACbklEQVQoz3VTWUtiYRg+W+56ljkeLDUXUrvJcYnGUETBpcYDrlmNOClBBIkgCGrgjUSBBF2lXXglKOQf6A9455+aR+tqoO/iO+/yvcvzvO8hCIJQKBSiKJpMJo1GA5XjOJvNtr29zTAMTdM7OztOp1MQBLh0Oh1keFUqFVQCH4/HEw6Ho9HowcGBy+VKJBJnZ2e5XC4QCIRCoWq1enNzk8/noeJuNpt3d3enp6cGg4GwWCyxWKxSqVxdXcGUyWRub28fHh46nQ7CID8/P08mk36/32g0YF8sFvP5/P7+PhKJEGgjmUwiN/IVCoVisdhut9/e3p6enhAJeTqdfnx8vLy8IGA8Hq9Wq+VyORwOZVkmJEk6Pj5Gk6VSKR6Po+d6vd7r9dDeebl8fX39+Pg4en3tdrvINRgM3t/fZ7PZV2VQYrVafT4fIDkcDtAD/L9lOZFKuff3/YFA+eLib72ekWW8QWutVgt5UZbn+TVnJEmq1WpQjURQtWq1S5KsgsDTtIFhXCbTT7tdZFm4WJbd29sDUq1WS3x3lJgCQahJSkGQirVMUt89RWWMFNPGTZEkBJbnWY7bgmVr64coWnd3ca/tm8putxu7gKh1MLqFArR6vV6pVGJbfh0dHR4eQsCqRMLhP5eXIMJutweDwc+5wAukX2WNRiOQgAOAwaN0Og3aIcCYzWbBLW6sEIaKmY1Go1QqxW5YWFdGGmwMyiIRx/NoDKuGdrCVfr8/fXICqtGa1+vFOtVqNahfG/oJm9qcdS6KUimVAAwT7JiCgI40GnhRA0DMZvO3bOspCv+EyDASwwg0jYFJNMNtpvjf+QfsQ5VuxYZoWwAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/80c2a3b6f744a0990dd9d5073c0a6359/28eb2/gamma-correction.webp 1248w\"],\n    \"sizes\": \"(max-width: 1248px) 100vw, 1248px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/80c2a3b6f744a0990dd9d5073c0a6359/350a9/gamma-correction.png 1248w\"],\n    \"sizes\": \"(max-width: 1248px) 100vw, 1248px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/80c2a3b6f744a0990dd9d5073c0a6359/350a9/gamma-correction.png\",\n    \"alt\": \"Gamma correction\",\n    \"title\": \"Gamma correction\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"Gamma correction weights the colors in an image more to the bright side or increasing intensity as light gets lighter. This is to try and mimic what the human eye does. But I wont go into great detail, theres loads of resources online which explain this in a lot of detail.\"), mdx(\"h2\", {\n    \"id\": \"merge-images\"\n  }, \"Merge Images\"), mdx(\"p\", null, \"The process of merging is quite laborious and Im hoping to potentially use blenders image compositor next time.\"), mdx(\"p\", null, \"But this article \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.thefrontdev.co.uk/exporting-particle-animations-from-blender-via-images-for-use-in-r3f-and-three.js\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"here\"), \" explains the website I used and as we once again did a 2893.0 x 1 texture / image we can easily merge these uniformly sized images. \"), mdx(\"p\", null, \"Here a few tries I did:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"2894px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"13.84%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAADABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAEDBP/EABcBAAMBAAAAAAAAAAAAAAAAAAACAwT/2gAMAwEAAhADEAAAAY0mN6wV/8QAFxAAAwEAAAAAAAAAAAAAAAAAAAECEf/aAAgBAQABBQJjmTEf/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAERMf/aAAgBAwEBPwGYRH//xAAYEQADAQEAAAAAAAAAAAAAAAAAAQIRIf/aAAgBAgEBPwGqfDWf/8QAFRABAQAAAAAAAAAAAAAAAAAAADH/2gAIAQEABj8CRH//xAAbEAACAgMBAAAAAAAAAAAAAAAAARFBITFxkf/aAAgBAQABPyHhVQlLjoUCw8P/2gAMAwEAAgADAAAAEPwP/8QAGBEAAwEBAAAAAAAAAAAAAAAAAAERQWH/2gAIAQMBAT8QaRppyP/EABgRAAMBAQAAAAAAAAAAAAAAAAABETHw/9oACAECAQE/EF9PoO2n/8QAGhABAAIDAQAAAAAAAAAAAAAAAQARIUFRMf/aAAgBAQABPxBhdZeGxggW5eRTaeJ//9k=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/61b04deeeb7522be8c508d3a8e5c9804/a3bc4/particle-image-1.1.webp 2500w\", \"/static/61b04deeeb7522be8c508d3a8e5c9804/cc502/particle-image-1.1.webp 2894w\"],\n    \"sizes\": \"(max-width: 2894px) 100vw, 2894px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/61b04deeeb7522be8c508d3a8e5c9804/44ecf/particle-image-1.1.jpg 2500w\", \"/static/61b04deeeb7522be8c508d3a8e5c9804/81ec5/particle-image-1.1.jpg 2894w\"],\n    \"sizes\": \"(max-width: 2894px) 100vw, 2894px\",\n    \"type\": \"image/jpeg\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/61b04deeeb7522be8c508d3a8e5c9804/81ec5/particle-image-1.1.jpg\",\n    \"alt\": \"First attempt\",\n    \"title\": \"First attempt\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"2894px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"5.2%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAABABQDASIAAhEBAxEB/8QAFwABAAMAAAAAAAAAAAAAAAAAAAECA//EABYBAQEBAAAAAAAAAAAAAAAAAAMABP/aAAwDAQACEAMQAAABwoLlgDf/xAAVEAEBAAAAAAAAAAAAAAAAAAAAQf/aAAgBAQABBQJX/8QAFhEBAQEAAAAAAAAAAAAAAAAAAAEx/9oACAEDAQE/AZqv/8QAFxEBAAMAAAAAAAAAAAAAAAAAAAEDMv/aAAgBAgEBPwG3KH//xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAY/An//xAAXEAEBAQEAAAAAAAAAAAAAAAAAATHR/9oACAEBAAE/IeLpX//aAAwDAQACAAMAAAAQhC//xAAVEQEBAAAAAAAAAAAAAAAAAAAAMf/aAAgBAwEBPxAU/8QAFxEAAwEAAAAAAAAAAAAAAAAAAAExcf/aAAgBAgEBPxCeog//xAAYEAACAwAAAAAAAAAAAAAAAAAAcUHR8P/aAAgBAQABPxChkyCP/9k=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/5bfb4dedff1629ee2cace05f472804e5/a3bc4/particle-image-1.2.webp 2500w\", \"/static/5bfb4dedff1629ee2cace05f472804e5/cc502/particle-image-1.2.webp 2894w\"],\n    \"sizes\": \"(max-width: 2894px) 100vw, 2894px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/5bfb4dedff1629ee2cace05f472804e5/44ecf/particle-image-1.2.jpg 2500w\", \"/static/5bfb4dedff1629ee2cace05f472804e5/81ec5/particle-image-1.2.jpg 2894w\"],\n    \"sizes\": \"(max-width: 2894px) 100vw, 2894px\",\n    \"type\": \"image/jpeg\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/5bfb4dedff1629ee2cace05f472804e5/81ec5/particle-image-1.2.jpg\",\n    \"alt\": \"Second attempt\",\n    \"title\": \"Second attempt\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"And here is the final image which I used in the codesandbox:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"2894px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"13.799999999999999%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAADABQDASIAAhEBAxEB/8QAFQABAQAAAAAAAAAAAAAAAAAAAAH/xAAWAQEBAQAAAAAAAAAAAAAAAAABAgP/2gAMAwEAAhADEAAAAVM6Af/EABQQAQAAAAAAAAAAAAAAAAAAABD/2gAIAQEAAQUCf//EABQRAQAAAAAAAAAAAAAAAAAAABD/2gAIAQMBAT8BP//EABURAQEAAAAAAAAAAAAAAAAAABAR/9oACAECAQE/Aaf/xAAUEAEAAAAAAAAAAAAAAAAAAAAQ/9oACAEBAAY/An//xAAYEAACAwAAAAAAAAAAAAAAAAAAARARUf/aAAgBAQABPyEpZH//2gAMAwEAAgADAAAAEHAf/8QAFhEAAwAAAAAAAAAAAAAAAAAAAAER/9oACAEDAQE/EIiI/8QAFhEBAQEAAAAAAAAAAAAAAAAAAQBR/9oACAECAQE/EFbK3//EABoQAAICAwAAAAAAAAAAAAAAAAABEZEhMYH/2gAIAQEAAT8Q4qGhvCiFGlR//9k=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/701d3a28e23e9c189d23af83d279b40c/a3bc4/particle-image-1.3.webp 2500w\", \"/static/701d3a28e23e9c189d23af83d279b40c/cc502/particle-image-1.3.webp 2894w\"],\n    \"sizes\": \"(max-width: 2894px) 100vw, 2894px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/701d3a28e23e9c189d23af83d279b40c/44ecf/particle-image-1.3.jpg 2500w\", \"/static/701d3a28e23e9c189d23af83d279b40c/81ec5/particle-image-1.3.jpg 2894w\"],\n    \"sizes\": \"(max-width: 2894px) 100vw, 2894px\",\n    \"type\": \"image/jpeg\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/701d3a28e23e9c189d23af83d279b40c/81ec5/particle-image-1.3.jpg\",\n    \"alt\": \"Final attempt\",\n    \"title\": \"Final attempt\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"h2\", {\n    \"id\": \"in-r3f-we-consume-this-textureimage\"\n  }, \"In R3F we consume this texture/image\"), mdx(\"p\", null, \"The final part of this puzzle is to consume this image inside of the \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"threejs\"), \" / \", mdx(\"inlineCode\", {\n    parentName: \"p\"\n  }, \"@react-three/fiber\"), \" shader:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"import { Suspense, useRef, useEffect, useCallback } from \\\"react\\\";\\nimport { Canvas, useFrame, useLoader } from \\\"@react-three/fiber\\\";\\nimport { OrbitControls } from \\\"@react-three/drei\\\";\\nimport download from \\\"./Smoke15Frames.png\\\";\\nimport * as THREE from \\\"three\\\";\\nimport { useMemo } from \\\"react\\\";\\nimport texture from \\\"./morph_particles-1.9.jpg\\\";\\n// Building on storing data in images and this is an\\n// example of a particle simulation in blender 1-240 frames\\n// sampled at every frame and only 5-6kb! bare in mind this\\n// is only 100 particles\\nfunction Points() {\\n  const tex = useLoader(THREE.TextureLoader, texture);\\n  tex.encoding = THREE.LinearEncoding;\\n  const orb = useLoader(THREE.TextureLoader, download);\\n  const pointsRef = useRef();\\n  const shaderRef = useRef();\\n\\n  const customShader = {\\n    uniforms: {\\n      positions: {\\n        value: tex\\n      },\\n      orb: {\\n        value: orb\\n      },\\n      time: {\\n        value: null\\n      }\\n    },\\n    vertexShader: `\\n      uniform sampler2D positions;\\n      uniform float time;\\n      varying vec2 vUv;\\n      attribute float index;\\n     \\n      void main () {\\n        vec2 myIndex = vec2((index + 0.5)/2893.0, (mod(time * 0.1, 1.0)));\\n\\n        vec4 pos = texture2D( positions, myIndex);\\n\\n        float x = (pos.x - 0.5) * 150.0;\\n        float y = (pos.y - 0.5) * 150.0;\\n        float z = (pos.z - 0.5) * 150.0;\\n        \\n        gl_PointSize =2.0;\\n        gl_Position = projectionMatrix * modelViewMatrix * vec4(x,y,z, 1.0);\\n      \\n      }`,\\n    fragmentShader: `\\n      void main () {\\n        gl_FragColor = vec4(0.3,1.0,1.0,0.2);\\n      }`\\n  };\\n\\n  let [positions, indexs] = useMemo(() => {\\n    let positions = [...Array(8682).fill(0)];\\n    let index = [...Array(2894).keys()];\\n\\n    return [new Float32Array(positions), new Float32Array(index)]; //merupakan array yang sesuai dengan buffer\\n  }, []);\\n\\n  useEffect(() => {\\n    if (pointsRef.current) {\\n      console.log({ indexs, positions });\\n      console.log({ pointsRef });\\n    }\\n  }, []);\\n\\n  useFrame(({ clock }) => {\\n    shaderRef.current.uniforms[\\\"time\\\"].value = clock.elapsedTime;\\n  });\\n\\n  return (\\n    <points ref={pointsRef}>\\n      <bufferGeometry attach=\\\"geometry\\\">\\n        <bufferAttribute\\n          attach=\\\"attributes-position\\\"\\n          array={positions}\\n          count={positions.length / 3.0}\\n          itemSize={3}\\n        />\\n        <bufferAttribute\\n          attach=\\\"attributes-index\\\"\\n          array={indexs}\\n          count={indexs.length}\\n          itemSize={1}\\n        />\\n      </bufferGeometry>\\n      <shaderMaterial\\n        ref={shaderRef}\\n        attach=\\\"material\\\"\\n        color={\\\"red\\\"}\\n        sizeAttenuation\\n        transparent\\n        depthTest\\n        vertexShader={customShader.vertexShader}\\n        fragmentShader={customShader.fragmentShader}\\n        uniforms={customShader.uniforms}\\n      />\\n    </points>\\n  );\\n}\\n\\nfunction AnimationCanvas() {\\n  return (\\n    <Canvas camera={{ position: [500, 150, 50], fov: 75 }}>\\n      <OrbitControls />\\n      <gridHelper />\\n      <Suspense fallback={null}>\\n        <Points />\\n      </Suspense>\\n    </Canvas>\\n  );\\n}\\n\\nexport default function App() {\\n  return (\\n    <div className=\\\"App\\\">\\n      <Suspense fallback={<div>Loading...</div>}>\\n        <color attach=\\\"background\\\" args={\\\"black\\\"} />\\n        <AnimationCanvas />\\n        <gridHelper />\\n      </Suspense>\\n    </div>\\n  );\\n}\\n\\n\")), mdx(\"p\", null, \"We use points as this seems like the best way to show the particles or we could use GPU particle instancing.\"), mdx(\"p\", null, \"We have a buffer geometry with a hardcoded number of positions, this needs to match the number of particles we used in blender exactly.\"), mdx(\"p\", null, \"We also need an index for figuring out the uvs of the image, uvs are 0-1 range and thats why we divide the index by 2893.0. We add 0.5 to the index to center it.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"vec2 myIndex = vec2((index + 0.5)/2893.0, (mod(time * 0.1, 1.0)));\\n\")), mdx(\"p\", null, \"We then do a texture lookup and then convert the small numbers back to the real useful numbers or coordinates.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"vec4 pos = texture2D( positions, myIndex);\\n\\nfloat x = (pos.x - 0.5) * 150.0;\\nfloat y = (pos.y - 0.5) * 150.0;\\nfloat z = (pos.z - 0.5) * 150.0;\\n\\ngl_PointSize =2.0;\\n\\ngl_Position = projectionMatrix * modelViewMatrix * vec4(x,y,z, 1.0);\\n\")), mdx(\"p\", null, \"I split up the xyz bit just to be clear whats happening.\"), mdx(\"iframe\", {\n    src: \"https://codesandbox.io/embed/youthful-feynman-jr24d1?fontsize=14&hidenavigation=1&theme=dark&view=preview\",\n    style: {\n      \"width\": \"100%\",\n      \"height\": \"500px\",\n      \"border\": \"0\",\n      \"borderRadius\": \"4px\",\n      \"overflow\": \"hidden\",\n      \"maxWidth\": \"500px\"\n    },\n    title: \"youthful-feynman-jr24d1\",\n    allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\",\n    sandbox: \"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n  }), mdx(\"h2\", {\n    \"id\": \"final-thoughts\"\n  }, \"Final Thoughts\"), mdx(\"p\", null, \"This is a great way to do particle animations in blender where it is arguably easier and then do minimal shader code avoiding the need for something more complicated like GPU particle simulation shaders etc.\"), mdx(\"p\", null, \"There are some great possibilities here like attaching the animation to a scroll event or doing a camera animation.\"), mdx(\"p\", null, \"This way is a lot more optimized than key-framing as key-framing 1000\\u2019s of particles is going to cause a bloated GLTF file. Where as these images could be Kb\\u2019s instead of Mbs (depending on the number of particles used).\"), mdx(\"p\", null, \"Anyhow, hope you find useful! \\uD83D\\uDE42\"));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABzElEQVQoz0WR247aQAyGJyQk4aACYgPMeA7OgQBBSwkBsRS1qAsSXbUXvW570/aiqvY1+uD1ANq1Pll/PLZjz7ByWa7KspjNNuv1uqoQcZpP3t4v5kWx3W6rqsqS1CiN2lwhXUxnu90DJbC7bi/DeDbOyXea7ZYf1p2ax5w6q7mMeYz5NTd4xaszCnWY3NRIRN1eqjE1iFLGRkvgruv4vlt3qP4FdoXavXG8OXYgF6thl1ES9XAd5no1L3AbvbDdbwWh32wETT9oBURINMmHYSMM+8121o+GCYdhiykptZEGaS0oT+X579PT85f91/cY48XiBDGxPk7imFZLjTFxls02q8WSKaoGoNTloTw/f378dXr8ffz+78f9Ism1QCliCUYIFNII0AIUgKJPBfv9nolowO8iJfh0mVefqo8/T8c/58WxBD7UwAUMOERcDUYyEnLAxcgy4kppW0wJ9GdxMYpmi/G7b4d8OQEOkoZSZJqEpicyUseCUMjTsf5w2DN7eDHaxdBLoinW83SS3iJGo3k1vN2DSVJ82K1t8bXe3hx11xpGQksrtFIXb7Xtayw3jZglGZMCaGxFMwIA56Tp+CVovW2qCNLEVVOQ9H9KS0uQzC38CwAAAABJRU5ErkJggg==","aspectRatio":1.8294573643410852,"src":"/static/1f2e643a0abda7274fbb320a16570e7f/a1946/particle-animation-hero.png","srcSet":"/static/1f2e643a0abda7274fbb320a16570e7f/5b37e/particle-animation-hero.png 236w,\n/static/1f2e643a0abda7274fbb320a16570e7f/49058/particle-animation-hero.png 472w,\n/static/1f2e643a0abda7274fbb320a16570e7f/a1946/particle-animation-hero.png 944w,\n/static/1f2e643a0abda7274fbb320a16570e7f/fea4a/particle-animation-hero.png 1020w","srcWebp":"/static/1f2e643a0abda7274fbb320a16570e7f/99fbb/particle-animation-hero.webp","srcSetWebp":"/static/1f2e643a0abda7274fbb320a16570e7f/77392/particle-animation-hero.webp 236w,\n/static/1f2e643a0abda7274fbb320a16570e7f/1f177/particle-animation-hero.webp 472w,\n/static/1f2e643a0abda7274fbb320a16570e7f/99fbb/particle-animation-hero.webp 944w,\n/static/1f2e643a0abda7274fbb320a16570e7f/02c68/particle-animation-hero.webp 1020w","sizes":"(max-width: 944px) 100vw, 944px"},"regular":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABzElEQVQoz0WR247aQAyGJyQk4aACYgPMeA7OgQBBSwkBsRS1qAsSXbUXvW570/aiqvY1+uD1ANq1Pll/PLZjz7ByWa7KspjNNuv1uqoQcZpP3t4v5kWx3W6rqsqS1CiN2lwhXUxnu90DJbC7bi/DeDbOyXea7ZYf1p2ax5w6q7mMeYz5NTd4xaszCnWY3NRIRN1eqjE1iFLGRkvgruv4vlt3qP4FdoXavXG8OXYgF6thl1ES9XAd5no1L3AbvbDdbwWh32wETT9oBURINMmHYSMM+8121o+GCYdhiykptZEGaS0oT+X579PT85f91/cY48XiBDGxPk7imFZLjTFxls02q8WSKaoGoNTloTw/f378dXr8ffz+78f9Ism1QCliCUYIFNII0AIUgKJPBfv9nolowO8iJfh0mVefqo8/T8c/58WxBD7UwAUMOERcDUYyEnLAxcgy4kppW0wJ9GdxMYpmi/G7b4d8OQEOkoZSZJqEpicyUseCUMjTsf5w2DN7eDHaxdBLoinW83SS3iJGo3k1vN2DSVJ82K1t8bXe3hx11xpGQksrtFIXb7Xtayw3jZglGZMCaGxFMwIA56Tp+CVovW2qCNLEVVOQ9H9KS0uQzC38CwAAAABJRU5ErkJggg==","aspectRatio":1.8314606741573034,"src":"/static/1f2e643a0abda7274fbb320a16570e7f/3ddd4/particle-animation-hero.png","srcSet":"/static/1f2e643a0abda7274fbb320a16570e7f/078a8/particle-animation-hero.png 163w,\n/static/1f2e643a0abda7274fbb320a16570e7f/e56da/particle-animation-hero.png 327w,\n/static/1f2e643a0abda7274fbb320a16570e7f/3ddd4/particle-animation-hero.png 653w,\n/static/1f2e643a0abda7274fbb320a16570e7f/c5cc7/particle-animation-hero.png 980w,\n/static/1f2e643a0abda7274fbb320a16570e7f/fea4a/particle-animation-hero.png 1020w","srcWebp":"/static/1f2e643a0abda7274fbb320a16570e7f/0acdf/particle-animation-hero.webp","srcSetWebp":"/static/1f2e643a0abda7274fbb320a16570e7f/ac59e/particle-animation-hero.webp 163w,\n/static/1f2e643a0abda7274fbb320a16570e7f/7660b/particle-animation-hero.webp 327w,\n/static/1f2e643a0abda7274fbb320a16570e7f/0acdf/particle-animation-hero.webp 653w,\n/static/1f2e643a0abda7274fbb320a16570e7f/75470/particle-animation-hero.webp 980w,\n/static/1f2e643a0abda7274fbb320a16570e7f/02c68/particle-animation-hero.webp 1020w","sizes":"(max-width: 653px) 100vw, 653px"},"narrow":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAALCAIAAADwazoUAAAACXBIWXMAAAsTAAALEwEAmpwYAAABzElEQVQoz0WR247aQAyGJyQk4aACYgPMeA7OgQBBSwkBsRS1qAsSXbUXvW570/aiqvY1+uD1ANq1Pll/PLZjz7ByWa7KspjNNuv1uqoQcZpP3t4v5kWx3W6rqsqS1CiN2lwhXUxnu90DJbC7bi/DeDbOyXea7ZYf1p2ax5w6q7mMeYz5NTd4xaszCnWY3NRIRN1eqjE1iFLGRkvgruv4vlt3qP4FdoXavXG8OXYgF6thl1ES9XAd5no1L3AbvbDdbwWh32wETT9oBURINMmHYSMM+8121o+GCYdhiykptZEGaS0oT+X579PT85f91/cY48XiBDGxPk7imFZLjTFxls02q8WSKaoGoNTloTw/f378dXr8ffz+78f9Ism1QCliCUYIFNII0AIUgKJPBfv9nolowO8iJfh0mVefqo8/T8c/58WxBD7UwAUMOERcDUYyEnLAxcgy4kppW0wJ9GdxMYpmi/G7b4d8OQEOkoZSZJqEpicyUseCUMjTsf5w2DN7eDHaxdBLoinW83SS3iJGo3k1vN2DSVJ82K1t8bXe3hx11xpGQksrtFIXb7Xtayw3jZglGZMCaGxFMwIA56Tp+CVovW2qCNLEVVOQ9H9KS0uQzC38CwAAAABJRU5ErkJggg==","aspectRatio":1.8387096774193548,"src":"/static/1f2e643a0abda7274fbb320a16570e7f/502b1/particle-animation-hero.png","srcSet":"/static/1f2e643a0abda7274fbb320a16570e7f/f2e6d/particle-animation-hero.png 114w,\n/static/1f2e643a0abda7274fbb320a16570e7f/4ddba/particle-animation-hero.png 229w,\n/static/1f2e643a0abda7274fbb320a16570e7f/502b1/particle-animation-hero.png 457w,\n/static/1f2e643a0abda7274fbb320a16570e7f/7ddc2/particle-animation-hero.png 686w,\n/static/1f2e643a0abda7274fbb320a16570e7f/435bf/particle-animation-hero.png 914w,\n/static/1f2e643a0abda7274fbb320a16570e7f/fea4a/particle-animation-hero.png 1020w","srcWebp":"/static/1f2e643a0abda7274fbb320a16570e7f/15384/particle-animation-hero.webp","srcSetWebp":"/static/1f2e643a0abda7274fbb320a16570e7f/31fce/particle-animation-hero.webp 114w,\n/static/1f2e643a0abda7274fbb320a16570e7f/e3e25/particle-animation-hero.webp 229w,\n/static/1f2e643a0abda7274fbb320a16570e7f/15384/particle-animation-hero.webp 457w,\n/static/1f2e643a0abda7274fbb320a16570e7f/0258d/particle-animation-hero.webp 686w,\n/static/1f2e643a0abda7274fbb320a16570e7f/64ea2/particle-animation-hero.webp 914w,\n/static/1f2e643a0abda7274fbb320a16570e7f/02c68/particle-animation-hero.webp 1020w","sizes":"(max-width: 457px) 100vw, 457px"},"seo":{"src":"/static/1f2e643a0abda7274fbb320a16570e7f/fea4a/particle-animation-hero.png"}}},{"id":"941b24df-54d8-521f-b345-63688ba9e3f1","slug":"/exporting-particle-animations-from-blender-via-images-for-use-in-r3f-and-three.js","secret":false,"title":"Exporting Particle Animations From Blender via Images for use in R3F and Three.js","author":"Rick","date":"October 16th, 2022","dateForSEO":"2022-10-16T00:00:00.000Z","timeToRead":5,"excerpt":"Exporting particle animations from blender to a r3f project. We use the particle simulation in blender, run an export script to save location data in images (PNG's) and then combine the images into a single large image. This has great potential for attaching textures to the points material for fire/smoke/snow or sand storms.","canonical_url":null,"subscription":true,"body":"var _excluded = [\"components\"];\n\nfunction _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Exporting Particle Animations From Blender via Images for use in R3F and Three.js\",\n  \"author\": \"Rick\",\n  \"date\": \"2022-10-16T00:00:00.000Z\",\n  \"hero\": \"./images/particle-animation-data-hero.png\",\n  \"excerpt\": \"Exporting particle animations from blender to a r3f project. We use the particle simulation in blender, run an export script to save location data in images (PNG's) and then combine the images into a single large image. This has great potential for attaching textures to the points material for fire/smoke/snow or sand storms.\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, _excluded);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"This article builds on top of the previous article where we stored location data of instanced points into the colour channels of pixels. I wont be going through it again here but briefly touching on it. If you fancy catching up on the previous article, \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.thefrontdev.co.uk/storing-positional-xyz-values-in-a-texture-and-reading-in-a-r3f-shader-material\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"here\"), \" it is \\uD83D\\uDD96\"), mdx(\"p\", null, \"So I here you ask why is this important?\"), mdx(\"p\", null, \"So doing a particle simulation manually on the coding side, is hard, no two ways about it. It requires some sort of instancing or GPU particles, which as said is hard and requires some expert knowledge. \"), mdx(\"p\", null, \"Another thing you need to know is you could do things like this:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1468px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"58.03814713896458%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAIAAADtbgqsAAAACXBIWXMAAAsTAAALEwEAmpwYAAACEUlEQVQoz01SZ4taURC9v0WwLCgESzSKdW0bJYpdQQVdG3YQ19ixV2zRZzfB8jtzeEI258N9M2+YM2cK+bVctNvtRqPRbDYb/+Hp4q3VapVKpVwu93q9TqdTrVbr9Xq/34dLCrGQQqkUiUTfaEgkkucrEAiEQiEMHo/HYrEYDIZOp1MqlXDFYrFcLpfJZEQqlRoMBgTMZrPL5fJ6vYFAwO/32+1249ubRqNxOByRSAQ/EfpOw2QyGWgQhOHYbDaIGY/H0+l0Pp8vFov9fl8qlcCIzA8aMIxGEH6CqNVqfHK53HK5vFwuf2icTifYyAfLer2mKArGZDKJx+Mo+I+CKBQKj8czm802FLVarTabzfF4PJ/Ph8MBOWAB1+PxuN/v1+t1u93GYrHPymgdHUItKg+HQ9CjFDLhYp6wQfSbxu12Awvo3t/fMSM0T1QqFWSEw+HBYDClARWj0Qh7QjL6p2jsdjuwoBdQ4L9er0cWwcS1Wq3FYslms9hnoVBIJBL5fB7z+0mj1Wp1u13MErpQALzRaBQ7QxbhcDjYJ5/PhwTwYfLBYDCTyRSLRbzJZDKdTqdSqVq1igvpDwYoi53hLpBFuC8vX8Xi523gF4Q4nc5QKITBYjaYpdVq9fl8Hq/X7XL63G64aBh3gisiIMCdfKHBZrOZTCZUIPa8OciDzeVytTqd4fVVLRL9sFohGCEk/wX1zBz3g8MhVgAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/cc5e6ba92ffffda0311e55940d739144/7d801/smoke-simulations-tutorial.webp 1468w\"],\n    \"sizes\": \"(max-width: 1468px) 100vw, 1468px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/cc5e6ba92ffffda0311e55940d739144/88420/smoke-simulations-tutorial.png 1468w\"],\n    \"sizes\": \"(max-width: 1468px) 100vw, 1468px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/cc5e6ba92ffffda0311e55940d739144/88420/smoke-simulations-tutorial.png\",\n    \"alt\": \"Tutorial example about attaching smoke textures on particles\",\n    \"title\": \"Tutorial example about attaching smoke textures on particles\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.blendernation.com/2019/09/24/tutorial-smoke-textures-and-making-smoke-with-textures/\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"Here\"), \" is a link to this.\"), mdx(\"p\", null, \"One final thing if you tried to keyframe particle animations in blender, it creates MB\\u2019s of data, this image for 100 particles and over 240 sample frames is between 5-6 kb.\"), mdx(\"p\", null, \"So we now know that this technique simplifies the coding experience, has some pretty useful use cases and has massive optimizations for storing animations, in particular particle animations..\"), mdx(\"p\", null, \"But how do we do it?\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"/5dcba271f269c89a989d07f2f7e497c8/grass-1.9.blend\"\n  }, \"Here\"), \" is the blender file.\"), mdx(\"p\", null, \"And here is the codeSandBox:\"), mdx(\"iframe\", {\n    src: \"https://codesandbox.io/embed/determined-germain-p2vug0?fontsize=14&hidenavigation=1&theme=dark\",\n    style: {\n      \"width\": \"100%\",\n      \"height\": \"500px\",\n      \"border\": \"0\",\n      \"borderRadius\": \"4px\",\n      \"overflow\": \"hidden\",\n      \"maxWidth\": \"500px\"\n    },\n    title: \"determined-germain-p2vug0\",\n    allow: \"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\",\n    sandbox: \"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n  }), mdx(\"p\", null, \"We will cover the following:\"), mdx(\"ol\", null, mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Particle simulation in blender\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Creating the script for saving data as images per frame of simulation\"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Combining the images into one and rotating \"), mdx(\"li\", {\n    parentName: \"ol\"\n  }, \"Using the image in a points object in r3f (building on the previous article)\")), mdx(\"h2\", {\n    \"id\": \"particle-simulation-in-blender\"\n  }, \"Particle Simulation in Blender\"), mdx(\"p\", null, \"So we are going to need to add a cone or other basic shape, go ahead and do shift + a and add a basic mesh.\"), mdx(\"p\", null, \"Next we are going to add a particle simulation to this cone or other basic mesh.\"), mdx(\"p\", null, \"Click on this tab in blender with the cone selected:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"968px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"116.32231404958677%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAADpklEQVQ4y2VT2ZKbRhTlRzIegYRYGrE3+yYhgdC+azIe2xprUk65nDx4kgd/ROK8+HtzgNhxKqduQdPcc5fTtxkhe6m5sSj2PcfcbRaOY9uW4Tm2IveFbkfocwLPfm/9XmdABIWIMEZbzjw/dDWL14eb+w8vX70bFms3Xcp0KvtTYheEloQWrSlOKZl5Ut2Xm9fz/YUpf+lMIiNRAyF+INnT7nCtNm/c4q1V/SpWP4njK0kuJH383uT4kh8/Lh8+MWq0cMJE1VWxz6ESTxOooVLbdG1dHUgDgygSzxNeFHuS0G0Nnr5L51XJ6Lo+nU59P2A5TpIJ1YhlaIoykBRVMk1FUQghgiyLkiQIYmt8v29aVlVVjGmak8nEdd00TQ3DGCiKptYAX1aUDsve3t5yHNfr9bT/Aj4MCKvVKggCfIMfhqHTwG+ABaV00MAwTNg34BdjWVZZllixLIsQnucZjRdY2AwCRPB0vc7ThkBpRJbxRhoGBQ+HQ4QQRdHzgqKcl9N5Vc2Lsgqi1A9iP0zCOMM6CFPPj/JxeffjQ5plh8OBCRoYTUGartdZTcu0bNO0BqrWmkwUPLGv61CKxnECT/TIIHsUx6BCVVkm3W6P47os1+W6MMjEQ14IBoG8BraNuCZ24M/EYZhGkW1aMqkPSSN9jQj6QFKJiKfMszz3AjE6HbbT6dw2QI9IiXprclKTTVngnWzlzq60fJWu3ubbq1c9aqN7OdqaFsXEA1APGs3n89PpVBQFE9R1R2hVurkxsgPdf7LWH4P9c3r6zd48093v7u55NJ7k+SjPc4wTOOg2SRJ81oKBDsEEUXSpOc6iMk9Dj1JL86juU92z9fbk6Ve4DcD/Rtb5Lus4bpoNYUmSTopyPCnyfFxVs2mD9XqNkcQCz9FolGUZAwHRiaHrCv8C0aMoasXAb/QG1+12u2lwPp/bBXYwV/+SNd1gBR0zFcdQMMTYTCbFbDYrynK5Wi2WwOp4OiH5fLHADq7DP+R2JDXTQyctGZKMx+NZjWq3XW/Wy9Nx/3R9vDsf16vFfrcpiglaq8cTZNyKbp+g5ySOWz5URdnldLbeHpfr3eF49/pyPZzvl6stdjC86IuBjOCrmsb2BlASzdTpqgp1zqbjZPMuevoSXf6IHz8v3v+VXT+Hlz+j65d483OeJQwI4A9U9QdBpg5NmwNE2e0phHEaJqPWgnj0dZ2HUZJhttujwxW76XYQBtVC4bbysNE9DPz/G0Ijwd9nO0FVlXWSywAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/ab91b62b695bfe921c18b03e4bd4cb23/cece5/particle-simulation-tab.webp 968w\"],\n    \"sizes\": \"(max-width: 968px) 100vw, 968px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/ab91b62b695bfe921c18b03e4bd4cb23/989a8/particle-simulation-tab.png 968w\"],\n    \"sizes\": \"(max-width: 968px) 100vw, 968px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/ab91b62b695bfe921c18b03e4bd4cb23/989a8/particle-simulation-tab.png\",\n    \"alt\": \"Particle simulation tab in blender\",\n    \"title\": \"Particle simulation tab in blender\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"As you can see as this is a test, I just used 100 particles and used the above lifetime settings.\"), mdx(\"p\", null, \"Here are some of the settings which are important -\"), mdx(\"p\", null, \"Velocity:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"742px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"62.53369272237197%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAANCAIAAAAmMtkJAAAACXBIWXMAAAsTAAALEwEAmpwYAAABrUlEQVQoz2VS227UMBTMZzXbhlyc2El8S+zEGwLabAWUpSwI8cATIPERVOoDL6UviJ9kkuymSzsaRceO55w5PvYopWVZ4ns+4WLC+RM82pyPeWma5nkOcTBh/ofg2QnmX492RvEsmDMRQpRSoxHGlK6k0iCCrnsOSCnVEYyxMAy94Ajf9+M4rqqKc55TYhUz8sAXa9P3vda6mlDXNcyOYniYaxZFgZrWNpLnid2l+1/p7iZ9d5Nd37rPP1+/uWqapp3gnMPJB3EURVhDn2WUZSQoe7//seq+rrpvq+476b/APDsBih1sQw8nEM/9IAX0laCaj6wE69p67dZCCHkELvih5/h/IFHbrpvGgQg2mwGwaGkCnKMASnrLvS8TTpKE87JtbGMNiGA7bC63gzX1cccgO2p4T2eI/hOSUoaBFTO50ELqZQkmhBwqoxpsGGNwE5hlQZOLen/2/q//9s7f3a929+TDXf5pjCf+Prv+E5h9FPje8oAwOjPCSiFYqZW7lO0AKrd9+Wo/XH2clyPdNuc6jiJvea7Qo1t0EsJ3GKYkXpizrGD0dAcH8Cz/AYjP4NmeIeTuAAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/7da5d9c87783731ed2e4fda725b69e2a/9fd9e/particle-simulation-velocity-settings.webp 742w\"],\n    \"sizes\": \"(max-width: 742px) 100vw, 742px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/7da5d9c87783731ed2e4fda725b69e2a/6b989/particle-simulation-velocity-settings.png 742w\"],\n    \"sizes\": \"(max-width: 742px) 100vw, 742px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/7da5d9c87783731ed2e4fda725b69e2a/6b989/particle-simulation-velocity-settings.png\",\n    \"alt\": \"Velocity settings for particle simulation\",\n    \"title\": \"Velocity settings for particle simulation\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"Field Weights:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"762px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"104.1994750656168%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAVCAIAAADJt1n/AAAACXBIWXMAAAsTAAALEwEAmpwYAAAC5klEQVQ4y3VUa28SQRTll6iJbf0BTWp3ZygL7M6+FygU+tKYyLLAAi2Qmmh8xNcfsGmKSHkUeRSt8Sd6BkzbJTo5H+6Z5O4999w7G4pEIoZh2LadSCQsywqHw4QQOj+It/5zkCWKYghRNBqVZVnXdcYY4ng8LklSLBZD8sbGxuP/nM3NzRAqoJSiKI7jIN80TQT4xMHhE6Zq9+4/WF17tLK69nBlFUBwg/X19dBC3kInvoK0VCql4SjxhKkCjsFStv70ILeX3Ua8uExa2laY/k2+e9CPxhRp90XUO5fcL5J7Gi2cOtUz0z+L5E9B5zdnopxaTgZFC7qmkP33YnkqFi/F4pCUhmZ9yGpDwRuCzm9GgrLzj8pwXtcY2X2DHOJdEK9Li13zuKfVemKhC8pR7AtKOpCMGCbDM43J5OAjqV6T8pj4E1qZmM0pq0/E8gSUo3IlsOxyMqadTmdMXSW5V8TrEfcrcdu00DZrba3SFvNtUI5CR5CDlWEVypqWxeQY2f9AKj9I6Tspj6g/Mppj9XgslkagHP5kuTKWBvkOVs3QyN47rrnYJ8UBLQ3M+qVaG4jeAJSjNBTYzu2ckYb1xIakUtuWqXPD4GrhghS61INhfW6Y2wXl8GBY5rbyYk+xmLphwG0Kw7hsiBxTf2w0xozLHnM53MVpQDaC+PygaccyaLCyVceousHK6UAyHgZ/YY5jwO3dt9wtPtUeLfbmsvtiocdHABQHAdkLwyQpatuOyuL08BOp/iJ8sFPqT/XmVKlPsXOgHJXZsmw0jPVKJpMm3M6+5Jrz5yTfom7LrrV0vyU+b4FyuG1B3g4kwzDHScBwVUHlz+ToN/GvUIRWZ8bJjDVmoj8D5aj+FFguIHv+i5DwqjFnuveaz7PwDctEvY55dKFWOqLbAeXwusu7vaiPt5ywzXnP1/NN5j1bJzO9ebXc880f6+7/IB6LUusZyZyQdJ2kGzTdiOUaUraBeAGaaQoR9Q/2yZp4SLkASQAAAABJRU5ErkJggg==')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/fecffe51501bab8dbf565690c2975702/52f3d/particle-simulation-physics-settings.webp 762w\"],\n    \"sizes\": \"(max-width: 762px) 100vw, 762px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/fecffe51501bab8dbf565690c2975702/35bc6/particle-simulation-physics-settings.png 762w\"],\n    \"sizes\": \"(max-width: 762px) 100vw, 762px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/fecffe51501bab8dbf565690c2975702/35bc6/particle-simulation-physics-settings.png\",\n    \"alt\": \"Field weights physics settings of blender particle simulation\",\n    \"title\": \"Field weights physics settings of blender particle simulation\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"The gravity has been turned off so the particles float upwards.\"), mdx(\"p\", null, \"So to get the particles to follow a curve we need to go onto the physics properties tab and select force field while we have a curve selected. I just created a bezier curve point up like smoke from a fire.\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"848px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"127.59433962264151%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAIAAAA44esqAAAACXBIWXMAAAsTAAALEwEAmpwYAAACxklEQVQ4y42U61KjQBCF50VcrCSQAAlhgUDuJpqoifd7aal/9P2fwY85CxX1z54qunqGPt093T1jRqPRdrsNwzCO475FbMGO4zj7FaIoSpLk7w56vZ7hGw6H0+kUL5PJBKUoiizL8NKziCzSNGVzYJFZoJjQYr1e4wLybDbDaxAEouECWbvoWmhZkj3P831/uVweHR0tFgu8nJ6eXlxcHB8fo+MLeXJyMp/PsdlsNugoWLJjOB4+REbyD4uzszM4h4eH4/H4+fn55eXl8fHx7e3t8/Pz4+Pj9fX16emJAIbEOA/JqFpRhX4F+aWo5+fnioxrlIODA8PxCE4OG4vLy0tSmliQswoJqAhybDGqYIhJhdjCEy6QcAi1Wq3YhMwOwVHqaoO5hVHC2MFhrWgwSQ9FfPaJQ4LqMIrsTeS6Sbsznk6oEDUgcxJWhtCUv7JlOaugX6bjeUGnM8hzfsMnpiqEBYp2wNZiVYG6MEum7HkUcR5KomPjUn3C+vb29vr6Gkmf6BD6zc0NSw6V57nx3Ubfb2WEznNcaEiXFpCxvrq6+k1mkEpy2HaTXkAhiyKnjARfW6CQnnrLtKHQXnb0F9dl2q1Ovx3SgzTPWRb13OMYC8LCYf/HxfjX535SpMUsy0py3cbcgvMrDuT8OyhQGdkP426cD7KUBVlpAAEF0yXRtN/f3z88PKBQCOVfnrnZ7nphDNlmXQwt4PAbo7ra7+/v1EzVuru7w0tJ3vMaTuAWNtP6wBpgdUt3QLMx2UGZduR6mR+kg0yPATT9Y6nrDRYWmgIBR2XkdrMZum3qSCgNc3175EiyHkkBm/IliVveMOgmWTq3l0lp0xieOyTXAKnjDHYgM7PvOF6rVT6d1RuA1Jyp1RjxyHW/Q37Nn729RrNZv7siKxrBqQqyfgBr6GKahuNA1qLGrqP6Jf8Ns28j/yD/J74A0aVgICubWzcAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/b19fa42d81fa75211b01c0e00d05fc73/31b09/particle-simulation-physics-properties-tab.webp 848w\"],\n    \"sizes\": \"(max-width: 848px) 100vw, 848px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/b19fa42d81fa75211b01c0e00d05fc73/c5b3e/particle-simulation-physics-properties-tab.png 848w\"],\n    \"sizes\": \"(max-width: 848px) 100vw, 848px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/b19fa42d81fa75211b01c0e00d05fc73/c5b3e/particle-simulation-physics-properties-tab.png\",\n    \"alt\": \"Physics properties tab where force field is\",\n    \"title\": \"Physics properties tab where force field is\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"and this is what it should look like in the 3d viewport:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1052px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"70.91254752851711%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAOCAIAAACgpqunAAAACXBIWXMAAAsTAAALEwEAmpwYAAABPUlEQVQoz42RaW6EMAyFc6qSxdjOAjPT5V9V9QStev8L9CUkMyBRqZ+eENh+thPMU8NOk3PWN4HpiLUnQWBabgrV1OvC1mDgdtgj5mmaxrT2rNWe0OAf1MneO9TCxGTjPFFwMFvn/+Jhbnv6MELkbRa7qNPZzYTECfcupntCXZUoUCdE9kVdEhcCQXTWxdzfmOdNA7xxUnpeaElakqrUCO8qDKbMO7ghzCoClZzWopdMGnUtKUbEhAdm52hUUyfDuSSW+HblXCRGfGZBGyzRZBRDmKNIFE2bYEOhxmvJa86If3683y5rjSy5aMyKbK00dUMWqPmbtPohrIlqpH6+v15vL1nlilDrjicqzfGsg7FYyRGbl1WWgsNjduyphpnp3H5vk3DVRXJqRx30C9t+695/RDjSLD1Xz6iPC/8FMbvIvVaplLYAAAAASUVORK5CYII=')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/bee2fa7ee91bcca26977aaff5c1f4542/628d7/particle-simulation-curve-3d-viewport.webp 1052w\"],\n    \"sizes\": \"(max-width: 1052px) 100vw, 1052px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/bee2fa7ee91bcca26977aaff5c1f4542/8f870/particle-simulation-curve-3d-viewport.png 1052w\"],\n    \"sizes\": \"(max-width: 1052px) 100vw, 1052px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/bee2fa7ee91bcca26977aaff5c1f4542/8f870/particle-simulation-curve-3d-viewport.png\",\n    \"alt\": \"How the force field curve should look like in the 3D viewport\",\n    \"title\": \"How the force field curve should look like in the 3D viewport\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"Now if you hit spacebar the animation should play and particles move upwards \\uD83C\\uDF89\"), mdx(\"p\", null, \"This is a wrap for the particle simulation, play around with the settings and curve for your desired effect!\"), mdx(\"h2\", {\n    \"id\": \"creating-the-script-for-saving-data-as-images-per-frame-of-the-simulation\"\n  }, \"Creating the Script for Saving Data as Images per Frame of the Simulation\"), mdx(\"p\", null, \"This is the script I used to store data in image pixels per frame of the animation.\"), mdx(\"p\", null, \"\\u26A0\\uFE0F\\u26A0\\uFE0F N.B. be careful with the complexity of the simulation especially if your just using a low powered computer or laptop! \\u26A0\\uFE0F\\u26A0\\uFE0F\"), mdx(\"p\", null, \"The script:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"import bpy\\nimport numpy as np\\nimport os\\n\\n\\nobject = bpy.data.objects[\\\"Cone\\\"]\\n\\ndef particleSetter(scene, degp):\\n    particle_systems = object.evaluated_get(degp).particle_systems\\n    particles = particle_systems[0].particles\\n    totalParticles = len(particles)\\n\\n    cFrame = scene.frame_current\\n    sFrame = scene.frame_start\\n    \\n    #at start-frame, clear the particle cache\\n    if cFrame == sFrame:\\n        psSeed = object.particle_systems[0].seed \\n        object.particle_systems[0].seed  = psSeed\\n        \\n    flatList = [None]*(3*totalParticles)\\n\\n    # additionally set the location of all particle locations to flatList\\n    particles.foreach_get(\\\"location\\\", flatList)\\n    \\n    \\n    arr = [] * 300\\n    \\n    #loop through each particle and amend for colour storage\\n    for x in flatList:\\n        arr.append(x / 20 + 0.5)\\n    \\n    print(arr)\\n    #store data in image \\n    \\n    size = 100, 1\\n\\n    image = bpy.data.images.new(\\\"pos-1.0-frame-%s\\\" % cFrame, width=size[0], height=size[1])\\n    pixels = [None] * size[0] * size[1]\\n    for x in range(size[0]):\\n        r = arr[x * 3 -2]\\n        g = arr[x * 3 -1]\\n        b = arr[x * 3]\\n        a = 1.0\\n        pixels[x] = [r, g, b, a]\\n    pixels = [chan for px in pixels for chan in px]\\n    image.pixels = pixels\\n    image.file_format = \\\"PNG\\\"\\n    image.filepath_raw = \\\"/tmp/position-frame-%s.png\\\" % cFrame\\n    image.save()    \\n\\n#clear the post frame handler\\nbpy.app.handlers.frame_change_post.clear() \\n\\n#run the function on each frame\\nbpy.app.handlers.frame_change_post.append(particleSetter)\\n\")), mdx(\"p\", null, \"Here are two article I found very useful when modifying python scripts to get my desired result - \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://devtalk.blender.org/t/manipulating-particles-in-python/7552/28\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \" and \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://stackoverflow.com/questions/14982836/rendering-and-saving-images-through-blender-python\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \".\"), mdx(\"p\", null, \"We have to get the evaluated particles with updated locations.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"def particleSetter(scene, degp):\\n    particle_systems = object.evaluated_get(degp).particle_systems\\n    particles = particle_systems[0].particles\\n    totalParticles = len(particles)\\n\")), mdx(\"p\", null, \"Store the particles locations in a flatList or a 1 dimensional array in JS.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"flatList = [None]*(3*totalParticles)\\n\\n# additionally set the location of all particle locations to flatList\\nparticles.foreach_get(\\\"location\\\", flatList)\\n\")), mdx(\"p\", null, \"Loop through the list and change location values to be from the original world coordinate range into colour compatiable in the range 0-1 as explained in \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.thefrontdev.co.uk/storing-positional-xyz-values-in-a-texture-and-reading-in-a-r3f-shader-material\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \" article.\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"arr = [] * 300\\n\\n#loop through each particle and amend for colour storage\\nfor x in flatList:\\n    arr.append(x / 20 + 0.5)\\n\")), mdx(\"p\", null, \"And finally store the location data in one frame in a image 100 width and 1 height:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"    size = 100, 1\\n\\n    image = bpy.data.images.new(\\\"pos-1.0-frame-%s\\\" % cFrame, width=size[0], height=size[1])\\n    pixels = [None] * size[0] * size[1]\\n    for x in range(size[0]):\\n        r = arr[x * 3 -2]\\n        g = arr[x * 3 -1]\\n        b = arr[x * 3]\\n        a = 1.0\\n        pixels[x] = [r, g, b, a]\\n    pixels = [chan for px in pixels for chan in px]\\n    image.pixels = pixels\\n    image.file_format = \\\"PNG\\\"\\n    image.filepath_raw = \\\"/tmp/position-frame-%s.png\\\" % cFrame\\n    image.save()   \\n\")), mdx(\"p\", null, \"The last thing is how do we use this script?\"), mdx(\"p\", null, \"Well blender has a text editor which you can type python in and then run a script, the little play button \\uD83D\\uDE0D\"), mdx(\"p\", null, \"So I would open up another plane by right clicking the edge of one of the planes and doing a vertical or horizontal split. Then open up the text editor, copy the script into a new text file, run the script with the play button.\"), mdx(\"p\", null, \"Nothing happens right?\"), mdx(\"p\", null, \"Correct because we have done this:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-python\"\n  }, \"#run the function on each frame\\nbpy.app.handlers.frame_change_post.append(particleSetter)\\n\")), mdx(\"p\", null, \"This means it will only run on change of the frame, one of the only things that actually worked during my research!\"), mdx(\"p\", null, \"So press the space bar and checkout all the images stored in the designated folder \\uD83D\\uDE0E\"), mdx(\"p\", null, \"We should have images for all the frames in our animation!\"), mdx(\"p\", null, \"Show me how to use in the shaders!\"), mdx(\"h2\", {\n    \"id\": \"combining-the-images-into-one-and-rotating\"\n  }, \"Combining the Images Into one and Rotating\"), mdx(\"p\", null, \"So before we use these in the shader we have to combine them into one image, most devices have a absolute limit on how many textures you can load and use in shaders.\"), mdx(\"p\", null, \"Therefore we cant rely on using all 240 textures as some devices might not allow it and stop working.\"), mdx(\"p\", null, \"So I settled on using \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.filesmerge.com/merge-images\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \" website for combining the images as it allowed me to combine 50 at once \\uD83D\\uDE02 I tried others and they only allowed 10-15 images at a time and I got lost half way through more than once haha The website has a simple ui and these are the settings I used:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"900px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"89.11111111111111%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAIAAADUsmlHAAAACXBIWXMAAAsTAAALEwEAmpwYAAABfUlEQVQ4y5VTi26DMAzs///dpKnaoxVdCwmQkCcJIRC6G2jV2qG1s4IVBV98ti+bPo6hH7AuG6WtVEbpVs6b7HBUysQhhRD7OHwHf/nN+ZcZY6y1oQvOtSGE/X6PE5xP03QTuQJOKRVFQQgpqyrP8xjjKnIdjDjnHJLDe++qSgrRntdsc75nNdOcm4fAppt86FMah2GYCU8FEZTKO+ClqIynp+fXt7fXLMu22+1u986YFsLi/6O00bOleJiQrZT2TsOW0DSvi+GcUFlV6t8Nm2aqSjml3fdV0wp4HEcMFnVSWmLGJ9jxWDNZ17qspJStMZ5QgYsu3bnKrLWGJOrZcAVjddMYTBicgQGelkpr/zP7qki+vHO90h7ghXaMw181gzkyU0pBPs9PBeGklKe8OeX88ME5F4yxG51eZfbeg7wQYva2qlXTQF7Yg7+GWh/tdtf1xvqP0mTUcOXB6/6oIA9kbpDX6FrYlyM/EEFkfPRJXgSCr4vJduOYplV2nw89Glg4MfJ5AAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/2e4e6b4237b03fbf65f8ea5fe05e7718/90807/image-merging-website-settings.webp 900w\"],\n    \"sizes\": \"(max-width: 900px) 100vw, 900px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/2e4e6b4237b03fbf65f8ea5fe05e7718/385f2/image-merging-website-settings.png 900w\"],\n    \"sizes\": \"(max-width: 900px) 100vw, 900px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/2e4e6b4237b03fbf65f8ea5fe05e7718/385f2/image-merging-website-settings.png\",\n    \"alt\": \"Settings for image merging website\",\n    \"title\": \"Settings for image merging website\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"And as our particle data images are 100 by 1 we can just layer them one after the other as they are all the same width and height!\"), mdx(\"p\", null, \"This will require two rounds for 100 particles, 4 initial sets of 50 or 40 and then a final one to get something which looks like this:\"), mdx(\"p\", null, mdx(\"span\", {\n    parentName: \"p\",\n    \"className\": \"gatsby-resp-image-wrapper\",\n    \"style\": {\n      \"position\": \"relative\",\n      \"display\": \"block\",\n      \"marginLeft\": \"auto\",\n      \"marginRight\": \"auto\",\n      \"maxWidth\": \"1098px\"\n    }\n  }, \"\\n      \", mdx(\"span\", {\n    parentName: \"span\",\n    \"className\": \"gatsby-resp-image-background-image\",\n    \"style\": {\n      \"paddingBottom\": \"45.537340619307834%\",\n      \"position\": \"relative\",\n      \"bottom\": \"0\",\n      \"left\": \"0\",\n      \"backgroundImage\": \"url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAACBElEQVQoz2WRzUtUYRSH5w9q0boWRdC9NKFXbeMq6AMbybAsP2Z833Pn807mgJUaBEmF1SaCoghaBJXURNDKhWhFVGJCDQZOOR/OPJ25kAy0eDjvu3n4/c6J7D9wkJ6OHryoh3e4K6SrRbQbr1P/p3rxRo7RlezHy5/DK8TxplJ4VyfonJ7Cm53Gm5nmyNwcu7u7ifQPDFFITRKYgLzNkxfF5AlsluDWJYI3Nwk+PiIovSZXWSbHulJWmgQQklUKSnRigsiJvgEyiQx2RPBHffxhH0kkkTuXkeI9ZOkJsvoKW1rEbn7Bbv1EqptIfQtbr+msYSuVUOqkUkSOx86QNjnMWAo7lsbGdd7I4b+dRz48w64VsRtLmPIqplrC1MvY7Sqm2cA0GlhlvFYn0xKmM5owpglNOkwoCYtcz2IfT2KL17Ar91X4QoWLmN/fMLUNlVVCSTum3iY8qcLseAYZ18rzUySfzyHvbyOfHiLrC4jK5M9XrbkR1pRtrakSv9HU2QzfVoW5nYR9p8nEfcxMAnk5iyw/Rb6/U9EKUl5DtkoqKyO1arivf/htiO6wJXRbO+wfHKTw4ArB4l2CHwsEtc96uV9KfeeK7eTb+P/KF4ns2beX6NEOnFgv7tkY7vkh3AsjuMNxJYEzanDjFkdX4lgfVxQ/iZtskcLR6fg+h4I8u1yXv9PFBC/+UYUaAAAAAElFTkSuQmCC')\",\n      \"backgroundSize\": \"cover\",\n      \"display\": \"block\"\n    }\n  }), \"\\n  \", mdx(\"picture\", {\n    parentName: \"span\"\n  }, \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/025a3/particle-animation-data-hero.webp 1098w\"],\n    \"sizes\": \"(max-width: 1098px) 100vw, 1098px\",\n    \"type\": \"image/webp\"\n  }), \"\\n          \", mdx(\"source\", {\n    parentName: \"picture\",\n    \"srcSet\": [\"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/38ec7/particle-animation-data-hero.png 1098w\"],\n    \"sizes\": \"(max-width: 1098px) 100vw, 1098px\",\n    \"type\": \"image/png\"\n  }), \"\\n          \", mdx(\"img\", {\n    parentName: \"picture\",\n    \"className\": \"gatsby-resp-image-image\",\n    \"src\": \"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/38ec7/particle-animation-data-hero.png\",\n    \"alt\": \"End image with all 240 frames locations data stored\",\n    \"title\": \"End image with all 240 frames locations data stored\",\n    \"loading\": \"lazy\",\n    \"style\": {\n      \"width\": \"100%\",\n      \"height\": \"100%\",\n      \"margin\": \"0\",\n      \"verticalAlign\": \"middle\",\n      \"position\": \"absolute\",\n      \"top\": \"0\",\n      \"left\": \"0\"\n    }\n  }), \"\\n        \"), \"\\n    \")), mdx(\"p\", null, \"Colourful right!\"), mdx(\"p\", null, \"If you didnt get something like this then something has probably gone wrong, if you need help contact me on \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"mailto:rick@thefrontdev.co.uk\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"rick@thefrontdev.co.uk\"), \". And I\\u2019ll try and help \\uD83D\\uDE42\"), mdx(\"p\", null, \"One thing I noticed is the animation plays the opposite way, so on a mac it was pretty easy to rotate the image 180 degrees right. This reverses the animation so it goes from the ground level to the sky rather than sky to ground. But yea didnt figure out why it did this!\"), mdx(\"p\", null, \"The last thing we need to do is consume this image in a shader.\"), mdx(\"p\", null, \"As previously stated this codesandbox was based of my previous one in \", mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"https://www.thefrontdev.co.uk/storing-positional-xyz-values-in-a-texture-and-reading-in-a-r3f-shader-material\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"this\"), \" article.\"), mdx(\"p\", null, \"The main things which changed were -\"), mdx(\"p\", null, \"The initial positions and index array:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"let [positions, indexs] = useMemo(() => {\\n    let positions = [...Array(300).fill(0)];\\n    let index = [...Array(100).keys()];\\n\\n    return [new Float32Array(positions), new Float32Array(index)]; \\n}, []);\\n\")), mdx(\"p\", null, \"Importing the right texture:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"import texture from \\\"./merge_from_ofoct.jpg\\\";\\n\")), mdx(\"p\", null, \"And this part of the vertex shader:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-javascript\"\n  }, \"vec2 myIndex = vec2((index + 0.5)/100.0, (mod(time * 0.2, 1.0)));\\n\\nvec4 pos = texture2D( positions, myIndex);\\n\\nfloat x = (pos.x - 0.5) * 20.0;\\nfloat y = (pos.y - 0.5) * 20.0;\\nfloat z = (pos.z - 0.5) * 20.0;\\n\")), mdx(\"p\", null, \"The way to think about this is for every vertex which we have 100 points, this code will run every frame. \"), mdx(\"p\", null, \"So we use the index 1-100 attribute per vertex to grab the color from the positions texture for every fragment and centre it using + 0.5.\"), mdx(\"p\", null, \"We then do this:\"), mdx(\"pre\", null, mdx(\"code\", {\n    parentName: \"pre\",\n    \"className\": \"language-glsl\"\n  }, \"(mod(time * 0.2, 1.0))\\n\")), mdx(\"p\", null, \"For the Y coordinate of the coordinate vec2 used to do the texture lookup :- \"), mdx(\"p\", null, \"The mod basically returns the remainder allowing repitition and we multiply time by 0.2 to slow it down. And the 1.0 I played around with until I got something which is useful for our human eyes lol\"), mdx(\"p\", null, \"And there we go, we have exported, formated images and then used in a r3f/threejs shader!\"), mdx(\"h2\", {\n    \"id\": \"final-thoughts\"\n  }, \"Final Thoughts\"), mdx(\"p\", null, \"This is a extremely powerful technique to export particle simulations from blender for a r3f/threejs project \\uD83D\\uDC40\"), mdx(\"p\", null, \"You could do any partical simulation in blender and save mbs by storing the location data in images!\"), mdx(\"p\", null, \"This could be used for smoke, fire, sand, snow. Honestly this is one of the most versitile techniques I think Ive come across.\"), mdx(\"p\", null, \"One thing to note is there is a margin of error on locations so it wont be exact.. but it will be good enough for environmental effects.\"), mdx(\"p\", null, \"I am yet to figure out how to avoid the error in blender, might very well be easier in other software suits but nothing ive tried as of yet removes the error in blender \\uD83C\\uDF0B\"), mdx(\"p\", null, \"Hope you enjoyed and stay tuned for some more articles in the pipeline.\"), mdx(\"p\", null, \"Contact me if you need any help with this!\"), mdx(\"p\", null, mdx(\"a\", {\n    parentName: \"p\",\n    \"href\": \"mailto:rick@thefrontdev.co.uk\",\n    \"target\": \"_blank\",\n    \"rel\": \"noreferrer\"\n  }, \"rick@thefrontdev.co.uk\")));\n}\n;\nMDXContent.isMDXComponent = true;","hero":{"full":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAACBElEQVQoz2WRzUtUYRSH5w9q0boWRdC9NKFXbeMq6AMbybAsP2Z833Pn807mgJUaBEmF1SaCoghaBJXURNDKhWhFVGJCDQZOOR/OPJ25kAy0eDjvu3n4/c6J7D9wkJ6OHryoh3e4K6SrRbQbr1P/p3rxRo7RlezHy5/DK8TxplJ4VyfonJ7Cm53Gm5nmyNwcu7u7ifQPDFFITRKYgLzNkxfF5AlsluDWJYI3Nwk+PiIovSZXWSbHulJWmgQQklUKSnRigsiJvgEyiQx2RPBHffxhH0kkkTuXkeI9ZOkJsvoKW1rEbn7Bbv1EqptIfQtbr+msYSuVUOqkUkSOx86QNjnMWAo7lsbGdd7I4b+dRz48w64VsRtLmPIqplrC1MvY7Sqm2cA0GlhlvFYn0xKmM5owpglNOkwoCYtcz2IfT2KL17Ar91X4QoWLmN/fMLUNlVVCSTum3iY8qcLseAYZ18rzUySfzyHvbyOfHiLrC4jK5M9XrbkR1pRtrakSv9HU2QzfVoW5nYR9p8nEfcxMAnk5iyw/Rb6/U9EKUl5DtkoqKyO1arivf/htiO6wJXRbO+wfHKTw4ArB4l2CHwsEtc96uV9KfeeK7eTb+P/KF4ns2beX6NEOnFgv7tkY7vkh3AsjuMNxJYEzanDjFkdX4lgfVxQ/iZtskcLR6fg+h4I8u1yXv9PFBC/+UYUaAAAAAElFTkSuQmCC","aspectRatio":2.205607476635514,"src":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/a1946/particle-animation-data-hero.png","srcSet":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/5b37e/particle-animation-data-hero.png 236w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/49058/particle-animation-data-hero.png 472w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/a1946/particle-animation-data-hero.png 944w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/824bf/particle-animation-data-hero.png 1098w","srcWebp":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/99fbb/particle-animation-data-hero.webp","srcSetWebp":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/77392/particle-animation-data-hero.webp 236w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/1f177/particle-animation-data-hero.webp 472w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/99fbb/particle-animation-data-hero.webp 944w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/2e9a0/particle-animation-data-hero.webp 1098w","sizes":"(max-width: 944px) 100vw, 944px"},"regular":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAACBElEQVQoz2WRzUtUYRSH5w9q0boWRdC9NKFXbeMq6AMbybAsP2Z833Pn807mgJUaBEmF1SaCoghaBJXURNDKhWhFVGJCDQZOOR/OPJ25kAy0eDjvu3n4/c6J7D9wkJ6OHryoh3e4K6SrRbQbr1P/p3rxRo7RlezHy5/DK8TxplJ4VyfonJ7Cm53Gm5nmyNwcu7u7ifQPDFFITRKYgLzNkxfF5AlsluDWJYI3Nwk+PiIovSZXWSbHulJWmgQQklUKSnRigsiJvgEyiQx2RPBHffxhH0kkkTuXkeI9ZOkJsvoKW1rEbn7Bbv1EqptIfQtbr+msYSuVUOqkUkSOx86QNjnMWAo7lsbGdd7I4b+dRz48w64VsRtLmPIqplrC1MvY7Sqm2cA0GlhlvFYn0xKmM5owpglNOkwoCYtcz2IfT2KL17Ar91X4QoWLmN/fMLUNlVVCSTum3iY8qcLseAYZ18rzUySfzyHvbyOfHiLrC4jK5M9XrbkR1pRtrakSv9HU2QzfVoW5nYR9p8nEfcxMAnk5iyw/Rb6/U9EKUl5DtkoqKyO1arivf/htiO6wJXRbO+wfHKTw4ArB4l2CHwsEtc96uV9KfeeK7eTb+P/KF4ns2beX6NEOnFgv7tkY7vkh3AsjuMNxJYEzanDjFkdX4lgfVxQ/iZtskcLR6fg+h4I8u1yXv9PFBC/+UYUaAAAAAElFTkSuQmCC","aspectRatio":2.2027027027027026,"src":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/3ddd4/particle-animation-data-hero.png","srcSet":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/078a8/particle-animation-data-hero.png 163w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/e56da/particle-animation-data-hero.png 327w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/3ddd4/particle-animation-data-hero.png 653w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/c5cc7/particle-animation-data-hero.png 980w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/824bf/particle-animation-data-hero.png 1098w","srcWebp":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/0acdf/particle-animation-data-hero.webp","srcSetWebp":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/ac59e/particle-animation-data-hero.webp 163w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/7660b/particle-animation-data-hero.webp 327w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/0acdf/particle-animation-data-hero.webp 653w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/75470/particle-animation-data-hero.webp 980w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/2e9a0/particle-animation-data-hero.webp 1098w","sizes":"(max-width: 653px) 100vw, 653px"},"narrow":{"base64":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAJCAYAAAAywQxIAAAACXBIWXMAABYlAAAWJQFJUiTwAAACBElEQVQoz2WRzUtUYRSH5w9q0boWRdC9NKFXbeMq6AMbybAsP2Z833Pn807mgJUaBEmF1SaCoghaBJXURNDKhWhFVGJCDQZOOR/OPJ25kAy0eDjvu3n4/c6J7D9wkJ6OHryoh3e4K6SrRbQbr1P/p3rxRo7RlezHy5/DK8TxplJ4VyfonJ7Cm53Gm5nmyNwcu7u7ifQPDFFITRKYgLzNkxfF5AlsluDWJYI3Nwk+PiIovSZXWSbHulJWmgQQklUKSnRigsiJvgEyiQx2RPBHffxhH0kkkTuXkeI9ZOkJsvoKW1rEbn7Bbv1EqptIfQtbr+msYSuVUOqkUkSOx86QNjnMWAo7lsbGdd7I4b+dRz48w64VsRtLmPIqplrC1MvY7Sqm2cA0GlhlvFYn0xKmM5owpglNOkwoCYtcz2IfT2KL17Ar91X4QoWLmN/fMLUNlVVCSTum3iY8qcLseAYZ18rzUySfzyHvbyOfHiLrC4jK5M9XrbkR1pRtrakSv9HU2QzfVoW5nYR9p8nEfcxMAnk5iyw/Rb6/U9EKUl5DtkoqKyO1arivf/htiO6wJXRbO+wfHKTw4ArB4l2CHwsEtc96uV9KfeeK7eTb+P/KF4ns2beX6NEOnFgv7tkY7vkh3AsjuMNxJYEzanDjFkdX4lgfVxQ/iZtskcLR6fg+h4I8u1yXv9PFBC/+UYUaAAAAAElFTkSuQmCC","aspectRatio":2.1923076923076925,"src":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/502b1/particle-animation-data-hero.png","srcSet":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/f2e6d/particle-animation-data-hero.png 114w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/4ddba/particle-animation-data-hero.png 229w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/502b1/particle-animation-data-hero.png 457w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/7ddc2/particle-animation-data-hero.png 686w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/435bf/particle-animation-data-hero.png 914w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/824bf/particle-animation-data-hero.png 1098w","srcWebp":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/15384/particle-animation-data-hero.webp","srcSetWebp":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/31fce/particle-animation-data-hero.webp 114w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/e3e25/particle-animation-data-hero.webp 229w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/15384/particle-animation-data-hero.webp 457w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/0258d/particle-animation-data-hero.webp 686w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/64ea2/particle-animation-data-hero.webp 914w,\n/static/1d6bcac64f0f73c60fd8a0fa85e05b58/2e9a0/particle-animation-data-hero.webp 1098w","sizes":"(max-width: 457px) 100vw, 457px"},"seo":{"src":"/static/1d6bcac64f0f73c60fd8a0fa85e05b58/824bf/particle-animation-data-hero.png"}}}],"pathPrefix":"/authors/rick","first":false,"last":false,"index":6,"pageCount":10,"additionalContext":{"author":{"authorsPage":true,"bio":"I am a creative frontend developer, I specialise in React, GLSL, postprocessing and R3F. I love to experiment with code and deal with complex topics.\n","id":"a2f54938-ce4a-58e3-a14f-42c21df2482a","name":"Rick","featured":true,"social":[{"url":"https://twitter.com/TheFrontDev"},{"url":"https://github.com/Richard-Thompson"}],"slug":"/authors/rick","avatar":{"small":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABRlsKyA51mANxhD//xAAcEAACAgIDAAAAAAAAAAAAAAABAgMSAAQREyD/2gAIAQEAAQUCCLCqVkRYwROt5aDCak7DFn2Dx3+P/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAgMAAwEAAAAAAAAAAAAAAAECESEQIDEy/9oACAEBAAY/AnuH1fEU/KIuMUtQ0WyoYedP/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBUSD/2gAIAQEAAT8hv6qbzGnBGvZesblRLKajqgyHnSZETPIHoo4SmR6uJW1r7fx//9oADAMBAAIAAwAAABCQyAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAeEAEAAgICAwEAAAAAAAAAAAABABEhMUFhIFGRsf/aAAgBAQABPxDOQFt9a7gbWsLru1ycRUEAjJbBWGActkvYxwhbwlRCKSwoC5sGwsd/kpeSkMZPRL0ptbPzw//Z","aspectRatio":0.7647058823529411,"src":"/static/80e6d82107a1db055d4e32d8c709c04c/fa1ea/Rick.jpg","srcSet":"/static/80e6d82107a1db055d4e32d8c709c04c/afb2b/Rick.jpg 13w,\n/static/80e6d82107a1db055d4e32d8c709c04c/7c20e/Rick.jpg 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/fa1ea/Rick.jpg 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/03612/Rick.jpg 75w,\n/static/80e6d82107a1db055d4e32d8c709c04c/61cdf/Rick.jpg 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/0ff54/Rick.jpg 1200w","srcWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/e7b2c/Rick.webp","srcSetWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/58718/Rick.webp 13w,\n/static/80e6d82107a1db055d4e32d8c709c04c/74aad/Rick.webp 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/e7b2c/Rick.webp 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/ed320/Rick.webp 75w,\n/static/80e6d82107a1db055d4e32d8c709c04c/66016/Rick.webp 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/9000d/Rick.webp 1200w","sizes":"(max-width: 50px) 100vw, 50px"},"medium":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAaABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAIBAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABRlsKyA51mANxhD//xAAcEAACAgIDAAAAAAAAAAAAAAABAgMSAAQREyD/2gAIAQEAAQUCCLCqVkRYwROt5aDCak7DFn2Dx3+P/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAwEBPwEf/8QAFBEBAAAAAAAAAAAAAAAAAAAAIP/aAAgBAgEBPwEf/8QAHBAAAgMAAwEAAAAAAAAAAAAAAAECESEQIDEy/9oACAEBAAY/AnuH1fEU/KIuMUtQ0WyoYedP/8QAGxABAAIDAQEAAAAAAAAAAAAAAQARITFBUSD/2gAIAQEAAT8hv6qbzGnBGvZesblRLKajqgyHnSZETPIHoo4SmR6uJW1r7fx//9oADAMBAAIAAwAAABCQyAD/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAEDAQE/EB//xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/EB//xAAeEAEAAgICAwEAAAAAAAAAAAABABEhMUFhIFGRsf/aAAgBAQABPxDOQFt9a7gbWsLru1ycRUEAjJbBWGActkvYxwhbwlRCKSwoC5sGwsd/kpeSkMZPRL0ptbPzw//Z","aspectRatio":0.7575757575757576,"src":"/static/80e6d82107a1db055d4e32d8c709c04c/61cdf/Rick.jpg","srcSet":"/static/80e6d82107a1db055d4e32d8c709c04c/7c20e/Rick.jpg 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/fa1ea/Rick.jpg 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/61cdf/Rick.jpg 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/59538/Rick.jpg 150w,\n/static/80e6d82107a1db055d4e32d8c709c04c/fd013/Rick.jpg 200w,\n/static/80e6d82107a1db055d4e32d8c709c04c/0ff54/Rick.jpg 1200w","srcWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/66016/Rick.webp","srcSetWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/74aad/Rick.webp 25w,\n/static/80e6d82107a1db055d4e32d8c709c04c/e7b2c/Rick.webp 50w,\n/static/80e6d82107a1db055d4e32d8c709c04c/66016/Rick.webp 100w,\n/static/80e6d82107a1db055d4e32d8c709c04c/d9b14/Rick.webp 150w,\n/static/80e6d82107a1db055d4e32d8c709c04c/6b183/Rick.webp 200w,\n/static/80e6d82107a1db055d4e32d8c709c04c/9000d/Rick.webp 1200w","sizes":"(max-width: 100px) 100vw, 100px"},"large":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAbABQDASIAAhEBAxEB/8QAGQAAAgMBAAAAAAAAAAAAAAAAAAECAwQF/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABg1aVCDnTzVmwxB//xAAcEAACAgMBAQAAAAAAAAAAAAABAgADBBESEzH/2gAIAQEAAQUCCLSqFbEWsEXr3aUEJ5JyGLPkHXvKxsn7P//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8BH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8BH//EABsQAAICAwEAAAAAAAAAAAAAAAABAiEQETEy/9oACAEBAAY/AndHreIp8IuKStDRtmoUcLz/AP/EABwQAQACAgMBAAAAAAAAAAAAAAEAESFBEFFhMf/aAAgBAQABPyG/qJvMalEGO5aivuyVEsi17FYkyHWyJlDOoGoo0Sks2uN21r3cGsTBHvH/2gAMAwEAAgADAAAAEOAFMP/EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQMBAT8QH//EABQRAQAAAAAAAAAAAAAAAAAAACD/2gAIAQIBAT8QH//EAB4QAQACAwACAwAAAAAAAAAAAAEAESExQRBhUXGR/9oACAEBAAE/EOgIHnWvcZWNF17tdORkgCmxgpDIO2JkNMCFprBCQ1LCqA/mCCCO4l8SkMZPgh3MbW7+TJQfdQg2hB4//9k=","aspectRatio":0.7522935779816514,"src":"/static/80e6d82107a1db055d4e32d8c709c04c/ec46e/Rick.jpg","srcSet":"/static/80e6d82107a1db055d4e32d8c709c04c/a2637/Rick.jpg 82w,\n/static/80e6d82107a1db055d4e32d8c709c04c/15203/Rick.jpg 164w,\n/static/80e6d82107a1db055d4e32d8c709c04c/ec46e/Rick.jpg 328w,\n/static/80e6d82107a1db055d4e32d8c709c04c/b69a5/Rick.jpg 492w,\n/static/80e6d82107a1db055d4e32d8c709c04c/23a36/Rick.jpg 656w,\n/static/80e6d82107a1db055d4e32d8c709c04c/0ff54/Rick.jpg 1200w","srcWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/5a48e/Rick.webp","srcSetWebp":"/static/80e6d82107a1db055d4e32d8c709c04c/2d087/Rick.webp 82w,\n/static/80e6d82107a1db055d4e32d8c709c04c/29d87/Rick.webp 164w,\n/static/80e6d82107a1db055d4e32d8c709c04c/5a48e/Rick.webp 328w,\n/static/80e6d82107a1db055d4e32d8c709c04c/42f2e/Rick.webp 492w,\n/static/80e6d82107a1db055d4e32d8c709c04c/dec03/Rick.webp 656w,\n/static/80e6d82107a1db055d4e32d8c709c04c/9000d/Rick.webp 1200w","sizes":"(max-width: 328px) 100vw, 328px"}}},"originalPath":"/authors/authors-rick","skip":6,"limit":6}}},"staticQueryHashes":["1143375668","1491088328","2444214635"]}