Oddity With Bump ?

  • Oldenburg was asking about creating water drops using the bump channel and I suggested using a normal map instead, although I'd never tried it. So I decided to try it myself. I created a procedural shader that produces a normal map for a hemisphere fitting into the UV map. One of the intermediate nodes can also be used as a bump map.
    Here's the shader (both normal and bump are connected, but that's just for the screenshot):
    (note the Math_Functions_20 Abs is there because the subsequent Sqrt node seems to produce a NaN result for -ve inputs which causes odd things in later nodes. Oddly making Math_Functions_20 a Clamp didn't fix it. Also the Math_Functions_10 Add bottom right was going to be used to control the radius of the hemisphere, but I haven't got to use it yet)

    I applied this shader (in PP2014) to a 1" x 1" horizontal plane (specifically a 4 vertex/1 face UV-mapped 1 PNU x 1 PNU square scaled to 0.00969). Illumination is a single infinite light at 45 degree elevation to the NE.

    Connecting only the normal channel it renders as I'd hope:

    Connecting only the bump channel... well... looks like a cone to me:

    I assumed that I'd connected the wrong node, but it's the same Sqrt node that's driving the blue channel of the normal map. Note my display units are inches, so bump is 0.5", matching the sphere radius and the 1" x 1" plane

    Can anybody spot my mistake?

    Or can anybody reproduce this in Poser 11? (I'll upload the shader if anybody wants to try)

    (and yes, I'm aware that water droplets on a surface aren't hemispherical !)

  • I next tried the above test using 0.5" displacement instead of bump and the thing was almost flat. So maybe it's something to do with the very small scale (0.00969) - 1" x 1" is very small for Poser ?

    So I tried the original bump/normal test but with the plane at normal size, i.e. 1PNU x 1PNU (103.2" x 103.2"), setting the bump value to 103.2" (I know it should actually be half that, but I've already rendered and composited the result and it proves that the problem was to do with my test. Now the version using bump looks correct, and the version using normals doesn't. So I reckon my calculation of the normals is not quite right.


    So the question is now can anybody see what's wrong with my calculation of the normal map ?

  • Here's what the normal should be (I think). Directions are in relation to the material room thumbnail, i.e. looking straight down onto the plane:

    red: 0.0=left, 1.0 =right. (0.5= no left/right component to normal). World X-axis
    green: 0.0=down, 1.0=up. (0.5= no down/up component to normal). World Z-axis
    blue: 0.0=away (into the screen), 1.0=directly toward you (out of the screen). World Y-axis

    Sum of red + green + blue = 1.0 (there's a definite error here, and I mean in addition to the missing multiplier of 2 for each component!)

  • (of course I mean the square root of the sum of the squares of red, green and blue co0rdinates = 1.0, not just the sum of the values = 1.0 ...)

    Still can't see what I've done wrong. I added a few nodes to the bottom of the shader to show me the square root of the sum of the squares of red, green and blue coordinates:


    Ignoring the bit outside the circle (plan view of the hemisphere) it's obviously not 1.0 for the whole circle, so something's not right)

  • Just baked a normal map of a hemisphere in Blender - by comparison my mat room generated normal map looks distinctly wrong (assuming of course that I baked this normal map correctly in Blender!)
    0_1496139355563_1 HemisphereNormalFromBlender.jpg
    If I apply this normal map (in tangent space) to my 1PNU plane (lit from NE at +45degs) and render I get this weird result:

    I don't have a clue what's going on. The procedurally generated hemisphere bump map applied to a non-scaled-down plane is the only one that seems right now.

  • This was only intended to be a quick and easy comparison of renders of a hemisphere using bump and normal maps :oS I seem to have:

    1. Odd behaviour of bump when object/scale is very small
    2. Normal map not rendering as expected

    I think I'll just pretend I never started this thread...

  • Poser Ambassadors

    I just started analyzing what you're doing vs. what you should be doing. Care to stay?

  • Poser Ambassadors

    My first difficulty with your first post is you calculate radius from 0 to .5 whereas I always calculate it from 0 to 1.

    The difference results in rather severe contortions to renormalize on your part where I don't have to. But that doesn't mean your OP is wrong. Just that it's hard to reason about it.

  • Poser Ambassadors

    Rather than be influenced/confused by your shader, I started my own. Here's mine.

    I am using a 12 inch square of my own construction, so I'm creating a hemisphere of radius 6 inches.

    My calculation starts with 2 * U - 1 and 2 * V - 1, resulting in -1 to 1 as my x,y coordinates. A simple Sqrt(x^2 + y^2) [not shown] gives me distance (d) from center on the 2D circle. For the bump height I need h = 6 inch * Sqrt(1 - d^2) which is what you see calculated here into the PoserSurface. For the CyclesSurface I use the Bump node which strictly is meters. Regardless of which root I render, the image is the same.


    Note: My sun is up 80 degrees, so 10 degrees off the vertical.

  • Poser Ambassadors

    I want to point out that in the Cycles root above, the shader IS USING A NORMAL MAP.

    I know you don't see a normal map there, but there is one. It's the output of the Bump node.

    However, it is not a tangent space normal map - it's the actual normal!!!!

    I believe you're trying to figure out how to make a tangent space normal map, right? The kind that you plug in to the PoserSurface Gradient_Bump input.

  • Poser Ambassadors

    I'm still reading the first post and I'm very confused by the shader nodes.

    You asked if I can spot the mistake? Well I can't because I have no idea what you're doing there.

    What formula are you implementing, first of all? If the formula is wrong, then the nodes don't matter.

  • I tend to confuse myself a lot ! Just took a break - reading your posts now.

  • Poser Ambassadors

    So I'm seeing the User_Defined assembly appears to be trying to calculate the normal vector from its xyz triple components.
    But - it's wonky.

    For the x component you feed U - .5 + .5 which is just U. So your x component varies from 0 to 1 and that seems about right but it's a wonky way to do it.

    For the y component similarly you feed V - .5 + .5 which is just V. Same comment.

    Now the z component (blue) seems wrong to me. It appears to be assembled as follows:

    x = U-.5 (varies from -.5 to .5)
    y = V-.5 (varies from -.5 to .5)

    d^2 = x^2 + y^2 (Math_Functions_38, varies from 0 to .25, center to edge)

    Abs(.25 - d^2) (Math_Functions_20, varies from .25 to 0, center to edge)

    Sqrt(Abs(.25 - d^2)) (Math_Functions_11, varies from .5 to 0, center to edge)

    I believe this should not be .5 to 0, but rather 1 to 0, like my height node, my Math_Functions_7.

  • Poser Ambassadors

    Grrrrr. Even when I use my height map calculation (spherical center 1, edge 0) I still don't get a match between the bump map and the normal map. I get a mismatch both in FF and SF but the mismatch is different for each.

  • I'm half-asleep at the moment (and likely half-asleep when I was doing all this too). but yes.

    The radius of my hemisphere's 0.5, the distance in the UV plane to any point (u,v) on or within the hemisphere is r = sqrt( (u-0.5)^2 + (v-0.5)^2 ), and I'm trying to calculate the height of the hemisphere above that point in the UV plane using h = sqrt ( (hemisphereRadius)^2 - d^2 )

  • Poser Ambassadors

    I just discovered that in SuperFly, I get a match when the blue color is from 1 to .5, not .5 to 0, not 1 to 0.

    So apparently SuperFly believes that a tangent space normal is fully capable of pointing in any direction, even having a negative Z. This is a surprise.

  • The redundant -0.5 and +0.5 math nodes... well, like you said, wonky !

    And bump and normal map versions rendering differently - so it's not just my imagination then.

  • I have to go - I'll be back (and hopefully awake) later

  • Poser Ambassadors

    I opened up Poser Pro 2014 just to confirm my findings because they are strange.

    Here are my findings:

    • As with red (x) and green (y), the blue (z) value is scaled identically. So the blue value for forward-facing/outward normals always has a positive z and therefore the blue value is always at least .5. A blue value of 0 indicates a reversed normal pointing straight into the surface.

    • FireFly does not use the blue channel value from the normal map AT ALL. It calculates it on its own using exactly the equation you were trying to build with nodes. You don't need to plug anything into the blue channel to use a constructed normal map -- all that matters is that the red and green are set correctly.

    • FireFly appears to be calculating the actual normal incorrectly. I have always suspected this as every time I constructed a normal map image from a bump map image, the FireFly render with the normal map NEVER matched that of the bump map from which it was derived. It may be that FireFly is using the wrong mapping for blue value. As a consequence, it is impossible to get FireFly to render the correct normals using a normal map.

    As I said, I am able to exactly reproduce results in SuperFly with correctly derived normals based on a height map using the hemisphere construction.

  • Poser Ambassadors

    Note that I will probably get lots of users objecting that they've used normal maps just fine for years.

    That is easily explained without contradiction of my findings.

    Here is the explanation:

    You never cared that it was wrong because you only did modest normal map deviations. The error I see in FireFly is only severe for normals pointing way off center. For normals that are only slightly off center, everything is directionally correct and only going to be noticed if you really pay attention to every little detail of a reference image from a renderer that is built correctly.