From df0764deac15d95c85f235d10d730602eeff38d1 Mon Sep 17 00:00:00 2001 From: Tarek Sherif Date: Mon, 8 Apr 2019 17:52:33 -0400 Subject: [PATCH] Flat shading in SimpleMeshLayer --- .../simple-mesh-layer-fragment.glsl.js | 10 ++++- .../simple-mesh-layer-fragment.glsl3.js | 37 +++++++++++++++++ .../simple-mesh-layer-vertex.glsl3.js | 40 +++++++++++++++++++ .../simple-mesh-layer/simple-mesh-layer.js | 23 ++++++++--- 4 files changed, 104 insertions(+), 6 deletions(-) create mode 100644 modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl3.js create mode 100644 modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-vertex.glsl3.js diff --git a/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl.js b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl.js index 5b37649bc38..ed2ec755512 100644 --- a/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl.js +++ b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl.js @@ -6,6 +6,7 @@ precision highp float; uniform bool hasTexture; uniform sampler2D sampler; uniform vec4 color; +uniform bool flatShade; varying vec2 vTexCoord; varying vec3 cameraPosition; @@ -14,8 +15,15 @@ varying vec4 position_commonspace; varying vec4 vColor; void main(void) { + vec3 normal; + if (flatShade) { + normal = normalize(cross(dFdx(position_commonspace.xyz), dFdy(position_commonspace.xyz))); + } else { + normal = normals_commonspace; + } + vec4 color = hasTexture ? texture2D(sampler, vTexCoord) : vColor / 255.; - vec3 lightColor = lighting_getLightColor(color.rgb * 255., cameraPosition, position_commonspace.xyz, normals_commonspace); + vec3 lightColor = lighting_getLightColor(color.rgb * 255., cameraPosition, position_commonspace.xyz, normal); gl_FragColor = vec4(lightColor / 255., color.a); // use highlight color if this fragment belongs to the selected object. diff --git a/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl3.js b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl3.js new file mode 100644 index 00000000000..180d40e504a --- /dev/null +++ b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-fragment.glsl3.js @@ -0,0 +1,37 @@ +export default `#version 300 es +#define SHADER_NAME simple-mesh-layer-fs + +precision highp float; + +uniform bool hasTexture; +uniform sampler2D sampler; +uniform vec4 color; +uniform bool flatShade; + +in vec2 vTexCoord; +in vec3 cameraPosition; +in vec3 normals_commonspace; +in vec4 position_commonspace; +in vec4 vColor; + +out vec4 fragColor; + +void main(void) { + vec3 normal; + if (flatShade) { + normal = normalize(cross(dFdx(position_commonspace.xyz), dFdy(position_commonspace.xyz))); + } else { + normal = normals_commonspace; + } + + vec4 color = hasTexture ? texture(sampler, vTexCoord) : vColor / 255.; + vec3 lightColor = lighting_getLightColor(color.rgb * 255., cameraPosition, position_commonspace.xyz, normal); + fragColor = vec4(lightColor / 255., color.a); + + // use highlight color if this fragment belongs to the selected object. + fragColor = picking_filterHighlightColor(fragColor); + + // use picking color if rendering to picking FBO. + fragColor = picking_filterPickingColor(fragColor); +} +`; diff --git a/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-vertex.glsl3.js b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-vertex.glsl3.js new file mode 100644 index 00000000000..c2addd53362 --- /dev/null +++ b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer-vertex.glsl3.js @@ -0,0 +1,40 @@ +export default `#version 300 es +#define SHADER_NAME simple-mesh-layer-vs + +// Scale the model +uniform float sizeScale; + +// Primitive attributes +in vec3 positions; +in vec3 normals; +in vec2 texCoords; + +// Instance attributes +in vec3 instancePositions; +in vec2 instancePositions64xy; +in vec4 instanceColors; +in vec3 instancePickingColors; +in mat3 instanceModelMatrix; +in vec3 instanceTranslation; + +// Outputs to fragment shader +out vec2 vTexCoord; +out vec3 cameraPosition; +out vec3 normals_commonspace; +out vec4 position_commonspace; +out vec4 vColor; + +void main(void) { + vec3 pos = (instanceModelMatrix * positions) * sizeScale + instanceTranslation; + pos = project_size(pos); + + vTexCoord = texCoords; + cameraPosition = project_uCameraPosition; + normals_commonspace = project_normal(instanceModelMatrix * normals); + vColor = instanceColors; + + gl_Position = project_position_to_clipspace(instancePositions, instancePositions64xy, pos, position_commonspace); + + picking_setPickingColor(instancePickingColors); +} +`; diff --git a/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer.js b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer.js index 046974601f0..9a1ea3789d4 100644 --- a/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer.js +++ b/modules/mesh-layers/src/simple-mesh-layer/simple-mesh-layer.js @@ -24,15 +24,17 @@ import {Layer, createIterable} from '@deck.gl/core'; import GL from '@luma.gl/constants'; -import {Model, Geometry, Texture2D, fp64, Buffer, PhongMaterial} from '@luma.gl/core'; +import {Model, Geometry, Texture2D, fp64, Buffer, PhongMaterial, isWebGL2} from '@luma.gl/core'; import {loadImage, loadFile} from '@loaders.gl/core'; import {Matrix4} from 'math.gl'; const {fp64LowPart} = fp64; import {MATRIX_ATTRIBUTES} from '../utils/matrix'; -import vs from './simple-mesh-layer-vertex.glsl'; -import fs from './simple-mesh-layer-fragment.glsl'; +import vs1 from './simple-mesh-layer-vertex.glsl'; +import fs1 from './simple-mesh-layer-fragment.glsl'; +import vs3 from './simple-mesh-layer-vertex.glsl3'; +import fs3 from './simple-mesh-layer-fragment.glsl3'; // Replacement for the external assert method to reduce bundle size function assert(condition, message) { @@ -73,7 +75,8 @@ function getTextureFromData(gl, data, opts) { function validateGeometryAttributes(attributes) { assert( - (attributes.positions && attributes.normals) || (attributes.POSITION && attributes.NORMAL) + attributes.positions || attributes.POSITION, + 'SimpleMeshLayer requires "postions" or "POSITION" attribute in mesh property.' ); } @@ -141,6 +144,10 @@ const defaultProps = { export default class SimpleMeshLayer extends Layer { getShaders() { const projectModule = this.use64bitProjection() ? 'project64' : 'project32'; + const gl2 = isWebGL2(this.context.gl); + const vs = gl2 ? vs3 : vs1; + const fs = gl2 ? fs3 : fs1; + return {vs, fs, modules: [projectModule, 'phong-lighting', 'picking']}; } @@ -176,6 +183,8 @@ export default class SimpleMeshLayer extends Layer { height: 1 }) }); + + this.context.gl.getExtension('OES_standard_derivatives'); } updateState({props, oldProps, changeFlags}) { @@ -187,6 +196,9 @@ export default class SimpleMeshLayer extends Layer { } if (props.mesh) { this.setState({model: this.getModel(props.mesh)}); + this.setState({ + hasNormals: Boolean(props.mesh.attributes.NORMAL || props.mesh.attributes.normals) + }); } this.getAttributeManager().invalidateAll(); } @@ -209,7 +221,8 @@ export default class SimpleMeshLayer extends Layer { this.state.model.draw({ uniforms: Object.assign({}, uniforms, { - sizeScale + sizeScale, + flatShade: !this.state.hasNormals }) }); }