Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flat shading with phong material with spot light

I am trying to achieve flat shading with the phong material. As the documentation says we have to set flatShading:true in config when creating the material. I have created a cube with these settings and created a spot light to focus at the center of the cube (not touching the vertices of the cube).

I assume the face of the cube should look same at all pixels but its not looking so. I see a reflection of the light at the center of the face. Indeed, changing the flatShading from true to false, is not affecting the light.

Here is the JS fiddle link to what i tried. https://jsfiddle.net/dj03gktb/.

Below is the code.

var camera, scene, renderer;

init();
animate();

function init() {

  camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 0.01, 10);
  camera.position.z = 4;
  scene.add(camera);

  scene = new THREE.Scene();

  var ambientLight = new THREE.AmbientLight(0xcccccc, 0.2);
  scene.add(ambientLight);

  var pointLight = new THREE.SpotLight({ color: 0xffffff, angle: Math.PI / 10, intensity: 2 });

  scene.add(pointLight);
  //pointLight.position.x = 5;
  pointLight.position.z = 1.5;
  pointLight.position.y = 0;

  var geometry = new THREE.BoxGeometry(1, 1, 1);
  //geometry.computeFlatVertexNormals();
  //geometry.rotateY(0.5);
  var material = new THREE.MeshPhongMaterial({ color: 0xff0000, flatShading: true, shininess: 100, specular: 0x00ff00 });

  var mesh = new THREE.Mesh(geometry, material);
  scene.add(mesh);

  renderer = new THREE.WebGLRenderer({ antialias: true });
  renderer.setSize(window.innerWidth, window.innerHeight);
  document.body.appendChild(renderer.domElement);
}
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

May be i have under stood flat shading wrongly or could be bug with the THREE.js or problem with the render engine.

Any help would be great.

like image 212
Boyapati Ravi Kumar Avatar asked Dec 21 '25 01:12

Boyapati Ravi Kumar


1 Answers

Unfortunately, using a cube to demonstrate flat shading is a bad example since you won't see any difference. Try it with a sphere instead:

var camera, scene, renderer;

init();
animate();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 4;

    scene = new THREE.Scene();
        
    var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.2 );
    scene.add( ambientLight );
        
    var spotLight = new THREE.SpotLight({ color: 0xffffff, angle: Math.PI / 10, intensity: 2});
    spotLight.position.z = 1.5;
    scene.add(spotLight);

    var geometry = new THREE.SphereBufferGeometry( 1, 12, 16);
    var material = new THREE.MeshPhongMaterial({color: 0xff0000, flatShading: true, shininess: 100, specular: 0x00ff00});

    var mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

}

function animate() {

    requestAnimationFrame( animate );
    renderer.render( scene, camera );

}
body {
  margin: 0;
}
canvas {
  display: block;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.js"></script>

I assume the face of the cube should look same at all pixels but its not looking so.

This is not what flat shading does. Normally vertex normals are interpolated in the fragment shader which produces the typical smooth rendering. Flat shading just ensures that the normals of a face are equal across its (flat) surface. So there is no interpolation of vertex normals. Apart from that, lighting calculations are not affected. Hence, you also see specular highlights.

like image 63
Mugen87 Avatar answered Dec 23 '25 16:12

Mugen87



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!