Project Octant Part 11: Shaders

By Shamus Posted Wednesday May 23, 2012

Filed under: Programming 120 comments

octant10_16.jpg

The texture stretching on these blobs is pretty annoying. There’s no good way to fix this without shaders. So let’s use shaders. As I’ve mentioned before, shaders are special programs that run on your graphics card. It goes something like this:

octant11_1.png

Now, that’s actually a simplified view. A more accurate flowchart is:

octant11_2.jpg

And even this is a bit of a simplification. It leaves out things like driver layers. Unless something goes horribly wrong, I shouldn’t need to think about all that stuff. You generally don’t need to worry about drivers unless you’re working on the bleeding edge and getting really close to the hardware. I’m talking John Carmack distance here, where your code is so close to the hardware that the fan on your graphics card starts shaving off your eyebrows.

This means I’m going to have to write two new programs: A vertex shader and a pixel shader. (The later is called a “fragment shader” 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:

  1. NVIDIA cg. 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’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’s entirely possible that the cg shaders don’t work for the same reason that the Microsoft webpage doesn’t work in Firefox. Maybe not. Maybe it’s just a stupid bug that doesn’t happen on my machine. It doesn’t matter. The upshot is, we’re not using the NVIDIA toolkit for this project.
  2. HLSL: “High Level Shader Language”. This is the Direct 3D way of doing things. If you’re going for a Microsoft platform using Microsoft tools, then this is your go-to language. I’m using OpenGL, which leaves us with…
  3. GLSL: The “OpenGL Shader Language”. This is obviously the way to go for my OpenGL -based project.

Right off the bat, I can see something is wrong here. These docs on GLSL are an absolute mess. The wiki 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 “here be dragons” if not for the fact that the link to the map itself is a 404.

Searching for example programs isn’t very helpful either. There are two kinds of example programs:

  1. Ultra-simple test programs: Here is how to create a flat-shaded, un-textured, colorless, unlit polygon. These little three-line programs can’t teach you anything because they don’t DO anything.
  2. 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.

Which leaves us with forums. Here is how things work on programming forums:

ALLEN: Hi, I’m new to driving and I need to move my car back around 5 meters. How can I move the car backwards?

(2 days later.)

ALLEN: Hello? This is still a problem. I’m sure someone knows how to do this.

BOB: I can’t believe you didn’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.

ALLEN: But I’m not on a hill. I’m in my driveway and it’s completely flat.

CARL: Dude, I don’t know what you’re trying to accomplish, but you should never be driving backwards. It’s dangerous and will confuse the other drivers. See the big window in FRONT of you? That’s your first clue. Don’t drive backwards.

ALLEN: I’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.

CARL: So just drive in circle until you’re pointed the right way.

ALLEN: I don’t have enough room to turn around like that. I only need to move back a few meters. I don’t understand why this has to be so hard.

CARL: Sounds like your “driveway” isn’t compatible with cars. It’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’re doing something wrong.

DAVE: I see your problem. You can adjust your car to move backwards by using the shifter. It’s a stick located right between the passenger and driver seats. Apply the clutch and move the stick to the “R” position.

ALLEN: But.. I don’t have a clutch. And there isn’t a stick between the seats.

CARL: Sounds like you’re trying to drive in Europe or something.

ALLEN: Ah. Nevermind. I figured it out.

The other major source of help that I find is… PDF files. And not good PDF files either. These are stupid, primitive documents that take forever to load, don’t have hyperlinks, don’t allow copy & paste, and don’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’m looking for, I have to do another search inside this document to find the topic, and then read this infuriating mess to see if it actually has the goods. (It doesn’t.) Like all PDFs, my only view options seem to be “too tiny to read” or “waste 75% of my screen space”.

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’re a scientist trying to simulate the behavior of light on the quantum level, or that you’ve never seen a computer before. Sometimes they shift between these two assumptions within the same document.

Dear dudes who make PDFs for on the web: Please look into HTML. I promise it’s documented WAY better than the stuff you’re documenting.

You’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’t have what you need.

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 – once you know how. Hilariously, the manual pages don’t list them under “built-in variables”. And after searching around some more, I find there are actually two different 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’t know why there are two different sets of variables, how they differ, or how to use them properly. Hours later I’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 “GLSL texture coords” into Google, not embarking on some Professor Layton-esque adventure of inscrutable puzzles provided by unhelpful idiots.

So now I have something that works, and I PROBABLY know what I’m doing, but I don’t really have a clear working knowledge. For example, at one point I was setting values in the vertex shader and they weren’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 “work anyway”. Doing things this way is like taking Carl’s advice and paving my yard. It solves the problem while leaving me ignorant.

This is not a programming language. This is folk knowledge.

I spend hours fooling around, trying to find the information I want. I manage to get something working.

octant11_3.jpg

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:

static float norm_table[256][16] = 
{
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  // 0
{0.785398,0.785398,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  // 1
{-0.785398,0.785398,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  // 2
{0,2.35619,2.35619,0,2.35619,2.35619,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  // 3
{-0.785398,-0.785398,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  // 4
{0.785398,0.785398,0.785398,0.12634,0.12634,0.785398,-1, -1, -1, -1, -1, -1, -1, -1, -1, -1},  // 5

Yes, with curly braces and everything. I wrote code to make code, which I then copy & 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’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’m not seeing any problem with western-facing walls. Actually, why isn’t this a bug? Why does this system work at all? I’ll have to investigate when I’m done with this post.)

Anyway.

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’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.

I love that the GPU is so fast that it’s more efficient to have the GPU normalize them EVERY FRAME as opposed to having the CPU normalize them ONCE. It’s a mad world.

octant11_4.jpg

Am I really 1,800 words into this entry? Shameful. Let’s wrap this up.

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’m going to set this aside. This project is about doing fun stuff, and mining forum threads and PDF files for basic information isn’t very giggle-inducing.

I’m not sure why it’s so hard to find what you need with GLSL. There are several versions of the help system for OpenGL itself, and they’re all pretty good. Sure, they have a severe case of 1998 web design, but that’s actually a plus when you’re dealing with documentation. But the GLSL pages have the usability of obfuscated c printed in wingdings.

Let’s work on something else for now and leave the shader stuff for later.

 


From The Archives:
 

120 thoughts on “Project Octant Part 11: Shaders

  1. Stardidi says:

    I´m building my own D3D Engine / game stuff right now and have found a LOT of info on HLSL.
    As both HLSL and GLSL are compiled to assembly wouldn’t it be possible to find documentated HLSL code for your needs and compile it using FXC from DirectX or some other HLSL compiler and then import this assembly code into your OpenGL project?

    This is a slight pain but allows you to have an a lot of info on shaders, while using OpenGL.

    1. Bryan says:

      Except then it only works on the video card that the HLSL was compiled for. Cg has the same issue, if you build using wrong profile and then ship the binary shader code.

  2. Primogenitor says:

    Maybe this is the one case where dead trees have better documentation than t’interwebs?

    1. Chargone says:

      my (admittedly limited) experience is that, no matter the context, the paper documentation is Always better. right up until something gets patched or ‘upgraded’. then it’s useless. but you Know it’s useless (and, if you got lucky enough that there was a useful changelog, you even know which Bits are useless, can note that, and the rest’s still good!) … still seems like a step up to me :P

      that said, i’m an end user for consumer grade stuff, not a programmer.

      1. Felblood says:

        The shift isn’t really different on a fundamental level, but imagine that the changelogs are now longer than the manual itself and often require the sort of Google scavenger-hunt, that Shamus is talking about above, to locate. Assuming you don’t have to make it yourself by gleaning scraps of useful data from forum threads.

        Keeping your knowledge and documentation up to date can consume more time than actually writing code, even when you’re supposedly a trained professional.

  3. Kdansky says:

    PDF files: Don’t use Adobe Reader unless you absolutely have to. Foxit (conveniently found at http://ninite.com/) absolutely crushes it in terms of usability, size and speed.

    That -1 seems really risky.

    Normalize your normals when you generate the map. Really, it’s too easy to pass up. I can’t wrap my head around why your normal generation would take less than a few milliseconds.

    Programming questions: Stackoverflow. Google doesn’t page-rank individual questions well there, but I always search for my programming problems on Stackoverflow first. It’s the best resource, bar none.

    1. Shamus says:

      “Normalize your normals when you generate the map. Really, it's too easy to pass up. I can't wrap my head around why your normal generation would take less than a few milliseconds.”

      Because I’m normalizing thirty-five thousands of the dang things for every 16x16x16 bit of cubic space, of which there are hundreds.

      The CPU is maxed out, and the GPU is doing almost nothing. Why burn more CPU to save GPU cycles.

      And yes, Foxit is the way to go. I won’t even put Adobe on my machine.

      1. Shamus says:

        Correction: The thirty-five thousand number would only be true if I used every possible vertex. (Like, a 3D checkerboard pattern of solid and empty space.) Still, I need a lot of them.

        1. Rick C says:

          Could you write a shader that would be called once at program startup to just calculate your normals?

          1. MichaelG says:

            I read about code that does lots of work in the shaders at startup and reads it all back, but I’m vague on the details.

            I assume the shaders write their results to some kind of rendering target, and then you copy it all back to the CPU and decode it.

            1. Bryan says:

              Seems like you could ARB_render_to_texture up something, then read the values back out of the texture that got rendered to. The reading-back operation will be slow, but if you only need to do it once it might work out OK.

              You’d have to figure out a reasonable encoding though. Hmm.

            2. Simon Buchan says:

              Don’t need to read it back out of the card if it’s only shaders that will need to read it….

      2. Mark says:

        I prefer SumatraPDF. Its light on features but its very quick on older machines.

        1. Another vote for SumatraPDF. If all you want to do is read PDFs, it works fantastic. Simple, light program.

        2. Dave B says:

          I use SumatraPDF for almost everything. I do, however, keep Adobe installed for those rare occasions when I need an advanced feature.

          My favorite feature of Sumatra, by far, is its ability to save your place in a document and automatically go there the next time you open it.

          1. wererogue says:

            My favourite feature of Sumatra, about 3 years ago when I uninstalled it for good, was to render the occasional PDF entirely in black, every time.

            It left such a delicious sour taste in my mouth that I can’t risk trying it again in case it doesn’t taste as sour.

        3. Eric says:

          SumatraPDF trounces Foxit. Foxit is a bloated, slow pig by comparison.

          1. Rod Spade says:

            Another option is PDF-XChange, which works well for me.

            1. PDF-XChange is not as slick as SumatraPDF, but it comes with a lot more features for what it loses in speed.

      3. Chiller says:

        Thanks for the tip on Foxit, I’ve never liked Adobe much. This looks good.

      4. Simon Buchan says:

        You hinted that you had figured this out in a comment on the last post, but you should only be computing a few hundred normals: marching cubes has the nice property that the edges of each cube are flat, therefore normals are not effected by neighbors. Still, unless you’re using the x87 float instructions even millions of normals should be sub-seconds to compute. If you *are* using flat ‘float’: for shame! get a math library supporting SIMD instruction sets like SSE: GLM is a great OpenGL C++ library, and for DirectX, recent versions of the DirectX (eg. Windows) SDK folded in the XNA Math library, giving you a pretty kitchen-sink set of tools (look for DirectX::XMVECTOR, DirectX::XMVector3Normalize()), all in-the-box for a recent Visual Studio install (perhaps not Express? Go grab the Windows SDK installer, in that case).

        Interestingly (to me), Windows 8 has a lightweight, fairly decent PDF reader built-in.

        Re: shaders, I found the Wiki to be fairly good about covering what you need to know, but it has the problem that you need to know enough GLSL to know what to look at and what to ignore.

        1. Shamus says:

          You’re saying I need to pave my yard to turn the car around?

          I kid. I’ve already got an entire toolkit of data types: 3D Vectors, color values, 2D vectors, matrices – and all the functionality to go with them: dots, normalizing, cross-products.

          So “download this other library and convert your entire 3D graphics system to use it, then adopt all your other code to use the new types” is not a trivial thing. I’d need to believe that there would be some huge payoff in speed before I’d be willing to do that.

          And I’m not sure what you mean about cubes not having an impact on their neighbors. I can turn off my normal stitching and see a whole mess of seams. The trick here is that your don’t need to merge normals if you want faced polygons, but if you want it to look like rounded, lumpy surfaces then you need to do stitching.

          1. Demo says:

            It is the case that there’s a finite number of possible orientations for the verticies in the same way there’s a smaller finite number of orientations for the faces, so you /could/ pre-calculate all you normals and just use a lookup table as you are doing for polygons.

            That being said you would need to take more care than you seemed to when doing the polygons in marching cubes, since if you tried to just brute-force it you’d need to look at 2^18 combinations. Considering symmetries would probably bring that number down to something manageable, but I’ve honestly no idea if it’d be quicker than what you have already.

            1. WJS says:

              2^18 isn’t manageable? That’s only about a quarter of a million. Compared to the multi-million counts that you get by not precalculating, I don’t see the issue.

          2. Simon Buchan says:

            :D I’m not going to *tell* you to do anything, it’s a for-fun project after all. (Damn internet, why can’t I put light-hearted ribbing in text?) I’ve not used GLM terribly much (more of a Direct3D guy myself), but it’s pretty easy to use (header only, exploits the heck out of C++ to make things work like GLSL), even if the headers are scary as all hell to read. If you’re curious about SIMD vs x87, I’ve seen 400x performance differences in certain edge cases, but I threw together a quick performance test, and naive normalize is only 3x slower than XMVector3Normalize(), though XMVector3NormalizeEst() is 30x, and good enough for graphics by far. But even my naive normalize() was chewing through 100 million vectors in 3.4 seconds, so I’m not sure why you’re seeing a performance problem just normalizing them.

            Right, yes, I forgot that you’re not doing the standard faceted faces, so yeah you do need to look at neighbors. In fact I’d guess that’s why you’re seeing a performance issue: the random jumps around in memory as you look at neighbors is probably trashing your CPU cache. You could probably pretty easily parallelize it, though…

    2. Rick says:

      Foxit is indeed great, but they’re starting to get carried away. Who needs Facebook sharing in a PDF reader?

      1. Blake says:

        Yeah I used to use Foxit but it got too big. SumatraPDF for me now.

  4. mac says:

    Instead of scrolling through a document, you have to scroll down, turn page, scroll up again, then back down, then turn the page again.

    Can’t you set your pdf viewer to ‘continuous’? So scrolling off one page brings you onto the next….

    I’m loving this series, by the way.

    1. Halceon says:

      That only works if the document is single pages itself. Sometimes people are so hung up on their dead trees, that they even make digital content in the form of a 2-page spread.

      1. Unbeliever says:

        To be fair, the entire purpose of the PDF format is the electronic capture of dead-tree data.

        If there’s any format where a person might safely assume their end-user would be printing the result, it would be PDF…

  5. Benjamin says:

    I happen to be nearing the end of a course on shader programming using GLSL. You may not need it, but I’d be happy to help in any way I can the next time you work with it, syntax or otherwise.

    Since I bought it for the course, I have the OpenGL “orange book” (the shaders bible) at my disposal, but I found this site to be a good (freely available) starting point. (Tradeoff: some of the function names are deprecated, and there are some typos in translation. They should be reasonably easy to recognize and correct.) The orange book has some good example code for different lighting types and other techniques.

    1. Bethor says:

      I’d suggest reading through good, modern tutorials such as this : http://www.arcsynthesis.org/gltut/ instead of nehe.

      To be honest, I’d actually suggest shooting yourself in the foot while setting yourself on fire over nehe. It’s horribly outdated and will cause exactly the headaches Shamus is describing, because it will tell you to use things like builtin variables that have been deprecated for 2-4 years at least.

      1. Benjamin says:

        That seems to be a better resource. Thanks.

        Still, Nehe isn’t as horrible as all that. If you use it, you just have to take it in with a grain of salt. Like many internet resources, it’s not ideal, but can work in a pinch.

      2. Matt says:

        Thank goodness some one mentioned this site. It really is a life saver and in a perfect world would be at the top of the google search results for OpenGL and glsl.

        That said the main reason for all the seemingly random answers to the same question probably has a lot to do with the fact that there are basically three “types” of glsl programs right now. You have “legacy” programs that had to play nice with the fix function pipeline, the “modern” programs that have completely left behind the fixed-function cruft and are instead working toward shader nirvana, and the “mobile” OpenGL es 2.0 programs that are somewhere in between, deprecating a lot of the crap from the legacy days and trying for fresh clean API for the modern mobile graphics gurus.

  6. Shamus’ Howto Guide to 3D Game Programming: $39.95 – if this existed, would sell a million copies. especially if you included the really nice new graphic illustrations you’ve been doing of late.

    1. CrushU says:

      Seconded.

      Use your writing skills for good, Shamus! Create documentation! ;)

    2. Dave B says:

      I look forward to its companion book: Documentation Procedures, or How to Explain Something to an Idiot (Who might be you someday).

    3. psivamp says:

      I’d buy it. Heck yes, I would buy it.

  7. Mephane says:

    ALLEN: Ah. Nevermind. I figured it out.

    Oh how I hate that. I have run into that very situation so often, it is always infuriating. Can’t people at least provide the very information they were looking for and eventually figure out themselves? Don’t they see that if it was a lot of hassle for them, it will most likely be to some other people?

    Really, do people not think even that far?

    /facepalm

    (P.S.: stackoverflow.com is the exact opposite of that situation and absolutely awesome, but still it happens often enough that a particular problem has not been tackled over there)

    1. zob says:

      that and this, the usual soul crushers of the internet.

      1. Mephane says:

        Sometimes I think xkcd has either the answer to or at least a funny comment on literally anything. :D

      2. Eruanno says:

        I was just thinking of that XKCD as I read that :P

    2. Philpax says:

      It’s obligatory xkcd comic time! Wisdom of the Ancients

      edit: aw, ninja’d

      1. Irridium says:

        Well it seems we haven’t posted that Penny Arcade strip yet, so here it is

        1. Rick C says:

          Wouldn’t This Penny Arcade be apposite as well?

        2. Sumanai says:

          The “you’re using X? You fool! You should be using Y!” is one of the most infuriating, since I don’t think I’ve ran into a single case where the opposite hasn’t happened.

          “You’re using single ply toilet paper? You should be using double ply so you don’t need to wrap it up!”

          “You’re using double ply? You should be using single ply, it’s cheaper and you just need to wrap it up a few times!”

          It gets even worse when the person doesn’t mention the Y, so if you’re not aware of any competition, you have nowhere to go. I ran into that kind of a comment when looking for a good AA-battery charger.

          1. X2Eliah says:

            Clearly your issue is that you are using AA batteries. Get with the times, everyone should use portable mobile solar panels with lithium selfcontained powerreserves. Better yet, look into setting up your own wind turbines with a short power relay, that should save you money in the long run (like 50 years or so). AA battery charger? Oh please.

            1. Sumanai says:

              Oh god, yes. Back when I used Debian GNU/Linux (around 2002) nearly all the solutions I found online was compiling a newer version of the software myself. This peaked with a suggestion to compile the kernel.

              For those who don’t know: At least back then the team behind Debian had three versions and the one titled “stable” had old versions of the software and when updates came they were often a year behind the release of the source code.

              Also compiling, at least back then, was not easy. It should have been a simple case of making sure dependencies were fulfilled and entering “./config && make && make install” (IIRC) to the command prompt, but the errors were often nonsense and it always came up with an error.

              1. WJS says:

                Yeah, compiling a newer version yourself does work, but if you want up to date software, a better solution would be “use something other than Debian”. If you think that it taking a year for software to be considered stable is unreasonable, then Debian is clearly not the distro for you. It’s real niche is in a server environment, where stability is much more important than having the latest shiny bells and whistles.

    3. krellen says:

      This is how I feel when looking for bizarre hardware/driver issues too. Those damn forum threads with no answers, and always ending with that “NVM, figured it out” post.

      1. Duncan says:

        The worst ones are when it has another post at the end, usually six months old, which just reads “hey I am having this exact same problem, what was the solution you came up with Allen?”.

        I think doing this should be a bannable offense. Even when the solution to my query ends up being “don’t be an idiot like me and declare your loop counters inside the loop”, if people can just skip to the end and see a summary of the solution it saves them a lot of time even when it is not the solution they are looking for.

        One way of dealing with the more general problem of how to get good information is talking to people who know in real time. I often look up irc channels called #GLSL or something. Sometimes that just means unhelpful idiots can be rude and unhelpful more directly, but at least it is faster, you can be in and out in a couple of minutes.

        1. MatthewH says:

          I sometimes wonder if “nevermind, I figured it out on my own” is really just a case of face-saving/butt-covering. “Well gee, the collected wisdom of the Internet can’t figure it out, and they’re being rude about it. I’ll just say I solved the problem and they’ll all leave me alone.”

          1. Dave B says:

            It’s also possible that they did actually figure it out, but they’re afraid that if they post their solution, someone else will tell them it is wrong and stupid.

            1. decius says:

              I once got deleted from a forum for posting how I fixed a problem.

              Granted, it was an official forum, the problem I was having was with copy protection, and the solution I found was to not run the copy protection…

            2. Mephane says:

              I would rather attribute to laziness and/or a lack of empathy for others who might have the same problem.

        2. AnZsDad says:

          This is one of the things that tools like Yahoo! Answers gets right. The person who posed the question chooses the “best” answer. That is helpful.

    4. Tharwen says:

      +1 for Stack Overflow

  8. X2Eliah says:

    Soo.. Are nVidia’s and DirectX’s shader languages likewise horrible as per documentation, or is this a consequence of glsl being, y’know, open source?

    1. Peter H. Coffin says:

      There is a level of proportionality between how much you pay for software (including development kits) and how well it’s documented. But the number of users of the software also influence. Roughly this works out to

      documentation_richness = num_users * (avg_installation_price + 1)

      Therefore, you get really good doco out of IBM, SAS, and MS (and half of Oracle) because the average seat cost is pretty high, and fairly good doco out of PHP, and MySQL and Java (the other half of Oracle) because there are a lot of users. But if you’re trying to write something for an open-source API for an out-of-production media player device or something similarly both rare and cheap, you’ll be spending more time researching how to write anything for it than you would writing ten things that use (for example) Apple Accessory Protocol.

    2. nmichaels says:

      OpenGL is open source and doesn’t have horrible documentation. It’s likely a consequence of it being less popular and not the sort of thing most hobbyists use.

      1. X2Eliah says:

        OpenGL is open source and doesn't have horrible documentation.

        And yet Shamus has written nearly 2000 words about how the shader code FOR OPENGL has absolute crap for documentation. It’s on his blog, you should look it up.

        Idk about the true technicalities, but it seems to me that the way you write your shaders is pretty damn important when you have to deal with opengl. Especially if it mandates a specific native coding language.

        1. nmichaels says:

          Whoah there, captain hostility. Maybe you should read the end of that rant for yourself. “There are several versions of the help system for OpenGL itself, and they're all pretty good.” I was just pointing out that open source does not imply crappy documentation. I was not arguing that GLSL was well documented, or that documentation was unimportant. I also was not trying to start a flame war.

          1. Alex the Too Old says:

            I also was not trying to start a flame war.

            And yet you called him “captain hostility”. Have you ever known an angry person to have a sense of humor?

            1. Mr Guy says:

              Hey, dude, I don’t know or care how old you are, but where do you get off saying anyone who’s ever gotten angry can’t possibly have ever had a sense of humor?

            2. X2Eliah says:

              Captain Hostility SMAAAAASH. RAWR SO ANGRY.

              For the record, I am deeply amused by this moniker.

              Who wants to be my sidekick, Trollboy? Underpants-on-outside is mandatory dresscode, I’m afraid.

    3. seven800 says:

      GLSL has really good documentation, it’s just not legally available for free on the internet. The Orange book is an excellent reference, and very readable to boot: OpenGL® Shading Language (Randi J. Rost)

  9. isamaru says:

    Shamus, please continue writing this series. I am writing this so you know that you have readers who enjoy this. :)
    I am a programmer who NEVER wants to deal with graphics and low level details like this, which is why this helps me so much. Once I have to work with colleagues who do, I won’t be for a stupid idiot who has no idea what kind of problems they face.

    1. Mephane says:

      And I am a programmer who always has some ideas of his own what to do in regards to 3D programming, but the more he learns about the more he does not want to spend his time with all of the hassle*. Personally I am most interested in data structures and algorithms themselves, but some of my hobby project idea would definitely require some level of 3D visualization to make any sense at all.

      *By which I mean all that library/driver/dependency/documentation kerfuffle. I don’t mind the math (heck implementing math can be quite fun, too), but when I am doing a hobby project the least thing I want to do is spend entire weekends figuring out how to do stuff that should nowadays be relatively simple.

      1. nmichaels says:

        Nobody wants to deal with the hassle parts. I would bet that they are the main reason for projects to fail before they get started.

      2. Simon Buchan says:

        People give it shit, but I totally recommend trying Direct3D 9: you can get graphics on the screen with less than a page of code, so there’s far less to go wrong, and you can slowly ramp up adding textures, shaders, animation, etc…. You don’t have to find and figure out any external dependencies, and the API uses types to lead you to what you can do with what, which I find far less confusing than trying to figure out what I have to have bound (or *not* bound!) for something to work in OpenGL. As a production API, OpenGL is fine, but it’s a total pain to learn the first time, especially on Windows. And don’t worry about “wasting time”: knowledge is pretty easily transferable between the two, there’s not much risk of lock-in in that sense (so long as you stick with the non-deprecated parts of both, of course).

    2. SteveDJ says:

      Don’t people see it? Shamus is going to “edit” his post here soon, with the same “NVM, figured it out”… and then we will never hear from Shamus again… :-)

      I, too, enjoy reading these articles. And this one in particular, with that forum example (including troll typos), was truely excellent writing. Keep up the good work, Shamus!

  10. Nick says:

    I’m loving the series, especially since this is something I’m going look into soon. But… were the GLSL examples in the WikiPedia page (and those linked to by it) not any help?

    1. Shamus says:

      Sure, they were helpful. But they’re not a proper reference document. No fog, no texture coords, no sampling, no passing user-defined types (uniform, varying, flat) between shaders. You just have to read dozens and dozens of programs, looking for one that does what you’re trying to do. This means unraveling stuff written by other coders and figuring out what variables are built-in, what variables are set through GL as parameters, and what variables are just “local” to this shader.

      You can spend a LOT of time doing that in order to find something that should, in a sane world, have a single, clear manual page on the reference site.

      1. Nick says:

        Right. I probably won’t bother with those too much, then…

      2. Simon Buchan says:

        The only non-deprecated builtin variables (AFAIK) are here: http://www.opengl.org/wiki/GLSL_Predefined_Variables. Current recommendation is to use Vertex Buffer Objects and Vertex Attributes to define your own inputs, so no input position attributes and friends. This is, of course, confusing as all hell for OpenGL veterans like yourself! Take a look at this lot for more details on (the much more flexible!) new methods http://www.opengl.org/wiki/Category:Core_API_Ref_Vertex_Arrays

  11. nmichaels says:

    I’d love to know what exactly the shaders do. I see the before and after pictures, but I’ve got no idea why the before was messed up the way it was or how shaders helped it become after.

    1. Pete says:

      Shaders are just programs that run on your graphic card. You feed the GPU some data (vertex or pixel) and it does some transformation on them. This is faster than using the CPU since GPUs are very good at math and parallelisation (the price for this is that using any branching logic completely kills the speed), and vertex/pixel data is by its nature mostly indepentent of each other (so you can work on all of it at once instead of in sequence)*.

      *Keep in mind that is is the probably-wrong understanding of someone who is yet to dabble in any 3D programming whatsoever.

      1. nmichaels says:

        I get what shaders are. I want to see the story of the shader that fixes this problem as explained by Shamus with fun graphics and silly broken screenshots and good explanations of transformation matrices.

  12. supermank17 says:

    I just wanted to put a quick word in on nVidia CG and Project Frontier: I don’t know that your use of CG shaders is the cause of the graphics glitches people are seeing. I’m running into the same issues (purple foliage, polygon artifacting, etc.), and both of my PCs are using nVidia GPUS. Admittedly, one of them is older (8800 GTS).

    1. MichaelG says:

      Frontier fails the same way on my NVidia GTS 250. I don’t think it’s a CG problem.

      1. Tharwen says:

        Me too. Clearly Shamus just made the trees purple to troll us.

  13. Hitch says:

    That’s why you don’t listen to Carl. A clutch and a manual transmission are much more of a European than an American thing these days. But Carl doesn’t realize that, so he’s never going to be any help.

    I always feel like PDF web pages are put up by people who still think “this silly web nonsense” will never catch on so there’s no need to waste money hiring some punk kid to write that stupid HTML stuff that’ll be obsolete the moment everyone gives up on this foolishness.

    1. nmichaels says:

      Most PDFs on the web started life as academic papers or presentations that needed to be in print form. PDFs are much better for dead-tree layout control than HTML. People just need to run latex2html on the sources instead of posting the pdfs.

    2. Volfram says:

      Reading this a year ago, yeah, Carl is a bloody idiot.

      But then I realized that in cases like this, I’m usually that idiot Carl. It was a very humbling realization.

  14. Daemian Lucifer says:

    “This project is about doing fun stuff, and mining forum threads and PDF files for basic information isn't very giggle-inducing.”

    Speak for yourself.I had a nice laugh out of this article.

    1. Yar Kramer says:

      I thought the point was that Shamus didn’t.

      1. WJS says:

        Well he should have been more specific then, shouldn’t he? :P

  15. Justin says:

    When I finally shifted from the fixed to the programmable pipeline, I picked a specific version of OpenGL and used only the functions in the core profile. In my case, I chose OpenGL 3.3 which is basically the modern interface (more recent versions have been primarily additive) and has a synced GLSL version (#330). Then I went out and got the Core Profile spec and the corresponding GLSL Spec. I read both documents completely through–in the past, jumping around to find what I thought I needed had left me ignorant of a number of things. Finally I got the quick reference cards, which you can print out and put on the wall next to your computer.
    All in all, it was quite an investment to make before starting on a project, but I feel like it paid off for me.

    1. Shamus says:

      Thanks for the link to the spec. That’s the best resource so far.

      1. Kyte says:

        http://www.arcsynthesis.org/gltut/index.html

        It’s a tutorial rather than a reference, but it’s very comprehensive and centered on OpenGL and GLSL. And unlike most tutorials, it’s for modern OpenGL.

        EDIT: Wait, why did it post it as a response? I refreshed the page to make it a normal reply!

    2. I love that it’s a 12-page “quick reference card”

      1. Kian says:

        It’s quick compared to the thousand page full manual. It’s actually a pretty awesome resource.

        It quickly tells you what is core and what is compatibility, and gives you the declaration of every single function in both the OpenGL API and the GLSL. I’m surprised they managed to pack that much information in twelve pages, and still make it readable and informative.

  16. Kian says:

    The OpenGL SuperBible 5th edition actually comes with tutorials that guide you from super simple to more complex shaders, pretty well documented and in small increments.

    The book isn’t online that I know, but you can download the example code (for windows, mac and linux) from here: http://www.starstonesoftware.com/OpenGL/

    It also comes with some handy matrix functions. I recommend the book for people getting started on graphics, but for someone more experienced the code alone is a godsend.

    I hope it helps you.

  17. StephenCEI says:

    I might actually be able to be useful here!

    This link has the course notes, slides, and examples from the shaders course I took last term. It starts with the basic graphics pipeline, but goes all the way up through vertex, fragment, geometry, and tessellation shaders. Don’t worry, you don’t need a textbook to make sense of it:

    http://web.engr.oregonstate.edu/~mjb/cs519/

    Also, if you’re going to experiment with shaders, GLman will be very useful:

    http://web.engr.oregonstate.edu/~mjb/glman/

    It’s like Renderman, but for OpenGL. And free.

    !!!Also, this:

    http://www.khronos.org/files/opengl41-quick-reference-card.pdf

  18. Dev Null says:

    Which leaves us with forums. Here is how things work on programming forums:

    Thank you for articulating this week’s rage at forums for me. Yesterday I finally gave up on the thread asking the Microsoft community for documentation of the format of some things that its storing as XML. Its XML; there’s obviously a schema definition for this thing somewhere that they’re using to produce and validate it. Do you think I could get a copy? Or do you think I got a lot of condescending pats on the head from people essentially saying “Oh end users are FAR too stupid to be allowed near XML…”

    This morning I searched for an unrelated issue about a binary file format. Miracle of miracles, I found someone had asked the exact question I wanted to know the answer to on some forum! Alas, the reply thread looked like a template for the example you used above, and no one ever answered the question. To add insult to injury, it turns out that the original poster was me, two years ago, the last time I stumbled over this issue. (And if I ever found the answer that time, I never came back to the forums and posted it, which would make this some kind of karma…)

    1. MichaelG says:

      Damn those past versions of me! So inconsiderate.

      1. Yar Kramer says:

        I know what you mean! Actually, I can’t decide who’s worse: past-me, who’s an ignorant putz, or future-me, who’s an overbearing know-it-all.

  19. Aquin says:

    Man. I went through exactly the headaches you described (PDFs and all) trying to figure out GLSL on my own. It was a nightmare I’d rather not repeat. I’m terrified of the day when I need shaders again, but it’ll have been too long since I last used them and I’ll need to start from scratch.

    It looms, oh Vishnu, it looms. -_-

  20. MatthewH says:

    I believe this is a universal problem. I remember a book I read in college War for the Everyday which I almost certainly totally misunderstood. I remember a chapter devoted to the late medievals and their obnoxious habbit of not documenting the basic stuff. “This is how we get the warhorses from the stable to the battlefield” never appears in the records. The authors comparison was to someone in the far future reading about our logistics and thinking the HMWV must be some type of magical incantation because we never pause to point out that it is a wheeled, off-road, four-wheel drive truck. Rather, we just say “the supplies are transported by HMWV.” Logistics was the the science of figuring out that maybe this wasn’t magic. (Though this might be me misunderstanding the book.)

    In my own field, I use statistics software all the time, and when I first started out I could not find -anywhere -basic instructions like “how do I get the data into the machine.” All the tutorials either provided the data ready-formatted or had me type the data in manually. Run into the same problem with Geographic Information Systems -everyone assumes you have the data already in the machine. A colleague finally pointed me to a good tutorial -which should get more google love than it does. (For those of you working with statistics -Carolina Population Center is great.)

    Even in my own work, I have pages of documentation I’ve produced -most of it helpful -but then there are places where I’m not sure what I was trying to do or how this procedure helped.

    I come to believe this universal tendency is the result of thinking “I know what I’m doing” and not thinking “how would I explain this to someone who has no idea what I’m thinking?”

    Might be why teachers teach best the subjects they are still learning.

  21. Christopher M. says:

    But – but – but – shaders are so much fun! One line in the vertex shader to make trees move in the wind; three dozen in the pixel shader to make volumetric shadows; and Heaven forbid you want to use branch statements in a shader model other than 2_x. Make a typo, and all of your trees go bright white. And good luck figuring out how anyone else made crepuscular rays work at better than 20 FPS.
    But once you get past the frustration, there’s nothing in the world better than seeing the end result come spectacularly to life. You just have to get there first.

  22. Rod Spade says:

    The fun C++ way to generate static tables is with template metaprogramming. “Fun” like solving a puzzle, not fun like just getting it to work right now.

  23. Velkrin says:

    Your example is missing one common occurrence in those sorts of threads:

    “I use X all the time, but I never have that problem.”

    I hate those people so very, very much.

    1. Dev Null says:

      Someday I’m going to find that guy and introduce his testacles to my knee.

      Than I’m going to say “I don’t know what you’re whining about: I use testacles AND knees all the time, and _I_ never have that problem.”

      Then I’m going to laugh hysterically til the nice men in the padded station wagon come to take me away…

  24. Tse says:

    About PDF files… I love them, you can make them compatible with every Adobe program (preserving editing capabilities), the resulting file can not be changed by mistake during printing, they are self-contained (don’t need external fonts) and can save all data used in the making of the file (all layers and vector data). Whenever I print something I always use a PDF file. That said, PDFs have a specific purpose and that purpose is not being viewed on a monitor!

    1. WJS says:

      PDFs are quite workable as an ebook format. The problem is with PDFs which are scans of printed documents with no OCR, not ones that never left the digital space in the first place.

  25. Mr Guy says:

    I love living in the future with all our crazy future problems.

    There was a day where we had shelves of reference books long as the eye could see, on every topic we cared about. We’d wear them out with thumbing through them. If we had a problem, we’d find the right book, go to the index, and pray. We’d read the chapter really carefully, and if we were very lucky it would mention something that we could eventually use to figure out the answer.

    Kids these days with The Google and The Facebook and The Interwebs and such. If they can’t type a question into a box and get an immediate and satisfying solution to their specific problem, they get all grouchy…:)

    And that’s the way it was and we liked it!

    1. Mephane says:

      I think no one complains if there is an open question no one has an answer to, not even on the internet. The issue is when someone poses that question, people go in all ranting totally unhelpful stuff, and at the very end the original poster states they found the solution, but does not bother to mention what that solution actually was.

      In you analogy, you would find a book with a chapter that at first seems to handle exactly your question, then digresses heavily into other areas under the pretense that this is all somehow necessary (but instead has nothing to do with the question at hand), and then just ends with the sentence “but of course this has all nothing to do with the solution, which is far simpler” without every stating the actual fact.

      1. Mr Guy says:

        I’m incredibly amused you think I’m making an analogy.

        I’m describing what the industry looked like as recently as ~15 years ago. Before the internet was widespread. Heck, before Google. Back when everyone with a problem was an island.

        It’s amazing to me how incredibly, unbelievably awesome the internet is. And how incredibly it’s increased productivity. You got “Error -191902”? Google it, you’ll probably get the answer. Need to do something unusual in Java? You’ll probably find an article on point, maybe even a tutorial.

        I’m not ripping on Shamus here for being ungrateful. He’s working in something sufficiently obscure that The Interwebs fail him.

        But it’s amazing to me that we’ve come so far that it’s notable to find an area of technology where “just Google it” DOESN’T work these days…

        1. decius says:

          I’m bothered that anyone savvy enough to want to comment on this blog post doesn’t know -about- the programming reference library days of computing.

          What about bang paths? Doesn’t everyone know about them, even if they’ve never used one?

          1. X2Eliah says:

            Why can’t non-programmer people enjoy this blog post? Or comment on what Shamus wrote, at least in concept?

            Why are you bothered that people outside your pr0 elite old-time coder-grandpa circle are allowed and interested in this post enough to comment?

            P.S. Captain Hostility strikes again! Just to pre-empt the whining.

            1. John Lopez says:

              You better register that nick before I do. A Google search shows that (for unfathomable reasons) that Captain Hostility isn’t a commonly used nick.

        2. WJS says:

          Shamus is working on something sufficiently obscure that The Interwebs fail him.

          Um, Shamus was working on GLSL shaders. That’s hardly all that obscure. That’s one of basically two ways to do game graphics.

  26. Bryan says:

    It should work to get a GLSL program out of a Cg program, using cgc (from the Cg SDK that you already have :-) ) and the GLSL profile. At least, I’d expect that would be true; it works here (Cg-3.1-from-April).

    cgc -profile glslv -entry standard Shaders/vertex.cg

    dumps out a GLSL vertex shader based on the standard one from Frontier, and:

    cgc -profile glslf -entry clouds Shaders/fragment.cg

    dumps out a GLSL fragment shader. On the other hand, it’s not terribly easy to figure out what these are actually doing either, so maybe not.

    (There are also arbvp1 and arbfp1 profiles, but those look more like some kind of assembly, so probably not the best idea.)

    Edit: On the other hand, you got a link to the opengl.org spec PDFs, as well, so (except for the general problem with PDFs) that might be enough too. Good luck!

  27. sab says:

    With the multiple references to webpages, I got an idea. You should Totally port this to WebGL. How much more cross-platform can you get? Surely there are no caveats to be found there.

  28. Zeet says:

    Hello Shamus, I love reading about your little programming projects.
    I will agree that OpenGL is probably a little badly documented, but I think it has just as much to do with the fact that it’s documented for and by people who know the language a bit too well.

    Or it’s because OpenGL is in some very weird limbo where it’s all four versions at the same time. When starting out OpenGL it’s way to easy to begin writing slow openGL 1 code, because they are still supporting it.

    Either way, did you see http://www.opengl.org/sdk/docs/manglsl/?
    It’s a list of most the GLSL commands and variables available. But forgot some vertex attributes, but because openGL is in this limbo state, you can in some ways easily mix openGL 2.0,3.0 and 4.0 together acidently.

  29. Jarenth says:

    Now, this has been said a thousand times before, but I feel one more can’t hurt: Shamus, I am consistently amazed by your ability to properly explain highly complex topics with just a pretty image and a few lines of humor. I like to think I’m pretty good at explaining things myself, but when I look at that shader flowchart and try to image how I would go from that to that picture of yours, all my brain offers up in reply is how much I like cookies.

    String makeDecentExplanation(String originalProblem) {
    return “I like cookies.”;
    }

Thanks for joining the discussion. Be nice, don't post angry, and enjoy yourself. This is supposed to be fun. Your email address will not be published. Required fields are marked*

You can enclose spoilers in <strike> tags like so:
<strike>Darth Vader is Luke's father!</strike>

You can make things italics like this:
Can you imagine having Darth Vader as your <i>father</i>?

You can make things bold like this:
I'm <b>very</b> glad Darth Vader isn't my father.

You can make links like this:
I'm reading about <a href="http://en.wikipedia.org/wiki/Darth_Vader">Darth Vader</a> on Wikipedia!

You can quote someone like this:
Darth Vader said <blockquote>Luke, I am your father.</blockquote>

Leave a Reply to Tharwen Cancel reply

Your email address will not be published.