Search Unity

Question Any (better) alternative to Decal Projector for decals?

Discussion in 'High Definition Render Pipeline' started by dgoyette, Sep 9, 2019.

  1. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    I've been using the Decal Projector since I migrated my project over to HDRP, and I've generally been frustrated with it compared to the decal component I was using under the built-in renderer. There are two major issues that bother me about Decal Projector, but I currently don't know of any way to address the issues (even in terms of buying a better decal component for HDRP.) The issues are:
    1. No ability to limit the decal to specific objects. For example, I add an explosion decal to objects that are hit by an explosion. But this decal will paint all nearby objects, which looks really weird if some objects are moving. Ideally each decal would draw only on as single object, so the object can move and bring the decal with it.
    2. No angle limit on the decal. If a decal is placed near multiple surfaces, such that the decal is normal to one surface, it will look terrible if it happens to overlap another surface that's perpendicular to the normal. Here the decal is bleeding onto the wall:
    upload_2019-9-9_16-15-4.png

    I don't need triplanar projection here, I just wish the decal would simply not draw on surfaces if the difference between the decal's orientation and the surface's normal is higher than a certain angle. I can limit this ugliness to a degree by making the decal very thin, but then things don't look good if the surface is just a little uneven.

    The decal system I was using under the built-in renderer had features to address these issues, but Decal Projector doesn't. And from what I've been able to look up, Decal Projector seems to be very low on the HDRP priority list, so I'm not optimistic the HDRP team is planning to improve it in the foreseeable future. That leaves buying a replacement, or building a replacement on my own. However, I don't see anything on the Asset Store that doesn't simply reuse Decal Project without adding any new rendering functionality. And in trying to build my own, it seems that using a "Normal Vector" node in a Decal shader doesn't give me the normal of each pixel, and instead just gives me the normal of the decal itself. That is, I seem to get the same value from the Normal Vector node for every pixel, regardless of whether it's a pixel on the floor or a pixel on the wall. So, I can't use the dot product of the pixel's normal and the decal's normal to try to apply an angle limit.

    So, anyone have any advice on a better approach to decals that addresses one or both of these issues? Thanks.
     
    Last edited: Sep 9, 2019
    rz_0lento likes this.
  2. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Regarding the normal vector issue in a Decal shader, to clarify that, I made a very simple Decal shader, which just sends the normal vector into the base color:

    upload_2019-9-9_18-30-31.png

    I then put the decal next to a corner. My expectation here was that the normal vector would correspond to the individual pixels being painted, and that the color on the wall would be different than the color on the floor. Instead, it seems the normal vector is the same for every pixels painted by the decal. For example, here's the decal near the corner, with a sphere within its bounds:

    upload_2019-9-9_18-32-11.png

    I would expect that sphere to be painted in many colors, given the various normal vectors each pixel should have, but it ends up having a uniform color.

    Does this seem like a bug? I'm inclined to report it, unless someone thinks it's really supposed to work this way.
     
  3. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    246
    Thats not how it works, youre outputting the normals of the decal volume geometry (which are just not set, thats why you end up with result like this i guess). To get the correct scene normals, you'd need to sample them from GBuffer, but i dont think theres a node for shader graph to access GBuffer. You can try writing your own, _GBufferTexture1 texture is what you need to access.
     
  4. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Thanks for the reply, and that disappointing. I tried seeing if _GBufferTexture1 lead to anything, but either I don't know how it works (which is true...) or it's not accessible from ShaderGraph. I tried comparing the Normal Vector node output (which should be the orientation of the decal as a whole) against the GBufferTexture1 value, hoping I could adjust opacity to hide the decal if the Dot product was small enough. But the decal still paints every surface the same, regardless of orientation of the decal or curvature of the model:

    upload_2019-9-11_11-13-38.png

    upload_2019-9-11_11-14-48.png

    I'd still be interested in knowing if anyone else knows of a way to limit decal drawing on surfaces based on relatively angle of the decal to the surface.
     
  5. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    246
    You cant just declare it as a property and hope it will appear there. You'd have to remove that property and use custom function node for that instead. Also normals in that buffer are encoded in some way, you'd have to encode them as well.
     
  6. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Fair enough. There have been some other properties I could just declare like that and they worked like magic, such as _MainTex for UI shaders, but maybe that's an exception. (I think I remember some LWRP shadergraph shader that also just declared _CameraOpaqueTexture as a property to get some data as well.)

    So I tried to create a custom node to sample _GBufferTexture1, but that just results in 'Undeclared identifier _GBufferTexture1'. There's some information on acessing GBuffer here: https://forum.unity.com/threads/hdrp-post-processing-shaders-accessing-gbuffers.726158/ , including some mention of a DECODE_FROM_GBUFFER. And it's not related to shader graph, and I'm not sure what of that code can be moved into a custom function, or if that's even reasonable, or what the gbuffer data ultimately represents once decoded. :) So, clearly out of my depth on accessing this data.

    And bug picture, it seems that so far there are no suggestion of other approaches than the Decal Projector, which is also disappointing, but maybe it's representative of how this isn't yet a fully mature system on which people can develop complex custom functionality, and it'll just take some time.
     
  7. SebLagarde

    SebLagarde

    Unity Technologies

    Joined:
    Dec 30, 2015
    Posts:
    934
    Hi,

    we are well aware of this two issues.

    We have a plan for 1), no ETA but it wil come with a cost which is a worry for us currently.
    We will implement decal layer (like light layer) which require an extra UAV in an already bandwith heavy DBuffer pass

    For 2) yes it is a problem due to the technique we used.

    We use DBuffer pass for our opaque decal.
    (you can see the different pros and cons of various decal approach: DBuffer, deferred decal, cluster decal) in this presentation (slide 53):
    http://advances.realtimerendering.com/s2018/Siggraph 2018 HDRP talk_with notes.pdf

    upload_2019-9-12_21-44-44.png

    This is our choice for HDRP are there is no silver bullet as highlight by the table above.
    If we were using cluster decal for projector then we could do the angular fading, but then we should drop support of mesh decals.
    The consequence is that angle fading is a problem. The DBuffer pass happen BEFORE the GBuffer pass, so it is expected that you can't access surface normal or GBuffer as it doens't exist when we render decal.

    A coarse solution with performance hit will be to reconstruct the normal from the depth buffer (with forward difference method for example) and test the angle. This work but maybe not at the quality you expect.

    We are evaluating alternative method for angle fading, but no ETA.

    In built-in, decal from asset store work because they are all using deferred decals method. But see the above tab for the limitation of this approach.
     
    Jonjonbo, PutridEx, hertz-rat and 2 others like this.
  8. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    Thank you, I really appreciate the detailed breakdown. I wasn't aware of that table before, but I guess that explains why I could never apply decals to transparent objects back when I was using Deferred Decals under the built-in renderer. Thanks for the breakdown of the tradeoffs, which I wasn't aware of. I'm glad to know it's still a topic of investigation, even if it's probably not happening any time soon.
     
  9. jjejj87

    jjejj87

    Joined:
    Feb 2, 2013
    Posts:
    1,117
    Not a decal expert here, but in my limited experience in decals, mesh decals are sort of useless and has very limited use cases. It is a cool feature, but I wouldn't trade it for transparency support of decals or angle fading. If DBuffer is already a full bus, maybe it is better to change to cluster...

    As for HDRP decal system in general, I think there should be a color override like the fade override. Color can be changed via the shader at the moment, but I often found my decals need to change colors to match surface color. This forces me to make multiple copies of the same material with different color variations.
     
  10. DGordon

    DGordon

    Joined:
    Dec 8, 2013
    Posts:
    649
    May I ask what were really gaining with mesh decals? Im finding the angle stuff pretty annoying, as it applies to so many normal usages ...

    Am I missing some great common use case for mesh decals?
     
  11. SebLagarde

    SebLagarde

    Unity Technologies

    Joined:
    Dec 30, 2015
    Posts:
    934
    > mesh decals are sort of useless and has very limited use cases.
    Not the opinion of many of our users :)
    Best example of usage are describe by star citizen artists : https://polycount.com/discussion/155894/decal-technique-from-star-citizen but there is others source on the web.

    > it for transparency support of decals
    We support it. We use cluster for transparent.

    >If DBuffer is already a full bus, maybe it is better to change to cluster...
    There is other tradeoff. If you want to use shader graph for example. With DBuffer, easy. With cluster, it mean you should rasterize texture on the fly in the atlas, which have a cost, in particular if you do animation of decal.

    There is always pros and cons for every choice. What fit to your usage, may not fit for other projects. You are still free to customize thing :). Sadly regarding decal, there is no silver bullet like for others features :)
     
    Camarent and Korindian like this.
  12. nsxdavid

    nsxdavid

    Joined:
    Apr 6, 2009
    Posts:
    476
    @SebLagarde

    It's hard to understand what you intend to actually work with decals. We spray copious amounts of bullet holes and scorch marks in our level using deferred decals (in the standard RP) currently. These obviously have alpha (transparency). Is the HDRP going to support this essential approach?
     
  13. customphase

    customphase

    Joined:
    Aug 19, 2012
    Posts:
    246
    Thats not what they mean when they say transparency support. They mean the support for transparent objects to receive decals, something you can not do with regular deferred decals.
     
  14. dgoyette

    dgoyette

    Joined:
    Jul 1, 2016
    Posts:
    4,195
    So, despite losing angle support that I had with deferred decals under the standard RP, I was really happy that HDRP decals worked on glass. @customphase already answered it correctly, but in HDRP the decals themselves can certainly contain transparency, whether they're projected on opaque or transparent objects. Here are two decals, one on a wall, and one on a window:

    upload_2019-9-17_16-17-34.png

    Under the standard RP, the decal on the glass would not have shown up, as deferred decals apparently don't draw on transparent objects.
     
    Camarent and hertz-rat like this.
  15. jjejj87

    jjejj87

    Joined:
    Feb 2, 2013
    Posts:
    1,117
    That's exactly my point, the guys at Star Citizen use it to retain high resolution texture details while keeping the workflow and performance fast enough. But this is assuming the underlying texture is monochromic. eg. metal surface with more decals covering the surface.

    To me it sounds very case specific.

    In most use cases, outside of SC, the unlying texture is not monochromic, and hence usually have high enough textures and most details if needed, rendered with decals. Hence my point, very limited situations where it actually benefits.
     
  16. nsxdavid

    nsxdavid

    Joined:
    Apr 6, 2009
    Posts:
    476
    I'm somehow failing to grasp what the difference is of a decal that's used for rendering a bullet hole vs. one that's a detail on an object like used in Star Citizen. Sure one is dynamic, and the other probably static.... but other than that, it's still the same thing rendering wise, is it not?
     
    Ogham5tone likes this.
  17. Bordeaux_Fox

    Bordeaux_Fox

    Joined:
    Nov 14, 2018
    Posts:
    589
    Bump, still no alternatives to the current HDRP decal. I need a solution that works with very steep angles and can be animated. As our project mature, we came to the point were we really see the limits of HDRP which limit us in graphical quality and flexibility. :(
     
  18. SebLagarde

    SebLagarde

    Unity Technologies

    Joined:
    Dec 30, 2015
    Posts:
    934
    Hi, we have now added support for Decal Layers (in very latest 10.x-preview not publish yet). So you can solve the issue of which mesh are affected (for those ok to pay an extra cost). Work on angle fading will start (as it rely on the code done for decal layer). No ETA but should be a close future rather than a far future.
     
    N04H08, PutridEx and florianBrn like this.