Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"flat" qualifier in glsl?

So I was reading "The Official OpenGL Guide" and in a section where they taught material lighting, they suddenly used the "flat" qualifier for an input variable in the fragment shader. I google'd the matter and all I came up with was "flat shading" and "smooth shading" and the differences between them, which I cannot understand how it is related to a simple "MatIndex" variable. here's the example code from the book:

struct MaterialProperties {
vec3 emission;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
// a set of materials to select between, per shader invocation
const int NumMaterials = 14;
uniform MaterialProperties Material[NumMaterials];
flat in int MatIndex; // input material index from vertex shader

What is this all about?

like image 442
Pilpel Avatar asked Dec 20 '14 14:12

Pilpel


People also ask

Which of the following storage qualifiers are available with OpenGL shading language?

There are three precision qualifiers: highp, mediump, and lowp.

What is gl_Position in GLSL?

gl_Position is a special variable that holds the position of the vertex in clip space. Since a vertex shader's main output is the position in clip space, it must always set gl_Position. This vertex shader just transforms each vertex position (by the VP matrix).

How do I optimize GLSL?

One way to speed up GLSL code, is by marking some variables constant at compile-time. This way the compiler may optimize code (e.g. unroll loops) and remove unused code (e.g. if hard shadows are disabled). The drawback is that changing these constant variables requires that the GLSL code is compiled again.


2 Answers

In the general case, there is not a 1:1 mapping between a vertex and a fragment. By default, the associated data per vertex is interpolated across the primitive to generate the corresponding associated data per fragment, which is what smooth shading does.

Using the flat keyword, no interpolation is done, so every fragment generated during the rasterization of that particular primitive will get the same data. Since primitives are usually defined by more than one vertex, this means that the data from only one vertex is used in that case. This is called the provoking vertex in OpenGL.

Also note that integer types are never interpolated. You must declare them as flat in any case.

In your specific example, the code means that each primitive can only have one material, which is defined by the material ID of the provoking vertex of each primitive.

like image 101
derhass Avatar answered Oct 12 '22 13:10

derhass


It's part of how the attribute is interpolated for the fragment shader, the default is a perspective correct interpolation.

in the GLSL spec section 4.5

A variable qualified as flat will not be interpolated. Instead, it will have the same value for every fragment within a triangle. This value will come from a single provoking vertex, as described by the OpenGL Graphics System Specification. A variable may be qualified as flat can also be qualified as centroid or sample, which will mean the same thing as qualifying it only as flat

Integral attributes need to be flat.

You can find the table of which vertex is the provoking vertex in the openGL spec table 13.2 in section 13.4.

like image 33
ratchet freak Avatar answered Oct 12 '22 12:10

ratchet freak