[x3d-public] Calculation of normal from normalTexture.

Holger Seelig holger.seelig at yahoo.de
Mon Apr 4 07:33:56 PDT 2022


Thank you all and taking the time to enlighten me. When considering tangent normals, this makes indeed sense.

Best regards,
Holger

> Am 03.04.2022 um 17:16 schrieb Andreas Plesch <andreasplesch at gmail.com>:
> 
> 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
> 
> _______________________________________________
> x3d-public mailing list
> x3d-public at web3d.org
> http://web3d.org/mailman/listinfo/x3d-public_web3d.org




More information about the x3d-public mailing list