Search Unity

Feature Request Getting Interpolated Vertex Values

Discussion in 'Shader Graph' started by dansitnick, May 9, 2019.

  1. dansitnick

    dansitnick

    Joined:
    Jun 9, 2016
    Posts:
    14
    Shader graph really needs a Position node for the fragment stage, where the value is read after the vertex displacement of the vertex stage.

    ------

    This is one of the most glaring issues of 5.13 that I'm seeing. If I were to set the Position parameter in the vertex stage, and then access the position again during the fragment stage, the value I would receive would not be modified at all by the vertex stage. Rather, I would get the same fragment position value if I hadn't updated the vertex position at all.

    This also seems to be reflected in the Screen Position node, which means it's very difficult to construct any shader that both displaces vertices and uses screen space effects.

    I'm currently using a really gross workaround that only works on planes, and any other uniformly spaced geometry with integer vertex positions.
    • Get the 4 surrounding vertex positions on each quad { (floor,floor) (floor,ceil) (ceil, floor) (ceil, ceil) }
    • Offset the positions by the displacement function
    • Determine which triangle the fragment is on (In my case, I compare (x - floor(x) > z - floor(z))
    • Using a custom node, get the barycentric (triangle) coordinates of the fragment's position https://gamedev.stackexchange.com/q...efficient-way-to-find-barycentric-coordinates. This will be a Vector3 whos values add up to 1
    • Multiply each vertex by its corresponding coordinate value (Vertex A * x, Vertex B * y, Vertex C * z).
    • Add the scaled vertices together. This will finally return the actual displaced position on the mesh.
    This is a lot of assumptions about the mesh, inefficient samples, and a ton of trial and error, just to adequately sample the Scene Depth on a vertex displaced shader.

    -------

    Additionally, the current behaviour of the Position node goes against its documentation because of this issue. https://docs.unity3d.com/Packages/com.unity.shadergraph@6.5/manual/Position-Node.html

    "Provides access to the mesh vertex or fragment's Position, depending on the effective Shader Stage of the graph section the Node is part of."

    Perhaps this is unintended functionality, and it'll be resolved in a future fix anyway. But if not, this would be extremely valuable.
     
    Last edited: May 9, 2019
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    I would say this isn't so much a feature request as a straight up bug. The world position that Shader Graph passes from the vertex shader to the fragment shader needs to be informed by the graph's manipulation of the vertices, otherwise lighting calculations will be broken by moving the vertices (and it currently is).
     
    DongJooByun and dansitnick like this.
  3. VirtualDarren

    VirtualDarren

    Joined:
    Apr 27, 2017
    Posts:
    2
    When is this bug going to be fixed?
     
  4. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,799
    If no one has done a bug report, it could even be never.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    I think it’s been fixed in the 2020 versions of Shader Graph?
     
    chrismarch and AcidArrow like this.
  6. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    i'm working on my first "complex" shader in shadergraph and for me it appears that at least "object position node" has the transformed position data after the vertex-position modification now. But what if i'd like to access the original position now? Is there a way to pass the unmodified vertex position from vertex stage to use it in fragment shader-stage?
     
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,352
    Nope.

    Best you can do is bake that data into a UV channel from script.
     
  8. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    hm that's inconvenient, i feel they should add sth. like a shader-stage-transfer-node. To work in vertex stage but output is fragment stage
     
    chrismarch likes this.
  9. olli_vrcoaster

    olli_vrcoaster

    Joined:
    Sep 1, 2017
    Posts:
    24
    upload_2020-3-17_12-49-10.png

    workaround with baking to uv1 works fine. Although mesh.uv are only Vector2. In my case no problem since i only need x and z position anyway.

    Here is the simple script i use to bake from editor:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [ExecuteInEditMode]
    6. public class bakeLocalPosToUV2 : MonoBehaviour
    7. {
    8.  
    9.     public Mesh baumMesh;
    10.     public bool bakeit;
    11.  
    12.     void Bake()
    13.     {
    14.         Vector3[] vertices = baumMesh.vertices;
    15.         Vector2[] uvPos = new Vector2[vertices.Length];
    16.  
    17.         for(int i= 0; i < uvPos.Length; i++)
    18.         {
    19.             uvPos[i].x = vertices[i].x;
    20.             uvPos[i].y = vertices[i].z;
    21.         }
    22.  
    23.         baumMesh.uv2 = uvPos;
    24.     }
    25.  
    26.     void Update()
    27.     {
    28.         if(bakeit)
    29.         {
    30.             bakeit = false;
    31.             Bake();
    32.         }
    33.     }
    34.  
    35. }
    36.