Source Filmmaker

Source Filmmaker

Shakes Oct 13, 2018 @ 8:17am
Recreating blue channel of normal map?
Long story short, trying to port a model but the blue channels for the normal maps are all black, so I'm assuming the game they're from (Quake Champions) does the blue channel in the shader. What I'm asking is if anyone here knows how to recreate the blue channels using GIMP (or other software) so I can get a normal map that doesn't give Source Engine (and Blender) an aneurism. As far as I know, Source Engine only uses RG normal maps for the "EyeRefract" shader. I've come close but the result has always been off slightly. Google has been less than helpful.

If memory serves me correctly, z = sqrt(1 - x^2 - y^2) where z is the blue channel value and x & y are the red and green values, respectively. I could do this manually for each pixel but I'd rather not do the calculation a million times (the normal maps are 1024*1024). Is there a way to automate this and generate an output image from the results? Perhaps in Python? Or is any of this actually necessary?
< >
Showing 16-24 of 24 comments
Marco Skoll Oct 14, 2018 @ 5:22am 
I'm somewhat lost here - where has this normal map that you're using as your test image come from?
Shakes Oct 14, 2018 @ 5:27am 
Originally posted by Marco Skoll:
I'm somewhat lost here - where has this normal map that you're using as your test image come from?
https://squircleart.github.io/shading/normal-map-generation.html

The grayscale image not quite halfway down the page, under "Normal Maps Components". That image contains the channel info for the tangent map example a little farther up.

I made a new image without that blue channel and used the script to try and modify it to replicate the blue channel of the original.
Last edited by Shakes; Oct 14, 2018 @ 5:30am
Marco Skoll Oct 14, 2018 @ 6:00am 
Well, despite him saying that the Z component can be directly encoded without the compression required for the other channels, neither Source's normal maps or the map he's provided actually do that.

Both Source and that normal map compress the Z component such that a value of less than 128 is assumed to be facing into the model.

Colour dropping some points on the map, some example values are 57 207 196, which add up to a vector of 1.28 if you take it that the Z channel is directly encoded, but 0.97 if you say that it's compressed. The latter is significantly closer to a properly normalised value that it seems that's where the mistake lies.

Try something like sqrt(1-((4*r^2-4*r+1)^2+(4*g^2-4*g+1)^2))/2+0.5 (EDIT: As Episoder says, this is wrong. See my later post for a better answer) to compress it in the same way as the other vectors, then see if it matches.
Last edited by Marco Skoll; Oct 14, 2018 @ 7:46am
episoder Oct 14, 2018 @ 6:59am 
i'm no math genius, but i'm sure the formula is wrong. been trying todo it in integer math. failed yet. i may try later again. got some to attend to.
Marco Skoll Oct 14, 2018 @ 7:19am 
Originally posted by episoder:
been trying todo it in integer math.
... hang on, you're right.You don't WANT the decompression to be parabolic.

You can just decompress linearly as (channel * 2) - 1 to get a range between -1 and 1, which is what you want, anyway.

Rethinking it, I think you want:

sqrt(1-((r*2)-1)^2+((g*2)-1)^2)/2+0.5

Still, what I said before still seems to be correct. The blue channel is compressed.
Last edited by Marco Skoll; Oct 14, 2018 @ 7:20am
Marco Skoll Oct 14, 2018 @ 10:54am 
Although it's not directly relevant to trying to restore the blue channel from the other two, I notice that the article's method for calculating normals actually just assumes a Z component of 1, then normalises based on that assumption.

This method won't actually allow a normal to lie flat against the surface, so if you're trying to create normal maps from scratch, I don't particularly recommend it.
Shakes Oct 14, 2018 @ 12:53pm 
Originally posted by Marco Skoll:
Although it's not directly relevant to trying to restore the blue channel from the other two, I notice that the article's method for calculating normals actually just assumes a Z component of 1, then normalises based on that assumption.

This method won't actually allow a normal to lie flat against the surface, so if you're trying to create normal maps from scratch, I don't particularly recommend it.
Not trying to do that, at least not at the moment.

Looking at this post[discourse.techart.online], it seems you were correct about the compression part. The equation given in that post gives a much better result, although the difference is still nonzero, if barely. Not sure how much closer I can get. This[i.imgur.com] is the difference between my new blue channel and the one given. Not sure where the noise is coming from but it's so close.

New expression for the moment is sqrt(1-((2r-1)^2+(2g-1)^2))/2+0.5
Despite being the same at first glance as the one you posted, it gives different results. I think placement of parenthesis is making a difference here.

Edit: Seems that forum link triggered Steam's anti-spam filter.
discourse techart online/t/how-to-calculate-the-blue-channel-for-normal-map/4436/7
Last edited by Shakes; Oct 14, 2018 @ 12:58pm
Marco Skoll Oct 14, 2018 @ 1:10pm 
Originally posted by Shakes:
Not sure where the noise is coming from but it's so close.
That's easy to answer.

The value I eye droppered before totalled to 0.97, so the normal map wasn't exactly perfectly normalised in the first place, so those differences will show up as noise as the reconstruction is assuming a perfectly normalised total.
episoder Oct 14, 2018 @ 1:44pm 
compression? pretty much irrelevant. the trick is to get the z on the curve aka the tangent hemi sphere. part of the unity normal cube. red is adding z to a half tilted vector. it will shorten and bend the normal. magenta is the tricky case. it's flat and should yield z=0. math is torture. :D

https://i.imgur.com/kPy1TLC.jpg
< >
Showing 16-24 of 24 comments
Per page: 1530 50

Date Posted: Oct 13, 2018 @ 8:17am
Posts: 24