Home Technical Talk

Vertex colors for storing PBR information

andrad
polycounter lvl 5
Offline / Send Message
Pinned
andrad polycounter lvl 5
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

  • thomasp
    Offline / Send Message
    thomasp hero character
    wouldn't it go both ways - if you need to change the mesh you'll also have to update the vertex colors every time.

    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.
  • radiancef0rge
    Offline / Send Message
    radiancef0rge ngon master
    What do you think? Is this a sensible approach or am I still making my life harder than it needs to be?

    This - just use textures, using vertex color will over complicate your workflow. 

    http://polycount.com/discussion/comment/2560440 

  • Axi5
    Offline / Send Message
    Axi5 interpolator
    Agree with above.

    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.
  • pior
    Offline / Send Message
    pior grand marshal polycounter
    It's totally doable, and works extremely well. What you have to do is not to store the PBR information directly in the vertex color themselves, but rather, use the vertex colors (or material IDs) to separate the model in chunks and then modulate that in your material nodes. UE4 does this very easily and you can save a ton of time and resources doing things this way.

    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).
  • radiancef0rge
    Offline / Send Message
    radiancef0rge ngon master
    pior said:
    It's totally doable, and works extremely well..
    Fair counter - if the art style allows, I agree with @pior
  • andrad
    Offline / Send Message
    andrad polycounter lvl 5
    Axi5 said:
    At the moment you're trying to reinvent the wheel, by replacing it with a square.
    Ha, nice. I thought as much.
    The question you need to ask yourself is: What am I trying to accomplish?
    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.
  • Axi5
    Offline / Send Message
    Axi5 interpolator
    Okay, I can see those points but do you have any examples where you're running out of texture memory using common methods? Perhaps you find something limited using them? Sampling a texture isn't as always as expensive as people believe.

    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.
  • pior
    Offline / Send Message
    pior grand marshal polycounter
    @andrad : Storing AO as vertex color data does not necessarily mean that you would multiply it over the color at all times. Modern game rendering techniques access and show the AO texture pass only when/where needed, selectively (for instance to have some nice occlusion effects in the places where direct light doesn't hit). Thus, one could put together a UE4 material in which the AO input is not a texture, but a black and white VC channel. Which can be then used as straight up AO in rendering sense, and/or as a slight overlay on top of the color if needed, and/or as a cavity pass to add roughness in the cracks, and so on. The possibilities are endless.

    @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).
  • andrad
    Offline / Send Message
    andrad polycounter lvl 5
    @pior: Alright, so it seems AO is a valid candidate for being stored inside vertex colors, provided the mesh is of high enough detail and the renderer is capable of selectively applying it where the lighting conditions are right. Thanks, I'll keep that in mind and see what I can do with it.

    @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.
  • ZacD
    Offline / Send Message
    ZacD ngon master
    If there's a hard seam between metal and non-metal, I don't see any issues with using vertex colors to control the masking. 
  • Noors
    Offline / Send Message
    Noors greentooth
    Sure it's doable. A long time ago, when textures had huge memory impact, everything was lit with vertex color, so you had to cut the meshes for shadows, etc...Then it was used only for AO. Again, your mesh have to be cut and thought for it.
    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

  • Carlosan
    Offline / Send Message
    Carlosan polycounter lvl 10
    You can do it on 3DCoat 2021.62 and up
  • sprunghunt
    Offline / Send Message
    sprunghunt polycounter
    I've been experimenting with storing a AO, curvature, and mask map in vertex color and then using that information to drive masks within a shader. This works because I'm also using Nanite in Unreal so those meshes are very high vertex count. You can see a quick flash of just the vertex colors at 0:03 in this video of my latest project.

    https://youtu.be/HXD6qF5hysg?t=3
  • radiancef0rge
    Offline / Send Message
    radiancef0rge ngon master
    golly thats a necropost from 2017
    looks dope @sprunghunt

Sign In or Register to comment.