I'm writing a custom ShaderMaterial and decided to include lights and fog. So far so good and I got the shader integrated with three.js build it fog, ambient and point lights (it serves my purpose).
However, the shading I get its smooth, not flat. Before you guys decide to suggest adding the shading: THREE.FlatShading flag to the ShaderMaterial, remember that this is a custom Shader and therefore that won't really do anything.
Since FlatShading is done by calculating the triangle centroid and fill all the colors based on that vector, I thought using the normal of the triangle vertices would do the trick.. obviously it doest... Is that a way of correctly have a FlatShading light where all the pixels inside the triangle have 1 single colour? If so, what am I missing?
here's my shader in CoffeeScript
class SomeShader
constructor: ->
@defines = {}
@uniforms = THREE.UniformsUtils.merge [
THREE.UniformsLib['fog']
THREE.UniformsLib['lights']
{
color: { type: 'c', value: new THREE.Color(0xffffff) }
}
]
@vertex = [
'uniform vec3 ambientLightColor;'
'#if MAX_POINT_LIGHTS > 0'
' uniform vec3 pointLightColor[MAX_POINT_LIGHTS];'
' uniform vec3 pointLightPosition[MAX_POINT_LIGHTS];'
' uniform float pointLightDistance[MAX_POINT_LIGHTS];'
'#endif'
'uniform vec3 color;'
'varying vec4 v_color;'
'void main() {'
# lights
' vec3 norm = normalMatrix * normal;'
' vec3 pos = (modelViewMatrix * vec4(position-norm, 1.0 )).xyz;'
' vec3 outgoingLight = vec3(1.);'
' vec4 addedLights = vec4(0., 0., 0., 1.);'
' #if MAX_POINT_LIGHTS > 0'
' for(int l = 0; l < MAX_POINT_LIGHTS; l++) {'
' vec3 lightDirection = normalize(pos - pointLightPosition[l]);'
' addedLights.rgb += clamp(dot(-lightDirection, norm), 0.0, 1.0) * pointLightColor[l];'
' }'
' #endif'
' addedLights += vec4(ambientLightColor, 1.);'
' v_color = vec4(outgoingLight, 1.) * addedLights;'
' gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);'
'}'
].join '\n'
@fragment = [
THREE.ShaderChunk['fog_pars_fragment']
'varying vec4 v_color;'
'void main() {'
' vec3 outgoingLight = vec3( 1. );'
THREE.ShaderChunk['fog_fragment']
' gl_FragColor = v_color * vec4(outgoingLight, 1.);'
'}'
].join '\n'
You are using ShaderMaterial and your are displacing your vertices in the vertex shader with a noise function. You also want to recompute the vertex normals so the shading is flat -- i.e., faceted.
To do that, you need to compute new normals using screen-space derivatives in the fragment shader, and also do your lighting calculation in the fragment shader.
So, in your vertex shader, compute the following varying:
varying vec3 vViewPosition;
vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );
vViewPosition = - mvPosition.xyz; // vector from vertex to camera
Then, in the fragment shader, compute the normal using screen-space derivatives:
normal = normalize( cross( dFdx( vViewPosition ), dFdy( vViewPosition ) ) );
Now, use your lighting model to compute the shading in the fragment shader.
three.js r.73
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With