PBR node material with coarse roughness. Issue with non-omni lights

Hi everbody,
Im trying to immerse myself into the node material editor. I wanted to create course roughness, as you may find on real walls without using a texture. I managed to create a material that looks okeyish with hemispheric light but behaves badly with the other lights. The the link below you can compare the preview with the hemispheric light and the two directional ones.
https://nme.babylonjs.com/#IM8LYU

on a bigger scene I found a similar problem with point lights. I assume it is in the way I setup the perturbednormals but I cannot figure it out.

Thanks !
luis

cc @PatrickRyan

@lb_artworks, what you are seeing is coming from a couple of sources. I cleaned up your graph a little to help understand what is going on, but I also found something going on with the height to normal node that I can’t explain. Here’s the current iteration of the graph, so let me lay out what you were missing in the flow. The reason the height to normal node is wired to the frag out is to illustrate what is going wrong.

  • When you are applying any tangent space normal to the graph, you need to include a perturb normal node. This takes care of telling the shader how to interpret the vectors from the normal channels. So whether you are passing a texture or something you created in shader, you will need to wire the RGB channels to the perturb normal node. Going straight from the height to normal node into the perturb normal node will result in incorrect vectors being passed.
  • For PBR rendering to work with IBL lighting, you need to wire up a reflection node. If you don’t wire a reflection node, you won’t get any contribution from IBL to the material light, so your metallics will look wrong as they don’t have any contribution from the environment. Dielectrics will be wrong as well, but since you don’t see environment reflection until the material is set to a very low roughness value, it may be harder to determine that the render is wrong when using punctual lights and IBL just from looking at it.
  • The perlin noise node returns values from -1 to 1, where you likely want your height map to be using values from 0 to 1. Height maps usually define no change in a surface at a value of 0.5 since most height maps are saved as 8-bit files. This means converting your noise to be within the range of 0-1 will align with what is expected from height maps. Your use of a clamp will also work as it eliminates values out of range, but will result in more areas of flat. This may be what you want, but remapping the range also gives you more control over the shape of the normal since you can then step or smoothstep the noise.
  • When passing a color to the PBRMaterial node, you want to make sure the color is in linear space as that is what the node expects. Any color3 or color4 node in our graph will be in gamma space since it is using a gamma picker. The color you see when picking is also in gamma space so the result will look wrong unless you click the “convert to linear space” on the node options. This will put the color in the correct space for the calculations to be done and then the lighting output on the PBRMaterial node will automatically convert back to gamma space which is what the frag out expects. If you want to manually assemble the contributions (diffuse direct, diffuse indirect, specular direct, etc.) those are in linear space so you can simply add them together however you like. You will then either need to do a manual conversion to gamma space on the output, or use the much easier method of setting the parameter on the frag out node to tell it the data wired to it is in linear space and to convert to gamma space for you.

This next part is for @Evgeni_Popov. I am seeing values on the height to normal node that are not reasonable for a tangent space normal map. This is what is wired to the frag out to illustrate the lighting problem. I checked the node and it appears to be set to tangent space, which I would expect. I even normalized the world vectors coming into the height to normal block to see if there was anything out of the ordinary with the normalization parameters on the block. The data coming in seems reasonable, but I don’t know if I am missing something or if there is a bug in the node. Thoughts?

@lb_artworks, I will leave you with one more thought with this shader. Performance can be an issue here depending on how you are using this shader. I know you said you wanted to do this without a texture, and normally, that is due to wanting to limit texture loads and fetches. However, using a noise node in the shader means you are calculating the perlin value for every pixel the material renders every frame. If this is for a wall, I can imagine that this shader covers a large percentage of the viewport, which means a lot of calculations per frame. If you want a cheaper solution that tiles well, maybe look at channel packing a couple of height maps into one texture. You will still need one texture sample per UV scale/offset, but you can potentially hide tiling artifacts better if you are mixing height maps from different noise masks and then using a height to normal on the mixed noises. You skip a lot of calculation from the perlin operation based on position seed. This may be a middle ground for you to look at if you are worried about performance of potentially large tangent space normal textures.

Hope this helps, but ping back with more questions.

1 Like

The world position should not be normalized:

@Evgeni_Popov, even with the world position not normalized, the results don’t look reasonable for a tangent space normal.

I wouldn’t expect to see the shift in color for the entire face on the one axis - can’t tell if it’s X or Z. The hard changes in color around the bevel don’t look that out of the ordinary, but the entire face shifting toward yellow-green seems to be wrong. What could be causing this?

1 Like

Patrick, thanks so much for the thorough explanation. I need some tests and time to fully digest it and confirm the impact on performance.

1 Like

@PatrickRyan This is a problem with the preview window of the NME. This PR will fix it:

4 Likes

You’re the best, @Evgeni_Popov!

Thanks so much for looking into the problem !

1 Like