OpenGLInterpolationQualifiers(GLSL)
(2023-03-16 15:18:54)
标签:
it |
分类: 技术 |
OpenGL 3 introduced three interpolation qualifiers that are at
our disposal in the vertex and fragment shaders. These
interpolation qualifiers allow to specify the way a vertex shader
output is interpolated across a primitive.
The OpenGL spec/wiki says:
flat: the value is not interpolated. The
value given to the fragment shader is the value from the Provoking
Vertex for that primitive.
smooth: performs a perspective
correct interpolation.
noperspective: performs a linear interpolation in window
space.
The default interpolation qualifier is smooth when no
qualifier is present.
Let's see in practice how these qualifiers affect the
rendering. I used GLSL Hacker to quickly code the
demo and play with GLSL shaders. All demos of this tutorial are
included in GLSL Hacker Code Sample Pack in the
GLSL_OpenGL_32_Interpolation/ folder.
The first 3D test is simple: a quad with a different color at
each vertex:
– vertex 0: red
– vertex 1: green
– vertex 2: blue
– vertex 3: yellow
Here is the GPU program used to render the quad:
Vertex shader:
#version 150
in vec4 gxl3d_Position;
in vec4 gxl3d_Color;
uniform mat4 gxl3d_ModelViewProjectionMatrix;
//flat out vec4 VertexColor;
smooth out vec4 VertexColor;
//noperspective out vec4 VertexColor;
void main()
{
}
Pixel shader:
#version 150
//flat in vec4 VertexColor;
smooth in vec4 VertexColor;
//noperspective in vec4 VertexColor;
out vec4 Out_Color;
void main()
{
}
With smooth qualifier, the rendering is:
With flat qualifier, the rendering is:
The flat qualifier disables the interpolation and each
triangle of the quad is colored with the last triangle vertex
color:
– triangle 0: vertices {0, 1, 2} – flat color is blue because
vertex 2 is blue.
– triangle 1: vertices {2, 3, 0} – flat color is red because
vertex 0 is red.
Why the last vertex? Because of the Provoking vertex.
By default, the provoking vertex is the last vertex of a primitive,
in our case the last vertex of a triangle. See HERE for more
details about the Provoking vertex.
With noperspective qualifier, the rendering is:
As you can see, the difference between noperspective and
smooth is really small, only a sharp eye can see some subtle
variations
Now the second test with a textured quad. Here is the GPU
program with texture mapping:
Vertex shader:
#version 150
in vec4 gxl3d_Position;
in vec4 gxl3d_TexCoord0;
uniform mat4 gxl3d_ModelViewProjectionMatrix;
noperspective out vec4 VertexUV;
//smooth out vec4 VertexUV;
//flat out vec4 VertexUV;
void main()
{
}
Pixel shader:
#version 150
noperspective in vec4 VertexUV;
//smooth in vec4 VertexUV;
//flat in vec4 VertexUV;
uniform sampler2D tex0;
out vec4 Out_Color;
void main()
{
}
With smooth qualifier, the rendering is:
This is the usual rendering (the one we usually expect) and
texture coordinates are interpolated with perspective
correction.
With flat qualifier, the rendering is:
The texture color at vertex 2 and vertex 0 is red that’s why
the quad is uniformly red (not a real red but RGB:{0.25; 0; 0}).
Other way to explain: texture color at provoking vertices is
RGB:{0.25; 0; 0}.
With noperspective qualifier, the rendering is:
With the noperspective qualifier, texture coordinates are
linearly interpolated in the screen space (or window space) and we
clearly see each triangle.
Last thing: interpolation qualifiers in vertex and pixel
shaders must match. If interpolation qualifiers mismatch like in
the following example:
Vertex shader:
...
smooth out vec vertex_color;
...
Pixel shader:
...
flat in vec vertex_color;
...
you will get some weird results.
On Windows + GTX 660, I got a black quad:
Under Mac OS X with the Intel HD 4000 GPU, the quand was
simply not displayed: