How does Blender do flat shading?

The interface, modeling, 3d editing tools, import/export, feature requests, etc

Moderators: jesterKing, stiv

maspeir
Posts: 29
Joined: Mon Feb 09, 2009 10:29 pm

How does Blender do flat shading?

Postby maspeir » Mon Sep 24, 2012 1:58 am

I have a game idea in mind that will be more or less retro. Think Spectre.

The problem is that from what I can find via Google, flat shading via GLSL is all but impossible. However, Blender does it. How? I have downloaded the source code, but dear God, that is a lot of code to sift through.

Can someone point me to the correct source files to look at? I have no intention of copying the source, but I definitely need a starting point.

Myrmecophagavir
Posts: 34
Joined: Tue Aug 24, 2010 1:40 am

Re: How does Blender do flat shading?

Postby Myrmecophagavir » Mon Sep 24, 2012 6:09 pm

maspeir wrote:The problem is that from what I can find via Google, flat shading via GLSL is all but impossible.


What makes you think this? Just output the same colour for each fragment of a given triangle.

maspeir
Posts: 29
Joined: Mon Feb 09, 2009 10:29 pm

Re: How does Blender do flat shading?

Postby maspeir » Wed Sep 26, 2012 10:13 pm

Myrmecophagavir wrote:
maspeir wrote:The problem is that from what I can find via Google, flat shading via GLSL is all but impossible.


What makes you think this? Just output the same colour for each fragment of a given triangle.


I wish it were that simple, but it isn't. In order to calculate the color of each fragment, I must first calculate the angle between the light ray and the normal. Unfortunately, the normals are interpolated across the polygon, so for each fragment, the calculated color value changes. This is the definition of smooth shading. What I need to do is shut off the normal interpolation, while leaving z and uv interpolation alone. I don't think that GLSL has a method of doing that.

I think I found the code in Blender that changes between flat and smooth shading and all it does is call glShadeModel. However, that is depreciated and I would like to stay clear of depreciated functions. If that is how Blender does it, that is a point that must be looked into. At some point in the future, flat shading will break.

Myrmecophagavir
Posts: 34
Joined: Tue Aug 24, 2010 1:40 am

Re: How does Blender do flat shading?

Postby Myrmecophagavir » Fri Sep 28, 2012 6:35 pm

maspeir wrote:I wish it were that simple, but it isn't. In order to calculate the color of each fragment, I must first calculate the angle between the light ray and the normal. Unfortunately, the normals are interpolated across the polygon, so for each fragment, the calculated color value changes. This is the definition of smooth shading. What I need to do is shut off the normal interpolation, while leaving z and uv interpolation alone. I don't think that GLSL has a method of doing that.


There are several ways of doing this: if you're restricted to an older version of GL (i.e. 2.x), you'll just have to duplicate the vertices in your buffer and modify the normals. This increases the amount of vertex data and, if using indices, reduces the effectiveness of the post-transform cache because you'll no longer be indexing the same verts even if you need to reuse all the other attributes.

If you have access to GLSL 1.30 or higher (mandated by GL 3.0 and above), or the EXT_gpu_shader4 extension, you can do the lighting in your vertex shader and tag the output colour with the 'flat' interpolation attribute. Values will be taken from the provoking vertex for each polygon, so you have to make sure those have the intended normals. You have to be careful when using indexed rendering here, because you can't reuse such a vertex as the provoking vertex for multiple polygons unless you also want them to share a normal. But you have to account for that when using glShadeModel with the fixed-function pipeline anyway.

(You could also tag your normals 'flat' and do the lighting in the fragment shader, but that would be pointless.)

The third option is to use a geometry shader. Ditch the normals from your vertex data and compute them dynamically with the cross product of the vertex positions in the geometry shader, then do the lighting there. Obviously you need access to geometry shaders for this, so GL 3.2 or higher or one of the geometry shader extensions.

I think I found the code in Blender that changes between flat and smooth shading and all it does is call glShadeModel. However, that is depreciated and I would like to stay clear of depreciated functions. If that is how Blender does it, that is a point that must be looked into. At some point in the future, flat shading will break.


I'm pretty sure glShadeModel only applies to the fixed-function pipeline, so it wouldn't help you if you're using shaders anyway. It's been removed from the core GL profile, but nothing has technically been deprecated (not depreciated, different word ;)) from the compatibility profile, so as long as the compat profile is still usable it's fine. Though if it only applies to the fixed-function pipeline, I'm not sure how Blender actually does its flat shading when you've enabled GLSL rendering.


Return to “Interface & Tools”

Who is online

Users browsing this forum: Google [Bot] and 2 guests