Logarithmic Depth Buffers and Problems of Scale (3D World Generation #9)

Поділитися
Вставка
  • Опубліковано 25 гру 2024

КОМЕНТАРІ • 133

  • @jackfrederiksen7979
    @jackfrederiksen7979 3 роки тому +93

    This is significantly more important than online classes.

  • @ZanCartoons
    @ZanCartoons 3 роки тому +49

    It’s going to be sad when you get the attention you deserve and can no longer comment back. Love the videos and would love to see more.

    • @simondev758
      @simondev758  3 роки тому +22

      Trying to respond, but man so many

  • @supermonkeywtf09
    @supermonkeywtf09 3 роки тому +17

    Fantastic presentation, this channel is just getting better and better; awesome work Simon!

  • @n8programs733
    @n8programs733 3 роки тому +5

    Was using a logarithmic depth buffer and needed to properly get world position in a shader. Your code was a lifesaver. Thank you!

  • @tomg0
    @tomg0 3 роки тому +13

    Your videos continue to inspire me! Thanks for all the work you put into making them. I have had horrible problems with z-fighting before when two planes were overlapping and almost at the same angle.

    • @simondev758
      @simondev758  3 роки тому +1

      Ah, did you get it fixed?

    • @tomg0
      @tomg0 3 роки тому +2

      @@simondev758 Yeah, I did, after a lot of searching around for a solution, pretty much the same as the way you did. I wish this video had come out back then, it would’ve been so much help...

  • @boredfish80
    @boredfish80 Місяць тому

    Half of what you say is way beyond what I understand (for now) yet it’s been a really fascinating series.
    I’m a backend web dev primarily, but always had an interest in further pursuing game dev. I just never considered JS could be a genuine medium for going this far.

  • @leontius5502
    @leontius5502 3 роки тому +3

    This is a lot like the Sebastian Lague coding adventures, but I like the fact that these videos are a lot more in-depth. Thanks for your pog content

  • @barthpaleologue
    @barthpaleologue 7 місяців тому

    The triangle wave trick at the end is next level! Thanks a lot for sharing your knowledge

  • @benmillions8961
    @benmillions8961 3 роки тому +2

    I just smacked my head into the sin wave? no, triangle wave? I guess, but not it. And derived a nice piece of code on a page about repeating noise textures.
    pointInRepeatingSpace = (originalPosition % (repeatingPeriod + repeatingPeriod)) % repeatingPeriod;
    which has solved the original jittery textures without causing the jaggy/strechy bits at the edge of the repeating period that the sin and triangle waves cause.
    source: ronja-tutorials 029-tiling-noise
    also side note: you're an inspiration!

    • @benmillions8961
      @benmillions8961 3 роки тому

      hmm, woke up this morning and found some streaky lines appearing where coordinates approached the repeating period, so I changed my repeating period to be a base 2 value (not sure if that helped), and changed to simply:
      pointInRepeatingSpace = originalPosition % repeatingPeriod;
      and the streaks are gone ... nope they moved to the location of the new base 2 value. I am not a smart man.

    • @simondev758
      @simondev758  3 роки тому

      Wait, so did this work or not? I love the simplicity here, really want to change my method if this is better.

    • @benmillions8961
      @benmillions8961 3 роки тому

      alright I think I just got it, and didn't just hide the problem from myself for the moment. So (position % divisor), gives distortion around axis 0, whereas the (position % divisor + divisor) % divisor) gives distortion approaching axis divisor. So I have just do both then test the absolute value of each, and use the original value, for the one that is lower in the absolute.
      And this seems to solved it.

    • @benmillions8961
      @benmillions8961 3 роки тому

      okay no, that just moved it again... hmm. this may be be a bust. But I feel like there's something here, so I'll keep going, will update if I find a good solution.

    • @benmillions8961
      @benmillions8961 3 роки тому

      it would appear that the issue with doing something like mod(position, 1024) is that when you get to the border the noise algorithm is trying to lerp between 1022 to 1023 to 0 to 1, and when it tries to bridge 1023 to 0 it (really rather gracefully) blows up, smearing textures along one axis or another. so a modification of the simplex noise algorithm is needed to make it understand that it too exists within a repeating period. Now I am not a math guy, like, I didn't do linear algerbra in school. So I'll hunt around and see what other tiling noise solutions are out there. The ronja-tutorials articles did have a relatively human-readable implementation of simplex noise so that seems like where I'll end up if I can't find an easier answer and have to write my own.

  • @altair5258
    @altair5258 3 роки тому +11

    So glad I found your channel, youre videos will be very helpful when I start my projects again after exams 😁

  • @superboy9431
    @superboy9431 3 роки тому +10

    Really good stuff there.

  • @VoidloniXaarii
    @VoidloniXaarii Рік тому

    The minute at 1:40 blew my mind on understanding not just depth buffer but also log & precision! Thank you so much! Ps: yes, I know I'm stupid but I take pride in trying to understand the universe nonetheless 😅 even over decades... Thank you so much

  • @butterfinger4393
    @butterfinger4393 3 роки тому +7

    You make it look easy

    • @simondev758
      @simondev758  3 роки тому

      Ideally after the explanation, you also think its easy.

  • @indycinema
    @indycinema 3 роки тому +5

    This is exactly the kind of content I need.

  • @codingsharma2550
    @codingsharma2550 3 роки тому +1

    My little brother is your huge fan, he is 13 years old... I don't know what much about programming but I appreciate your work... Keep it up 👍

    • @simondev758
      @simondev758  3 роки тому

      Awesome, hope he learns a lot from these!

  • @ToothlessXDIn
    @ToothlessXDIn 3 роки тому

    Video by video you are educating something's we never learned in our life(both academic/self thought,i am kind of both). I wish you are teacher when i started learning programming. Quality over quantity.
    Thank you from bottom of heart.

  • @therajloonaticproductions2574
    @therajloonaticproductions2574 3 роки тому +1

    I really appreciate these videos. This is a thorough level of detail. Keep it up.

  • @bigmistqke
    @bigmistqke 3 роки тому +1

    Amazing content. Binged all ur content in one day. So many little nuggets of information I would never ever find otherwise. Thank u so much! As a request I was hoping if u could cover how to do raycasting and how u would be able to 'walk' on a vertex-shader displaced mesh.

    • @bigmistqke
      @bigmistqke 3 роки тому

      Or like how does raycasting even work on a shader level? And more generally: how to get information out of a shader?

    • @simondev758
      @simondev758  3 роки тому

      What do you mean by "walk" on a vertex-shader displaced mesh? Do you mean apply a vertex shader to say, some terrain to generate a heightfield, and then put a character on it?

  • @TomTom-du5qv
    @TomTom-du5qv 3 роки тому +1

    Nice stuff man, I ran into all these problems when testing large distances. Initially I used log depth and wrote to gl_fragdepth, I later replaced this with a reversed Z projection matrix, then I switched my camera code over to double precision and then used double precision throughout my shader pipeline. It worked but man it hit performance hard.

    • @simondev758
      @simondev758  3 роки тому

      Nice! Was that in openGL or webgl? I thought the reversed-Z trick didn't work in OpenGL because of the NDC space bounds, and you needed an extension to change that.

  • @djpeterson7479
    @djpeterson7479 3 роки тому

    I've been dealing with these problems for a while now. It's cool to see new solutions. I'm doing everything through Unity which is a bit of a bummer because though I could technically fix all my problems with what you presented, I'd have to throw out pretty much all my current materials, it appears. Still, I've been considering rewriting my old engine one day and might take these ideas and implement them in there. Great video!

  • @marcospampi7154
    @marcospampi7154 3 роки тому +1

    There's a Unity' conference about Kerbal Space Program and how they solved z-clipping, and basically works pretty well for Kerbin being 600km in radius, they've opted for 4 to 5 render targets: sky and far space, far planet, near planet, iva (optional) and UI; no logarithmic depth buffer mentioned.
    Basically the second render has a far from player near plane, while the third renders what's nearby ( less than 1 km I guess ); sky, well renders the kerbol system and the atmosphere.
    Anyway, great awesome stuff!

    • @simondev758
      @simondev758  3 роки тому +1

      That sort of multi-stepped approach is what Outerra (the ones who wrote up the log depth buffer thing) used before they figured out the log depth trick.
      I like the log depth because it's simple, doesn't introduce any complexity in the way the scene is handled, kinda just scales. Whether or not Kerbal had a good reason to use their approach, no idea, but if I find out I'll definitely make a video on it :)

    • @marcospampi7154
      @marcospampi7154 3 роки тому

      @@simondev758 well, the only reason I could think of is the broken texture effect, anyway it'd be perfectly fine having two cameras instead ( near linear, far logarithmic ), they maybe have thought it was simpler this way.

    • @marcospampi7154
      @marcospampi7154 3 роки тому

      ​@@simondev758 sorry if I spam you, but there are two interesting articles about map generation in this blog: www.redblobgames.com/
      Namely, Polygonal Map Generation and Tiling a sphere with Voronoi, which are very interesting, they are worth reading.

  • @Skeffles
    @Skeffles 3 роки тому

    Really enjoyable explanation and the planet is looking great!

  • @ZParodie
    @ZParodie 3 роки тому +1

    You're a madman, I love ur video
    Ty for the great content

  • @HuynhLuong227
    @HuynhLuong227 2 роки тому +1

    great!!!, very thanks Simon

  • @hamzzashaffi
    @hamzzashaffi 3 роки тому +3

    Thanks for such a great video, Simon! :)

  • @Huitretf2
    @Huitretf2 2 роки тому +1

    Thanks you for your work. It helped me well !

  • @Learnbynet
    @Learnbynet 3 роки тому +2

    hi , did you have a video to learn Entity-Component-System ? i see only video about javascript ? did you have one video where you talk in deep about this ?

  • @Jianju69
    @Jianju69 3 роки тому

    This is EXACTLY the video I was looking for! Thank you!

  • @VoidloniXaarii
    @VoidloniXaarii Рік тому

    Thank u so much. You're so amazing and so generous ❤

  • @cylam9188
    @cylam9188 3 роки тому +2

    Man, you should work in ThreeJS!

  • @zemlidrakona2915
    @zemlidrakona2915 Рік тому

    Here's what I did for Z-fighting which has worked for me. I basically try to touch the Z numbers as little as possible after converting them to view space. First I took the projection calculation out of the matrix since it appeared to cause some instability at very long ranges. I just do this in a post step. For the final divide I just pick a very large power of two since that shouldn't touch the mantissa bits at all. So far this has worked at millions of kilometers. You do need a good LOD system however.

  • @Rococo_
    @Rococo_ 3 роки тому +1

    I watch this man for his beautiful voice

    • @Rococo_
      @Rococo_ 3 роки тому +1

      and the tutorials too

  • @emanuelsiu1232
    @emanuelsiu1232 3 роки тому +2

    Your content is so eye opening. You address so many topics I’ve been curious about as a novice game and web developer. Unfortunately there are a lot of core concepts and algorithms you mention still fly over my head. Do you have any recommendations on how/where to get started for these base fundamentals? Like how did you start your career, because the way you handle yourself is way more advanced and experienced than any ol google search will do.

    • @simondev758
      @simondev758  3 роки тому

      Any particular things I said? That way I can get a better idea of which way to steer you.
      As for me, how I started? I'll probably answer that more in a future video, but I got a bsc. in computer science, self-taught all the gamedev stuff to start, worked at major studios for about a decade, mostly as graphics/optimization, learned a lot, did another long stint at Google, again on performance. A lot of this info is out there, but hard to find, especially if you don't know what to look for.

    • @emanuelsiu1232
      @emanuelsiu1232 3 роки тому

      Awesome, thank you! (TLDR version below) As far as what you said in this video I couldn't keep up with the math around z-buffers (not because I can't do math, lol). I actually do want to know the details behind it all. I've worked in Maya, Blender, Unity, and Unreal for 5 + years, but they pretty much have everything done for you when it comes to models/graphics/optimization/renders. BUT, over the past 3 years, I've become a certified Full-Stack web developer and general programmer and I wanted to marry my past skillsets to the web. I became very familiar with Javascript, landed in Three.js, then hit a wall when I no longer had the performance perks of unreal. A few high res models, 4k textures, and performance tanked. On top of that, I've never tampered with custom shaders or knew what is actually happening under the hood all the way to the roots.
      TLDR: Long story short - I want to make web apps with a perfect balance of performance and high-quality detailed artwork with all the bells and whistles (high res textures, shadows, reflections, etc.) and truly understand the deep underlying basics of graphics. But I have no idea what the limits are, or how to determine them, or how to bend them according to needs.

  • @snvoltorb
    @snvoltorb 3 роки тому

    Love your channel man! Thank you for the amazing content!

  • @Gnomek
    @Gnomek 3 роки тому +2

    Can you recommend entry-level design patterns for game programming?

    • @adamhenriksson6007
      @adamhenriksson6007 3 роки тому

      How entry level? Using good naming conventions and a clear file structure helps a lot

    • @Gnomek
      @Gnomek 3 роки тому

      State and architecture for example.

    • @simondev758
      @simondev758  3 роки тому

      +1 to that recommendation, seems to cover a lot of territory.

  • @system6379
    @system6379 2 роки тому

    Channels like this with high education always seen less popular.

    • @simondev758
      @simondev758  2 роки тому

      I'm pretty happy to have the audience I've built thus far, amazing this many people care what I have to say heh

    • @system6379
      @system6379 2 роки тому +1

      @@simondev758I love you. 🥰 Knowledge you are giving us free are priceless.

  • @NaiyoGames
    @NaiyoGames 3 роки тому

    holy shit, dropping knowledge again!! love it haha

  • @shadowjackal4827
    @shadowjackal4827 3 роки тому +1

    Big Brain. That's all I have to say.

  • @vectrangle
    @vectrangle 3 роки тому +1

    UA-cam suggested this video to me without me having watched the first 8, may I suggest you put a link to the full playlist in the description for others like me?

    • @simondev758
      @simondev758  3 роки тому

      Good idea, will make sure to do that from now on!

  • @AsciiKing
    @AsciiKing 3 роки тому

    These are fantastic. Thank you.

  • @Professor_Bugs
    @Professor_Bugs 3 роки тому

    This guy sounds a whole lot like Jim Keller :-)
    (If you read this Simon, you can take it as a huge compliment)

  • @bourbonbobo
    @bourbonbobo 3 роки тому +2

    This is really interesting but why not just use a saw wave as long as your texture tiles it should be fine right?

    • @simondev758
      @simondev758  3 роки тому +2

      That's interesting, I saw it but didn't try it. My problem is that the terrain isn't textured with uv's, but I'm using triplanar mapping using the world space coordinates. I kinda think the saw tooth pattern won't work since you have that dropoff instead of linearly coming down again, since the mapping + I've got some tiling pattern breakup code that uses gradient noise + world space position to break up the obvious patterns.
      I may need to revisit how the terrain is textured, maybe go fully procedural, but I'll try the saw pattern when I'm at home.

    • @bourbonbobo
      @bourbonbobo 3 роки тому

      @@simondev758 yeah as long as you run each of the world axes through it before any other processing it should probably work. Unless maybe your working with a large scale noise for variation but imo that's something I'd reccomend writing to the vertex colours if you can work it out because in this case they're going to be a lot better suited to large scale features without suffering floating point issues.

  • @Chevifier
    @Chevifier 2 роки тому +1

    Im gonna spend a whole day to learn this and convert it to GDScripting

  • @mike1hav
    @mike1hav Рік тому +1

    I wish I could translate maths into code that easy!

  • @Thinzy
    @Thinzy 3 роки тому

    awesome stuff man

  • @-abigail
    @-abigail 2 роки тому

    I don't know if it's available in the browser but if you can set the texture wrap parameters to GL_MIRRORED_REPEAT then that implements the triangle wave sampling in the sampler itself.

  • @emapta862
    @emapta862 3 роки тому

    Hey, had a question....
    I've trying to download some fbx files from mixamo and apply them in the third person camera, but, the models appear very blur in the browser,....what shall I do to get them loaded fully..?

  • @salvagaming4678
    @salvagaming4678 3 роки тому

    Great video

  • @Biel7318
    @Biel7318 Рік тому +1

    maybe chainsaw mapping instead of triangle, so instead of repeating the inverted texture you just repeat the texture uninverted?

  • @danielgrizzlus3950
    @danielgrizzlus3950 5 місяців тому

    Do I have to implement this if my engine allows a reverse z depth buffer?

    • @simondev758
      @simondev758  5 місяців тому

      Hard to say, it gives a similar effect, but without testing, you won't know for sure.

  • @thomaseichler2368
    @thomaseichler2368 3 роки тому

    You did it :D Awesome!!

  • @AnotherGameDev2411
    @AnotherGameDev2411 3 роки тому +1

    I'm a front end dev. I've started thinking about a game I wanna make. I decided to make it a text based web multiplayer RPG (because i know nothing about graphics)
    seeing your videos made me think about maybe using three.js to make my game feel like an actual... game.
    So I thank you for showing me how I can take my JS skills even further.
    I do have a question I'd love to get your take on.
    My expertise using Vue JS is way higher than my expertise using Vanila
    Do you think using a framework hurts performance to the point where its not worth the hustle?
    (especially for HTML and state management for data)

    • @simondev758
      @simondev758  3 роки тому

      I've been doing js stuff mostly because I feel like this is slightly unexplored territory. You may need to do some investigation here and tell me.

  • @HelloWorld-sr5wf
    @HelloWorld-sr5wf 3 роки тому

    Can you please make tutorial on js3 and webgl please

  • @claws61821
    @claws61821 3 роки тому

    I seem to recall that one of the most common ways to clean up any waveform's output is to give it another waveform or two in parallel. I could be remembering that wrong, but how much would it hurt to try?

    • @simondev758
      @simondev758  3 роки тому +1

      I was thinking something along those lines, output a second wave from the vertex to use as the tiling breakup. I'll try it if I come back around to the texturing.

  • @oblivion_2852
    @oblivion_2852 3 роки тому +1

    I find it odd that I'm learning more about opengl in javascript than I have by using C++ xD

  • @nadercs2669
    @nadercs2669 3 роки тому

    crazy stuff!!! where do I start from to start building open 3d worlds and become something like this one day ?

  • @overloader7900
    @overloader7900 3 роки тому

    Would the writing to depth cost be mostly mitigated if using deferred shading?

    • @simondev758
      @simondev758  3 роки тому

      Writing to depth just overrides some common hardware optimizations, since you basically must run the pixel shader rather than depth testing and discarding a fragment after vertex transform.

    • @overloader7900
      @overloader7900 3 роки тому

      @@simondev758 Since we need to modify depth we need to run fragment shader anyway, so that cost is a given, but with deferred shading any costly shaders like lighting will only be run once per fragment anyway, so that kinda works like a z pre-pass? And how fast is hw z-discard, compared to core count, anyway?

    • @simondev758
      @simondev758  3 роки тому

      @@overloader7900 The depth testing happens on the gpu.
      So I guess it would depend entirely on your setup. I'm thinking of a setup where you do a depth prepass, followed by a full opaque pass to write fill the gbuffer. Maybe you combine those if performance says its fine. Where do we modify depth from fragment shaders, as you mention?

    • @overloader7900
      @overloader7900 3 роки тому

      @@simondev758 Does it matter where it gets written if it is written to at all? The cost of threads had to be dispatched is there, but is it large enough to saturate the cores? Forward rendering is an obvious no because of lots of overdraw (although with occlusion culling?).
      The difference between depth prepass and deferred rendering is that in deferred rendering you also save some basic information(very cheap shader) in buffer, like normals, color, positions, etc. And in pre-pass you just save the depth, and then re-rendering it, only saving data if depths are equal.
      So deferred requires more memory and probably bandwidth on first pass, but pre-pass has cost of twice the geometry...

    • @simondev758
      @simondev758  3 роки тому

      @@overloader7900 So if I'm understanding right, you're asking if it matters while writing depth, ie. writing to gl_fragdepth WHILE populating the depth buffer.
      That's an interesting question, and I'm pretty sure yes it still matters and probably hurts early discard optimizations. A cursory search online gave me this: www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt
      An opengl extension specifically written to allow you to write to depth from the fragment shader while still allowing early fragment discard to work.

  • @CharlesVanNoland
    @CharlesVanNoland Рік тому

    Writing to gl_FragDepth *IS* a big deal if you have a lot of overdraw in your scene because it won't skip running a shader if its resulting pixel will be behind what's already in the framebuffer. You effectively break the early-out functionality that hardware graphics have relied on for 25 years to keep things as fast as possible. Yes, in this project's case where there isn't a lot of overdraw, it's not going to hut anything, but in anything that has expensive material shaders and many objects/geometry in the scene, you want to take advantage of the Z-buffer omitting shader executions as much as possible, and render front-to-back to further leverage that functionality.

    • @simondev758
      @simondev758  Рік тому

      I point at early-out breakage literally in the same sentence, like... just a few words before. At the end of the day, numbers and profiling are king. If your use case demands this and you're willing to eat the cost, then go for it. It's all about knowing the option exists, and the trade-offs therein.

  • @arpu4967
    @arpu4967 3 роки тому +1

    will this source on github?

    • @simondev758
      @simondev758  3 роки тому +1

      Your post reminded me, it's up now!

    • @arpu4967
      @arpu4967 3 роки тому

      @@simondev758 thx this looks awesome! still lookink how we could use compressed Texture with ktx2 you know github.com/KhronosGroup/KTX-Software toktx2 command line

  • @RamRevivo
    @RamRevivo Рік тому

    so im currently pursuing a CS degree , and is very interested in computer graphics and video game development, especially this kind of space sims, if you dont mind sharing, how did you learn how to do this?

  • @tristunalekzander5608
    @tristunalekzander5608 Рік тому +1

    I found the last part interesting, I don't get why you would use a wave to reduce the size of your numbers, if you were getting floating point errors in the fragment shader before, putting them through a sine wave shouldn't help I would think? And it mirrors your texture at the borders. Why can't you just say, for instance just looking at the x coordinate, why can't you say, vCoords.x = coords.x % max; % being a floating point mod that treats negative numbers properly, like -1%3=2

  • @harshjain8345
    @harshjain8345 3 роки тому +1

    Valuable stuff... Btw what are your pc specs as i'm curious.....plz mention your specs...thanks!

    • @simondev758
      @simondev758  3 роки тому +1

      I have an old desktop from 2014: gtx 750 ti, i7 4790k,

  • @robertwyatt3912
    @robertwyatt3912 3 роки тому

    For the far-away planet stuff, couldn’t you also just dynamically turn the terrain into normal maps, since from far enough away it is basically just flat anyway.

    • @simondev758
      @simondev758  3 роки тому

      Good idea, I'm thinking of doing something like that, possibly switching to raymarched terrain at a distance.

  • @henriqueprado9205
    @henriqueprado9205 3 роки тому +1

    In three.js you have an example on log buffer. Check this
    threejs.org/examples/#webgl_camera_logarithmicdepthbuffer

    • @simondev758
      @simondev758  3 роки тому

      Yep, mentioned in video. But you need to understand those in order to backproject into viewspace depth when reading from the depth buffer.

  • @keokawasaki7833
    @keokawasaki7833 3 роки тому

    Me not understanding a lick of things: mhmm interesting

  • @arhaisme
    @arhaisme 3 роки тому

    I thought the depth buffer in OpenGL is always logarithmic?

    • @blueble3997
      @blueble3997 3 роки тому

      No, hyperbolic by default

    • @blueble3997
      @blueble3997 3 роки тому

      aka 1/distance

    • @arhaisme
      @arhaisme 3 роки тому

      I see

    • @blueble3997
      @blueble3997 3 роки тому

      @@arhaisme ..., said the blind man to the deaf girl as he picked up his hammer and saw

    • @blueble3997
      @blueble3997 3 роки тому

      Anyways, it’s due to the inherent precision of floating point numbers being higher the smaller the number gets, and nothing to do with OpenGL specifically

  • @dabbopabblo
    @dabbopabblo 3 роки тому

    just use seamless textures and wrap them using a mod function. then you wont get that mirroring effect, and you can layer more over to give variance

  • @venoenix
    @venoenix Рік тому

    is this inspired by space engine?

    • @simondev758
      @simondev758  Рік тому

      Nah, although space engine is impressive

  • @gazehound
    @gazehound 3 роки тому

    WOOO

  • @metagen77
    @metagen77 3 роки тому +3

    Ooooooh!

  • @jordanhall1136
    @jordanhall1136 3 роки тому

    Your voice has that baratone rumble that AI-generated voices typically have

  • @N1ghtR1der666
    @N1ghtR1der666 2 роки тому

    a triangle wave should repeat textures correctly if the texture is repeatable both ways, perhaps this texture isn't? ua-cam.com/video/kfM-yu0iQBk/v-deo.html

  • @kevinb1594
    @kevinb1594 3 роки тому

    What kind of education do you need to understand this shit... I can't imagine your run of the mill game dev knows this? If so holy crap they are underpaid. Us web developers over here making bank because we watched a 3 minute CSS tutorial once and this guy is spitting straight maths.