<blockquote>
  <p>How are screenspace normals created, and is this step before or after using normal maps or bump maps?</p>
</blockquote>

<p>They are created after using normal maps. In deferred rendering, you write to the various buffers (diffuse, normal, depth, etc.) in fragment shaders. By this time, the normal maps would have already been read.</p>

<blockquote>
  <p>If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals,...</p>
</blockquote>

<p>If you are referring to normal maps on models, normal maps can stay the same. You can compress normal maps as well if you want, but this becomes irrelevant to what you do for writing to the normal buffer.</p>

<blockquote>
  <p>...and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?</p>
</blockquote>

<p>Your model's normals are computed per vertex and interpolated through rasterization to be per fragment. The normal maps are processed per fragment, but these are just texture lookups, and these can be applied to the camera-space normals produced from the previous pipeline steps. Therefore, a view matrix is no longer necessary.</p>

<blockquote>
  <p>Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?</p>
</blockquote>

<p>The idea behind 2-component normals versus 3-component normals is that the vector magnitude isn't often taken into account for normals. Also, normals facing away from the camera generally aren't useful. With two components, you can use model a hemisphere facing the camera. You unpack them the same way you pack them.</p>

<p>Think about normals as positions. When converting from world space (x, y, z) to screenspace (x, y, depth), but the depth does not effect where on the screen a mesh gets displayed. Convert the 3D vector to a vector in terms of screenspace (through view matrix multiplications).</p>

<p>Then you can discard the z-component (aligned with the camera) as long as you normals are unit vectors (because you can derive z from the other two vectors).</p>

CC BY-SA 3.0
2016-09-03T03:37:28.513Z
Thanks Aces, but I'm still a bit confused. You multiply each fragment by the view Matrix after the usual normal mapping, pass the x and y to the deferred shader, and then multiply by inverse the view Matrix during the deferred shader?
Karim Abdel Hamid
CC BY-SA 3.0
2016-09-03T04:05:47.103Z
Yes, you can do that, but you can also just calculate the vertex normals through the vertex shader and apply the normal map from there. That way, you don't need to multiply each fragment by the View matrix.
aces
CC BY-SA 3.0
2016-09-03T02:56:55.973Z
2016-09-03T04:07:59.903Z
2016-09-03T04:07:59.903Z
aces
<blockquote>
  <p>I'm trying to condense my Deferred Rendering G-Buffer. So I have some questions about getting 2-component Screenspace Normals. I know Frostbite and Killzone (the only two AAA company's G-Buffers I could find) use them.</p>
</blockquote>

<p>I'm confused when you say "screenspace normals", Killzone uses view-space normals, they store the X &amp; Y coordinate of the normal in FP16 format, and reconstruct Z using $z = sqrt(1.0 - Normal.x^2 - Normal.y2)$ a problem with that is that we lack the sign of Z, even in view-space the normals can point away from the camera, i.e. Z is not always positive.</p>

<blockquote>
  <p>How are screenspace normals created, and is this step before or after using normal maps or bump maps? If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals, and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?</p>
</blockquote>

<p>After loading your normal maps, you construct a TBN matrix to transform from tangent space to e.g. world space before writing to the G-Buffer. So in essence, your normals in the G-Buffer are stored in world-space, not screen-space. With that you can apply lighting in world space, as far as I'm aware, Crytek &amp; Epic do the lighting in world-space now.</p>

<p>I'm not sure what you mean by "screenspace-ness", but when writing any sort of data to the G-Buffer, you're essentially writing their current value, if the normals are in world-space, they will remain in world-space when written to the G-Buffer. When you sample the G-Buffer on the second pass, for each texel, you get an RGB color (assuming you're using RGB) that maps to your coordinate data.</p>

CC BY-SA 3.0
2017-06-17T16:57:08.867Z
Cannot imagine a normal with negative Z in screen (view) space. It would require the culling turned off which itself is a bad idea from the performance perspective.
Grief
CC BY-SA 3.0
2016-09-04T13:38:32.540Z
2016-09-04T13:38:32.540Z
Fred Garnier
<p>I'm trying to condense my Deferred Rendering G-Buffer. So I have some questions about getting 2-component Screenspace Normals. I know Frostbite and Killzone (the only two AAA company's G-Buffers I could find) use them.</p>

