So we are trying out a swatch based workflow, where you have 32 or whatever materials on a tiny swatch texture, with corresponding albedo, metalness, roughness
Then we use a mask for edge wear basically, and this works pretty good, but we are struggling with finding a way to apply tiling detail maps (normal, maybe albedo) for these swatches and are not sure how to go about for these or if this is even possible. Putting a normal on a swatch texture is not the issue, but tiling this small window of the swatch. Maybe with triplanar mapping somehow?
Does anyone have any idea or achieved something similar?
Replies
http://wiki.polycount.com/wiki/MultiTexture#Variation_Blending
This works for albedo, gloss, metalness as these only require flat color to work and the swatch resolution does not matter
But now I would like to try if I can put a tiling low res detail albedo and detail normal on a corresponding swatch sheet,
but of course tiling wont work as the other swatches are around each other - and I am searching if there is a possible trick to get around that.
@Eric, I checked but didnt find anything of the sorts - unless Im missing something
I know about detail maps but this is a bit more crazy, I basically would have to snap-shot one piece from the atlas and make that tiling in isolation - not sure if thats even possible
Maybe If the swatches are in one 1D strip and you could have tiling in one direction and do something with that in some way?
You'd be better off using texture arrays rather than an atlas though if the engine supports it- much less fuckery involved
I would only need 1 tiling value for all these as we could just keep texel density consistent (to decent degree) for the UV
(An atlas is what I take as an array of textures on one sheet from uniquely UVd meshes merely combined but sure this is also a kind of atlas, Photoshop term I guess > Color Swatches - also "Atlas workflow" would be confusing - that would just be making assets in batches in my mind at least)
Texture arrays hmm, does this not have the heavy lookup cost from the many textures or is that batched? That is not supported by shader graph or such in Unity I think however but Ill have a look. Btw are texture lookup costs proportional to texture size or is there a fixed cost in addition?
I dont use unity at work so no idea what their implementation is like
however
Unity has support for texture arrays
AFAIK the lookup cost is significantly less than loading a list of non arrayed textures - I think its kind of dealt with before it becomes a problem.
Under dx11 I believe you must ensure that all packed maps are the same resolution and its not possible to dynamically load/unload textures from the array at runtime.
This can lead to a fairly significant static memory cost but you only end up paying for a single material so usually balances out favourably.
Under dx12 I believe its possible to have mismatched texture dimensions and to perform some loading/unloading at runtime.
This will all be dependant on engine support so you'll need to discuss it with your programmers to be sure
Now I just gotta look up some good masking workflow
First off from playing with this sort of approach myself I would say that there is an interesting variation to the swatch approach consisting of relying on vertical gradients as opposed to just a grid of swatches. This lets you vary value intensity by shifting UVs up and down, which can be very impactful since value read is such an important part of picture making. Like so :
Now regarding the tiling of surface details as you mention :
"But now I would like to try if I can put a tiling low res detail albedo and detail normal on a corresponding swatch sheet"
If I may ask : why assume that the detail maps (color and normals) would have to be placed inside the square swatches to begin with ? You could simply deal with the tiliing of these components through a secondary UV channel and ... that's it !
Pushing things further you'd likely end up with 3 UV sets : set 1 for color/material swatch assignement, set 2 for vertical mapping of gradients (of course 1 and 2 could be combined is using the vertical gradient stripe approach), an optional set 3 for "regular pelt unwrap" in case uniquely mapped textures are ever needed on hero items, but also to control the tiling of detail color maps/normalmaps ; and maybe also an optional set 4 if an engine requires one for lightmap baking. And then vertex colors could also be leveraged to store AO/cavity too ...
(of course the above would require to have a different material per ... material (!), as the tiling normalmap would need to be a full square texture of its own. But ! Imagining that one would need different sets of tiling details/normals for each material is just an assumption too. Maybe all materials could very well be described using a single tiling normalmap with a few generic dings and scratches, and the tiling diffuse and roughness could very well be generic stylized noise/paint strokes. Hence a single material and a single set of textures for everything. The tiling elements and surface damage are really just tertiary/most minor components of the overall look after all).
https://docs.unrealengine.com/udk/Three/TerrainAdvancedTextures.html#Texture Packing: Implementing large texture tile sets
A similar multi-uv method
https://polycount.com/discussion/comment/1588220/#Comment_1588220
(see earlier wiki link for additional examples)
@ Pior,
I was also considering a horizontal strip, where we would put the albedo on top, and then metalness, gloss etc always vertically below and work with UV offset to sample those, this would save you different sheets for metalness etc
Yeah values are important but I think we will have a real palette with fitting values in the materials
Adding another UV channel however would double the vertice count and Im not a fan of that performance loss
What we tried now with the Texture arrays is:
- Make base materials, put them into one array (one array for albedo, one for normal with gloss and metalness in blue and alpha)
- Make wear materials, in a secondary array as above, all with 128x128 or so tiling maps
- Use one RGB mask (r,g,b,yellow,teal,pink, black - depending on blending order this accounts to 7 masks) - to get 7 switchable materials (we also tried grayscale splits which would account to many more masks at shader complexity and painting confusion cost)
These masks are then used in a predefined fashion (base material 1-3, highlight metal, plastics, optional 1, optional 2 or such)
- Use one RGB mask for a wear mask, global roughness, global camo and secondary color mask (vertex colors could also be used, but any masking workflow is fine)
The wear mask is blending between the upper base material and the secondary wear materials (like dark rubber, and then bright worn rubber)
- The advantage is that we only need the basic UV channel (+ lightmap / trim uv) as its just used with masks
- You will mainly need to paint a wear mask to differentiate between top and low layer material and get realistic looking imperfections and with full tiling detail resolution
- You can build up a material library and use them throughout and swap them easily
- With the texture array workflow you can just input new texture arrays thematically (like swapping palette for a russian prop to a police prop)
but with the extra freedom of being able to change materials with just number changes (like police palette has 2-3 variations for their Highlight metal material)
- Compared to the UV workflow, after you have set the mask, you can just change a number in your material and swap out materials in runtime extremely conveniently, even if you have an in engine UV editor, this would be way faster and is very cool to do
- If you do it like us and many things with the same material, like sci-fi environments, you can then just scroll through materials and get a different style for the level in seconds, or just replace all chrome with copper
Edit: I guess you can also make that work in the swatch workflow with UV offsets
- Compared to the UV workflow you get tiling details for each layer
Disadvantages so far are:
- You need to paint the masks in relative abstraction (although could be solved with a example shader in painting apps - this only works if you keep a pattern tho)
- if the masks are too low res, you need to be careful with baked details, like screws, although those wouldn't work at all with the UV based workflow
- Of course do you need a lot more memory than the swatches, which could be just 4 pixel per material, but should be no problem depending on your usage
- Switching materials in the texture array is more effort than changing a swatches texture
- Arrays only work above shader model 3.5
This array stuff seems extremely powerful and Id really recommend looking into those
Tried this UDK approach in Blender and the seams are pretty strong if the texture quadrants differ from each other color wise. In distant mip levels especially. Wonder have modern support in Dx11/12 fixed it somehow?
http://oliverm-h.blogspot.com/2013/04/how-to-create-ue3udk-texture-atlases.html?m=1
That link is from here
http://wiki.polycount.com/wiki/Texture_atlas#Tutorials
https://shaderbits.com/blog/tiling-within-subuv-or-volume-textures
- Note that this doesn't only work with volume textures, but works with any type of atlas (volume texture is an atlas of slices basically) and you would run into issues, regardless if its a 2d or 3d texture. Flipbooks with details reaching the edge can also suffer from this (as its shown in the post).
Another thing that I can confirm is that the wider border may still be needed, because viewing from a grazing angle still shows the neighbour tiles a little bit. But its hard to spot when viewing it from far. I only used 1 px padding:
Textures used:
Without padding:
With padding:
- You can't use mips
- The 1px border is still needed, if you want to have any texture filtering
- ???
So its better to have individual textures.
give it a try if you haven't
Edit - I just found a post on their forum. It has a lot of bullshiting, but one guy found that using "r.AllowTexture2DArrayCreation 1" in the console enables them...Wtf...
If you use it, make sure to put it into an ini file so you don't have to re-enable it every time you open the editor. On the other hand, the previous forum post says that it does not work in a material so I guess we will have to try and see:
https://forums.unrealengine.com/unreal-engine/feedback-for-epic/116810-texture-2d-array-support/page4
I would assume they create a gigantic volume texture from the list of textures, because of the way it works. Like putting all texture on top of each other and select which one is needed by changing the z coordinate. I may be wrong though. Also, I don't get why is it not exposed, why are they saying that it doesn't work when actually it does.
Texture arrays are big lists of separate texture files that are treated like a single map at the time they're drawn- you could think of them as being a little like UDIMs in that you access a specific texture by index.
You get the one draw call benefit of using an atlas without the limitations on tiling and the seams.
The downsides are added complexity in terms of setting it all up at the engine level and the fact you have to load all the textures in the array at once (dx12 fixes this I think)
In terms of authoring, on our own engine it's completely transparent to the artists, we simply flag a set of textures as being an array and they are compiled appropriately.
the array works by tricking the mip map function into storing more textures, very smart idea actually