Search Unity

Proper Way to Add Vertex Normal In Vertex Shader

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

  1. AhSai

    AhSai

    Joined:
    Jun 25, 2017
    Posts:
    38
    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

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    895
    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

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    7,145
    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.
    https://www.alanzucconi.com/2019/07/03/interactive-map-01/

    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.
    https://blog.selfshadow.com/publications/blending-in-detail/

    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.