Search Unity

Feature Request Preskinned / BindPose vertex position

Discussion in 'Shader Graph' started by thelebaron, Apr 5, 2020.

  1. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    Is getting something like this feasible? Looking over the (fairly old now) gdc slides for L4D2 https://steamcdn-a.akamaihd.net/apps/valve/2010/gdc2010_vlachos_l4d2wounds.pdf as well as looking at how Doom Eternal handles destruction on their animated characters, from what I gather getting the vertex position from a bind pose is whats necessary to properly handle this type of effect, which afaik isn't possible currently(if it is, I'd love to be pointed in the right direction).
    I can see this being useful for more than just replicating dynamic damage systems, so I'd like to humbly request this feature :)
     
  2. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    also I would assume this request might also overlap with the animation department @Mecanim-Dev
     
  3. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    This wouldn't be a shader graph feature, it's not something that exist for any kind of Unity shader. Currently it's acheived by storing the original vertex positions in unused UV channels, either spread across two UVs if done in an external tool (as Unity is limited to importing 2 components per UV), or in a single UV set if done from script.
     
  4. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    Thanks, could you elaborate a little more on how to go about this? It sounds a little like the latter way might be easier to address unless this is something that most 3d dcc's have the ability that I am overlooking.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    3ds Max actually has a built in thing for this, but unfortunately it can only copy the object space XYZ to the UVW of a UV set, and Unity won't import the W component, only the UV. I suspect other dccs have something like this too. Though you can kind of get the Z manually by applying a planar UV and making sure the length & width is 1x1 in object space and make sure the corner is aligned to the pivot. Hacky, but doable. A little easier if you're okay scripting something in your dcc to do it.

    In Unity you can copy the vertex positions and set them on the mesh directly with something like this:
    Code (csharp):
    1. // set TEXCOORD3 to the object's vertex positions
    2. mesh.SetUVs(3, mesh.vertices);
    When you do that gets tricky. Once a mesh is imported to modify it you'd have to make a copy to modify that and save it as a new asset ... which in my experience is harder than it sounds for any skinned mesh and something always goes wrong. The alternative would be to use
    OnPostprocessModel
    to do the modifications on import. A common trick is to add some suffix or prefix to your source file name and do a string comparison of the
    assetPath
    to see if you should do anything extra to the asset.
    https://docs.unity3d.com/ScriptReference/AssetPostprocessor.OnPostprocessModel.html

    That function will give you the base gameobject of the mesh prefab. So you'd need to use
    g.GetComponentInChildren<SkinnedMeshRenderer>()
    to find the first skinned mesh (or maybe
    GetComponentsInChildren
    and iterate over the returned array).
     
    thelebaron likes this.
  6. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    upload_2020-4-13_17-33-59.png

    Thanks bgolus! surprised how simple this turned out to be, anyway just an image of it working(left is with the world space position and right is the new import pose position from uvs), if anyone else is interested https://github.com/thelebaron/rigged_mesh_culling


    I was wondering if I could pick your brain on doom eternal's approach. I'm not really sure on the overlap, my own guess is that l4d zombie wound models are all separate themselves as well as from the zombies themselves and something like this I see being more or less straightforward, pick and choose at runtime from a collection.

    But in eternal, all wounds per demon are contained inside as a single(generally speaking) merged mesh.

    For the sake of illustration: red dots would be any sort of visual damage mesh. They are also merged as one mesh(and a model may be composed of a multiple similar meshes containing many merged details that are shown individually depending on the context).

    Would this just be a variation of the mesh culling, ie having a culling sphere cover each individual part and then that is disabled to then show a wound? this seems like it could get expensive given some of the smaller demons appear to have near 50-100 sub meshes that could each be toggled on and off independantly.

    From an artistic authoring perspective, keeping it all confined to one model with only a few meshes keeps it simple, but programming wise I am left a little stumped on how they separate all that data out.

    upload_2020-4-13_18-47-26.png
     
    sterlingcrispin likes this.
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    The first L4D game had hand built full body models for possible wounds, up to 5 per base zombie variation. And it just swapped from the base model to a bespoke wounded model when one died if the damage done was to a part of the body that had a wound model.

    L4D2 changed it to something more like what you're doing, where it's using pose space projections to clip geometry & display blood splatter around the hole. Then it appears they made several types of reusable gore models that made up the internal body parts that are exposed as well as cover the edges. Their talk on it mentions they made 53 unique wounds, with up to 2 of them visible at a time per character.
    https://steamcdn-a.akamaihd.net/apps/valve/2010/gdc2010_vlachos_l4d2wounds.pdf

    Basically what that means is there were only 53 possible locations for wounds to appear per zombie type, and there's still a bespoke model for each wound type. The benefit is the wound meshes could be reused for each type of zombie rather than being limited to a zombie variant. (ie: a zombie with a jacket and a zombie with a t-shirt could both use the same wound meshes where as in the first game they had to make custom full body wound meshes for each of those.)


    What Doom Eternal is doing ... all I know about is the Digital Foundry video that talks about it briefly and shows a little video clip of wounds being activated in the editor. How it's described in the video doesn't really give any good information about the actual implementation. As much as I love the Digital Foundry guys and their videos, they're not devs and still come at things mostly from a layperson / player perspective, albeit a generally more technically savvy one. The most technical description they give is "multiple geometric layers sort of smashed together." That could describe many systems out there, including the L4D2 system, but I don't think it's exactly that system. They don't have to deal with the variation issues that L4D2 had. But at the same time it seems to be very similar.

    It's clear in playing the game there are 3 levels to the system. Intact mesh, a full body "under skin" mesh, and custom dismemberment meshes for glory kills / chainsaw kills / gibbed deaths. Most of the time when you shoot something "off" an enemy they don't actually remove that body part unless it's a full kill, usually it's just revealing an interior / smaller version of the body. With some weapons & attacks you can basically remove all of an enemy's armor & skin showing their bones and muscles without killing them. So my guess is they have hand authored masks and fill geometry for the outer skin layer chunks that can be replaced one at a time or in large batches and they've hand models all the possible (allowed) variations. They're also using big blood decals to hide any transitions. There's probably some amount of extra smartness in the implementation and authoring tools, and hopefully it's something they do talks on in the future, but so far there's been scant little official info. We'll probably see something around the Siggraph time frame (end of July) since that's when they did their talks on the previous game's tech. But mostly it's down to having a lot of highly skilled artists and the time & money to do it.
     
  8. thelebaron

    thelebaron

    Joined:
    Jun 2, 2013
    Posts:
    857
    upload_2020-4-15_17-58-37.png

    Heres a little more information on what Ive been able to glean from one of the extracted model(the soldier), each regular model (that as you mention isnt a specific glory kill/death model) contains several distinct meshes inside(each color block represents this, though the head, torso and legs are actually separate for the red zone, though I thought to just include it as one for the same of visual brevity).

    What perplexes me in terms of applying towards unity; is the middle/yellow chunk, given its one "mesh" yet in actuality many separate parts(I coloured some of them), which also has one shared texture, but each "part" is able to toggled on/off at will, as well as the corresponding parts around the other meshes.

    L4D2 applied generic ellipsoids to cull parts of a body mesh, but this approach seems a little more finer grained given some of the shapes of the wounds?
    I guess what I'm asking is there a way to pregroup these face/triangle selections and somehow toggle their visibility individually?
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Unity meshes can be several parts too. Most commonly because they have separate material IDs, but also if it has too many vertices or bones it’ll be split. These are stored as sub meshes. As far as the editor shows you, it’s a single mesh object. As far as the GPU is concerned it’s no different than separate meshes.

    You could replicate the Doom Eternal system by giving them each their own material ID, and only assigning a material to that index when you want it to be visible. If you leave it empty it won’t be rendered.
     
    thelebaron and Elizabeth_LeGros like this.
  10. sterlingcrispin

    sterlingcrispin

    Joined:
    Oct 23, 2013
    Posts:
    18
    hey thanks for posting this code snippet I was working through the same problem and was using textures this is a much cleaner solution than what I had going on
     
    thelebaron likes this.
  11. faulknermano

    faulknermano

    Joined:
    Oct 30, 2015
    Posts:
    2
    I am currently writing a texture bombing subgraph and been using object-spaced vertex position as my reference space. It didn't work so well during skinned mesh deformation, and that's why I ended up here trying to find a solution.

    The baked UV solution seems to be a good one, and even if there were an issue with the W component, I found that I can export 2 UV sets -- one mapped planar-z and planar-x, and that enough to work with.

    Thanks for the suggestions!