{"id":15956,"date":"2012-05-23T04:57:58","date_gmt":"2012-05-23T09:57:58","guid":{"rendered":"http:\/\/www.shamusyoung.com\/twentysidedtale\/?p=15956"},"modified":"2013-09-22T15:56:31","modified_gmt":"2013-09-22T20:56:31","slug":"project-octant-part-11-shaders","status":"publish","type":"post","link":"https:\/\/www.shamusyoung.com\/twentysidedtale\/?p=15956","title":{"rendered":"Project Octant Part 11: Shaders"},"content":{"rendered":"<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant10_16.jpg' class='insetimage'   alt='octant10_16.jpg' title='octant10_16.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>The texture stretching on these blobs is pretty annoying. There&#8217;s no <em>good<\/em> way to fix this without shaders. So let&#8217;s use shaders. As I&#8217;ve mentioned before, shaders are special programs that run on your graphics card. It goes something like this:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant11_1.png' class='insetimage'   alt='octant11_1.png' title='octant11_1.png'\/><\/td><\/tr><\/table><\/p>\n<p>Now, that&#8217;s actually a simplified view. A more accurate flowchart is:<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant11_2.jpg' class='insetimage'   alt='octant11_2.jpg' title='octant11_2.jpg'\/><\/td><\/tr><\/table><\/p>\n<p><!--more-->And even this is a bit of a simplification.  It leaves out things like driver layers.  Unless something goes horribly wrong, I shouldn&#8217;t need to think about all that stuff.  You generally don&#8217;t need to worry about drivers unless you&#8217;re working on the bleeding edge and getting really close to the hardware. I&#8217;m talking <a href=\"http:\/\/en.wikipedia.org\/wiki\/John_D._Carmack\">John Carmack<\/a> distance here, where your code is so close to the hardware that the fan on your graphics card starts shaving off your eyebrows. <\/p>\n<p>This means I&#8217;m going to have to write two new programs: A vertex shader and a pixel shader. (The later is called a &#8220;fragment shader&#8221; by programmers who are trying to impress you with their mysterious and esoteric knowledge.) I can write these programs in one of three different languages:<\/p>\n<ol>\n<li><strong>NVIDIA cg<\/strong>.  This is a shading language made by NVIDIA. In theory it follows some sort of standard that should make it work on ATI hardware as well, although I have my doubts. I used this on Project Frontier because I was familiar with it and because I already had the SDK.  It&#8217;s probably not a great platform to use for this. In fact, I suspect the problems people are having (purple foliage, artifacting on the grass polygons) are the result of using this NVIDIA system on ATI hardware. It&#8217;s entirely possible that the cg shaders don&#8217;t work for the same reason that the Microsoft webpage doesn&#8217;t work in Firefox. Maybe not. Maybe it&#8217;s just a stupid bug that doesn&#8217;t happen on my machine.  It doesn&#8217;t matter. The upshot is, we&#8217;re not using the NVIDIA toolkit for this project.\n<\/li>\n<li><strong>HLSL<\/strong>: &#8220;High Level Shader Language&#8221;.  This is the Direct 3D way of doing things.  If you&#8217;re going for a Microsoft platform using Microsoft tools, then this is your go-to language.  I&#8217;m using OpenGL, which leaves us with&#8230;\n<\/li>\n<li><strong>GLSL<\/strong>: The &#8220;OpenGL Shader Language&#8221;. This is obviously the way to go for my OpenGL -based project.\n<\/li>\n<\/ol>\n<p>Right off the bat, I can see something is wrong here.  <a href=\"http:\/\/www.opengl.org\/sdk\/docs\/manglsl\/\">These docs<\/a> on GLSL are an absolute mess. <a href=\"http:\/\/www.opengl.org\/wiki\/Category:OpenGL_Shading_Language\">The wiki<\/a> is even worse.  If you ever Google something and find forum posts listed above the official documentation in the search order, you know you are sailing right into the inky black void near the edge of the map, a place that would be labeled &#8220;here be dragons&#8221; if not for the fact that the link to the map itself is a 404. <\/p>\n<p>Searching for example programs isn&#8217;t very helpful either. There are two kinds of example programs:<\/p>\n<ol>\n<li>Ultra-simple test programs: Here is how to create a flat-shaded, un-textured, colorless, unlit polygon. These little three-line programs can&#8217;t teach you anything because they don&#8217;t DO anything.\n<\/li>\n<li>Super-complex programs for a very specific purpose: Here is how to do toon shading on a bump-mapped, multi-textured, reflective surface with a specular map and fresnel shading.  These programs are just pages of un-commented equations and are too advanced and specific to be used to learn how to do anything.<\/li>\n<\/ol>\n<p><a name=\"forums\"><\/a>Which leaves us with forums.  Here is how things work on programming forums:<br \/>\n<b><br \/>\nALLEN: Hi, I&#8217;m new to driving and I need to move my car back around 5 meters. How can I move the car backwards?<\/p>\n<p>(2 days later.)<\/p>\n<p>ALLEN: Hello? This is still a problem. I&#8217;m sure someone knows how to do this.<\/p>\n<p>BOB: I can&#8217;t believe you didn&#8217;t figure this out yourself.  Just take your foot off the gas and let the car roll backwards down the hill. Tap the bake when you get to where you want to be. Boom. Done.<\/p>\n<p>ALLEN: But I&#8217;m not on a hill. I&#8217;m in my driveway and it&#8217;s completely flat.<\/p>\n<p>CARL: Dude, I don&#8217;t know what you&#8217;re trying to accomplish, but you should never be driving backwards. It&#8217;s dangerous and will confuse the other drivers. See the big window in FRONT of you? That&#8217;s your first clue. Don&#8217;t drive backwards.<\/p>\n<p>ALLEN: I&#8217;m not trying to drive backwards. I just need to move back a little bit so I can get out of my driveway and start driving forwards.<\/p>\n<p>CARL: So just drive in circle until you&#8217;re pointed the right way.<\/p>\n<p>ALLEN: I don&#8217;t have enough room to turn around like that. I only need to move back a few meters. I don&#8217;t understand why this has to be so hard.<\/p>\n<p>CARL: Sounds like your &#8220;driveway&#8221; isn&#8217;t compatible with cars. It&#8217;s probably made for bikes.  Call a contractor and have them convert some of your yard into driveway to be standards-compliant with the turning radius of a car. Either way, you&#8217;re doing something wrong.<\/p>\n<p>DAVE: I see your problem. You can adjust your car to move backwards by using the shifter.  It&#8217;s a stick located right between the passenger and driver seats.  Apply the clutch and move the stick to the &#8220;R&#8221; position.<\/p>\n<p>ALLEN: But.. I don&#8217;t have a clutch.  And there isn&#8217;t a stick between the seats. <\/p>\n<p>CARL: Sounds like you&#8217;re trying to drive in Europe or something. <\/p>\n<p>ALLEN: Ah. Nevermind. I figured it out.<\/p>\n<p><\/b><\/p>\n<p>The other major source of help that I find is&#8230; PDF files. And not good PDF files either.  These are stupid, primitive documents that take forever to load, don&#8217;t have hyperlinks, don&#8217;t allow copy &#038; paste, and don&#8217;t allow links to specific parts of the document.  So when Google points me at the document with the promise that it might contain what I&#8217;m looking for, I have to do <em>another<\/em> search inside this document to find the topic, and then read this infuriating mess to see if it actually has the goods. (It doesn&#8217;t.) Like all PDFs, my only view options seem to be &#8220;too tiny to read&#8221; or &#8220;waste 75% of my screen space&#8221;.  <\/p>\n<p>Instead of scrolling through a document, you have to scroll down, turn page, scroll up again, then back down, then turn the page again.  This is even more infuriating because most PDFs are written either under the assumption that you&#8217;re a scientist trying to simulate the behavior of light on the quantum level, or that you&#8217;ve never seen a computer before.  Sometimes they shift between these two assumptions within the same document. <\/p>\n<p><em>Dear dudes who make PDFs for on the web: Please look into HTML. I promise it&#8217;s documented WAY better than the stuff you&#8217;re documenting.<\/em><\/p>\n<p>You&#8217;re trying to figure out how to do something you know is simple, and you just need a bit of help with the syntax.  And the top search results are all like the thread above: Long exchanges filled with misinformation and bad advice which you must read all the way to the end before you discover it doesn&#8217;t have what you need. <\/p>\n<p>As an example of the many, many mysteries I had to unravel: I wanted to add texture mapping to my vertex shader.  Which means I need access to the texture coordinates. This is a very simple thing to do &#8211; <em>once you know how<\/em>.  Hilariously, the <a href=\"http:\/\/www.opengl.org\/sdk\/docs\/manglsl\/\">manual pages<\/a> don&#8217;t list them under &#8220;built-in variables&#8221;.  And after searching around some more, I find there are actually two <em>different<\/em> built-in variables for getting texture coords. I find these in example code.  So now I see how to make a program that works, but I don&#8217;t know why there are two different sets of variables, how they differ, or how to use them properly. Hours later I&#8217;m working on something else and I run into a PDF that mentions the two variables exist because one is what the vertex shader GETS from OpenGL, and the other is what the vertex shader GIVES to the pixel shader.  See? Simple and clear. This is something I should be able to find by typing &#8220;GLSL texture coords&#8221; into Google, not embarking on some Professor Layton-esque adventure of inscrutable puzzles provided by unhelpful idiots. <\/p>\n<p>So now I have something that works, and I PROBABLY know what I&#8217;m doing, but I don&#8217;t really have a clear working knowledge.  For example, at one point I was setting values in the vertex shader and they weren&#8217;t going to the pixel shader. Again, it was probably something trivial to fix, but without a proper manual I could be making a dozen really stupid mistakes that just happen to &#8220;work anyway&#8221;. Doing things this way is like taking Carl&#8217;s advice and paving my yard.  It solves the problem while leaving me ignorant.<\/p>\n<p>This is not a programming language. This is <em>folk knowledge. <\/em><\/p>\n<p>I spend hours fooling around, trying to find the information I want. I manage to get something working. <\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant11_3.jpg' class='insetimage'   alt='octant11_3.jpg' title='octant11_3.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>You might remember last time I said I needed surface normals. I wrote some code to calculate all the possible normals for my 256 cube configurations. I actually had it print these out into a text file, as C++ code.  Like this:<\/p>\n<pre lang=\"c\">\r\nstatic float norm_table[256][16] = \r\n{\r\n{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  \/\/ 0\r\n{0.785398,0.785398,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  \/\/ 1\r\n{-0.785398,0.785398,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  \/\/ 2\r\n{0,2.35619,2.35619,0,2.35619,2.35619,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  \/\/ 3\r\n{-0.785398,-0.785398,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  \/\/ 4\r\n{0.785398,0.785398,0.785398,0.12634,0.12634,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  \/\/ 5<\/pre>\n<p>Yes, with curly braces and everything.  I wrote code to make code, which I then copy &#038; pasted into a header file.  (The negative ones at the end of each line are used to mark the end of the list.  I did it this way because that keeps it consistent with how the marching cubes code works. (The stuff I swiped from online.) It wasn&#8217;t until just now that I realized this could lead to a bug:  Any walls that face due west (which would be a normal of -1, 0, 0) would end the list.  And yet, I&#8217;m not seeing any problem with western-facing walls.  Actually, why <em>isn&#8217;t<\/em> this a bug? Why does this system work at all? I&#8217;ll have to investigate when I&#8217;m done with this post.)<\/p>\n<p>Anyway. <\/p>\n<p>So when two cubes are beside each other, they need to share verts.  To make the surfaces nice and rounded, their normals must be averaged together.  Right now I&#8217;m just adding them together. Other programmers will notice that this should result in normals that are no longer normalized. I actually send the normals off to the GPU in this state, and have the vertex shader normalize them on the way in. <\/p>\n<p>I love that the GPU is so fast that it&#8217;s more efficient to have the GPU normalize them EVERY FRAME as opposed to having the CPU normalize them ONCE. It&#8217;s a mad world.<\/p>\n<p><table   class=\"\" cellpadding='0' cellspacing='0' border='0' align='center'><tr><td><img src='https:\/\/www.shamusyoung.com\/twentysidedtale\/images\/octant11_4.jpg' class='insetimage'   alt='octant11_4.jpg' title='octant11_4.jpg'\/><\/td><\/tr><\/table><\/p>\n<p>Am I really 1,800 words into this entry? Shameful.  Let&#8217;s wrap this up. <\/p>\n<p>You know, there are a lot of things I wanted to try once I got my hands on some shaders.  I wanted to mess with better lighting, maybe get some fog going. But I&#8217;m going to set this aside.  This project is about doing fun stuff, and mining forum threads and PDF files for basic information isn&#8217;t very giggle-inducing. <\/p>\n<p>I&#8217;m not sure why it&#8217;s so hard to find what you need with GLSL.  There are several versions of the help system for OpenGL itself, and they&#8217;re all pretty good.  Sure, they have a severe case of 1998 web design, but that&#8217;s actually a plus when you&#8217;re dealing with documentation.  But the GLSL pages have the usability of <a href=\"http:\/\/www.ioccc.org\/index.html\">obfuscated c<\/a> printed in wingdings. <\/p>\n<p>Let&#8217;s work on something else for now and leave the shader stuff for later.  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>The texture stretching on these blobs is pretty annoying. There&#8217;s no good way to fix this without shaders. So let&#8217;s use shaders. As I&#8217;ve mentioned before, shaders are special programs that run on your graphics card. It goes something like this: Now, that&#8217;s actually a simplified view. A more accurate flowchart is:<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[66],"tags":[233],"class_list":["post-15956","post","type-post","status-publish","format-standard","hentry","category-programming","tag-octant"],"_links":{"self":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/15956","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=15956"}],"version-history":[{"count":0,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=\/wp\/v2\/posts\/15956\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=15956"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=15956"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.shamusyoung.com\/twentysidedtale\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=15956"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}