I want to make a retro-style game like Spectre. I’m trying to stay away from depreciated functions. I DO understand that it will work for the foreseeable future. Still, depreciated means going away at some point and I would like to stay ahead of that.

The problem is that the only way to do flat shading that I can find is via glShadeModel. I cannot find any method of doing flat shading via the programmable pipeline and what little I could find mentioning flat shading states that it cannot be done. Is this correct?

The only idea that I can come up with is to do all transformations and lighting calculations on the CPU side and send the calculated polygon shade to the GPU via a uniform. That doesn’t seem to be the most efficient method. Unfortunately, it seems to be the only method.

How can I do this? Is this going to be addressed in a future gl version? Flat shading is still needed in 3D modelers and CAD/CAM applications.

BTW, even if GLSL didn’t do this for you and only offered perspective-correct (bi)linear interpolation, you could still get them same effect by simply putting out the same color for all vertices of the current primitive.

Two words… geometry shader. The outcome is the exact same only you’re choosing the provoking vertex yourself. Performance may be an issue if you’re using multiple objects very high poly-count or hundreds of objects with low to medium poly-counts.

Yes, I know, provoking vertex + flat interpolation solves your problem more easily and probably more efficiently but it’s not the only way you could go. However, it doesn’t hurt to think of other ways of solving a problem.

Alfonse’s answer is the best answer using flat for the interpolator qualifier, but it requires beyond GL2.1. Geometry shader is fine where the the normal is computed within it (but that requires GL3.x and GLES2 and GLES3 do NOT have Geometry shaders). The solution dFdx/dFdy works in GL2.1 and MOST GLES2.x implementations but makes one do a cross-product and normalize from the fragment shader (i.e. letting p be a varying holding the position in 3-space, typically eye coordinates, then the normal (co)vector is given by normalize( cross(dFdx§, dFdy§ ) [assuming a particular orientation for the triangle in question]… on the other hand if you are going for old school look (i.e. low polygon count anyways), you might as well bite the bullet and split the geometry so that each usage of a point is given a unique index…