Search Unity

  1. Unity 2020.1 has been released.
    Dismiss Notice
  2. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Proper Way to Add Vertex Normal In Vertex Shader

Discussion in 'Shaders' started by AhSai, Aug 10, 2019.

  1. AhSai


    Jun 25, 2017
    I have a flat water plane with just a normal map as ripple, and I am trying to add a simple black and white texture to represent a bump behind a boat. In the vertex shader, I use tex2Dlod to read the texture and displace the corresponding vertex position, and use the same texture to create a normal map from greyscale and add it to my vertex normal (just a normal addition with y and z swapped). However, when I try to bring the scale of the normal up, it also flatten the normal for the rest of the plane (i think it is because of the normalize is saturating all the normals as a whole). So what is the proper way of adding the vertex normal within the vertex shader with a normal map?
  2. Invertex


    Nov 7, 2013
    Normals don't really have an intensity. You get a more intense looking normal by having a greater change in angles across the map. So what you want to do is multiply or pow() your grayscale before converting to normal to get a more widely varying normal map.

    As for mixing the normal with the vertex normal I'm not entirely sure in this case. I'd imagine you'd want to convert the map to object space and assign that value as your vertex normal, or use Unity's built in BlendNormals(n1,n2) function and with the vertex normal and object space converted map, but maybe someone else can advise on that better.
  3. bgolus


    Dec 7, 2012
    If you have a flat, axis aligned plane, and the UVs are also axis aligned, then there's no need to do anything with the original vertex normals. Just use the generated normal as is, with the components swapped to match object or world space.

    @AlanZucconi posted a tutorial on the topic just last month.

    The normal blend you are doing isn't going to produce great results. It's averaging the normals, which is almost never the correct option. @Invertex's suggestion of using the BlendNormals() function isn't totally bad, but any blend function is going to assume tangent space normals, or at least assumes a vector of (0,0,1) is the base surface normal. The blend function Unity provides is known as the "Whiteout" blend, and maxes out at perturbing the normal by 45 degrees. For displacement it's not unusual to need more than that on steep inclines. For that you probably want to use RNM blending.

    But, like I said, it's kind of moot since you probably shouldn't be blending at all.
    Last edited: Aug 12, 2019
    Invertex likes this.