NickBuryak / infinity_tile_shader

Shader snippets for Artomatix Infinity Tiles (Wang Tiles)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Infinity Tile Shader

Shader snippets for Artomatix Infinity Tiles (Wang Tiles)

Artomatix Infinity Tiles are automatically generated Wang Tiles. Artomatix generates the Wang tiles, which is normally a tedious and lengthy process (example here: http://www.pathofexile.com/forum/view-thread/55091). This repository contains some shader snippets for rendering these tiles in either HLSL or GLSL.

What are Wang Tiles?

(Chunks of this explanation are from http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter12.html)

Wang tiles are square tiles in which each tile edge is encoded with a color. A valid tiling requires all shared edges between tiles to have matching colors. When a set of Wang tiles is filled with texture patterns that are continuous across matching tile edges, a valid tiling from such a set can produce an arbitrarily large texture without pattern discontinuity. A sample Wang tiling is shown below:

We carefully pack the texture tiles into a single texture map so that we can perform texture fetching and filtering on this single texture via texturing hardware.

Because we use this arrangement, texture filtering and mipmapping will work as expected because each tile always tiles with the tiles beside it in our packed texture.

How do we render them?

We use an approach based on the one desribed in http://graphics.stanford.edu/papers/tile_mapping_gh2004/final/paper_final.pdf to render the wang tiles using a fragment shader. The basic algorithm is as follows:

  • Calculate which tile we are currently in
  • Generate a hash for each of the four edges of the current tile. Because the wang tile set we are using is complete, we are always able to render any combination of edge hashes
  • By carefully choosing the values we hash, we can make sure that the edge colours always match. Eg: we might hash the west side with hash(x), and the east side with hash(x-1). In this way, the west edge of tile (n, m) will always be the same as the east edge of tile (n+1, m)
  • We actually use both the x and y in our hashes with some multiplication and addition as it gives better results but we make sure not to violate the basic principle
  • The final step is to turn the 4 edge hashes into uv a tile index (x and y, from 0-4), and then turn that into a texture coordinate
  • Finally we do the texture sample. We do that here because we need to do a slightly specialised texture sample. Because our texture coords can vary a lot from one pixel to the next at a tile border, we can end up using bad mip levels just at the edges. This is obviously undesireable, so we use the built in mechanism of ddx and ddy to fix this (google ddx ddy hlsl if you don't know what this is)

We also support a predefined chunk passed in as a texture. The texture is generated by wang.py, and just contains the xy grid coords in the 4x4 tile set in the red and green channels. The reason that we want this is that while the hashing method described above will produce decent results, there's no way to ensure that it doesn't place the same tile beside itself. The predefined section is generated sequentially, and tries to space tiles out so they aren't placed close to themselves, but will repeat over long distances.

How do I integrate this?

We have generators that create custom snippets for unity and unreal, and you can generate a snippet for your own custom engine too. To run the generators, just clone this repo to something with a unix shell, make, python and cpp (cpp comes with any or c++ compiler) installed (cygwin should do, or osx or linux), and run make. Also require the PIL python libary. You can download prebuilt versions of the unity and unreal snippets here.

Unity

You can get our unity plugin from our site here which handles all of this, but if you don't want to, you can use our shader snippet from here directly (it's the same code). running make will create unity_wang.cginc. You can then include this and use the wangSample function it defines, which takes two params, a texture sampler (which must contain a packed wang tile set), and the input uv coords. You must also define a sampler called wangSampler, into which you must pass the wang_layout_array.png file which is generated when you run make. This texture must have its Texture type set to advanced, and then disable generate mip maps, format to Automatic Truecolor, and filter mode to Point. Alternatively, you can omit the wangSampler and disable the pregenerated section in the centre by adding #define NO_PREDEFINED to unity_base.cginc.

Unreal

You can get our unreal plugin from our site here which handles all of this, but if you don't want to, you can use our shader snippet from here directly (it's the same code). To add in the snippet (which is generated into unreal_snippet.txt), you need to create a material in unreal, and add a custom node. Then paste the contents of unreal_snippet.txt into the code box in the custom node. On the custom node, set a few properties: Set Output Type to CMOT Float 2, create two inputs called uv, and wang. Create two Texture Objects (not Texture Samplers) and set their textures to the packed wang tile set, and the wang_layout_array.png that is generated by the makefile, then pass them into the tex and wang inputs accordingly. Pass the texture coords into the uv input (TexCoord node). The wang_layout_array texture needs a few import settings in unreal: Mip Gen Settings: NoMipmaps, Texture Group: 2D pixels(unfiltered), Compression Settings: VectorDisplacementmap (RGBA8), and untick SRGB. You might need to click reimport in the top right after setting these. The output from the custom node is our new UV coords, which we can pass into a TextureSample node. To fix any problems with mipmapping, set the MipValueMode on the TextureSample node to Derivative(explicit derivative to compute mip level), then pass in the original coords run through DDX and DDY nodes.

Custom

Have a look at custom_base.txt, and put in whatever settings you want in there, then run make. A snippet will be generated in custom_snippet.txt, which you can integrate into your game as you see fit. If you do use the pregenerated section, you'll need to define a sampler called wangSampler and pass in the wang_layout_array.png texture as described in the unreal and unity sections. Make sure to disable mipmapping and compression on this texture, and do no texture filtering (filtering set to point or nearest).

About

Shader snippets for Artomatix Infinity Tiles (Wang Tiles)

License:MIT License


Languages

Language:Python 47.6%Language:GLSL 46.6%Language:Makefile 5.1%Language:C++ 0.7%