[x3d-public] Calculation of normal from normalTexture.

Andreas Plesch andreasplesch at gmail.com
Sun Apr 3 08:16:46 PDT 2022


Thanks for your explanations. Some points below.

On Sun, Apr 3, 2022 at 1:02 AM Michalis Kamburelis
<michalis.kambi at gmail.com> wrote:
>
> In general, as both approaches make sense ("multiply only XY" or
> "multiply only Z"), for X3D it's better to just follow glTF.
>
> As for the rationale behind glTF decision -- one reason that comes to
> my mind is that in current glTF and X3D version ("multiply only XY")
>
> - if one wants to *almost* disable normal texture, then you can use
> just very small "normalScale" values.
>
> - and "normalScale" = 0 has (expected) result that "normal map effect
> is completely disabled".
>
> Whereas in "multiply only Z" approach, "normal *= vec3(1, 1,
> normalScale)", to deemphasize normal map one has to invent huge
> values, as normalScale must reach infinity if you want to really make
> normal XY irrelevant.

True, but the only time an author would want to use a normal map and
perhaps scale it, is when you want to show some detail which is
relevant.

In other words, to default normal is already 0,0,1, so why use a
normal map then.

In any case, I bet inventing a huge value such as 1000 for a normal of
(1,1,1000) which would correspond to 89.9 degrees away from the
tangent would not be an obstacle for any use case.

> And in this approach, "normalScale = 0" achieves
> normals that are always orthogonal to the surface (never "coming out"
> of the polygon), which I guess is less often a useful effect, or maybe
> it seems less natural.

Yes, 0 would not be useful.Probably, this is the underlying rationale
since it may be difficult to explain that to authors. But it may be
just a convention.

In a similar vein, the impact of going from 0.3 to 0.2 would be huge
while going from 0.8 to 0.7 would be small.

With xy scaling these changes correspond to going from 3 to 5 compared
to going from 1.25 to 1.45. This probably reflects the visual impact
more directly.

> For authors, the the definition "multiply only XY" seems easier to
> explain: "normalScale" allows to "emphasie" the normal map, bigger ->
> more emphasized. This seems more natural, at least with such wording.

Well, to me, the opposite is true. I am just envisioning a normal and
just scaling how far the tip of the normal vector is away from the
tangent is most natural. This corresponds to scaling z.

> The above is just my hypothesis "why glTF did it this way". I didn't
> look at any conversation archives from Khronos to actually find out
> the real reasons.
>
> Both versions seem "basically sensible to achieve the same function",
> so it's just better to follow the glTF.

Yes, completely agreed. I was curious since it seemed strange and
violated expectations for me.

https://github.com/KhronosGroup/glTF/issues/885 seems to be the place
where normalScale was introduced in 2017 but there is no discussion on
the rationale. Perhaps an industry standard, or somehow obvious.

Andreas

