{"id":42495,"date":"2018-04-24T06:00:32","date_gmt":"2018-04-24T10:00:32","guid":{"rendered":"http:\/\/shamusyoung.com\/twentysidedtale\/?p=42495"},"modified":"2018-04-24T09:19:05","modified_gmt":"2018-04-24T13:19:05","slug":"pixel-city-redux-3-shader-rant","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=42495","title":{"rendered":"Pixel City Redux #3: Shader Rant"},"content":{"rendered":"<p>Last time I talked about making a special shader in Unity. It turns out that writing Unity shaders is a mixture of awesome and awful. But before we can get  into that, we need to fix these buildings:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_buildings1.jpg' width=100% alt='Bah. Close enough. Ship it.' title='Bah. Close enough. Ship it.'\/><\/div><div class='mouseover-alt'>Bah. Close enough. Ship it.<\/div><\/p>\n<p>See, I&#8217;m going to be writing the lighting shader. My hope is that I&#8217;ll be able to use Unity to save me from the arduous task of writing my own shadowing system. I want buildings to be able to cast shadows on each other, the ground, and even themselves. But a cube doesn&#8217;t have any overhanging bits that might cast shadows on itself. So before I go messing around with shaders, let&#8217;s make some more complex buildings.<\/p>\n<p>I don&#8217;t need to make the full building generator just yet. All I need is something complex enough to self-shadow.<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_buildings2.jpg' width=100% alt='Kind of amazing what a huge improvement it is to just add ledges.' title='Kind of amazing what a huge improvement it is to just add ledges.'\/><\/div><div class='mouseover-alt'>Kind of amazing what a huge improvement it is to just add ledges.<\/div><\/p>\n<p>I&#8217;ll probably throw most of this code away later. These buildings are stupidly primitive. There&#8217;s a triangle pair for every single window, there aren&#8217;t any &#8220;gaps&#8221; with no windows, the ledges all look the same, there&#8217;s no street detail, and there isn&#8217;t any clutter on the roof. But these buildings can self-shadow, which is what counts.<\/p>\n<p>So let&#8217;s work on that shader&#8230;<\/p>\n<p><!--more--><\/p>\n<h3>The Shader<\/h3>\n<p>Remember that a shader is a special program that runs on your graphics card. It&#8217;s not written in the same language as the rest of the program. If you&#8217;re using OpenGL to make your graphics, then you program your shaders in a language called GLSL. If you&#8217;re using DirectX, then you&#8217;ll write your shaders in a language called HLSL. In Unity, you&#8217;re using a modified version of HLSL. <\/p>\n<p>In the OpenGL world, I really dislike how messy it can get when you&#8217;re trying to manage your shaders. Rendering is usually a multi-stage process. Somewhere at the core of your program you&#8217;ll have a bit of logic to the effect of:<\/p>\n<ul>\n<li>Grab all the FooBar objects in the scene and render them using shader A.\n<li>Now take all the Widget objects and render them with Shader B.\n<li>Now take all the Whatsit objects and render them with Shader A, except with a few different parameters than the ones we used for FooBars.\n<li>Now take all the <em>transparent<\/em> FooBars and and Widgets and render them with Shader C, in the order of their current distance from the camera.\n<li>Now finish it off by applying Shader D to the entire screen.<\/ul>\n<p>I&#8217;m leaving out a lot of details, but hopefully you get the idea. The program is sending various scene elements to different shaders and when you&#8217;re looking at the C++ code you can&#8217;t see what the individual shaders do. To see that, you need to switch over to this other programming language (and maybe even a different text editor) to look at all of those scattered source files. And when you&#8217;re looking at the shader code itself you can&#8217;t tell when it gets used. You can alleviate this by liberally commenting your code and documenting the structure, but that doesn&#8217;t change the fact that some of the most intensely complex logic in your program is straddling two different languages and several different source files.<\/p>\n<p>In the world of Unity, they move a lot of the &#8220;what objects get drawn by which shader&#8221; logic into the shader itself, and made it so that you can bundle all of your shaders into one file. This weirded me out at first, but once I start building my shader I realized how much clearer and more manageable this system is. I really like it.<\/p>\n<p>ON THE OTHER HAND&#8230;<\/p>\n<p><a href=\"https:\/\/docs.unity3d.com\/Manual\/SL-ShadingLanguage.html\">The documentation<\/a> for the Unity shader language barely exists, and the parts that do exist are apparently written for people who already understand it. There&#8217;s almost no example code whatsoever. And even when it does give you a bit of code, it does so without giving you the full context of where it&#8217;s used.<\/p>\n<p>Car analogies are played out, so let&#8217;s try&#8230;<\/p>\n<h3>A Baking Analogy<\/h3>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/stock_cake.jpg' width=100% alt='Dangit. Now I want cake. I guess I should stick to car analogies.' title='Dangit. Now I want cake. I guess I should stick to car analogies.'\/><\/div><div class='mouseover-alt'>Dangit. Now I want cake. I guess I should stick to car analogies.<\/div><\/p>\n<p>I search for &#8220;How do I make chocolate cake?&#8221;. Then I wind up on the Unity documentation for Chocolate cake, where it tells me:<\/p>\n<blockquote><p>Chocolate Cake is a kind of food. It can be made in a kitchen using ingredients. <\/p>\n<p>Related topics: Cupcakes, Dessert, Cooking.<\/p><\/blockquote>\n<p>The docs are so aggressively useless that sometimes I wonder if it wouldn&#8217;t be better if Unity just took them down so they stop poisoning the search results. (Probably not. I&#8217;m sure they very occasionally answer people&#8217;s questions.) Most of what I learned about Unity came from <a href=\"?p=21365\">forum discussions<\/a>. <\/p>\n<p>So I read a few forums and I see people talking about &#8220;eggs&#8221;. Apparently eggs are an ingredient in chocolate cake? So I look up eggs in the docs.<\/p>\n<blockquote><p>Eggs are an ingredient. The are frequently used in making various cakes. They should not be added during the cooking process.<\/p>\n<p>Related topics: Cupcakes, Chickens, Chicken breeding.<\/p><\/blockquote>\n<p>Okay. I see that cupcakes keep showing up in related topics. Maybe <b>that&#8217;s<\/b> where the payload of information is.<\/p>\n<blockquote><p>Cupcakes are a smaller type of cake. Please refer to <a href=\"https:\/\/docs.unity3d.com\/Manual\/SL-Reference.html\">the documentation on Chocolate Cake<\/a> for more information.<\/p>\n<p>Related topics: Chocolate Cake, Food, Feudalism in the 12th Century, The Moon Landing.<\/p><\/blockquote>\n<p>Or maybe not. <\/p>\n<p>Sometimes it&#8217;s even worse than this! Sometimes the only &#8220;help&#8221; I can find is one of the Unity tutorial <strong>videos<\/strong>. Regular video is bad enough, but these are archives of livestream sessions. It&#8217;s incredibly demoralizing to reach for something simple like, &#8220;Where are the options to disable [some feature]?&#8221; and the best &#8220;answer&#8221; is <a href=\"https:\/\/unity3d.com\/learn\/tutorials\/modules\/intermediate\/live-training-archive\/character-animation-setup\">an hour and a half of unedited footage<\/a> for a previous version of Unity that you can&#8217;t even be sure will answer your question. This system is so bad at providing information that it borders on encryption. <\/p>\n<p>But after several frustrating hours of trying to break through the layers of obfuscation in the Unity documentation, I do manage to learn a few things.<\/p>\n<h3>The Few Things I Learned<\/h3>\n<p>The Unity shader language forms a hierarchy. You write a single shader. That shader might contain many subshaders. Each subshader might contain multiple passes. Each pass contains a vertex shader and a fragment shader. So then you finally come across a few lines of example code in the skeletal Unity documentation, but you have no idea where this code goes within that structure. I searched for ages and I never did find just a simple example shader that the user could start with. The closest thing I could find was this:<\/p>\n<pre lang=\"c\" line=\"1\">Shader \"MyShader\" {\r\n    Properties {\r\n        _MyTexture (\"My Texture\", 2D) = \"white\" { }\r\n        \/\/ other properties like colors or vectors go here as well\r\n    }\r\n    SubShader {\r\n        \/\/ here goes the 'meat' of your\r\n        \/\/ - surface shader or\r\n        \/\/ - vertex and program shader or\r\n        \/\/ - fixed function shader\r\n    }\r\n    SubShader {\r\n        \/\/ here goes a simpler version of the SubShader\r\n        \/\/ above than can run on older graphics cards\r\n    }\r\n}<\/pre>\n<p>This is supposedly an &#8220;Example&#8221; program, except it has only a single line of code (Line 3) that actually <strong>does<\/strong> something. The rest is just comments and curly braces. Lines 7-10 are a description of what sort of code might go here, without telling me what that code is or what it does. (Or where to look that up.) It&#8217;s the equivalent of, &#8220;After the ingredients are combined, put them inside of a specific container and place the container in the appropriate appliance for a length of time or until the cake is a particular color.&#8221; I swear it&#8217;s taunting me by explicitly listing the things I need to know that it refuses to tell me.<\/p>\n<p>Maybe elsewhere I&#8217;d find something that was supposedly an &#8220;example program&#8221; that fills in lines 7-10, but I try pasting it in and it doesn&#8217;t work and I have no idea why. There&#8217;s no <em>starting point<\/em> for learning any of it. I couldn&#8217;t just find the basic framework and build up from there. <\/p>\n<p>I did eventually find <a href=\"http:\/\/catlikecoding.com\/unity\/tutorials\/rendering\/part-2\/\">this tutorial<\/a> on a blog called Catlike Coding, and that basically saved this project. I never would have gotten anywhere without it. I don&#8217;t know where author Jasper Flick got his knowledge, but I&#8217;m guessing it wasn&#8217;t from the relentlessly unhelpful and secretive manual pages.<\/p>\n<p>The Catlike tutorials give me the crucial first step of explaining the overall structure of a shader and how it operates with Unity, and then it gives a working example that will actually compile. From there I can begin modifying it to meet my needs. The Catlike project builds towards photorealism effects, and I&#8217;m headed in the opposite direction, but at least I have some sort of foothold on what I&#8217;m trying to learn. <\/p>\n<p>When I&#8217;m done, I have lighting and shadows:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting1.jpg' width=100% alt='If you look closely you can see a red speck on the left and a blue one on the right. That&apos;s the origin of the lights. There&apos;s also a green light positioned below the camera.' title='If you look closely you can see a red speck on the left and a blue one on the right. That&apos;s the origin of the lights. There&apos;s also a green light positioned below the camera.'\/><\/div><div class='mouseover-alt'>If you look closely you can see a red speck on the left and a blue one on the right. That&apos;s the origin of the lights. There&apos;s also a green light positioned below the camera.<\/div><\/p>\n<p>You&#8217;ll notice that the scene is no longer textured. This is the lighting component of the scene, with nothing else.<\/p>\n<p>How the program builds this:<\/p>\n<p>Shader pass #1: Render the entire scene. I could use this lighting pass to project sunlight onto the scene, but I&#8217;m not planning on using sunlight in this world. So for now everything is drawn solid black. Later I&#8217;ll do something else with this shader pass, but for now it&#8217;s just a pitch-black city.<\/p>\n<p>Shader pass #2: Lighting pass. Unity goes through every light in the scene. You&#8217;ll notice I&#8217;ve got three: Red, green, and blue.For each light, it renders all of the objects that fall within that light&#8217;s radius and might possibly be illuminated by it. My shader renders these objects with this particular light&#8217;s properties. This lighting contribution is added to the existing image. When this pass is done, we have the image above. <\/p>\n<p>I should add that most of step #2 is automated. Unity sorts through the objects in the scene and figures out which objects need to be illuminated by which lights. So that&#8217;s a bunch of work I don&#8217;t have to do. Like, Unity just saved me from writing hundreds of lines of code.<\/p>\n<p>In OpenGL, we would do things a little differently. We would render the entire scene at full brightness, producing something like this:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting2.jpg' width=100% alt='I know the sidewalks look goofy. We&apos;ll take care of that mess in a later entry.' title='I know the sidewalks look goofy. We&apos;ll take care of that mess in a later entry.'\/><\/div><div class='mouseover-alt'>I know the sidewalks look goofy. We&apos;ll take care of that mess in a later entry.<\/div><\/p>\n<p>Then we&#8217;d do the lighting pass. Except, instead of drawing directly to the screen, we&#8217;d draw into a framebuffer. A framebuffer is like another screen you can draw to. It&#8217;s the same size as the viewport. (So if the user is running the game at 1920&#215;1080, your hidden framebuffer would be the same dimensions.) <\/p>\n<p>So then we have two different images: The scene at full brightness is in the main viewport, and we&#8217;ve got the lighting stored in a spare framebuffer. We could then draw the framebuffer into the main viewport, having it multiply the two images together.  Here is what that looks like if I take the two previous screenshots and combine them in an image editor using a multiplication filter:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting3.jpg' width=100% alt='This is actually an image edit and not a render.' title='This is actually an image edit and not a render.'\/><\/div><div class='mouseover-alt'>This is actually an image edit and not a render.<\/div><\/p>\n<p>Yeah. That&#8217;s exactly what we&#8217;re going for. Except, Unity doesn&#8217;t give me the ability to create a framebuffer. When I search for how to do this, I get endless forums posts where people answer with &#8220;Use a render texture&#8221;. A render texture is a texture you draw into and then slap on an object in the scene. It&#8217;s used for things like mirrors or in-game security screens that show you what&#8217;s going on elsewhere in the level. In the world of OpenGL this would be the wrong way to do things<span class='snote' title='1'>Render textures MUST be a power of 2. So to make one large enough for a 1920&#215;1080 display I&#8217;d need to make a gargantuan 2048&#215;2048 texture, even though half of that texture memory would go completely to waste.<\/span>. <\/p>\n<p>What I&#8217;m trying to do here is called &#8220;deferred rendering&#8221;. I see that Unity offers a totally different rendering path that supports deferred rendering, but that whole system is built around assumptions that you&#8217;ll be using stuff like normal maps and other modern-day FX. The documentation on that stuff is in even worse shape than the rest of the docs. I think to use this I&#8217;d have to start over, except I&#8217;d be making something even more complicated with less information.<\/p>\n<p><strong>Shamus, why don&#8217;t you just look at the&#8230;<\/strong><\/p>\n<p>Let me stop you right there, because I&#8217;ve seen a LOT of these sorts of answers over the last couple of days as I&#8217;ve waded through forums looking for answers. I get the sense that the Unity documentation was in better shape in the past than it is now. This is bad because the various forum questions are now poisoned with flippant <a href=\"https:\/\/en.wikipedia.org\/wiki\/RTFM\">RTFM<\/a> answers that have become useless. <a href=\"https:\/\/docs.unity3d.com\/Manual\/RenderTech-DeferredShading.html\">This page<\/a> in the Unity docs tells me to go and look at the built-in shaders so I can see a working example of the thing I&#8217;m interested in. But when I follow the link it redirects me to a generic download page where I can download Unity itself. <\/p>\n<p>The page is confusingly designed and it looks like you&#8217;ve been redirected somewhere useless, but if you poke around you&#8217;ll find a download for the promised shaders. But then I download the file and it&#8217;s just hundreds of shader source files. Okay, thanks&#8230; but which one of these &#8211; or which several of them &#8211; are the answer to my question of &#8220;How does rendering system X work?&#8221; I wanted to know which shaders were used in which order, and now I&#8217;m looking at a huge pile of random shaders and I have no idea where to go from here. <\/p>\n<p>I&#8217;ve spent half a day of chasing links that promise knowledge but only take me to unfinished manual pages, dead links, and unrelated topics. <em>Maybe<\/em> there&#8217;s some magical combination of search terms that will take me to the payload of information, but the longer this goes on the more I suspect it just isn&#8217;t there.<\/p>\n<p>I&#8217;ll come back to deferred rendering later in the project, but at this point I&#8217;d really like to get back to programming.<\/p>\n<h3>Let&#8217;s Get Back to Programming<\/h3>\n<p>So now maybe you&#8217;re asking:<\/p>\n<p><strong>Shamus, why can&#8217;t you just draw everything into the main viewport? Why not just draw the full-bright city and then layer the lights on top of it?<\/strong><\/p>\n<p>Remember that each light adds itself to what&#8217;s already there. Then the result of those passes is multiplied with the full bright scene. If I draw the full bright scene and then ADD the lights to it, then it would be trying to brighten an already maximum-bright scene. If I multiplied each pass, then I wouldn&#8217;t get the right result. During the pass for the red light, everywhere the red light isn&#8217;t touching would be turned black. Then when the blue light came along, it wouldn&#8217;t be lighting the brick face of the building, it would be lighting a pure black void.<\/p>\n<p>Or to put it another way. What I&#8217;m trying to do is this:<\/p>\n<p><code>Frambuffer = (Redlight + BlueLight + Greenlight)<br \/>\nViewport = Buildings<br \/>\nFinalImage = Viewport * Framebuffer<\/code><\/p>\n<p>I want to add the lights together, and then combine it after the adding is done. That&#8217;s not the same as:<\/p>\n<p><code>FinalImage = Buildings * Redlight * BlueLight * Greenlight<\/code><\/p>\n<p>And it&#8217;s also not the same as:<\/p>\n<p><code>FinalImage = Buildings + Redlight + BlueLight + Greenlight<\/code><\/p>\n<p>Only the first will produce correct results.<\/p>\n<p>Hm. Maybe I can hack my way around this.<\/p>\n<h3>Whatever Works, Right?<\/h3>\n<p>Rather than build up the lighting contributions in a framebuffer and then multiply them with the viewport, what if I did it the other way? What if I add all the lights together FIRST, inside the viewport. (Which is what I&#8217;m doing now.) Then I&#8217;ll draw the textured buildings into the scene using a multiply filter. Will Unity let me do that? If I stick another extra shader pass at the end will Unity just blindly throw all the objects into it?<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting4.jpg' width=100% alt='Okay. That worked. Huh.' title='Okay. That worked. Huh.'\/><\/div><div class='mouseover-alt'>Okay. That worked. Huh.<\/div><\/p>\n<p>Apparently so!<\/p>\n<p>Yes, this looks almost identical to the previous image. But this one really was built with shaders and the previous one was created with an image editor. So basically I&#8217;m doing: <\/p>\n<p><code>Redlight + BlueLight + Greenlight * Buildings<\/code><\/p>\n<p>(Yes, in mathematics you normally do multiplication before addition, but since we&#8217;re drawing color values onto a canvas the order of operations is strictly left-to-right.)<\/p>\n<p>Now, let&#8217;s get back to that first shader pass. (The one that&#8217;s all black.) What I&#8217;m thinking of using that for is emissive stuff. (Stuff that glows.)<\/p>\n<p>Right now I&#8217;ve got my window texture. It&#8217;s your standard 32 bit texture, with a byte for the red, green, blue, and alpha channels. The alpha channel is used for transparency. So a single window looks like this:<\/p>\n<p><center><img decoding=\"async\" src=\"images\/pixelcity2_texturemap6.jpg\" title=\"For the record, the checkerboard pattern is supposed to represent transparent regions.\"\/><\/center><\/p>\n<p>(Yeah I didn&#8217;t put a lot of time into this texture.)<\/p>\n<p>You&#8217;ll notice the windows don&#8217;t completely obscure the wall behind them. The window itself is opaque, but then around the window is some empty space where you can see through to the bricks \/ concrete \/ whatever behind it.<\/p>\n<p>The thing is, we&#8217;re using an entire byte for that alpha value, and we don&#8217;t need to. I don&#8217;t plan on having windows with soft faded edges that blend in with the wall. In my textures, the window is either fully opaque or fully transparent. We only need one bit (a single zero \/ one value) for that. That means we&#8217;ve got another seven bits I can use for other things. <\/p>\n<p>So I make the highest bit control the alpha, and I use the next bit for emissive glow. If the bit is set, then during the first render pass this pixel will be drawn at full brightness rather than pure black.<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting5.jpg' width=100% alt='Wow. That made a big difference.' title='Wow. That made a big difference.'\/><\/div><div class='mouseover-alt'>Wow. That made a big difference.<\/div><\/p>\n<p>Yeah. Now the windows glow. Above I said that every single window was a triangle pair. (A rectangle.) This is stupidly wasteful and I&#8217;ll make it more efficient later. But since we&#8217;re already making so many polygons, it should be trivial to assign each building its own color, and then have every polygon in the building be a random offset from that:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting6.jpg' width=100% alt='You know, this flat-poly stuff looks really unexpectedly cool. I might come back to this later.' title='You know, this flat-poly stuff looks really unexpectedly cool. I might come back to this later.'\/><\/div><div class='mouseover-alt'>You know, this flat-poly stuff looks really unexpectedly cool. I might come back to this later.<\/div><\/p>\n<p>Now, instead of making the windows pure white, I&#8217;ll have them use the polygon color to determine the glow coming from the window:<\/p>\n<p><div class='imagefull'><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/pixelcity2_lighting7.jpg' width=100% alt='Apparently there&apos;s a city-wide rave going on?' title='Apparently there&apos;s a city-wide rave going on?'\/><\/div><div class='mouseover-alt'>Apparently there&apos;s a city-wide rave going on?<\/div><\/p>\n<p>Not bad, giving how much of this I&#8217;m half-assing. Okay, the magenta windows look pretty silly, but I think we&#8217;re on the right track here.<\/p>\n<p>Eventually I&#8217;ll come up with a less ridiculous way of lighting these windows, but for now this works.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time I talked about making a special shader in Unity. It turns out that writing Unity shaders is a mixture of awesome and awful. But before we can get into that, we need to fix these buildings: See, I&#8217;m going to be writing the lighting shader. My hope is that I&#8217;ll be able to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[],"class_list":["post-42495","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/42495","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=42495"}],"version-history":[{"count":46,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/42495\/revisions"}],"predecessor-version":[{"id":42646,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/42495\/revisions\/42646"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=42495"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=42495"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=42495"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}