<p>How are screenspace normals created, and is this step before or after using normal maps or bump maps? If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals, and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?</p>

<p>Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?</p>

<shader><transformations><deferred-rendering><normal-mapping>
Screenspace Normals - Creation, Normal Maps, and Unpacking
Karim Abdel Hamid
# Screenspace Normals - Creation, Normal Maps, and Unpacking

(Asked by: username_0 on 2016-09-03)

I'm trying to condense my Deferred Rendering G-Buffer. So I have some questions about getting 2-component Screenspace Normals. I know Frostbite and Killzone (the only two AAA company's G-Buffers I could find) use them.

How are screenspace normals created, and is this step before or after using normal maps or bump maps? If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals, and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?

Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?

**Tags:** shader, transformations, deferred-rendering, normal-mapping


---

## 2 answers

### Answer by username_1 on 2016-09-03. Score: 4

> How are screenspace normals created, and is this step before or after using normal maps or bump maps?

They are created after using normal maps. In deferred rendering, you write to the various buffers (diffuse, normal, depth, etc.) in fragment shaders. By this time, the normal maps would have already been read.

> If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals,...

If you are referring to normal maps on models, normal maps can stay the same. You can compress normal maps as well if you want, but this becomes irrelevant to what you do for writing to the normal buffer.

> ...and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?

Your model's normals are computed per vertex and interpolated through rasterization to be per fragment. The normal maps are processed per fragment, but these are just texture lookups, and these can be applied to the camera-space normals produced from the previous pipeline steps. Therefore, a view matrix is no longer necessary.

> Finally, how are they unpacked? I realize you can get the blue component using pythagoras, but how are they returned to world space?

The idea behind 2-component normals versus 3-component normals is that the vector magnitude isn't often taken into account for normals. Also, normals facing away from the camera generally aren't useful. With two components, you can use model a hemisphere facing the camera. You unpack them the same way you pack them.

Think about normals as positions. When converting from world space (x, y, z) to screenspace (x, y, depth), but the depth does not effect where on the screen a mesh gets displayed. Convert the 3D vector to a vector in terms of screenspace (through view matrix multiplications).

Then you can discard the z-component (aligned with the camera) as long as you normals are unit vectors (because you can derive z from the other two vectors).

> **Comments:**
> **username_0**: Thanks username_1, but I'm still a bit confused. You multiply each fragment by the view Matrix after the usual normal mapping, pass the x and y to the deferred shader, and then multiply by inverse the view Matrix during the deferred shader?  
> **username_1**: Yes, you can do that, but you can also just calculate the vertex normals through the vertex shader and apply the normal map from there. That way, you don't need to multiply each fragment by the View matrix.  

---

### Answer by username_2 on 2016-09-04. Score: 3

> I'm trying to condense my Deferred Rendering G-Buffer. So I have some questions about getting 2-component Screenspace Normals. I know Frostbite and Killzone (the only two AAA company's G-Buffers I could find) use them.

I'm confused when you say "screenspace normals", Killzone uses view-space normals, they store the X & Y coordinate of the normal in FP16 format, and reconstruct Z using $z = sqrt(1.0 - Normal.x^2 - Normal.y2)$ a problem with that is that we lack the sign of Z, even in view-space the normals can point away from the camera, i.e. Z is not always positive.

> How are screenspace normals created, and is this step before or after using normal maps or bump maps? If it's done before using normal maps, how are normal maps going to be affected by the screenspace-ness of the normals, and if after, how can you justify using a Model-View matrix on all fragments rather on vertices? Isn't that a lot more calculations?

After loading your normal maps, you construct a TBN matrix to transform from tangent space to e.g. world space before writing to the G-Buffer. So in essence, your normals in the G-Buffer are stored in world-space, not screen-space. With that you can apply lighting in world space, as far as I'm aware, Crytek & Epic do the lighting in world-space now.

I'm not sure what you mean by "screenspace-ness", but when writing any sort of data to the G-Buffer, you're essentially writing their current value, if the normals are in world-space, they will remain in world-space when written to the G-Buffer. When you sample the G-Buffer on the second pass, for each texel, you get an RGB color (assuming you're using RGB) that maps to your coordinate data.

> **Comments:**
> **username_3**: Cannot imagine a normal with negative Z in screen (view) space. It would require the culling turned off which itself is a bad idea from the performance perspective.  

---

