26 comments

  • nine_k11 hours ago
    Technically this is not related to voxels (&quot;volumetric pixels&quot;, so to say), which split the 3D space equally along all three axes. This is just a height map, a set of prisms, not entirely unlike a Doom map. Every prism has a regular fixed-size square base.<p>For 1992, this was mind-boggling though.
    • maybewhenthesun7 hours ago
      Still, it was <i>called</i> voxel rendering back then. Not technically correct, sure, but it sounded as cool as it looked!
    • dabidab2 hours ago
      Technically you could say that it is volumetric pixels though, no? The height map and prisms are an _implementation detail_. What is being rendered is pixels with volume.
    • burnte7 hours ago
      Playing it on a decent PC in 2992 was mind blowing.
      • jagged-chisel6 hours ago
        OMG - you need to write an article on what’s a decent PC nearly a millennium in the future!
      • kh_hk7 hours ago
        I bet
    • amelius9 hours ago
      This height map contains vertical elements though.
      • jere9 hours ago
        This is a vague statement. Are you suggesting each column can can have multiple layers of terrain, air, terrain? IIUC, the article disputes this:<p>&gt; Such maps limit the terrain to “one height per position on the map” - Complex geometries such as buildings or trees are not possible to represent.<p>FWIW I&#x27;m working on a voxel sandcastle game. People usually seem particularly surprised by this style because they&#x27;re so used to such games being rendered by height maps which don&#x27;t allow tunnels or arches or overhangs.
    • cubefox10 hours ago
      No? Each pixel on a height map corresponds to a column of voxels of the specified height. You could represent the same height data with a fully general octree and it would look exactly the same.
      • bastawhiz10 hours ago
        It&#x27;s kind of weird to call them &quot;columns of voxels&quot; when the columns can&#x27;t have gaps and the &quot;voxels&quot; below the topmost are ignored completely. Which is to say, they&#x27;re just columns...which is (definitionally) just a height map.<p>In fact, an octree for this approach would be _meaningfully worse_ because finding &quot;the topmost voxel&quot; in each column is O(logn)—or maybe worse?—versus O(1) for a height map. With no benefits, because you never look at any other voxels.
        • cubefox8 hours ago
          &gt; It&#x27;s kind of weird to call them &quot;columns of voxels&quot; when the columns can&#x27;t have gaps<p>No, it&#x27;s not weird. The columns don&#x27;t have gaps because they are columns represented by a height map, which can&#x27;t display <i>arbitrary</i> voxel geometry (unlike octrees), but that doesn&#x27;t mean they can&#x27;t display voxel geometry at all.<p>&gt; Which is to say, they&#x27;re just columns...which is (definitionally) just a height map.<p>Yes. A height map is representing voxel data without overhangs.<p>&gt; In fact, an octree for this approach would be _meaningfully worse_<p>That&#x27;s irrelevant. The fact remains that rendering the same height data using an octree would look exactly the same. If the latter displays voxel geometry, the former does too.
          • jere6 hours ago
            &gt; A height map is representing voxel data without overhangs.<p>A height map <i>can</i> represent voxel data if the columns are integer heights, in the same way an integer can &quot;represent&quot; an infinite number of countable things. It&#x27;s like saying the number 7 is &quot;related&quot; to a group of 7 ducks. The relationship is kind of meaningless.<p>But more importantly height maps can use also floating point heights in which case there&#x27;s no reasonable mapping between the two. So your statement isn&#x27;t generally true.
          • bastawhiz7 hours ago
            Your argument comes down to the meaning of &quot;voxel&quot;, then. Voxels have volume, and they are represented with polygon faces. If you think that applies here, I guess more power to you.
    • DonHopkins9 hours ago
      Louis Castle developed a &quot;voxel plus&quot; software renderer for Westwood Studios&#x27; 1997 Blade Runner. It used &quot;voxels&quot; (with scare quotes) for character animation, not just terrain.<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Blade_Runner_(1997_video_game)" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Blade_Runner_(1997_video_game)</a><p><a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=17171287">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=17171287</a><p>madmoose on May 28, 2018 | parent | context | favorite | on: How Voxels Became ‘The Next Big Thing’<p>Blade Runner didn&#x27;t actually use voxels, they used a rather unique technique that they called &quot;slice animations&quot;.<p>The 3D models were sliced from bottom to top into a couple of hundred slices (depending on desired quality) by intersecting the model with a horizontal plane and storing the resulting polygons.<p>The engine can only rotate the models around the vertical axis.<p>I made a hacky javascript version of the renderer a long time ago:<p><a href="http:&#x2F;&#x2F;thomas.fach-pedersen.net&#x2F;bladerunner&#x2F;mccoy_anim_13_frame_0.html" rel="nofollow">http:&#x2F;&#x2F;thomas.fach-pedersen.net&#x2F;bladerunner&#x2F;mccoy_anim_13_fr...</a><p>EDIT: Let me also plug our WIP Blade Runner engine for ScummVM:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;scummvm&#x2F;scummvm&#x2F;tree&#x2F;master&#x2F;engines&#x2F;bladerunner" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;scummvm&#x2F;scummvm&#x2F;tree&#x2F;master&#x2F;engines&#x2F;blade...</a><p>digi_owl on May 28, 2018 | prev [–]<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Blade_Runner_%281997_video_game%29" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Blade_Runner_%281997_video_gam...</a><p>Seems that the people that developed the game considers it voxel based.<p>madmoose on May 28, 2018 | parent | next [–]<p>The page you linked quotes Louis Castle:<p>&gt; What we are using is not voxels, but sort of &#x27;voxels plus.&#x27;<p>So &quot;not voxels&quot;. Louis Castle probably called it voxel-like because he didn&#x27;t want to get too technical in an interview. Their technique has not been described in detail in the press but see <a href="http:&#x2F;&#x2F;deadendthrills.com&#x2F;future-imperfect-the-lost-art-of-westwoods-blade-runner&#x2F;" rel="nofollow">http:&#x2F;&#x2F;deadendthrills.com&#x2F;future-imperfect-the-lost-art-of-w...</a> [Dead URL -- I tried to rewrite it with archive.org but it&#x27;s down for me and apparently everyone else now -- can anyone else get through? -Don] for an article that calls it a &quot;slice model&quot;-technique.<p>I&#x27;m not an expert on voxels but I&#x27;ve reverse engineered and reimplemented most of the Blade Runner rendering engine and in my opinion it doesn&#x27;t count as voxels. For one, you&#x27;re never going to be able to rotate the models around any axis other than the vertical.<p>LouisCastle on May 28, 2018 | root | parent | next [–]<p>Fun! Yeah, we stored our data as slices for space and restricted rotation to the Y axis. Both were optimization since each frame of an animation was a full model there was no need to rotate them. The renderer could render them from any angle though so I still consider them voxels. More like voxels lite then voxel plus. We also used a lot of sprite cards with zdepth and a quick normal hack for lighting. You had to cut corners where you could back then!!<p>madmoose on May 28, 2018 | root | parent | next [–]<p>Hello Louis!<p>I&#x27;ve certainly had a lot of fun figuring out how you did what you did, so thank you for that, no matter what you call it :)<p>You certainly crammed a lot of tech into one engine! Full screen 15 BPP videos with full z-buffer with smaller alpha-channeled videos rendered on top, character models with lighting. Even the UI is looping videos.<p>Once I get proper path finding working Blade Runner will be a lot more playable in our ScummVM engine.<p>I&#x27;ve probably rewatched the opening scene of the game a thousand times while working on it...<p>I only wished that you had used a scripting language for your game code instead of compiling it to DLLs. I know you optimized heavily for speed but it would have made our task a lot easier :)<p>DonHopkins on May 28, 2018 | root | parent | prev | next [–]<p>So that&#x27;s why you didn&#x27;t include the Deckard -vs- Pris scene where she rotates around the X-axis! ;)<p><a href="https:&#x2F;&#x2F;youtu.be&#x2F;e9t5ikxjAQ4?t=1m9s" rel="nofollow">https:&#x2F;&#x2F;youtu.be&#x2F;e9t5ikxjAQ4?t=1m9s</a><p>pjtr on May 28, 2018 | root | parent | prev | next [–]<p>Fun indeed!<p>Can you talk about how the artists authored the original models? Was it an automated conversion from a standard polygon model or from a full voxel model? Or was it all drawn in this special slice format directly somehow?<p>madmoose on May 28, 2018 | root | parent | next [–]<p>Not Louis, but the article I linked above says they used 3D Studio Max and converted it to the slice model format.
  • superjan9 hours ago
    Off topic: The very first assignment in this game is called “oil tank holiday”: fly the chopper to unguarded oil tanks, shoot and watch them burn, and then fly home. No enemies. Just learn to fly and shoot.<p>I apply this in testing code. After you write some code, try to think of the absolute minimal test to prove that your code does anything at all without crashing. These are my “oil tank holiday” tests. It is always humbling to see those fail.
    • ggambetta9 hours ago
      What I&#x27;m hearing is that the smoke in smoke tests comes from the oil tanks!
  • a1o12 hours ago
    When this was first posted I made a game with a port of this approach to AGS Engine. Nowadays AGS is much faster since we have improved a lot of things, but this wasn’t the case at the time, so I had to make a few little tricks to make the rendering work well with the engine at the time.<p><a href="https:&#x2F;&#x2F;github.com&#x2F;ericoporto&#x2F;i_rented_a_boat" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ericoporto&#x2F;i_rented_a_boat</a>
  • snickerer8 hours ago
    C++ version of this game, using exactly the same original Comanche map and rendering algorithm: <a href="https:&#x2F;&#x2F;codeberg.org&#x2F;Lew_Palm&#x2F;voxelcopter" rel="nofollow">https:&#x2F;&#x2F;codeberg.org&#x2F;Lew_Palm&#x2F;voxelcopter</a>
  • mft_8 hours ago
    Brings back memories. Comanche was incredible when it came out, running on (IIRC) our family’s 386SX-16.<p>I tried to replicate the effect in Visual Basic, albeit with very limited success at the time.
    • nomel16 minutes ago
      Delta force 2 for me [1]! The only real problem with it was you could see characters as moving single pixels across the map...and hit them without too much trouble.<p>[1] <a href="https:&#x2F;&#x2F;youtu.be&#x2F;SyBh91UYVS8" rel="nofollow">https:&#x2F;&#x2F;youtu.be&#x2F;SyBh91UYVS8</a>
  • blaze3311 hours ago
    Previous discussion (2017): <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=15772065">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=15772065</a>
  • tdeck12 hours ago
    It&#x27;s interesting that the color maps seem to have shadows &quot;built in&quot;, so that you get a 3D bevel effect from just looking at the color map.
  • binarymax9 hours ago
    Is this the same algo used for Magic Carpet (1994)? The style looks very familiar, and I always wondered how they pulled it off.<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Magic_Carpet_(video_game)" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Magic_Carpet_(video_game)</a>
    • jaen9 hours ago
      The game originally used a &quot;voxel&quot; engine [1], but the final release switched to affine texture mapping (with a heightmap-based terrain, still).<p>The voxel-style engines tend to feature a longer draw distance (due to it being cheaper to render, as you can easily use various hacks to eg. halve texture accesses far away).<p>For a detailed look into the rendering of Magic Carpet, start from Slide 8 of [2].<p>[1]: <a href="https:&#x2F;&#x2F;tcrf.net&#x2F;Prerelease:Magic_Carpet_(DOS)#1993" rel="nofollow">https:&#x2F;&#x2F;tcrf.net&#x2F;Prerelease:Magic_Carpet_(DOS)#1993</a> [2]: <a href="https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20180330004301&#x2F;http:&#x2F;&#x2F;www.glenncorpes.com&#x2F;procedural-landscapes-gdce-2001" rel="nofollow">https:&#x2F;&#x2F;web.archive.org&#x2F;web&#x2F;20180330004301&#x2F;http:&#x2F;&#x2F;www.glennc...</a>
  • Panzerschrek8 hours ago
    I used this approach in one of my demos: <a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=xjbDxvboOjo" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=xjbDxvboOjo</a>. Plot twist: the highmap is dynamically-generated.
  • karmakaze10 hours ago
    First thing that comes to my mind is the procedural generation in Rescue on Fractalus! (Behind Jaggi Lines) 1984 by LucasFilm Games which blew my mind on Atari 6502.
  • totetsu9 hours ago
    Was this also how the flight sim that used to be hidden in EXEL.EXE had been built, I wonder.
  • mthoms10 hours ago
    This sure brings back memories.<p>I remember figuring all this out as a self-taught teenager (pre-internet) with some books, a whole lot of time, and only a high-school level understanding of trigonometry. I built different versions - first in Pascal, then C, then Assembly.<p>Figuring out the algorithm was hard, but one of the optimizations I was most proud of was inventing (or so I thought) lookup tables to get around the slow floating point multiplication of my 16MHz 80286 CPU. I also remember &quot;inventing&quot; (ha!) the old bit shift + add technique.<p>There was something immensely satisfying about squeezing every last drop of performance out of a machine.<p>Nothing ever came of it. It was more or less a demo, but man did it make me feel like I accomplished something magical. I&#x27;d give anything to have a look at that source code today, but this post is the next best thing. So thanks for sharing. This made my day.
    • mrexroad8 hours ago
      &gt; I remember figuring all this out as a self-taught teenager (pre-internet) with some books, a whole lot of time […] but man did it make me feel like I accomplished something magical.<p>As a parent with kids in college, high school, and middle school, I lament (worry about?) how many obstacles youth now have reaching this dynamic. That thread of curiosity, discovery, struggle, and sense of accomplishment (or just learnings) is so profoundly formative. I’ve had mixed success creating space for it across my kids, but I sure miss the “pointless” threads I followed b&#x2F;c of empty time when I was a kid.
    • bananaboy3 hours ago
      The 286 didnt have an integrated floating point unit so you would have been using a software floating point library that came with your compiler. That would have been very slow indeed!
  • mondainx9 hours ago
    Reading Voxel always takes me back, way back.. I played Comanche for hours and read up on Voxel tech in various magazines of the day; so clever and easy to implement. Nice demo and thanks for the trip down memory lane.
  • Jare11 hours ago
    [Edit] ah ok they clarify later as a performance enhancement. I think it was pretty integral to the algorithm, but ok.<p>Wait why do they say painter&#x27;s algorithm. Comanche and other such voxel terrain engines went front to back and never had overdraw.
    • s-macke11 hours ago
      Author here. Yes, it is integral. I chose this approach to first show how to draw it from back to front, because the code is easier to understand this way.
      • Lerc8 hours ago
        I think it&#x27;s worth noting that you can tilt with this method, but not roll.<p>Great for a helicopter game, Less so for general flight sim.<p>That was a large part of how games were designed back in the day. Start with what you have the ability to do, find the game that matches what you can do.
        • nnevatie6 hours ago
          Notice the demo video from Comanche also shows roll.<p>Edit: To support roll, the renderer essentially rendered the voxel terrain into a frame buffer and then applied camera transformations that gave the appearance of a fully rotating viewpoint. The terrain itself was not being raycast through a true 3D voxel volume.
    • swiftcoder11 hours ago
      Reverse painters algorithm is still painters algorithm. You trade off the cost of a full screen clear before the frame, in return for eliminating overdraw
      • knome11 hours ago
        You could avoid a full screen clear by using the y-buffer to draw in sky segments after rendering terrain.
        • swiftcoder11 hours ago
          You still need to have some sort of mask to tell you which pixels have not yet been written this frame
          • knome11 hours ago
            that&#x27;s what the y-buffer is that the article mentions in the front-to-back rendering section.<p>it tracks how tall each columns write is so you can use it to only write the diff between it and the voxel behind it, skipping writing anything at all if the voxel behind is shorter than the current height.<p>So once you&#x27;re done rendering front-to-back, you&#x27;ve got a y-buffer of highest-writes you can slap your blue sky across from highest-to-screentop on each line, avoiding the need to clear by write the sky to the full screen before starting the render.
            • swiftcoder10 hours ago
              yes, I guess you can get away with only clearing the y buffer, rather than the whole screen
  • esafak11 hours ago
    I remember how groundbreaking Comanche was. Now I learned that it was a result of the programmer&#x27;s experience in the medical industry (CT&#x2F;MRI scanning): <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Voxel_Space" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Voxel_Space</a>
  • acrinimiril9 hours ago
    Looking back even further, games like Koronis Rift did a lot with much less. Still, both are impressive and brilliant.
  • IAmGraydon2 hours ago
    Ahhh Comanche. One of my favorite games of my childhood.
  • taneq12 hours ago
    If you render columns instead of rows you can render near-to-far without a Y-buffer and with zero overdraw. :)
    • bananaboy3 hours ago
      It does render columns though. Maybe we are talking about different things but the algorithm is essentially: for x = 0 to 319 draw_vertical_line(x, height). The detail there though is whether you cast a ray for each column or do what this does and go from far plane to near plane drawing the columns.
    • nkrisc10 hours ago
      You just store the last highest Y value as you iterate near to far?
    • mthoms10 hours ago
      This is true.<p>I vaguely remember there was something about the VGA architecture of the day that made this approach much slower, but I might be misremembering. My recollection of it is fuzzy. I&#x27;m hoping someone will chime in to remind me what I might be thinking of.<p>It might also just have been that this approach didn&#x27;t work well with my lookup table optimization (see my other post).
      • bananaboy3 hours ago
        You might be thinking of unchained VGA modes but in unchained modes you want to draw columns because that means you only have to switch which memory plane is active four times instead of every four pixels, ie select plane 0, draw column 0, 4, 8, etc then select plane 1 and draw columns 1, 5, 9, etc etc
        • mthoms3 hours ago
          This is what I was thinking of, thanks.
      • lowbloodsugar9 hours ago
        I imagine that far map squares are more than one pixel wide so that read is amortized. Not so if going vertically.
        • mthoms3 hours ago
          This was part of it as well. At least - as I recall - with the early flat (MarioCart 1 inspired) versions I made. But in that case, the closer &quot;terrain&quot; pixels always became multiple on-screen pixels so my lookup table for each of the 360 degree viewpoints contained only a single byte to add to each x and y coordinate, plus a single byte for each length.<p>Had to keep the memory use down and multiplication was really computationally expensive.
  • DonHopkins8 hours ago
    I would love to see somebody code this up to run in the browser -- it&#x27;s from 2003, so I bet it could now run really fast with lots of voxels. It will steal your face right off your head. Happy Halloween!<p><a href="https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9SplEU05z64" rel="nofollow">https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=9SplEU05z64</a><p>Using Deformations for Browsing Volumetric Data<p>1,367 views Jul 31, 2009: A prototype user interface for browsing volume data. Presented at IEEE VIS 2003 by Michael J. McGuffin, Liviu Tancau, and Ravin Balakrishnan. For more information, see<p><a href="https:&#x2F;&#x2F;profs.etsmtl.ca&#x2F;mmcguffin&#x2F;research&#x2F;#mcguffin_vis2003" rel="nofollow">https:&#x2F;&#x2F;profs.etsmtl.ca&#x2F;mmcguffin&#x2F;research&#x2F;#mcguffin_vis2003</a><p><a href="https:&#x2F;&#x2F;profs.etsmtl.ca&#x2F;mmcguffin&#x2F;research&#x2F;volumetricBrowsing&#x2F;" rel="nofollow">https:&#x2F;&#x2F;profs.etsmtl.ca&#x2F;mmcguffin&#x2F;research&#x2F;volumetricBrowsin...</a>
  • davrosthedalek10 hours ago
    Obligatory link to mars.com: <a href="https:&#x2F;&#x2F;chaos.if.uj.edu.pl&#x2F;~wojtek&#x2F;MARS.COM&#x2F;" rel="nofollow">https:&#x2F;&#x2F;chaos.if.uj.edu.pl&#x2F;~wojtek&#x2F;MARS.COM&#x2F;</a>
  • TheChaplain12 hours ago
    I really love this kind of articles, so much to learn.
  • bryantoken7 hours ago
    hello
  • haruharuha10 hours ago
    This rendering approach reminds me of a project I saw a while back that explored what the world would look like from the perspective of a 1D or 2D being. Someone actually built a interactive demo based on that exact premise.<p>edited, I found it: <a href="https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;gamedev&#x2F;comments&#x2F;m19vl2&#x2F;1d_game_proof_of_concept_web_demo_works_for&#x2F;" rel="nofollow">https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;gamedev&#x2F;comments&#x2F;m19vl2&#x2F;1d_game_pro...</a>
  • swordlucky66612 hours ago
    [dead]