{"id":962,"date":"2014-10-29T10:29:11","date_gmt":"2014-10-29T08:29:11","guid":{"rendered":"https:\/\/esimov.com\/blog\/?p=962"},"modified":"2019-05-03T11:17:05","modified_gmt":"2019-05-03T09:17:05","slug":"perlin-noise-based-minecraft-rendering-experiment","status":"publish","type":"post","link":"https:\/\/esimov.com\/blog\/2014\/10\/29\/perlin-noise-based-minecraft-rendering-experiment\/","title":{"rendered":"Perlin noise based Minecraft rendering experiment"},"content":{"rendered":"<p>Recently i was involved in a few different commercial projects, was toying with Golang, the shiny new language from Google and made some small snippets to test the language capability (i put them in my <a href=\"https:\/\/gist.github.com\/esimov\">gist repository<\/a>). In conclusion i somehow completely missed the creative coding. I had a few ideas and conceptions which i wanted to realize at an earlier or later stage. One of them was to adapt <a href=\"http:\/\/jsfiddle.net\/uzMPU\/\">Notch minecraft renderer<\/a> to be used in combination with perlin or simplex noise for generating random rendering maps.<\/p>\n<p><a href=\"https:\/\/www.esimov.com\/experiments\/javascript\/minecraft\/\" rel=\"attachment wp-att-973\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/esimov.com\/blog\/wp-content\/uploads\/2014\/10\/minecraft-650x450.png\" alt=\"minecraft\" width=\"650\" height=\"380\" class=\"aligncenter size-medium wp-image-973\" \/><\/a><\/p>\n<p>For that reason i ported to Javascript the original perlin noise algorithm written in Java. You can find the code here: <a href=\"https:\/\/gist.github.com\/esimov\/586a439f53f62f67083e\">https:\/\/gist.github.com\/esimov\/586a439f53f62f67083e<\/a>. I won&#8217;t go into much details of how the perlin noise algorithm  is working, if you are interested you can find a well explained paper here: <a href=\"http:\/\/webstaff.itn.liu.se\/~stegu\/simplexnoise\/simplexnoise.pdf\">http:\/\/webstaff.itn.liu.se\/~stegu\/simplexnoise\/simplexnoise.pdf<\/a>.<\/p>\n<p>As a starting point I put together a small experiment creating randomly generated perlin noise  maps, and testing the granularity and dispersion of randomly selected seeding points to see how much they can be customized to create different noise patterns. I&#8217;m honest, actually these maps are not 100% randomly distributed, although they can be randomly seeded too, but for our scope I used a pretty neat algorithm for uniform granularity:<\/p>\n<pre class=\"language-javascript\"><code class=\"language-javascript\">\r\n<span class=\"token comment\" spellcheck=\"true\">\/\/ Seeded random number generator\r\n<\/span><span class=\"token keyword\">function<\/span> seed<span class=\"token punctuation\">(<\/span>x<span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n    x <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span>x<span class=\"token operator\">&lt;<\/span><span class=\"token operator\">&lt;<\/span><span class=\"token number\">13<\/span><span class=\"token punctuation\">)<\/span> ^ x<span class=\"token punctuation\">;<\/span>\r\n    <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span> <span class=\"token number\">1.0<\/span> <span class=\"token operator\">-<\/span> <span class=\"token punctuation\">(<\/span> <span class=\"token punctuation\">(<\/span>x <span class=\"token operator\">*<\/span> <span class=\"token punctuation\">(<\/span>x <span class=\"token operator\">*<\/span> x <span class=\"token operator\">*<\/span> <span class=\"token number\">15731<\/span> <span class=\"token operator\">+<\/span> <span class=\"token number\">789221<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">+<\/span> <span class=\"token number\">1376312589<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;<\/span> 0x7fffffff<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">\/<\/span> <span class=\"token number\">1073741824.0<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\r\n<span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<p>And here is the working example:<\/p>\n<p data-height=\"366\" data-theme-id=\"0\" data-slug-hash=\"eAoHv\" data-default-tab=\"result\" data-user=\"esimov\" class='codepen'>See the Pen <a href='http:\/\/codepen.io\/esimov\/pen\/eAoHv\/'>Perlin metaball<\/a> by Endre Simo (<a href='http:\/\/codepen.io\/esimov'>@esimov<\/a>) on <a href='http:\/\/codepen.io'>CodePen<\/a>.<\/p>\n<p><script async src=\"\/\/codepen.io\/assets\/embed\/ei.js\"><\/script><\/p>\n<p>The question that may arise: why should we need the perlin noise &#8220;thing&#8221; to generate different minecraft styled procedural terrain map? By generating randomly distributed noise we can further adjust the color mapping, then extract some of the areas above or below to certain values, which at a later state we can combine or even integrate into the core map generation logic. If you look at the alchemy behind the code responsible for programatically generating the terrain blocks, you will soon realize that we have all the ingredients (by manipulating some pixels here and there) to integrate the noise map into the block generation algorithm.<\/p>\n<p>In <kbd>InitMap<\/kbd> function we populate the map array with some initial values, then at a later stage after we generate the noise map, we extract the data as follows:<\/p>\n<pre class=\"language-javascript\"><code class=\"language-javascript\">\r\n<span class=\"token keyword\">for<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token keyword\">var<\/span> cell <span class=\"token operator\">=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span> cell <span class=\"token operator\">&lt;<\/span> pixels<span class=\"token punctuation\">.<\/span>length<span class=\"token punctuation\">;<\/span> cell <span class=\"token operator\">+<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">4<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n    <span class=\"token keyword\">var<\/span> ii <span class=\"token operator\">=<\/span> Math<span class=\"token punctuation\">.<\/span>floor<span class=\"token punctuation\">(<\/span>cell<span class=\"token operator\">\/<\/span><span class=\"token number\">4<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\r\n    <span class=\"token keyword\">var<\/span> x <span class=\"token operator\">=<\/span> ii % canvasWidth<span class=\"token punctuation\">;<\/span>\r\n    <span class=\"token keyword\">var<\/span> y <span class=\"token operator\">=<\/span> Math<span class=\"token punctuation\">.<\/span>floor<span class=\"token punctuation\">(<\/span>ii <span class=\"token operator\">\/<\/span> canvasWidth<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\r\n    <span class=\"token keyword\">var<\/span> xx <span class=\"token operator\">=<\/span> <span class=\"token number\">123<\/span> <span class=\"token operator\">+<\/span> x <span class=\"token operator\">*<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token number\">02<\/span><span class=\"token punctuation\">;<\/span>\r\n    <span class=\"token keyword\">var<\/span> yy <span class=\"token operator\">=<\/span> <span class=\"token number\">324<\/span> <span class=\"token operator\">+<\/span> y <span class=\"token operator\">*<\/span> <span class=\"token punctuation\">.<\/span><span class=\"token number\">02<\/span><span class=\"token punctuation\">;<\/span>\r\n    \r\n    <span class=\"token keyword\">var<\/span> value <span class=\"token operator\">=<\/span> Math<span class=\"token punctuation\">.<\/span>floor<span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>perlin<span class=\"token punctuation\">.<\/span>noise<span class=\"token punctuation\">(<\/span>xx<span class=\"token punctuation\">,<\/span>yy<span class=\"token punctuation\">,<\/span><span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token operator\">*<\/span><span class=\"token number\">256<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>              \r\n    pixels<span class=\"token punctuation\">[<\/span>cell<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> pixels<span class=\"token punctuation\">[<\/span>cell <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> pixels<span class=\"token punctuation\">[<\/span>cell <span class=\"token operator\">+<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> value<span class=\"token punctuation\">;<\/span>\r\n    pixels<span class=\"token punctuation\">[<\/span>cell <span class=\"token operator\">+<\/span> <span class=\"token number\">3<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token number\">255<\/span><span class=\"token punctuation\">;<\/span> <span class=\"token comment\" spellcheck=\"true\">\/\/ alpha.\r\n<\/span><span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<p>then we go through the pixels data, setting up the condition on which data should be processed. In our actual case if the pixel color extracted is below to some certain value (this values are actually values extracted from the perlin noise map) then we set the map data to 0. This is why the perlin noise seed granularity is important. As smoother the transition between points is, as subtle would be the map generated.<\/p>\n<pre class=\"language-javascript\"><code class=\"language-javascript\">\r\n<span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>pixelCol <span class=\"token operator\">&amp;<\/span> 0xff <span class=\"token operator\">*<\/span> <span class=\"token number\">0.48<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">64<\/span> <span class=\"token operator\">-<\/span> y<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&lt;<\/span><span class=\"token operator\">&lt;<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\r\n    map<span class=\"token punctuation\">[<\/span>i<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">;<\/span>\r\n<span class=\"token punctuation\">}<\/span>\r\n<\/code><\/pre>\n<p>This is the basic logic for generating random minecraft terrain. We can even adjust the seed offset in perlin noise script to generate different patterns, however in my experiment seems that this doesn&#8217;t matter to much.<\/p>\n<p>The rendering engine is based on notch code, however i made some optimization adding some fake shadows and distance fog, creating a more ambiental environment.<\/p>\n<p>This is the code which creates the distance fog effect:<\/p>\n<pre class=\"language-javascript\"><code class=\"language-javascript\">\r\n<span class=\"token keyword\">var<\/span> r <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>col <span class=\"token operator\">&gt;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token number\">16<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;<\/span> 0xff<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> br <span class=\"token operator\">*<\/span> ddist <span class=\"token operator\">\/<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">255<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">255<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\r\n<span class=\"token keyword\">var<\/span> g <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>col <span class=\"token operator\">&gt;<\/span><span class=\"token operator\">&gt;<\/span> <span class=\"token number\">8<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;<\/span> 0xff<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> br <span class=\"token operator\">*<\/span> ddist <span class=\"token operator\">\/<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">255<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">255<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\r\n<span class=\"token keyword\">var<\/span> b <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span>col<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">&amp;<\/span> 0xff<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> br <span class=\"token operator\">*<\/span> ddist <span class=\"token operator\">\/<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token number\">255<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">255<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\r\n\r\n<span class=\"token keyword\">if<\/span><span class=\"token punctuation\">(<\/span>ddist <span class=\"token operator\">&lt;<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">155<\/span><span class=\"token punctuation\">)<\/span> r <span class=\"token operator\">+<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">155<\/span><span class=\"token operator\">-<\/span>ddist<span class=\"token punctuation\">;<\/span>\r\n<span class=\"token keyword\">if<\/span><span class=\"token punctuation\">(<\/span>ddist <span class=\"token operator\">&lt;<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">255<\/span><span class=\"token punctuation\">)<\/span> g <span class=\"token operator\">+<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">255<\/span><span class=\"token operator\">-<\/span>ddist<span class=\"token punctuation\">;<\/span>\r\n<span class=\"token keyword\">if<\/span><span class=\"token punctuation\">(<\/span>ddist <span class=\"token operator\">&lt;<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">255<\/span><span class=\"token punctuation\">)<\/span> b <span class=\"token operator\">+<\/span><span class=\"token operator\">=<\/span> <span class=\"token number\">255<\/span><span class=\"token operator\">-<\/span>ddist<span class=\"token punctuation\">;<\/span>  \r\n\r\npixels<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">(<\/span>x <span class=\"token operator\">+<\/span> y <span class=\"token operator\">*<\/span> w<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">4<\/span> <span class=\"token operator\">+<\/span> <span class=\"token number\">0<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> r<span class=\"token punctuation\">;<\/span>\r\npixels<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">(<\/span>x <span class=\"token operator\">+<\/span> y <span class=\"token operator\">*<\/span> w<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">4<\/span> <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> g<span class=\"token punctuation\">;<\/span>\r\npixels<span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">(<\/span>x <span class=\"token operator\">+<\/span> y <span class=\"token operator\">*<\/span> w<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">*<\/span> <span class=\"token number\">4<\/span> <span class=\"token operator\">+<\/span> <span class=\"token number\">2<\/span><span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> b<span class=\"token punctuation\">;<\/span>\r\n<\/code><\/pre>\n<p>Playing with values i discovered that actually i can &#8220;move the camera around the scene&#8221; (actually here we have a fictive camera, meaning that not the camera is moving around scene, but the objects are projected around some fictive coordinates), so it was quite easy to get the mouse position and adjust the camera relative to the mouse position, this way including some user interaction into the scene.<\/p>\n<h2>Version 2<\/h2>\n<p>Even tough the desired effect pretty much satisfied my expectations, something was really missing from the original version: it was not possible to generate randomly seeded terrain maps and also the generated map was pretty much the same. So I have extended the first version with random map generation, replaced the Perlin noise generator with the simplex noise, added fake shadow and fog to give the feeling of depth and on top of these i have also included a control panel to play with the values. This is how it came out:<\/p>\n<p><a href=\"https:\/\/www.esimov.com\/experiments\/javascript\/minecraft_v2\/\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/esimov.com\/blog\/wp-content\/uploads\/2014\/10\/mincraft-map.png\" alt=\"\" width=\"958\" height=\"616\" class=\"aligncenter size-full wp-image-1284\" srcset=\"https:\/\/esimov.com\/blog\/wp-content\/uploads\/2014\/10\/mincraft-map.png 958w, https:\/\/esimov.com\/blog\/wp-content\/uploads\/2014\/10\/mincraft-map-300x193.png 300w, https:\/\/esimov.com\/blog\/wp-content\/uploads\/2014\/10\/mincraft-map-768x494.png 768w, https:\/\/esimov.com\/blog\/wp-content\/uploads\/2014\/10\/mincraft-map-650x418.png 650w\" sizes=\"auto, (max-width: 958px) 100vw, 958px\" \/><\/a><\/p>\n<p>The source code can be found on my Github page:<\/p>\n<p><a href=\"https:\/\/github.com\/esimov\/minecraft.js\">https:\/\/github.com\/esimov\/minecraft.js<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is an adapted version of Notch&#8217;s javascript based minecraft rendering experiment, extended with Perlin noise based terrain simulation.<\/p>\n","protected":false},"author":1,"featured_media":973,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[63,47,7,5,52,20,1],"tags":[68,48,65,49,44,64],"class_list":["post-962","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-3d","category-blog","category-experiments","category-general","category-html5-2","category-javascript","category-uncategorized","tag-3d","tag-canvas","tag-experiments-2","tag-html5","tag-javascript-2","tag-minecraft"],"_links":{"self":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts\/962","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/comments?post=962"}],"version-history":[{"count":3,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts\/962\/revisions"}],"predecessor-version":[{"id":1286,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/posts\/962\/revisions\/1286"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/media\/973"}],"wp:attachment":[{"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/media?parent=962"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/categories?post=962"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/esimov.com\/blog\/wp-json\/wp\/v2\/tags?post=962"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}