Search Unity

Question Performing math per vertex/fragment

Discussion in 'Shader Graph' started by arkano22, Oct 4, 2021.

  1. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    Hi there,

    I'm translating a small hand-written shader to Shadergraph: all my shader does is take some per-vertex data, and perform some simple math in the fragment stage after the data has been interpolated.

    However I hit a wall: Shadergraph insists on performing this math per-vertex, and I couldn't find a way to specify this *must* be done in the fragment stage. Watched tons of Shadergraph videos, read the documentation, but there's no mention of this anywhere except this:

    https://docs.unity3d.com/Packages/com.unity.shadergraph@7.4/manual/Shader-Stage.html

    Mentions shader stages, but apparently there's no way to control which stage your nodes get added to. There must be something very simple I'm missing, can you help? (Unity 2019.3.10, Shaderlab 7.4.1, URP)
     
  2. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    You might want to update to 2020 or the newest. You can do a few more things with the shader graph but I'm not sure.
     
  3. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    Looks like all 2020 (shader graph 10) does is separate the master node in a "stack" with two sections, vertex and fragment, cosmetic change but as far as functionality goes the inputs are still the same as the master node. I couldn't get this working there either.

    The documentation about the Normal Vector node goes:

    "Provides access to the mesh vertex or fragment's Normal Vector."
    (https://docs.unity3d.com/Packages/com.unity.shadergraph@7.4/manual/Normal-Vector-Node.html)

    Vertex or fragment normal vector, but how do I select which one?? Is this automatic? If so, how does the compiler determine which is used?

    Edit: just found out about SG10's custom interpolators feature. This does give finer control about how data gets passed from the vertex to the fragment stage and solves my issue, but my original question still applies to previous SG versions since I need this working in Unity 2019: is it possible to explicitly ask for per vertex/fragment data or manually influence which stage does each node get added to? Seems pretty darn basic functionality to be missing....
     
    Last edited: Oct 5, 2021
  4. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    You probably need to hand write shader code for what you need in 2019.
     
  5. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    This is a built-in pipeline shader that I'm converting to HDRP. Been trying to hand-write it for the past 3 months with no luck, most of the time spent reverse-engineering HDRP. Since the recommended way to go for simple shaders is using ShaderGraph, that's what I'm trying to do. However it does not seem to cover anything beyond basic use cases (and even then, only certain basic use cases from what I've seen so far).

    This shader is about 5 lines in the vertex shader and just 2 lines in the fragment shader, doesn't do anything exotic. If anyone has any tips on writing shaders for HDRP that is actually feasible and does not require to tear apart the entire render pipeline, I'm all ears. :/
     
  6. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    SRP is missing a lot of features and I think 2021 will be the first unity version with usable tools (especially URP).
    It might be trivial, but from what I know it is not possible unless you write custom SRP. Without custom interpolators you can only modify normals and vertex position in vertex stage, so if you need something more you must write shader.
     
  7. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    In your SG 10 custom interpolator shader file, select on the file and click on compile and show code. That might give you a hint on how it is written.
     
  8. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    A +10000 lines of code monster shader pops up. Not even going to try taking that apart when the original is less than 20 lines long in total.

    Guess I’ll have to desist on working with HDRP for now.
     
  9. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    Question would be why you need shader graph to make this shader? If you already have shader in text form can't you just change it to work in HDRP?
     
    mistergreen2016 likes this.
  10. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    This shader does basic lambertian lighting using the main directional light dir/color. This is very easy to do in both built-in and URP since light direction and color are exposed as macros in the shader.

    Haven’t found a way to do that in HDRP, so I tought using shadergraph would be the way to go if I wanted any kind of integration with the lighting system. All I need is a poor-man’s lit shader.

    If you’re curious, the shader is a spherical particle billboard impostor. For each particle, the mesh contains 4 vertices collapsed onto a single point. The vertex shader expands vertices in view space to create a camera-facing quad, and the fragment shader calculates per-fragment sphere normals and does a dot product with the light direction to get some basic shading.The result is a lit sphere made of just 2 tris.
     
  11. Qriva

    Qriva

    Joined:
    Jun 30, 2019
    Posts:
    1,314
    I used HDRP once and for very short time, so I don't know exact differences but it should be doable. Actually URP does not expose light properties, I think I always used custom node to get it properly.
    No clue how to do this in HDRP, but you could even hack it by making script on your main light to set global shader properties and then read them in shader, however I would not push myself into HDRP no matter what if that means a lot of trouble.
     
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,348
    Writing a shader by hand that works with the URP's lighting is fairly straightforward.
    Writing a shader by hand that works with the HDRP's lighting ... just yeah, no. Don't even try to do it. Use Shader Graph.

    What input on the master node / master stack your nodes connect to controls what stage they get calculated in. If your nodes connect to the vertex position, vertex normal, or vertex tangent, it's done in the vertex shader stage. If it's connected to anything else it's done in the fragment shader stage. If for some reason you have nodes that connect to both, they're run twice, once in the vertex and once in the fragment.

    Prior to SRP 10 you have no way to calculate data per vertex and pass it onto the fragment. You also have no way to control how data is interpolated. It will always be passed to the fragment shader using linear, perspective corrected interpolation. Some nodes also do completely different things depending on if they're being used in the vertex or the fragment. The Normal Vector for example, if used in the vertex shader stage, that's getting the original mesh normal and transforming it into the space you request. If used in the fragment shader stage, that's getting the world normal (which is the only normal Shader Graph passes from the vertex to the fragment) and transforming that into the space you request. It will also be with whatever modifications you might have done to the vertex normal if you're connecting nodes to that input on the master node / stack. The same is true for the Position node (though some versions of Shader Graph transform the position into world space first even in the vertex shader). There's no way to get the original vertex position or normal in the fragment shader if it's been modified in the vertex shader stage, unless you store that data in an extra UV set on the mesh itself.
     
    arkano22 likes this.
  13. arkano22

    arkano22

    Joined:
    Sep 20, 2012
    Posts:
    1,928
    Thanks Ben, it's reassuring to know that I'm on the right path. My brain hurts from looking at HDRP innards. Also thanks for the very detailed explanation about how SG deals with shader code generation.

    That's a bummer :(. I can't work around this in 2019 then. This work I'm doing is for an asset of mine, so I'll either have to wait until I can drop support for older Unity versions or make a patch/add on for newer Unity versions.
     
  14. mistergreen2016

    mistergreen2016

    Joined:
    Dec 4, 2016
    Posts:
    226
    I'm working with URP, the shader graph code for that is 10000+ lines of code as well.
     
  15. BOXOPHOBIC

    BOXOPHOBIC

    Joined:
    Jul 17, 2015
    Posts:
    509
    Hi. I can only recommend amplify shader editor, as it works in all pipelines and you can pass vertex to fragment easily, by simply using the vertex to fragment node. It will generate all the needed interpolators automatically.

    The second best part about it is that you can create custom shader templates to work with the graph.

    It still have some missing passes for hdrp, but for the most parts it works perfectly.

    Hope it helps :)