hello fellow polycounters,
I am seeking advice concerning best practices for providing maps in the metallic/roughness PBR workflow. The tldr version of my question is this:
Do you think it is a good idea to use vertex colors to provide roughness and metalness information if it saves on texture samplers?
I have experimented with this in the past, sometimes excessively, where I would have vertex color red for roughness, blue for metalness, green for primary (< 0.25), secondary (< 0.50) and tertiary colors (< 0.75) and emissive areas (> 0.9). I then would have used one linear-color spaced texture where each channel contained things like scratches or macro variations that were multiplied with the corresponding vertex color values. This afforded me a lot of variation on a single mesh and a lot of reusability between a relatively small amount of different textures.
Until I ran into the first problems with scalability. Authoring assets this way would hardcode metal and roughness information directly into the mesh, which means I would need to re-author the mesh if I wanted to change these values. If I wanted to use the same mesh in a metallic and non-metallic version, I would have to maintain two versions of the same mesh with just the vertex colors being different! That's just crazy. On top of that, if I wanted to use the same material on multiple meshes, I'd have to make sure they all follow the same vertex color layout. I came to the conclusion that this hassle was not worth saving a couple of megabytes in texture memory. I also should point out that I do not develop for mobile platforms.
Still, I would like to use vertex colors in a productive way. I feel I have these color channels lying around instead of being put to use. I am now thinking about a moderate use of the aforementioned workflow:
I'd use a completely texture-based workflow for "materially" complex assets (think bicyles or car interiors), hero assets and characters. This would be the way most of us are constructing their materials. For relatively statc, large-area tiling surfaces I would try to use one vertex color channel to encode the metalness value. The reasoning behind this is that for stuff like sci-fi corridors, car exteriors and the like, what's metal and what isn't doesn't change much between vatiations of the asset. All other parameters would be controlled by texture inputs.
What do you think? Is this a sensible approach or am I still making my life harder than it needs to be? I realize that this is in part heavily opinion-based and opinions are therefore very welcome.
Best regards
Replies
overall i think it mostly depends on the functionality you have available to apply and preview vertex colors vs doing it via textures and how easy it is for vertex colors to get lost in translation.
personally i've not come across a truly nice vertex color toolset that would make me want to work this way. i've also not seen the process of copy/pasting or deriving vertex colors from a texture working in predictable enough a manner to fully rely on that.
therefore when i use vertex colors it's always a final step, like applying tweaked vertex normals. too easy to lose work to be good for more - for my taste.
This - just use textures, using vertex color will over complicate your workflow.
http://polycount.com/discussion/comment/2560440
The question you need to ask yourself is: What am I trying to accomplish?
And then take the necessary steps to outline that.
At the moment you're trying to reinvent the wheel, by replacing it with a square.
For instance you could simply store vertexcolor AO in R, and then simply use material IDs to apply materials at will. With some cleverly designed tileable overlays you could get some very clean results, since the materials could call the AO stored as vertex colors, modulate its intensity, combine it with overlays, multiply by colors or gradients, and so on.
But of course the asset would need to be planned that way right from the start, with materials being cleanly separated per polygons. Good for clean hard surface accessories (sunglasses...) and some props (clean modern chairs, archviz elements, and so on).
My main goal with all of this was to 1.) save texture memory by using vertex rgb instead of texture rgb channels, and 2.) maybe save some computing cost since vertex operations are usually faster at least as long as there are less vertices on the mesh than pixels in the texture.
One thing that I know is common but I want to avoid as much as possible is storing AO in the vertex colors. Mainly because AO is lighting information and lighting information does not - to my understanding, at least - belong to the mesh but to the scene that lights it. Really small cavities are probably the exception, but expressing that level of granularity with vertex colors would require really high-poly meshes, I think. Having said that, my experience with baking AO to vertex colors is limited, so some of the above might just be wrong.
There might be other solutions to solve your problems, or ideas. Or maybe the problems aren't problems at all and this could just be pre-optmisation, a bad habit we all have to break sometimes.
@Axi5 : While there are performance benefits, imho the most impactful aspect is visual. An asset designed to work that way would naturally need to be built very cleanly, favoring modeled details over a traditionally baked high to low. This works especially well on facial accessories that are tiny and thin but seen close-up in a character selection screen for instance (hence the earlier example of sunglasses).
@Axi5: I am indeed not facing any problems right now. My motivation is to experiment and establish a workflow before I start on the bulk of the work. I'm familiar with the dangers of premature optimization, but I think this is not (yet) a case of it... I can quit any time I want! ☺
Anyway, thanks so far for the responses. The consensus for now seems to be that sticking to textures for PBR information will probably save me some headaches and that I should be wary of overdoing it with packing too much information into the vertex colors.
But usually metal and gloss are stored in different channels of the same map, so there's no really loss of vram. Also the texture size could be minimal for an object with few variations. you should run some tests depending of the platform to see if it is useful. Vertex color could also be used instead for stuff like masking, cheap animations. For instance here the animation is using vertex color for direction etc : https://www.youtube.com/watch?v=eVnt0oXULTA
http://blog.nordeus.com/art/50-shaders-of-forge-prototyping-with-shader-forge.htm
https://youtu.be/HXD6qF5hysg?t=3
looks dope @sprunghunt