PDA

View Full Version : help with flat shading



ale211734
06-23-2015, 09:01 AM
I would like use flat shading with vbo. I wish that each face has the same color as with the old glShadeModel(GL_FLAT).
Someone have some piece of shader to do it?

I tried this fragment shader but doesn't work correctly... I saw some sort of color interpolation on the faces.
I tried to use it:


bool resultVertex=p.attachVertexShader(STRINGIFY(
varying vec3 ec_pos;
void main()
{
ec_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
gl_Position = ftransform();
}
));

bool resultFragment=p.attachFragmentShader(STRINGIFY(
varying vec3 ec_pos;

void main()
{
vec3 ec_normal = normalize(cross(dFdx(ec_pos), dFdy(ec_pos)));
vec3 light_dir=vec3(0.0,0.85,0.85);
float d=dot(light_dir,ec_normal);
gl_FragColor = vec4(d,d,d,0);

}));



Thanks.

mobeen
06-23-2015, 10:08 PM
For flat appearance, I would suggest computing the color per-vertex (use flat qualifier for OpenGL v3.3 and above) as follows rather than per-fragment as you are doing currently. You will still get some interpolated color due to rasterizer interpolation but it should be flatter looking as compared to per-fragment result.


//vertex shader
varying vec4 color;
void main() {
vec3 ec_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec3 ec_normal = normalize(cross(dFdx(ec_pos), dFdy(ec_pos)));
vec3 light_dir=vec3(0.0,0.85,0.85);
float d=dot(light_dir,ec_normal);
color = vec4(d,d,d,0);
gl_Position = ftransform();
}

//fragment shader
varying vec4 color;
void main() {
gl_FragColor = color;
}

GClements
06-24-2015, 11:10 AM
I tried this fragment shader but doesn't work correctly... I saw some sort of color interpolation on the faces.
I tried that approach and it worked fine, with no trace of variation.

Although dFdx/dFdy are only approximate, I can't conceive of any way that the results could be other than in the plane of the primitive. The magnitudes could vary, but the normalize() takes care of that.

GClements
06-24-2015, 11:13 AM
For flat appearance, I would suggest computing the color per-vertex (use flat qualifier for OpenGL v3.3 and above) as follows rather than per-fragment as you are doing currently.
You can't realistically compute the face normal in the vertex shader, as a vertex shader knows nothing of the other vertices forming the face. You can do it in a geometry shader.


You will still get some interpolated color due to rasterizer interpolation
A "flat"-qualified variable isn't interpolated.





//vertex shader
varying vec4 color;
void main() {
vec3 ec_pos = (gl_ModelViewMatrix * gl_Vertex).xyz;
vec3 ec_normal = normalize(cross(dFdx(ec_pos), dFdy(ec_pos)));

dFdx and dFdy can only be used in a fragment shader.

ale211734
06-25-2015, 09:37 AM
You can't realistically compute the face normal in the vertex shader, as a vertex shader knows nothing of the other vertices forming the face. You can do it in a geometry shader.


A "flat"-qualified variable isn't interpolated.


dFdx and dFdy can only be used in a fragment shader.


Hello,
how can i calculate face normale with geometric shader and pass it to fragment shader?
can someone can help me with code?

GClements
06-25-2015, 11:10 AM
how can i calculate face normale with geometric shader and pass it to fragment shader?



layout(triangles) in;
layout(triangle_strip, max_vertices=3) out;

out vec3 normal;

void main()
{
vec3 v1 = gl_in[1].gl_Position - gl_in[0].gl_Position;
vec3 v2 = gl_in[2].gl_Position - gl_in[0].gl_Position;
normal = normalize(cross(v1, v2));
for (int i = 0; i < gl_in.length(); i++) {
gl_Position = gl_in[i].gl_Position;
EmitVertex();
}
EndPrimitive();
}