Flat shading for 3D objects?

edited February 2018 in GLSL / Shaders

Is there a way to disable the nice smooth shading in P3D sketches? For example, to look like this:

_SHADING

When making files for 3D printing, I find it's nice to have just flat shading, so you can see all the triangles.

Answers

  • Post some code.

    You can probably get flat shading by defining your own normals for each vertex. But that does mean having to define each triangle individually and not as part of a strip / fan.

    Oh, actually, there is a global enable flag in opengl that might be turn-offable. glsmooth?

    https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glShadeModel.xml

    Um, gl2.1...

  • edited February 2018

    First of all you can set flat/smooth shading in you 3D modeling tool and then export it

    Yes, koogs is right, you should run some processing exampels, so you get a feeling of it.
    https://processing.org/tutorials/pshader/

    I created a little scetch, ftw

    /** 
     * Simpel Diffuse
     *
     * ^;.;^
     * nabr (2018/Feb/11)
     *
     * forum.processing.org/two/discussion/26309/flat-shading-for-3d-objects
     */
    
    
    // won't work on iphone 5, raspberry pi 2, android before 2015 or any device befor 10000 bc
    
    
    PShape s;
    PShader shdr;
    
    void setup() {
    
      size(960, 540, P3D);
    
      noStroke();
    
      // note: running in an error missing .mlt file means we don't load/reference for textures in the obj file as relative in the link to http.
      s = loadShape("https://"+"raw.githubusercontent.com/JoeyDeVries/LearnOpenGL/master/resources/objects/nanosuit/nanosuit.obj");
    
      // use on local drive 
      //s = loadShape("nanosuit.obj");
    
      s.scale(30f);
      s.rotateX(PI);
      s.rotateY(PI);
    
    
      // processing.org/reference/loadShader_.html
      shdr=new PShader(this, new String[] {"#version 150"
        ,"in vec4 position,normal;"
        +"uniform mat4 projectionMatrix,modelviewMatrix;"
        // the key here is flat default is smooth interpolation 
        +"flat out vec3 vN;"
        +"void main() {"
        // normal matrix
        +"mat4 nrm_Mtrx = transpose(inverse(modelviewMatrix));"
        // vertex normal
        +"vN = normalize(vec3(nrm_Mtrx*vec4(normal.xyz,0.)).xyz);"
        +"gl_Position = projectionMatrix*modelviewMatrix*position;"
        +"}"
        }, new String[] {"#version 150"
          ,"flat in vec3 vN;"
          +"uniform vec3 LDir;"
          +"uniform vec3 surfaceColor;"
          +"out vec4 fragColor;"
          +"void main() {"
          // simpel diffuse
          +"float brightness = clamp( max(0., dot(vN, normalize(LDir) ) ) ,0.,1.);"
          +"fragColor.rgb = brightness * surfaceColor;"  
          +"fragColor.a=1.0;"
          +"}"
        });
        shader(shdr);
    }
    
    void draw() {
    
      background(127);
    
      float dirX = (mouseX / float(width) - 0.5) * 2;
    
      // depends on camera setup range form -/+ 0 - 1000
      shdr.set("LDir", dirX, 1f, 3f );
    
      // range from 0 - 1
      shdr.set("surfaceColor",.5f,.5f,1.f);
    
      translate(width*0.5f, height*0.5f+220 );
      rotateY(frameCount*.001f);
      // sphere(150);
    
      shape(s);
    }
    

    // output (note this gif is compressed)

        Alt Text

  • Thanks @nabr and @koogs! I didn't include code because it's embedded in a really complex project. I'm using a combination of primitives, the Shapes3D library, and some custom shapes generated with TRIANGLE_STRIP.

    But ideally, this would be something that could be applied like a hint() command in setup()... maybe that's asking for too much :)

    @nabr's shader works well! But I'd have to change my entire code for applying color to various shapes. I'll file this away for future projects.

  • edited February 2018

    (Did some research this topic on processing, their is no answer todate. So i post my some of my discoveries for the benefit of the community)

    @jeffthompson Hello

    glShadeModel(GL_FLAT) is deprecated since then 10 years, this is how things work befor shaders were introduced.

    You can also compute the hole thing on the CPU.

    It should (untested) work with Processing Version <= 2.2.1

    Pseudocode https://github.com/processing/processing/wiki/Advanced-OpenGL-in-Processing-2.x

    PGraphicsOpenGL pg = (PGraphicsOpenGL)g;  
    PGL pgl = beginPGL();    
    gl2 = ((PJOGL)pgl).gl.getGL2();  
    
    
    gl2.glShadeModel(GL.GL_FLAT); // enable flat shading
    

    Second:

    "in a really complex project."

    Pseudocode

    // 
    void flatShading(float red, float blue, float green ) {
      if (enableFlatShading==true) {
        PShader flatshader = loadShader("flat.vert","flat.frag");
        flatshader.set("color", red, blue, green); 
      }
      else {
      resetShader(); // reset to default processing shaders
      }
    }
    

    hahah too complex. :)

    And as i already wrote.Its a modern shader approach transpose inverse of Camera/Object View Matrix (MatrixMath is done on the CPU previously). For backward compatibility, use an older version shader, you can find tones of them on the web.

    see here: (works on browsers, should work everywhere)
    https://github.com/glslify/glsl-face-normal

    If you think about the graphicpipeline. Cube, or what ever shape, will create you some Buffers and then everything is send to shaders, in order to change the color, you have to tweek the shader. https://processing.org/tutorials/pshader/

    Probably also there is a way to implement flat shading direct into Shapes3D library.

  • Thanks @nabr, this is super helpful. Filling away to use in future projects. I feel like I need to make an automated project-builder that includes basic settings for camera, lights, and flat shading. Add to the to-do list...

Sign In or Register to comment.