Three.js - CanvasRenderer problems: flat shading? - three.js

I'm trying to use CanvasRenderer (three.js) as a fallback for devices not supporting WebGL. Is there some comparison page with explanation what is different and cannot be used with CanvasRenderer?
I'm experiencing two main issues:
flat shading, lights are completely missing (is MeshPhongMaterial supported?), I don't see any lighting nor shadows (are shadows supported in CanvasRenderer)? All I see is the diffuse texture without any lighting. In WebGL my current setup is PointLight, DirectionalLight, softShadows, antialiasing and MeshPhongMaterial (with diffuse, bump, spec and env map)
this.materialM = new THREE.MeshPhongMaterial({
ambient : 0x050505,
color : this.model.color,
specular : 0xcccccc,
shininess : 100,
bumpScale : BUMP_SCALE,
reflectivity : REFLECTIVITY,
});
transparent polygon edges (I know it can be tweaked with material.overdraw = 0.5 yet it produces other artifacts (as it probably does only some scaling of polys along the normal?), but I can do with this one
Any help on 1. or some general overview of what is not possible in CanvasRenderer when comparing to WebGLRenderer is greatly appreciated!
three.js r68

CanvasRenderer has limitations.
MeshPhongMaterial is not supported in CanvasRenderer -- it falls back to MeshLambertMaterial.
MeshLambertMaterial is supported, but not when the material has a texture -- it falls back to MeshBasicMaterial. ( MeshBasicMaterial is rendered without regards to scene lights. )
Shadows are not supported.
material.overdraw = 0.5 is helpful in hiding polygon edges when the material is opaque. It may still leave artifacts if the material is transparent.
three.js r.68

Related

outline shader only threejs

based on previous questions: Outline object (normal scale + stencil mask) three.js
I am trying to make a material shader for threejs to render only the contour and not both with the object. Should this be the right reference or is there a more straighforward way to do it?
At the moment, the most straightforward solution I could find is from: https://stemkoski.github.io/Three.js/Outline.html with a slightly scaled marching cube using side: THREE.BackSide param in its material.

Change/specify the dark color, so unlit areas have a specific color

Is there a simple way in three.js to specify a color for "dark"? That is, in a scene with light, the colors of an object fade to black. What I want is for them to fade to a different color. I want to specify what color "unlit" is. I'm using a MeshPhongMaterial in this particular case.
Answer: There is no way to do this in the current three.js version. I've selected an answer with possible workarounds.
It is called ambient light.
scene.add( new THREE.AmbientLight( 0x222222 ) );
The argument to the constructor is the color of the light.
When using MeshPhongMaterial, it is also advisable to set the ambient reflectance of the material to match the material's diffuse reflectance, also know as the color.
material.color.set( 0xff0000 );
material.ambient.set( 0xff0000 );
If you follow this advice, your scene should look pretty good.
three.js r.64

Easy way to use light in fragment shader

I have a Collada object which i load per Three.js into my scene.
Now I want to change some vertex positions of the model in the
vertex shader, which is no problem.
But with this I have to skip the exported collada material and take a
ShaderMaterial.
The problem is now that I have to calculate the complete lighting of
the scene in my fragment shader.
Before, with the collada material, the complete lighting was calculated by the framework by using a directional light and a hemisphere light.
So my question is, if there is a solution where I can leave the fragmentShader untouched and all the colors are calculated as if I would use no ShaderMaterial.
I tried to use THREE.ShaderLib and pass only the fragmentShader of the phong shader
and my own vertexShader. But this gave only errors that not the same varyings are defined in both shaders.
Unfortunately, you are correct. You have to create your own ShaderMaterial, and it will be tedious to incorporate scene lighting.
If your scene lighting is not that important, you can hack in some ambient light and a single light at the camera location in your fragment shader.
If your scene lighting is important, then you need to set the ShaderMaterial parameter lights: true, and you will have access to the scene light uniforms in your vertex and fragment shaders.
three.js r.63

Three.js canvas renderer seams between polygons

I'm already feeling comfortable enough with this library, but this one made me tired already:
When I'm trying to simply render a mesh without any textures, exported from blender to .obj (triangulating, smoothing groups enabled), the WebGL renderer does that perfectly, but I also need to make it possible with canvas renderer, and here comes the trouble; polygon edges have seams between them and become partially seen through
Just to make it clear, providing screenshots
WebGL Renderer
https://www.monosnap.com/image/OVaQO8yLDU9Wl6ufhADDVCEWg
Canvas renderer
https://www.monosnap.com/image/1AYeyHjWkGx9fQ6vg6xLr0EcV
mesh is quite complex, ~7k triangles
When using CanvasRenderer, you need to set
material.overdraw = 0.5; // or some number between 0 and 1
This will help to alleviate the problem.
Note: overdraw used to be a boolean; it is now a float.
three.js r.63

Specular highlights with a model imported from Blender?

I made in Dice with 2 different colored materials in Blender and exported it with the Blender exporter. In my three.js code, I use JSONLoader to get the mesh and use new THREE.MeshFaceMaterial(); as material.
This loads the model just fine with the two different colored materials showing correctly. But my problem is, that I want the dice to have specular highlights on the surface. Is this even possible with exported Blender models?
I managed to get a Sphere with specular highlights when I used THREE.MeshPhongMaterial() as material for the sphere, but the sphere wasn't imported from Blender and as far as I know, I can't apply a Phong Material when I load the Mesh with JSONLoader, or is there a trick? Please remember: I got two differently colored materials on the dice, which I import from Blender in the JSON file. The dice by itself is red, but the dots should be black. So I am not talking about different colors on each side of a cube or so, but two different colors on every side of the cube. Can you help me?
Here's the code snippet:
loader.load("models/dice.js", function(geometry){
var material = new THREE.MeshFaceMaterial();
material.specular = 0xffffff;
material.shininess = 10000000000;
dice=new THREE.Mesh(geometry, material);
dice.position.set(0,-400,5);
dice.scale.set(75, 75, 75);
dice.overdraw = true;
dice.name="dice";
navscene.add(dice);
});
If it helps, I am able to create a texture out of the two materials and apply them in Blender, so that the JSONLoader loads the texture instead of the materials, but I wasn't able to achieve a specular highlight either with that.
Thx West, you pointed me into the right direction. The problem was, that Blender's standard material type is Lambert. In Blender, this Lambert material produces the desired specular highlight, but once imported to three, the effect is gone. I don't know if this is a bug, or a desired behaviour.
The solution is to set the material type in Blender to Phong material. This works even after import. My guess is, that THREE.MeshFaceMaterial is an array which contains all the loaded materials, whether they are lambert, phong or whatever. It is even possible to mix those material types. So it appears to me, that THREE.MeshFaceMaterial doesn't seem to be a "stand alone" material type at all. Correct me if I'm wrong please.
If your mesh geometry has a materials array, you can always change the array elements after you load the geometry:
geometry.materials[ i ] = new THREE.MeshPhongMaterial( ... );
You then leave the mesh's material as MeshFaceMaterial:
mesh = new THREE.mesh( geometry, new THREE.MeshFaceMaterial() );
The exporter script you are using may set geometry.materials to Lambert material by default, based on your settings. Have a look at the script source code and see if you can figure it out.

Resources