{"id":119,"date":"2018-04-02T18:00:47","date_gmt":"2018-04-02T23:00:47","guid":{"rendered":"http:\/\/www.chroniclesoftright.com\/blog\/?p=119"},"modified":"2018-04-02T15:58:34","modified_gmt":"2018-04-02T20:58:34","slug":"high-resolution-height-maps","status":"publish","type":"post","link":"https:\/\/www.chroniclesoftright.com\/blog\/2018\/04\/02\/high-resolution-height-maps\/","title":{"rendered":"High resolution height maps"},"content":{"rendered":"<p>I&#8217;ve been working on loading and saving height maps for terrain lately.\u00a0 My first attempt at this just used a grayscale image and the engine read the [r, g, b] values from each pixel and placed the corresponding terrain vertex at the appropriate height.\u00a0 This works fine but it&#8217;s not a very efficient use of the image data.\u00a0 Since the image is grayscale each pixel&#8217;s [r, g, b] value is the same number repeated three times.<\/p>\n<p>I don&#8217;t care so much about the inefficiency but the lack of resolution was annoying.\u00a0 What I mean is that in a grayscale image each pixel is somewhere between [0, 0, 0] (ignoring alpha values) and [255, 255, 255].\u00a0 That means the world&#8217;s terrain can only have 256 distinct height values.\u00a0 This can be scaled arbitrarily so I might have each step set at 0.1 meters, but then the highest point in the game could only ever be 25 meters.\u00a0 Actually, it would be half of that since the terrain has to be able to account for distances below sea level as well.\u00a0 Or I might have each step be 2 meters so that I could have towering peaks of 256 meters and abyssal depths of 256 meters, but the terrain itself would jump up and down by increments as high as player characters are tall, so neither of these is ideal.<\/p>\n<p>Since this is quite insufficient for a world that&#8217;s at all interesting I have been looking at other options.\u00a0 My first though was to just add r + g + b to get a range of 768.\u00a0 Divided in half this gives me a max height of 384 meters.\u00a0 I could live with this and just accept that Lyridia is a fairly flat place but my terrain step distance would still be 1 meter, and I just don&#8217;t think that would look very good.\u00a0 Again, I could scale this down but then my max height goes down and the world gets pretty flat and boring again.\u00a0 Plus, with this method a pixel with color [255, 0, 0] represents the same height as another with [128, 127, 0] or another with [0, 255, 0] or another with [2, 0, 253].\u00a0 With so many colors representing the same ultimate value I knew there had to be a better way to store more resolution in a standard image.<\/p>\n<p>I kept coming back to the number 16.7 million in my head.\u00a0 That&#8217;s the number of possible color combinations for a 24 bit monitor.\u00a0 It&#8217;s 256 x 256 x 256.\u00a0 With that in mind, I figured there must be a way to get 16.7 million discreet levels in a world terrain and this is (I think) how you do it.<\/p>\n<p>For any pixel, the [r] value has the largest effect.\u00a0 I thought it would be fun to have a maximum terrain delta of 65,536 meters, so I multiply each [r] value by 256 to get <em>r<\/em>.\u00a0 Then each [g] value is left unmodified as <em>g<\/em>, then each [b] value is divided by 255 to get <em>b<\/em>.\u00a0 Now just add <em>r<\/em> + <em>g<\/em> + <em>b<\/em> to get your terrain height.\u00a0 No need to scale anything as this gives you a massive delta by altering the [r] values but extremely fine gradations by altering the [b] value.\u00a0 A terrain height represented by [0, 0, 1] is just 0.003922 meters high!\u00a0 That&#8217;s less than a quarter of an inch.\u00a0 Yet [255, 255, 255] is over 40 miles high!<\/p>\n<p>This may all be incredibly obvious to anyone who has done this type of work before but that&#8217;s definitely not me so it was fun and challenging to figure out how to make this work.\u00a0 The long and the short of it is that I can store height maps for Lyridia as standard .png files with more resolution than I&#8217;ll ever need and I&#8217;m pretty excited about that.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve been working on loading and saving height maps for terrain lately.\u00a0 My first attempt at this just used a grayscale image and the engine read the [r, g, b] values from each pixel and placed the corresponding terrain vertex at the appropriate height.\u00a0 This works fine but it&#8217;s not a very efficient use of&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[],"class_list":["post-119","post","type-post","status-publish","format-standard","hentry","category-planning-and-development"],"_links":{"self":[{"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/posts\/119","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/comments?post=119"}],"version-history":[{"count":1,"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions"}],"predecessor-version":[{"id":120,"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/posts\/119\/revisions\/120"}],"wp:attachment":[{"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/media?parent=119"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/categories?post=119"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.chroniclesoftright.com\/blog\/wp-json\/wp\/v2\/tags?post=119"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}