Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Confusions about values passed by vert shader to frag shader

Discussion in 'Shaders' started by cwbeta, Sep 25, 2018.

  1. cwbeta

    cwbeta

    Joined:
    Jan 12, 2017
    Posts:
    30
    When I'm learning unity shader, I have a great confusion about the values passed by vert shader to frag shader.

    The vertex shader is only calculated on each vertex, while the frag shader is calculated on each pixel.
    Frag shader needs the data passed by vertex shader to work, but the sum of vertexes apparently does not match the sum of pixels, so how?

    Does vertex shader do interpolations in order to pass so much data to frag shader?

    Is there anyone who can explain this? Many thanks.
     
  2. neoshaman

    neoshaman

    Joined:
    Feb 11, 2011
    Posts:
    6,469
  3. jRocket

    jRocket

    Joined:
    Jul 12, 2012
    Posts:
    688
    Yes, it interpolates the values. This is why doing lighting in the vertex shader was very popular back in the day. It is much cheaper, as you only have to calculate the lighting for each vertex instead of each pixel.
     
    cwbeta likes this.
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,256
    Some pendantitry here, but no, the vertex shader does not do any interpolating. The vertex shader's only job is to process the data from a single vertex and pass it back to the GPU. The GPU then uses that data, along with two other vertices, to rasterize a triangle on screen. Depending on the GPU's architecture, the data sent to each fragment shader is interpolated with additional specialized hardware, or it is done in the fragment shader itself and each pixel gets the data from all 3 vertices and the barycentric coordinate for that pixel.

    Now understand when I say the fragment shader is doing the interpolation, I don't mean the shader you wrote, but specifically the shader that runs on the GPU. Just like most computer code people write today, that's not what's running on the GPU. When you write a shader for Unity you're using HLSL, or High Level Shader Language. The GPU is running a compiled version of the shader written in shader assembly code specific to that GPU. Between the shader you write and the one that runs on the GPU, there may be 3, or even more "iterations" of that shader, especially with Unity. For example, here's the path a surface shader takes going from the file you write to running on a Windows DirectX GPU:
    1. The Surface Shader written in a .shader file. This written in HLSL
    2. The vertex fragment shader generated by the Surface Shader parser. Still HLSL.
    3. One of many potentially hundreds or thousands of shader variants is generated by the shader preprocessor. Also still HLSL.
    4. The variant is passed to the DirectX Shader Compiler, which outputs to DXBC, or DirectX Bytecode, or alternatively DXIL, or DirectX Intermediate Language. This is an intermediate shader format that is still hardware agnostic. It in no way resembles the HLSL code you original wrote and is closer to assembly in terms of the instructions it contains. If you select a shader and click on the "Compile and Show Code", the instructions you see are what are contained in this version.
    5. The DirectX drivers for your GPU takes the DXBC or DXIL shader and parses it, sometimes making modifications or completely replacing parts of, or all of it with further optimizations.
    6. The DXBC or DXIL shader is then compiled into GPU specific assembly code which actually runs on the GPU.
    I might be missing a step in there too. If you're targeting something other than DirectX on Windows, there's going to be another step or two between steps 4 and 5 which take the DXBC/DXIL and passes it to a translation tool that will output a shader in the language needed for that platform. Then you start over at step 4, only replace "DirectX" with "OpenGL", or "Metal", or "Vulkan", etc.



    ...

    But back to the original question. Yes, the values are being interpolated. As far as the shader code you write is concerned, you only get the interpolated value and not the value in each vertex. Even if all 3 vertices have the same value, the value the fragment shader gets is still interpolated, and may not even exactly match the value in the vertices due to floating point math.
     
    xVergilx and cwbeta like this.
  5. cwbeta

    cwbeta

    Joined:
    Jan 12, 2017
    Posts:
    30
    Thanks for all the replies above!