{"id":234,"date":"2022-01-06T08:37:54","date_gmt":"2022-01-06T16:37:54","guid":{"rendered":"https:\/\/markhashimoto.org\/?p=234"},"modified":"2022-01-27T11:12:22","modified_gmt":"2022-01-27T19:12:22","slug":"trails","status":"publish","type":"post","link":"https:\/\/markhashimoto.org\/?p=234","title":{"rendered":"Trails"},"content":{"rendered":"\t\t<div data-elementor-type=\"wp-post\" data-elementor-id=\"234\" class=\"elementor elementor-234\">\n\t\t\t\t\t\t<section class=\"elementor-section elementor-top-section elementor-element elementor-element-ea50b4c elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"ea50b4c\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-100 elementor-top-column elementor-element elementor-element-c91d7b8\" data-id=\"c91d7b8\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-b31a652 elementor-widget elementor-widget-text-editor\" data-id=\"b31a652\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>I am generally interested in real time 3D techniques and how they can be implemented in interactive environments like Touchdesigner. One technique I was happy to wrangle in was trails, and I thought I&#8217;d talk a bit about it. The explanation assumes some intermediate knowledge of Touchdesigner and OpenGL. <\/p><p>The construction of trails includes a feedback element for storing curve information, followed by curve extrusion. Curve extrusion is a technique in computer graphics which converts a curve into a 3D object. It&#8217;s used to accurately model things like tubes, ribbons, or wire. It can be used in conjunction with particle systems as a way to render the path that a particle follows over time; it can also be used independently of particles, constructed from parametric equations or other means of defining space curvature.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-ac8ecbf elementor-widget elementor-widget-image\" data-id=\"ac8ecbf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img fetchpriority=\"high\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?fit=1920%2C1080&amp;ssl=1\" class=\"attachment-full size-full wp-image-235\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?resize=1200%2C675&amp;ssl=1 1200w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.4.jpg?w=1600&amp;ssl=1 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-c972341 elementor-widget elementor-widget-text-editor\" data-id=\"c972341\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Big thanks to Atagen for sharing <a href=\"https:\/\/www.youtube.com\/watch?v=ykpkqmoxRyo\">his implementation<\/a>, which I decided to base mine off of. Would recommend watching if you want to see how the system works in its entirety. What&#8217;s great about this technique is that it leverages instancing, which allows for parallelized computation.<\/p>\n<p>I decided to take a similar approach, using feedback to store a buffer of texture values, then sampling this buffer in the material shader where the curve framing is handled. I wanted this technique to play well with particle simulations in particular, where I could throw the resulting texture of a particle system into it, and have it pump out the extruded trails of the particles&#8217; paths in a variety of shapes and forms.<\/p>\n<p>There were several features I added to the base technique that helped me with this.<\/p>\n<ul>\n<li>Flat Shading<\/li>\n<li>3D Texture Buffer<\/li>\n<li>Alpha Clipping<\/li>\n<\/ul>\n<p>Fl<strong>at Shading<\/strong><\/p>\n<p>Currently the computation of the surface normals in the vertex shader is setup such that they always point directly away from the center of the tube, which gives them a smoothed appearance. This is fine when the tube has a circular-ish cross section, but when the cross section has say three edges, we begin to notice the shading interpolation between vertices, and the visual result feels off. In order get better results with tubes that have more pronounced edges we can use flat shading.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-01f24ca gallery-spacing-custom elementor-widget elementor-widget-image-gallery\" data-id=\"01f24ca\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image-gallery.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-image-gallery\">\n\t\t\t<div id='gallery-1' class='gallery galleryid-234 gallery-columns-3 gallery-size-medium'><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"01f24ca\" data-elementor-lightbox-title=\"Tube_VisualizeNormals.2-3\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjQ0LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZU5vcm1hbHMuMi0zLmpwZyIsInNsaWRlc2hvdyI6IjAxZjI0Y2EifQ%3D%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.2-3.jpg?ssl=1\"><img decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.2-3.jpg?fit=300%2C300&amp;ssl=1\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-244\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.2-3.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.2-3.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.2-3.jpg?resize=150%2C150&amp;ssl=1 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-1-244'>\n\t\t\t\tCircular Cross Section &#8211; Smooth Shaded\n\t\t\t\t<\/figcaption><\/figure><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"01f24ca\" data-elementor-lightbox-title=\"Tube_VisualizeNormals.5-1\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjQ4LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZU5vcm1hbHMuNS0xLmpwZyIsInNsaWRlc2hvdyI6IjAxZjI0Y2EifQ%3D%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.5-1.jpg?ssl=1\"><img decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.5-1.jpg?fit=300%2C300&amp;ssl=1\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-248\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.5-1.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.5-1.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.5-1.jpg?resize=150%2C150&amp;ssl=1 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-1-248'>\n\t\t\t\tTriangular Cross Section &#8211; Smooth Shaded\n\t\t\t\t<\/figcaption><\/figure><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"01f24ca\" data-elementor-lightbox-title=\"Tube_VisualizeNormals.6\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjUwLCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZU5vcm1hbHMuNi5qcGciLCJzbGlkZXNob3ciOiIwMWYyNGNhIn0%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.6.jpg?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.6.jpg?fit=300%2C300&amp;ssl=1\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-250\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.6.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.6.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.6.jpg?resize=150%2C150&amp;ssl=1 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-1-250'>\n\t\t\t\tTriangular Cross Section &#8211; Flat Shaded\n\t\t\t\t<\/figcaption><\/figure><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"01f24ca\" data-elementor-lightbox-title=\"Tube_VisualizeNormals.3-2\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjQ1LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZU5vcm1hbHMuMy0yLmpwZyIsInNsaWRlc2hvdyI6IjAxZjI0Y2EifQ%3D%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.3-2.jpg?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.3-2.jpg?fit=300%2C300&amp;ssl=1\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-245\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.3-2.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.3-2.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.3-2.jpg?resize=150%2C150&amp;ssl=1 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-1-245'>\n\t\t\t\tCircular Cross Section &#8211; Smooth Shaded\n\t\t\t\t<\/figcaption><\/figure><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"01f24ca\" data-elementor-lightbox-title=\"Tube_VisualizeNormals.4-1\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjQ5LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZU5vcm1hbHMuNC0xLmpwZyIsInNsaWRlc2hvdyI6IjAxZjI0Y2EifQ%3D%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.4-1.jpg?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.4-1.jpg?fit=300%2C300&amp;ssl=1\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-249\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.4-1.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.4-1.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.4-1.jpg?resize=150%2C150&amp;ssl=1 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-1-249'>\n\t\t\t\tTriangular Cross Section &#8211; Smooth Shaded\n\t\t\t\t<\/figcaption><\/figure><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"01f24ca\" data-elementor-lightbox-title=\"Tube_VisualizeNormals.7-1\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjY0LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZU5vcm1hbHMuNy0xLmpwZyIsInNsaWRlc2hvdyI6IjAxZjI0Y2EifQ%3D%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.7-1.jpg?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"300\" height=\"300\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.7-1.jpg?fit=300%2C300&amp;ssl=1\" class=\"attachment-medium size-medium\" alt=\"\" aria-describedby=\"gallery-1-264\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.7-1.jpg?w=500&amp;ssl=1 500w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.7-1.jpg?resize=300%2C300&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeNormals.7-1.jpg?resize=150%2C150&amp;ssl=1 150w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-1-264'>\n\t\t\t\tTriangular Cross Section &#8211; Flat Shaded\n\t\t\t\t<\/figcaption><\/figure>\n\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-7e04908 elementor-widget elementor-widget-text-editor\" data-id=\"7e04908\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Flat shading takes the surface of each primitive, and assigns the vector perpendicular to this surface as the normal for all the vertices in that primitive. This is a common scenario when using SOPs, in which context we would look to the Facet operator. But with this technique, we are handling our vertex information in the material shader, including the calculation of our surface normals, so I figured flat shading should happen somewhere in there.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-d0529cf elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"d0529cf\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-4bfb3c7\" data-id=\"4bfb3c7\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2bbf9f8 elementor-widget elementor-widget-image\" data-id=\"2bbf9f8\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<a href=\"https:\/\/docs.unity3d.com\/2019.3\/Documentation\/Manual\/ComputingNormalPerpendicularVector.html\">\n\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"228\" height=\"145\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/surface-normal.png?fit=228%2C145&amp;ssl=1\" class=\"attachment-large size-large wp-image-257\" alt=\"\" \/>\t\t\t\t\t\t\t\t<\/a>\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-06dde2f\" data-id=\"06dde2f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-a70b6b2 elementor-widget elementor-widget-text-editor\" data-id=\"a70b6b2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Using the geometry shader worked well since vertex information is available per primitive at this stage. The vertex positions in a triangular primitive allow us to calculate a vector perpendicular to the plane they intersect; this becomes our new normal, now updated for shading.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-9ac318e elementor-widget elementor-widget-text-editor\" data-id=\"9ac318e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<pre>vec3 faceNormal = -normalize(cross(gl_in[1].gl_Position.xyz - <br \/>gl_in[0].gl_Position.xyz,<br \/>gl_in[2].gl_Position.xyz - gl_in[0].gl_Position.xyz));<\/pre>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-8447748 elementor-widget elementor-widget-image-gallery\" data-id=\"8447748\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image-gallery.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-image-gallery\">\n\t\t\t<div id='gallery-2' class='gallery galleryid-234 gallery-columns-2 gallery-size-full'><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"8447748\" data-elementor-lightbox-title=\"Tube_VisualizeShading.2\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjU1LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZVNoYWRpbmcuMi5qcGciLCJzbGlkZXNob3ciOiI4NDQ3NzQ4In0%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?fit=1920%2C1080&amp;ssl=1\" class=\"attachment-full size-full\" alt=\"\" aria-describedby=\"gallery-2-255\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?resize=1200%2C675&amp;ssl=1 1200w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.2.jpg?w=1600&amp;ssl=1 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-2-255'>\n\t\t\t\tSquare Cross Section &#8211; Smooth Shaded\n\t\t\t\t<\/figcaption><\/figure><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon landscape'>\n\t\t\t\t<a data-elementor-open-lightbox=\"yes\" data-elementor-lightbox-slideshow=\"8447748\" data-elementor-lightbox-title=\"Tube_VisualizeShading.3\" data-e-action-hash=\"#elementor-action%3Aaction%3Dlightbox%26settings%3DeyJpZCI6MjU2LCJ1cmwiOiJodHRwczpcL1wvbWFya2hhc2hpbW90by5vcmdcL3dwLWNvbnRlbnRcL3VwbG9hZHNcLzIwMjFcLzEyXC9UdWJlX1Zpc3VhbGl6ZVNoYWRpbmcuMy5qcGciLCJzbGlkZXNob3ciOiI4NDQ3NzQ4In0%3D\" href=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?ssl=1\"><img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?fit=1920%2C1080&amp;ssl=1\" class=\"attachment-full size-full\" alt=\"\" aria-describedby=\"gallery-2-256\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?resize=1200%2C675&amp;ssl=1 1200w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Tube_VisualizeShading.3.jpg?w=1600&amp;ssl=1 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/><\/a>\n\t\t\t<\/div>\n\t\t\t\t<figcaption class='wp-caption-text gallery-caption' id='gallery-2-256'>\n\t\t\t\tSquare Cross Section &#8211; Flat Shaded\n\t\t\t\t<\/figcaption><\/figure>\n\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-376c2e0 elementor-widget elementor-widget-text-editor\" data-id=\"376c2e0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><strong>3D Texture Buffer<\/strong><\/p>\n<p>The texture buffer is used to store all of the position information for all the curves. In order to know what information belongs to which curve, we determine an axis along which the curve will be defined; every pixel along that axis in the buffer will contain the information for one curve. I&#8217;ll try to illustrate this based on how it works in the base example.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-1dd7e4b elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"1dd7e4b\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-6824f7f\" data-id=\"6824f7f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-650a280 elementor-widget elementor-widget-image\" data-id=\"650a280\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"593\" height=\"208\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-2.png?fit=593%2C208&amp;ssl=1\" class=\"attachment-medium_large size-medium_large wp-image-281\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-2.png?w=593&amp;ssl=1 593w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-2.png?resize=300%2C105&amp;ssl=1 300w\" sizes=\"(max-width: 593px) 100vw, 593px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-e8e6d7f\" data-id=\"e8e6d7f\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c6b9436 elementor-widget elementor-widget-text-editor\" data-id=\"c6b9436\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Let&#8217;s say that this drawing represents a 1-D texture. This texture stores the current position for N number of particles P.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-7f8bca0 elementor-widget elementor-widget-text-editor\" data-id=\"7f8bca0\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>To include information about the particle&#8217;s trail, we construct a 2D buffer and use feedback to store the position information at previous frames.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-7f123fb elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"7f123fb\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-ddda324\" data-id=\"ddda324\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-2c22b70 elementor-widget elementor-widget-image\" data-id=\"2c22b70\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"768\" height=\"757\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-3.png?fit=768%2C757&amp;ssl=1\" class=\"attachment-medium_large size-medium_large wp-image-282\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-3.png?w=842&amp;ssl=1 842w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-3.png?resize=300%2C296&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-3.png?resize=768%2C757&amp;ssl=1 768w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-016fbb8\" data-id=\"016fbb8\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-e67c7bf elementor-widget elementor-widget-text-editor\" data-id=\"e67c7bf\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Here, the y axis is dedicated to time, measured in frames. t(0) represents the current frame, and extends to M-1 frames in the past, with a total buffer length of M. Because we want a trail to contain the positions for a single particle across time, we define our curve C along the y axis.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-05b1080 elementor-widget elementor-widget-text-editor\" data-id=\"05b1080\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>In this N x M texture we can store information for N curves, each M frames in length. Since we define our curve along the y axis of time, we use the remaining axes to determine how many curves we can store. In this case, we use a 2-D texture, and determine the number of curves with the x axis, using its length N. This essentially limits us to using 1-D textures, and the resolution caps that come with them, when representing particle information. But often particle simulations are optimized to fit in square or square-ish 2-dimensional textures. This is where using a 3D Texture becomes handy.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-c61351d elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"c61351d\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-b8c06aa\" data-id=\"b8c06aa\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-28eb192 elementor-widget elementor-widget-image\" data-id=\"28eb192\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"766\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-11.png?fit=1024%2C766&amp;ssl=1\" class=\"attachment-large size-large wp-image-291\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-11.png?w=1200&amp;ssl=1 1200w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-11.png?resize=300%2C225&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-11.png?resize=1024%2C766&amp;ssl=1 1024w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-11.png?resize=768%2C575&amp;ssl=1 768w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-e186969\" data-id=\"e186969\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-7e6ef0e elementor-widget elementor-widget-text-editor\" data-id=\"7e6ef0e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Now, we define our particles on the x and y axis, and time along the z, with a depth of D. Defining our curves along the z axis allows us to use 2D textures to hold all the particle information at a given time step.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-047f1b3 elementor-widget elementor-widget-text-editor\" data-id=\"047f1b3\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>This way we can store information for more particles, and more curves, in a way that is flexible with input dimensions. I ended up choosing 3D Textures over a 2D Texture Array to allow for interpolation between depth slices. Using Compute Shaders to construct the 3D buffer ensures good performance when texture sizes start getting large.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2ae9212 elementor-widget elementor-widget-text-editor\" data-id=\"2ae9212\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><strong>Alpha Clipping<\/strong><\/p>\n<p>Having implemented a buffer that handles 2D textures, I decided to test it out with a simple particle system. This is what I get<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-4b53ea1 elementor-widget elementor-widget-video\" data-id=\"4b53ea1\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;hosted&quot;,&quot;controls&quot;:&quot;yes&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"e-hosted-video elementor-wrapper elementor-open-inline\">\n\t\t\t\t\t<video class=\"elementor-video\" src=\"https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Tube_VisualizeShading.2.mov\" controls=\"\" preload=\"metadata\" controlsList=\"nodownload\"><\/video>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-12556e2 elementor-widget elementor-widget-text-editor\" data-id=\"12556e2\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Not bad, but we notice these flickering dark portions of the trail; these are created because our particle has respawned somewhere within our frame buffer. Our shader creates a connected tube along the positions of a particle across all time frames. Even if there is a significant discontinuity in the position along these time frames, in this case when our particle respawns, the material shader will still treat the points as as single curve, and render the connection between the &#8220;death&#8221; point and spawn point.<\/p>\n<p>This could be considered a feature but lets say we want to remove these guys. We would essentially want to clip the tube between the point where the particle dies and where the particle respawns. In this way the trails will end where particles die and begin again where particles are born.<\/p>\n<p>To isolate this portion of the tube we need access to the life attribute of the particles at every point along their trail. We can do this by running the current life attributes into another feedback buffer, and sample this life buffer in the material shader along with the position buffer.<\/p>\n<p>Lets take a look at how this works in a 2-D buffer scenario<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-a8c751c elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"a8c751c\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-da06bc2\" data-id=\"da06bc2\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-c7de995 elementor-widget elementor-widget-image\" data-id=\"c7de995\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"469\" height=\"806\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-12.png?fit=469%2C806&amp;ssl=1\" class=\"attachment-large size-large wp-image-308\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-12.png?w=469&amp;ssl=1 469w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/image-12.png?resize=175%2C300&amp;ssl=1 175w\" sizes=\"(max-width: 469px) 100vw, 469px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-120aa5a\" data-id=\"120aa5a\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-33ba421 elementor-widget elementor-widget-text-editor\" data-id=\"33ba421\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>In this example we have a life buffer for a system of 2 particles, with a buffer length of 5 frames. At every frame, a particle&#8217;s life is decremented by 0.1, when it reaches 0, the particle&#8217;s life is reset to 1 and is respawned.<\/p>\n<p>This means that when a particle is alive, it&#8217;s life is always decreasing as time increases. The only time a particles life will increase is when it is re-spawned. We can use this information to check if a re-spawn has occurred between two frames. <\/p>\n<p>We compare life values between frames by sampling the neighbors of the current pixel in the y direction. In the case that no respawn has occurred, the up neighbor should have a value greater than the current pixel, and the down neighbor should have a value less. When either of these conditions fail, we know that the current pixel lives at either the &#8220;death&#8221; point or spawn point.<\/p>\n<p>\u00a0<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-8fb0833 elementor-widget elementor-widget-text-editor\" data-id=\"8fb0833\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>Great, so we&#8217;ve isolated the part of tube where the discontinuity lies, but how do we remove it from the render? This is where the idea of alpha clipping comes into play<\/p><p>The vertex shader is where we sample our buffers and check if we have hit a discontinuity point, but we cannot discard vertices in the vertex shader; however, we can discard fragments in the pixel shader. So we need a way for the vertex shader to tell the pixel shader when we have hit a point on the tube that we do not want to render. We do this by setting the alpha to zero whenever we hit a discontinuity point, when the pixel shader receives color information with an alpha value of zero, it will know to discard the fragment. By setting the alpha at both discontinuity points to zero, the interpolated alpha values between them should also become zero, and the entire section will be flagged for discard.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<section class=\"elementor-section elementor-inner-section elementor-element elementor-element-8fb68a2 elementor-section-boxed elementor-section-height-default elementor-section-height-default\" data-id=\"8fb68a2\" data-element_type=\"section\" data-e-type=\"section\">\n\t\t\t\t\t\t<div class=\"elementor-container elementor-column-gap-default\">\n\t\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-e611d05\" data-id=\"e611d05\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-daefb04 elementor-widget elementor-widget-text-editor\" data-id=\"daefb04\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<pre>float life = texelFetch(sLifeMap, id, 0).r;<br \/>float lifeNext = texelFetch(sLifeMap, idNext, 0).r;<br \/>float lifeBefore = texelFetch(sLifeMap, idBefore, 0).r;<br \/><br \/>if(lifeBefore &gt; life || lifeNext &lt; life) {<br \/>color.a = 0.0;<br \/>}<\/pre>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t<div class=\"elementor-column elementor-col-50 elementor-inner-column elementor-element elementor-element-33403af\" data-id=\"33403af\" data-element_type=\"column\" data-e-type=\"column\">\n\t\t\t<div class=\"elementor-widget-wrap elementor-element-populated\">\n\t\t\t\t\t\t<div class=\"elementor-element elementor-element-41ea78e elementor-widget elementor-widget-image\" data-id=\"41ea78e\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"442\" height=\"438\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/MAT_DiscardAlpha.png?fit=442%2C438&amp;ssl=1\" class=\"attachment-large size-large wp-image-774\" alt=\"\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<div class=\"elementor-element elementor-element-de7776f elementor-widget elementor-widget-text-editor\" data-id=\"de7776f\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The material operators in Touchdesigner have a very handy feature in the common page which allows us to tell the pixel shader to discard fragments that fall above or below a given alpha threshold. Playing with this value and the vertex resolution of the base geometry provided a much better result.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-e369c56 elementor-widget elementor-widget-video\" data-id=\"e369c56\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;hosted&quot;,&quot;controls&quot;:&quot;yes&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"e-hosted-video elementor-wrapper elementor-open-inline\">\n\t\t\t\t\t<video class=\"elementor-video\" src=\"https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Tube_AlphaClip_clean.0.mov\" controls=\"\" preload=\"metadata\" controlsList=\"nodownload\"><\/video>\n\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-a5b34a5 elementor-widget elementor-widget-text-editor\" data-id=\"a5b34a5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p>The ability to discard based on alpha gives us a lot of control over which sections of trail we want to render.<\/p>\n<p><strong>Variations<\/strong><\/p>\n<p>There are lots of possible variations of this technique but to describe a few<\/p>\n<p>I<strong>nstancing on Curve Points <\/strong><\/p>\n<p>Given that we have access to the points along each curve, we can instance objects at these points. We can bypass the curve extrusion all together or combine these instances with the extruded curve.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-11bb9e1 elementor-widget elementor-widget-image\" data-id=\"11bb9e1\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?fit=1920%2C1080&amp;ssl=1\" class=\"attachment-full size-full wp-image-311\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?resize=300%2C169&amp;ssl=1 300w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?resize=1024%2C576&amp;ssl=1 1024w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?resize=1200%2C675&amp;ssl=1 1200w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2021\/12\/Trail_ParallelTransport.9.jpg?w=1600&amp;ssl=1 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-2d9f8bb elementor-widget elementor-widget-image\" data-id=\"2d9f8bb\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"image.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<img loading=\"lazy\" decoding=\"async\" width=\"1920\" height=\"1080\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trails_Mix_Test.3.jpg?fit=1920%2C1080&amp;ssl=1\" class=\"attachment-large size-large wp-image-740\" alt=\"\" srcset=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trails_Mix_Test.3.jpg?w=1920&amp;ssl=1 1920w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trails_Mix_Test.3.jpg?resize=768%2C432&amp;ssl=1 768w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trails_Mix_Test.3.jpg?resize=1536%2C864&amp;ssl=1 1536w, https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trails_Mix_Test.3.jpg?w=1600&amp;ssl=1 1600w\" sizes=\"(max-width: 800px) 100vw, 800px\" \/>\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-93641c5 elementor-widget elementor-widget-text-editor\" data-id=\"93641c5\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><strong>Manipulating Position Data<\/strong><\/p>\n<p>We can filter our position data before running it through the feedback buffer to get some interesting effects. For example, we can use a Limit TOP to quantize our position values, which gives a more discrete trail.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-0abac43 elementor-arrows-position-inside elementor-pagination-position-outside elementor-widget elementor-widget-image-carousel\" data-id=\"0abac43\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;slides_to_show&quot;:&quot;1&quot;,&quot;autoplay_speed&quot;:4843,&quot;navigation&quot;:&quot;both&quot;,&quot;autoplay&quot;:&quot;yes&quot;,&quot;pause_on_hover&quot;:&quot;yes&quot;,&quot;pause_on_interaction&quot;:&quot;yes&quot;,&quot;infinite&quot;:&quot;yes&quot;,&quot;effect&quot;:&quot;slide&quot;,&quot;speed&quot;:500}\" data-widget_type=\"image-carousel.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-image-carousel-wrapper swiper\" role=\"region\" aria-roledescription=\"carousel\" aria-label=\"Image Carousel\" dir=\"ltr\">\n\t\t\t<div class=\"elementor-image-carousel swiper-wrapper\" aria-live=\"off\">\n\t\t\t\t\t\t\t\t<div class=\"swiper-slide\" role=\"group\" aria-roledescription=\"slide\" aria-label=\"1 of 3\"><figure class=\"swiper-slide-inner\"><img decoding=\"async\" class=\"swiper-slide-image\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.17.jpg?fit=1920%2C1080&amp;ssl=1\" alt=\"Trail_ParallelTransport.17\" \/><\/figure><\/div><div class=\"swiper-slide\" role=\"group\" aria-roledescription=\"slide\" aria-label=\"2 of 3\"><figure class=\"swiper-slide-inner\"><img decoding=\"async\" class=\"swiper-slide-image\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.13.jpg?fit=1920%2C1080&amp;ssl=1\" alt=\"Trail_ParallelTransport.13\" \/><\/figure><\/div><div class=\"swiper-slide\" role=\"group\" aria-roledescription=\"slide\" aria-label=\"3 of 3\"><figure class=\"swiper-slide-inner\"><img decoding=\"async\" class=\"swiper-slide-image\" src=\"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.15.jpg?fit=1920%2C1080&amp;ssl=1\" alt=\"Trail_ParallelTransport.15\" \/><\/figure><\/div>\t\t\t<\/div>\n\t\t\t\t\t\t\t\t\t\t\t\t<div class=\"elementor-swiper-button elementor-swiper-button-prev\" role=\"button\" tabindex=\"0\">\n\t\t\t\t\t\t<i aria-hidden=\"true\" class=\"eicon-chevron-left\"><\/i>\t\t\t\t\t<\/div>\n\t\t\t\t\t<div class=\"elementor-swiper-button elementor-swiper-button-next\" role=\"button\" tabindex=\"0\">\n\t\t\t\t\t\t<i aria-hidden=\"true\" class=\"eicon-chevron-right\"><\/i>\t\t\t\t\t<\/div>\n\t\t\t\t\n\t\t\t\t\t\t\t\t\t<div class=\"swiper-pagination\"><\/div>\n\t\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-02ece51 elementor-widget elementor-widget-text-editor\" data-id=\"02ece51\" data-element_type=\"widget\" data-e-type=\"widget\" data-widget_type=\"text-editor.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t\t\t<p><strong>Wrap Up<\/strong><\/p>\n<p>I hope you got something out of this extended rant on trails and curve extrusion, and that some of these techniques help with improving your own 3d tool kit. When implemented correctly, this technique should play real nice with all sorts of setups, so experimenting is highly encouraged.<\/p>\t\t\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t<div class=\"elementor-element elementor-element-bb372ee elementor-widget elementor-widget-video\" data-id=\"bb372ee\" data-element_type=\"widget\" data-e-type=\"widget\" data-settings=\"{&quot;video_type&quot;:&quot;vimeo&quot;}\" data-widget_type=\"video.default\">\n\t\t\t\t<div class=\"elementor-widget-container\">\n\t\t\t\t\t\t\t<div class=\"elementor-wrapper elementor-open-inline\">\n\t\t\t<iframe class=\"elementor-video-iframe\" allowfullscreen allow=\"clipboard-write\" title=\"vimeo Video Player\" src=\"https:\/\/player.vimeo.com\/video\/664549571?color&amp;autopause=0&amp;loop=0&amp;muted=0&amp;title=1&amp;portrait=1&amp;byline=1#t=\"><\/iframe>\t\t<\/div>\n\t\t\t\t\t\t<\/div>\n\t\t\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/div>\n\t\t\t\t\t<\/div>\n\t\t<\/section>\n\t\t\t\t<\/div>\n\t\t","protected":false},"excerpt":{"rendered":"<p>I am generally interested in real time 3D techniques and how they can be implemented in interactive environments like Touchdesigner. One technique I was happy to wrangle in was trails, and I thought I&#8217;d talk a bit about it. The explanation assumes some intermediate knowledge of Touchdesigner and OpenGL. The construction of trails includes a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":465,"comment_status":"open","ping_status":"open","sticky":false,"template":"elementor_theme","format":"standard","meta":{"nf_dc_page":"","om_disable_all_campaigns":false,"_uag_custom_page_level_css":"","_monsterinsights_skip_tracking":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[6],"tags":[17],"class_list":["post-234","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rendering-techniques","tag-article"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Trails - Mark Hashimoto<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/markhashimoto.org\/?p=234\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Trails - Mark Hashimoto\" \/>\n<meta property=\"og:description\" content=\"I am generally interested in real time 3D techniques and how they can be implemented in interactive environments like Touchdesigner. One technique I was happy to wrangle in was trails, and I thought I&#8217;d talk a bit about it. The explanation assumes some intermediate knowledge of Touchdesigner and OpenGL. The construction of trails includes a [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/markhashimoto.org\/?p=234\" \/>\n<meta property=\"og:site_name\" content=\"Mark Hashimoto\" \/>\n<meta property=\"article:published_time\" content=\"2022-01-06T16:37:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-01-27T19:12:22+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1920\" \/>\n\t<meta property=\"og:image:height\" content=\"1080\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"mkhashimoto00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"mkhashimoto00\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"12 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234\"},\"author\":{\"name\":\"mkhashimoto00\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#\\\/schema\\\/person\\\/8414a4966acb675562e3912022358c90\"},\"headline\":\"Trails\",\"datePublished\":\"2022-01-06T16:37:54+00:00\",\"dateModified\":\"2022-01-27T19:12:22+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234\"},\"wordCount\":1683,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/markhashimoto.org\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1\",\"keywords\":[\"Article\"],\"articleSection\":[\"Rendering Techniques\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/markhashimoto.org\\\/?p=234#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234\",\"url\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234\",\"name\":\"Trails - Mark Hashimoto\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/i0.wp.com\\\/markhashimoto.org\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1\",\"datePublished\":\"2022-01-06T16:37:54+00:00\",\"dateModified\":\"2022-01-27T19:12:22+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/markhashimoto.org\\\/?p=234\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#primaryimage\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/markhashimoto.org\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/markhashimoto.org\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1\",\"width\":1920,\"height\":1080},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/?p=234#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/markhashimoto.org\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Trails\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#website\",\"url\":\"https:\\\/\\\/markhashimoto.org\\\/\",\"name\":\"Mark Hashimoto\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/markhashimoto.org\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#organization\",\"name\":\"Mark Hashimoto\",\"url\":\"https:\\\/\\\/markhashimoto.org\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/markhashimoto.org\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Logo_Test.4.jpg?fit=120%2C90&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/markhashimoto.org\\\/wp-content\\\/uploads\\\/2022\\\/01\\\/Logo_Test.4.jpg?fit=120%2C90&ssl=1\",\"width\":120,\"height\":90,\"caption\":\"Mark Hashimoto\"},\"image\":{\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/markhashimoto.org\\\/#\\\/schema\\\/person\\\/8414a4966acb675562e3912022358c90\",\"name\":\"mkhashimoto00\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f5138bfeff6f47f25b25981c0cd5060d04d4b9da3a7e32f4e33ee07c32d1880b?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f5138bfeff6f47f25b25981c0cd5060d04d4b9da3a7e32f4e33ee07c32d1880b?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f5138bfeff6f47f25b25981c0cd5060d04d4b9da3a7e32f4e33ee07c32d1880b?s=96&d=mm&r=g\",\"caption\":\"mkhashimoto00\"},\"url\":\"https:\\\/\\\/markhashimoto.org\\\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Trails - Mark Hashimoto","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/markhashimoto.org\/?p=234","og_locale":"en_US","og_type":"article","og_title":"Trails - Mark Hashimoto","og_description":"I am generally interested in real time 3D techniques and how they can be implemented in interactive environments like Touchdesigner. One technique I was happy to wrangle in was trails, and I thought I&#8217;d talk a bit about it. The explanation assumes some intermediate knowledge of Touchdesigner and OpenGL. The construction of trails includes a [&hellip;]","og_url":"https:\/\/markhashimoto.org\/?p=234","og_site_name":"Mark Hashimoto","article_published_time":"2022-01-06T16:37:54+00:00","article_modified_time":"2022-01-27T19:12:22+00:00","og_image":[{"width":1920,"height":1080,"url":"https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg","type":"image\/jpeg"}],"author":"mkhashimoto00","twitter_card":"summary_large_image","twitter_misc":{"Written by":"mkhashimoto00","Est. reading time":"12 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/markhashimoto.org\/?p=234#article","isPartOf":{"@id":"https:\/\/markhashimoto.org\/?p=234"},"author":{"name":"mkhashimoto00","@id":"https:\/\/markhashimoto.org\/#\/schema\/person\/8414a4966acb675562e3912022358c90"},"headline":"Trails","datePublished":"2022-01-06T16:37:54+00:00","dateModified":"2022-01-27T19:12:22+00:00","mainEntityOfPage":{"@id":"https:\/\/markhashimoto.org\/?p=234"},"wordCount":1683,"commentCount":0,"publisher":{"@id":"https:\/\/markhashimoto.org\/#organization"},"image":{"@id":"https:\/\/markhashimoto.org\/?p=234#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1","keywords":["Article"],"articleSection":["Rendering Techniques"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/markhashimoto.org\/?p=234#respond"]}]},{"@type":"WebPage","@id":"https:\/\/markhashimoto.org\/?p=234","url":"https:\/\/markhashimoto.org\/?p=234","name":"Trails - Mark Hashimoto","isPartOf":{"@id":"https:\/\/markhashimoto.org\/#website"},"primaryImageOfPage":{"@id":"https:\/\/markhashimoto.org\/?p=234#primaryimage"},"image":{"@id":"https:\/\/markhashimoto.org\/?p=234#primaryimage"},"thumbnailUrl":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1","datePublished":"2022-01-06T16:37:54+00:00","dateModified":"2022-01-27T19:12:22+00:00","breadcrumb":{"@id":"https:\/\/markhashimoto.org\/?p=234#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/markhashimoto.org\/?p=234"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/markhashimoto.org\/?p=234#primaryimage","url":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1","contentUrl":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1","width":1920,"height":1080},{"@type":"BreadcrumbList","@id":"https:\/\/markhashimoto.org\/?p=234#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/markhashimoto.org\/"},{"@type":"ListItem","position":2,"name":"Trails"}]},{"@type":"WebSite","@id":"https:\/\/markhashimoto.org\/#website","url":"https:\/\/markhashimoto.org\/","name":"Mark Hashimoto","description":"","publisher":{"@id":"https:\/\/markhashimoto.org\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/markhashimoto.org\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/markhashimoto.org\/#organization","name":"Mark Hashimoto","url":"https:\/\/markhashimoto.org\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/markhashimoto.org\/#\/schema\/logo\/image\/","url":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Logo_Test.4.jpg?fit=120%2C90&ssl=1","contentUrl":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Logo_Test.4.jpg?fit=120%2C90&ssl=1","width":120,"height":90,"caption":"Mark Hashimoto"},"image":{"@id":"https:\/\/markhashimoto.org\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/markhashimoto.org\/#\/schema\/person\/8414a4966acb675562e3912022358c90","name":"mkhashimoto00","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f5138bfeff6f47f25b25981c0cd5060d04d4b9da3a7e32f4e33ee07c32d1880b?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f5138bfeff6f47f25b25981c0cd5060d04d4b9da3a7e32f4e33ee07c32d1880b?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f5138bfeff6f47f25b25981c0cd5060d04d4b9da3a7e32f4e33ee07c32d1880b?s=96&d=mm&r=g","caption":"mkhashimoto00"},"url":"https:\/\/markhashimoto.org\/?author=1"}]}},"uagb_featured_image_src":{"full":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1",1920,1080,false],"thumbnail":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=96%2C96&ssl=1",96,96,true],"medium":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=300%2C169&ssl=1",300,169,true],"medium_large":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=768%2C432&ssl=1",768,432,true],"large":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1024%2C576&ssl=1",1024,576,true],"1536x1536":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1536%2C864&ssl=1",1536,864,true],"2048x2048":["https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1",1920,1080,true],"awb_sm":["https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg",500,281,false],"awb_md":["https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg",800,450,false],"awb_lg":["https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg",1280,720,false],"awb_xl":["https:\/\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg",1920,1080,false]},"uagb_author_info":{"display_name":"mkhashimoto00","author_link":"https:\/\/markhashimoto.org\/?author=1"},"uagb_comment_info":0,"uagb_excerpt":"I am generally interested in real time 3D techniques and how they can be implemented in interactive environments like Touchdesigner. One technique I was happy to wrangle in was trails, and I thought I&#8217;d talk a bit about it. The explanation assumes some intermediate knowledge of Touchdesigner and OpenGL. The construction of trails includes a&hellip;","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/markhashimoto.org\/wp-content\/uploads\/2022\/01\/Trail_ParallelTransport.10.jpg?fit=1920%2C1080&ssl=1","_links":{"self":[{"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/posts\/234","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=234"}],"version-history":[{"count":5,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions"}],"predecessor-version":[{"id":885,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/posts\/234\/revisions\/885"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=\/wp\/v2\/media\/465"}],"wp:attachment":[{"href":"https:\/\/markhashimoto.org\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=234"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=234"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/markhashimoto.org\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=234"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}