>
> Regards,
> Michalis
>
> niedz., 3 kwi 2022 o 06:35 Andreas Plesch <andreasplesch at gmail.com> napisał(a):
> >
> > It makes sense to stay compatible with glTF but what is the reason to scale x and y instead of just only scaling z ?
> >
> > normal_tangent *= vec3(1.0, 1.0, castle_normalScale);
> >
> > It would have the same effect (just reciprocal) and is conceptually cleaner.
> >
> > Thanks, Andreas
> >
> >
> >>
> >>
> >> In short, the spec equation is correct. Let me explain why and what is
> >> the purpose of it:
> >>
> >> ( BTW, this is consistent with glTF material.normalTextureInfo.scale,
> >> https://www.khronos.org/registry/glTF/specs/2.0/glTF-2.0.html#_material_normaltextureinfo_scale
> >> ).
> >>
> >> 1. We deliberately multiply only XY (and not Z) components.
> >> Intuitively, "normalScale" allows the normalmap effect to be:
> >>
> >> - more emphasized, when normalScale > 1 (larger normalScale => larger
> >> XY compared to Z in tangent space => the effect of the normal map is
> >> more visible, as the surface looks more "rough")
> >>
> >> - or deemphasized, , when normalScale < 1 (smaller normalScale => the
> >> normals resemble more (0,0,1) in tangent space => normalmap effect is
> >> less visible)
> >>
> >> Multiplying all 3 vector components by normalScale wouldn't have any
> >> effect, indeed. As you say, the whole vector is normalized anyway.
> >>
> >> Note that this means that, regardless of the normalScale value, the
> >> lighting equations *always* work with normalized vectors. Using the
> >> "normalScale" doesn't make them non-normalized. This is deliberate,
> >> lighting equations in general are prepared assuming that normals
> >> (after all processing) are normalized.
> >>
> >> 2. Here's CGE/view3dscene implementation of it:
> >>
> >> https://github.com/castle-engine/castle-engine/blob/master/src/scene/glsl/source/bump_mapping.fs#L28
> >>
> >> It's just
> >>
> >> """
> >>  vec3 normal_tangent = texture2D(castle_normal_map,
> >>     castle_TexCoord<NormalMapTextureCoordinatesId>.st).xyz * 2.0 - vec3(1.0);
> >>
> >>   normal_tangent *= vec3(castle_normalScale, castle_normalScale, 1.0);
> >> """
> >>
> >> We normalize later.
> >>
> >> 3. I created test model for it:
> >>
> >> https://github.com/michaliskambi/x3d-tests/blob/master/pbr/enhanced_phong_material/bump_mapping_normalscale.x3dv
> >>
> >> with correct output on
> >>
> >> https://github.com/michaliskambi/x3d-tests/blob/master/pbr/enhanced_phong_material/bump_mapping_normalscale.png
> >>
> >> 4. I did just confirm it quickly looking at glTF sample viewer implementation:
> >>
> >> https://github.com/KhronosGroup/glTF-Sample-Viewer/blob/master/source/Renderer/shaders/material_info.glsl#L141
> >>
> >> They do this (comments from me):
> >>
> >> """
> >> #ifdef HAS_NORMAL_MAP
> >>
> >> info.ntex = texture(u_NormalSampler, UV).rgb * 2.0 - vec3(1.0);  //
> >> get normal vector from texture
> >>
> >> info.ntex *= vec3(u_NormalScale, u_NormalScale, 1.0); // multiply XY
> >> by normalScale
> >>
> >> info.ntex = normalize(info.ntex); // normalize
> >>
> >> info.n = normalize(mat3(t, b, ng) * info.ntex); // convert from
> >> tangent space to proper space (didn't check now whether this is to
> >> object or eye space)
> >> ...
> >> """
> >>
> >> Regards,
> >> Michalis
> >>
> >>
> >> sob., 2 kwi 2022 o 10:06 Holger Seelig <holger.seelig at yahoo.de> napisa?(a):
> >> >
> >> > Looking at X3DOneSidedMaterialNode https://www.web3d.org/specifications/X3Dv4Draft/ISO-IEC19775-1v4-CD1/Part01/components/shape.html#X3DOneSidedMaterialNode I can find there the calculation of the normal as following:
> >> >
> >> > normal.xyz = normalize((textureSample(normalTexture).rgb * vec3(2,2,2) - vec3(1,1,1)) * vec3(normalScale, normalScale, 1))
> >> >
> >> > Think the handling of normalScale is wrong, the vector must include 3 times normalScale, not z equal 1, like so:
> >> >
> >> > vec3(normalScale, normalScale, normalScale)
> >> >
> >> > The second issue I notices is that the normalScale is applied before normalization, but that means that it has not effect. Normalization means multiplying the vector with a factor, so that the length of the vector is one (1), this makes the multiplication with the normalScale factor undone.
> >> >
> >> > Best regards,
> >> > Holger.
> >> >
> >> > _______________________________________________
> >> > x3d-public mailing list
> >> > x3d-public at web3d.org
> >> > http://web3d.org/mailman/listinfo/x3d-public_web3d.org
> >> -------------- next part --------------
> >> A non-text attachment was scrubbed...
> >> Name: bump_mapping_normalscale.x3dv
> >> Type: application/octet-stream
> >> Size: 6485 bytes
> >> Desc: not available
> >> URL: <http://web3d.org/pipermail/x3d-public_web3d.org/attachments/20220403/cdf75004/attachment.obj>
> >> -------------- next part --------------
> >> A non-text attachment was scrubbed...
> >> Name: bump_mapping_normalscale.png
> >> Type: image/png
> >> Size: 382578 bytes
> >> Desc: not available
> >> URL: <http://web3d.org/pipermail/x3d-public_web3d.org/attachments/20220403/cdf75004/attachment.png>
> >>
> >> ------------------------------
> >>
> >> Subject: Digest Footer
> >>
> >> _______________________________________________
> >> x3d-public mailing list
> >> x3d-public at web3d.org
> >> http://web3d.org/mailman/listinfo/x3d-public_web3d.org
> >>
> >>
> >> ------------------------------
> >>
> >> End of x3d-public Digest, Vol 157, Issue 4
> >> ******************************************
> >
> > _______________________________________________
> > x3d-public mailing list
> > x3d-public at web3d.org
> > http://web3d.org/mailman/listinfo/x3d-public_web3d.org



-- 
Andreas Plesch
Waltham, MA 02453



More information about the x3d-public mailing list