PDA

View Full Version : Rasterization stage and matrix interpolation

skybig
01-16-2018, 07:14 PM
Hi everyone,

I am a little confused about the rasterization stage. For example, my vertex shader is something like this:

#version 410 core

in vec3 position;
in vec3 normal;
in vec3 tangent;

out vec3 worldPosition;
out vec3 worldNormal;
out mat4 TBN;

uniform mat4 modelMatrix;
uniform mat4 mvp;
...

main() {

//...

}

And my fragment shader is something like this:

#version 410 core

in vec3 worldPosition;
in vec3 worldNormal;
in mat4 TBN;

out vec4 fragColor;

main() {

// ...

}

For my understanding, the GPU will interpolate both the worldPosition&worldNormal transferred from vertex shader to fragment shader as per-fragment value. My question is: how about the matrix? Do I get a per-fragment value for the 4x4 matrix? If so, is it correct for my TBN matrix after interpolation?

Thanks!

GClements
01-16-2018, 11:39 PM
For my understanding, the GPU will interpolate both the worldPosition&worldNormal transferred from vertex shader to fragment shader as per-fragment value. My question is: how about the matrix? Do I get a per-fragment value for the 4x4 matrix?
Yes. Vertex shader outputs are interpolated unless they're integers or integer vectors (ivec/uvec) or have the "flat" qualifier.

If so, is it correct for my TBN matrix after interpolation?
It depends upon what you mean by "correct". E.g. the result of interpolating orthonormal matrices typically isn't orthonormal. OTOH, transforming a vector by the result of interpolating matrices is equivalent to transforming the vector by the original matrices then interpolating: (u*A+v*B).x = u*(A.x)+v*(B.x).

skybig
01-17-2018, 02:10 AM
Yes. Vertex shader outputs are interpolated unless they're integers or integer vectors (ivec/uvec) or have the "flat" qualifier.

It depends upon what you mean by "correct". E.g. the result of interpolating orthonormal matrices typically isn't orthonormal. OTOH, transforming a vector by the result of interpolating matrices is equivalent to transforming the vector by the original matrices then interpolating: (u*A+v*B).x = u*(A.x)+v*(B.x).

Thank you for the reply! So, the rasterizer does interpolate the 4x4 matrix (mat4).

For the "correct" part, my situation is that I'm gonna do the normal mapping so I'd like to calculate the TBN matrix (tangent, bitangent, normal) to transfer the normal in tangent space (within the texture) to world space . I'm just thinking if I do the calculation in vertex shader, and after the rasterizer, I use them in the fragment shader, do I get the correct result? (get the correct world normal)

Does it more often to calculate the TBN matrix in fragment shader?

Silence
01-17-2018, 04:28 AM
You will generally precompute the TBN axis and use them as vertex attributes. Then simply create the 3*3 matrix in the vertex shader using the at least 2 precomputed axis, and pass it to the fragment shader.

GClements
01-17-2018, 06:17 AM
Thank you for the reply! So, the rasterizer does interpolate the 4x4 matrix (mat4).

For the "correct" part, my situation is that I'm gonna do the normal mapping so I'd like to calculate the TBN matrix (tangent, bitangent, normal) to transfer the normal in tangent space (within the texture) to world space . I'm just thinking if I do the calculation in vertex shader, and after the rasterizer, I use them in the fragment shader, do I get the correct result? (get the correct world normal)

Does it more often to calculate the TBN matrix in fragment shader?
It's typical to calculate the matrix in the vertex shader and interpolate. The matrix typically isn't renormalised (orthogonalised) in the fragment shader. Note that you only need a 3x3 matrix (normals are directions, not positions). But you should normalise the transformed normal, as the interpolated matrix won't preserve lengths.

skybig
01-17-2018, 06:32 PM
You will generally precompute the TBN axis and use them as vertex attributes. Then simply create the 3*3 matrix in the vertex shader using the at least 2 precomputed axis, and pass it to the fragment shader.

Thank you!! Got it!

skybig
01-17-2018, 06:34 PM
It's typical to calculate the matrix in the vertex shader and interpolate. The matrix typically isn't renormalised (orthogonalised) in the fragment shader. Note that you only need a 3x3 matrix (normals are directions, not positions). But you should normalise the transformed normal, as the interpolated matrix won't preserve lengths.

Got it! And correct, I should use mat3! Thank you very much!

Silence
01-17-2018, 11:57 PM
It's typical to calculate the matrix in the vertex shader and interpolate. The matrix typically isn't renormalised (orthogonalised) in the fragment shader. Note that you only need a 3x3 matrix (normals are directions, not positions). But you should normalise the transformed normal, as the interpolated matrix won't preserve lengths.

Just to clarify what you wrote GClements, do you mean to calculate the tangent and binormal inside the vertex shader ? Or was you meaning (like I wrote in my post) to use the pre-computed axis stored as vertex attributes as the 3*3 matrix axis ?

GClements
01-18-2018, 12:56 AM
Just to clarify what you wrote GClements, do you mean to calculate the tangent and binormal inside the vertex shader ? Or was you meaning (like I wrote in my post) to use the pre-computed axis stored as vertex attributes as the 3*3 matrix axis ?
If you have T,B,N as vertex attributes, then the vertex shader will simply copy them (either as a mat3 or as 3 separate vec3s). Sometimes B is calculated in the vertex shader as N×T. Rarely, T might be computed from other information but this isn't usually possible in a vertex shader; computing T,B,N in a tessellation evaluation shader is fairly common.

PS: B is the "bitangent". Surfaces have two tangents (tangent and bitangent) and one normal, curves have one tangent and two normals (normal and binormal). Unfortunately, someone once mistakenly used the curve terminology for a surface and the error has since propagated across countless tutorials.