diff --git a/.travis.yml b/.travis.yml index 55a330fcc9..b1707a9bce 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,11 +53,12 @@ before_script: - export DISPLAY=:99.0 script: + # Use the glslangValidator to validate all .frag and .vert files + - find . \( -name '*.frag' \) -exec sh -c 'for n; do python scripts/preprocess_glsl.py "$n" | bin/glslangValidator --stdin -S frag || exit 1; done' sh {} \+ + - find . \( -name '*.vert' \) -exec sh -c 'for n; do python scripts/preprocess_glsl.py "$n" | bin/glslangValidator --stdin -S vert || exit 1; done' sh {} \+ - npm run build - npm run docs - mkdir -p _build - # Use the glslangValidator to validate all .frag and .vert files - - find . \( -name '*.frag' -o -name '*.vert' \) -exec bin/glslangValidator {} \+ - ctest -S cmake/travis_build.cmake -VV || true - if [ -f _build/test_failed ] ; then false ; fi # Build the website to ensure that it will pass diff --git a/scripts/preprocess_glsl.py b/scripts/preprocess_glsl.py new file mode 100755 index 0000000000..b6b0d58640 --- /dev/null +++ b/scripts/preprocess_glsl.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 + +import argparse +import os +import re +import sys + + +def readSource(source): + data = open(source).read() + parts = re.split('(\\$[-.\\w]+)', data) + for idx, chunk in enumerate(parts): + if chunk.startswith('$') and len(chunk) > 1: + parts[idx] = readSource(os.path.join(os.path.dirname(source), chunk[1:] + '.glsl')) + return ''.join(parts) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + description='Preprocess glsl files to handle includes in the same way ' + 'as shader-loader. The output of this can sent to glslangValidator.') + parser.add_argument('source', help='Source file') + args = parser.parse_args() + data = readSource(args.source) + sys.stdout.write(data) diff --git a/src/webgl/pointFeatureFS.glsl b/src/webgl/pointFeatureFS.glsl new file mode 100644 index 0000000000..9085398c0a --- /dev/null +++ b/src/webgl/pointFeatureFS.glsl @@ -0,0 +1,41 @@ +/* pointFeature common fragment shader */ + +#ifdef GL_ES + precision highp float; +#endif +varying vec4 fillColorVar; +varying vec4 strokeColorVar; +varying float radiusVar; +varying float strokeWidthVar; + +void pointFeatureFragment(float rad) { + vec4 strokeColor, fillColor; + float endStep; + // No stroke or fill implies nothing to draw + if (rad > 1.0) + discard; + // If there is no stroke, the fill region should transition to nothing + if (strokeColorVar.a == 0.0) { + strokeColor = vec4(fillColorVar.rgb, 0.0); + endStep = 1.0; + } else { + strokeColor = strokeColorVar; + endStep = radiusVar / (radiusVar + strokeWidthVar); + } + // Likewise, if there is no fill, the stroke should transition to nothing + if (fillColorVar.a == 0.0) + fillColor = vec4(strokeColor.rgb, 0.0); + else + fillColor = fillColorVar; + // Distance to antialias over. First number is in pixels + float antialiasDist = 1.5 / (radiusVar + strokeWidthVar); + if (rad < endStep) { + float step = smoothstep(max(0.0, endStep - antialiasDist), endStep, rad); + vec4 color = mix(fillColor, strokeColor, step); + float step2 = smoothstep(max(0.0, 1.0 - antialiasDist), 1.0, rad); + gl_FragColor = mix(color, vec4(color.rgb, 0.0), step2); + } else { + float step = smoothstep(max(0.0, 1.0 - antialiasDist), 1.0, rad); + gl_FragColor = mix(strokeColor, vec4(strokeColor.rgb, 0.0), step); + } +} diff --git a/src/webgl/pointFeaturePoly.frag b/src/webgl/pointFeaturePoly.frag index 284e20445c..d4b54da447 100644 --- a/src/webgl/pointFeaturePoly.frag +++ b/src/webgl/pointFeaturePoly.frag @@ -1,46 +1,12 @@ /* pointFeature square/triangle fragment shader */ -#ifdef GL_ES - precision highp float; -#endif -uniform float aspect; -varying vec4 fillColorVar; -varying vec4 strokeColorVar; -varying float radiusVar; -varying float strokeWidthVar; +$pointFeatureFS + varying vec3 unitVar; // distinct for square/triangle void main () { - vec4 strokeColor, fillColor; - float endStep; - // No stroke or fill implies nothing to draw if (fillColorVar.a == 0.0 && strokeColorVar.a == 0.0) discard; float rad = length(unitVar.xy); // distinct for square/triangle - if (rad > 1.0) - discard; - // If there is no stroke, the fill region should transition to nothing - if (strokeColorVar.a == 0.0) { - strokeColor = vec4(fillColorVar.rgb, 0.0); - endStep = 1.0; - } else { - strokeColor = strokeColorVar; - endStep = radiusVar / (radiusVar + strokeWidthVar); - } - // Likewise, if there is no fill, the stroke should transition to nothing - if (fillColorVar.a == 0.0) - fillColor = vec4(strokeColor.rgb, 0.0); - else - fillColor = fillColorVar; - // Distance to antialias over. First number is in pixels - float antialiasDist = 1.5 / (radiusVar + strokeWidthVar); - if (rad < endStep) { - float step = smoothstep(max(0.0, endStep - antialiasDist), endStep, rad); - vec4 color = mix(fillColor, strokeColor, step); - float step2 = smoothstep(max(0.0, 1.0 - antialiasDist), 1.0, rad); - gl_FragColor = mix(color, vec4(color.rgb, 0.0), step2); - } else { - float step = smoothstep(max(0.0, 1.0 - antialiasDist), 1.0, rad); - gl_FragColor = mix(strokeColor, vec4(strokeColor.rgb, 0.0), step); - } + pointFeatureFragment(rad); } diff --git a/src/webgl/pointFeaturePoly.vert b/src/webgl/pointFeaturePoly.vert index a145f59fbd..d27b6c2d3f 100644 --- a/src/webgl/pointFeaturePoly.vert +++ b/src/webgl/pointFeaturePoly.vert @@ -1,46 +1,18 @@ /* pointFeature square/triangle vertex shader */ -#ifdef GL_ES - precision highp float; -#endif -attribute vec3 pos; -attribute float radius; -attribute vec3 fillColor; -attribute vec3 strokeColor; -attribute float fillOpacity; -attribute float strokeWidth; -attribute float strokeOpacity; -attribute float fill; -attribute float stroke; -uniform float pixelWidth; -uniform float aspect; -uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -varying vec4 fillColorVar; -varying vec4 strokeColorVar; -varying float radiusVar; -varying float strokeWidthVar; +$pointFeatureVS + +uniform float pixelWidth; // for non-sprite +uniform float aspect; // for non-sprite attribute vec2 unit; // for non-sprite varying vec3 unitVar; // for non-sprite void main(void) { - strokeWidthVar = strokeWidth; - fillColorVar = vec4(fillColor, fillOpacity); - strokeColorVar = vec4(strokeColor, strokeOpacity); - // No stroke or fill implies nothing to draw - if (stroke < 1.0 || strokeWidth <= 0.0 || strokeOpacity <= 0.0) { - strokeColorVar.a = 0.0; - strokeWidthVar = 0.0; - } - if (fill < 1.0 || radius <= 0.0 || fillOpacity <= 0.0) - fillColorVar.a = 0.0; - /* If the point has no visible pixels, skip doing computations on it. */ - if (fillColorVar.a == 0.0 && strokeColorVar.a == 0.0) { - gl_Position = vec4(2, 2, 0, 1); + radiusVar = pointFeaturePrep(); + if (radiusVar == 0.0) { return; } - radiusVar = radius; // for non-sprite unitVar = vec3(unit, 1.0); vec4 p = (projectionMatrix * modelViewMatrix * vec4(pos, 1.0)).xyzw; diff --git a/src/webgl/pointFeatureSprite.frag b/src/webgl/pointFeatureSprite.frag index f463897315..9fd189665c 100644 --- a/src/webgl/pointFeatureSprite.frag +++ b/src/webgl/pointFeatureSprite.frag @@ -1,46 +1,13 @@ /* pointFeature sprite fragment shader */ -#ifdef GL_ES - precision highp float; -#endif -uniform float aspect; -varying vec4 fillColorVar; -varying vec4 strokeColorVar; -varying float radiusVar; -varying float strokeWidthVar; -// the square/triangle shade defines unitVar +$pointFeatureFS + +// the square/triangle shader defines unitVar void main () { - vec4 strokeColor, fillColor; - float endStep; // No stroke or fill implies nothing to draw if (fillColorVar.a == 0.0 && strokeColorVar.a == 0.0) discard; float rad = 2.0 * length(gl_PointCoord - vec2(0.5)); // distinct for sprite - if (rad > 1.0) - discard; - // If there is no stroke, the fill region should transition to nothing - if (strokeColorVar.a == 0.0) { - strokeColor = vec4(fillColorVar.rgb, 0.0); - endStep = 1.0; - } else { - strokeColor = strokeColorVar; - endStep = radiusVar / (radiusVar + strokeWidthVar); - } - // Likewise, if there is no fill, the stroke should transition to nothing - if (fillColorVar.a == 0.0) - fillColor = vec4(strokeColor.rgb, 0.0); - else - fillColor = fillColorVar; - // Distance to antialias over. First number is in pixels - float antialiasDist = 1.5 / (radiusVar + strokeWidthVar); - if (rad < endStep) { - float step = smoothstep(max(0.0, endStep - antialiasDist), endStep, rad); - vec4 color = mix(fillColor, strokeColor, step); - float step2 = smoothstep(max(0.0, 1.0 - antialiasDist), 1.0, rad); - gl_FragColor = mix(color, vec4(color.rgb, 0.0), step2); - } else { - float step = smoothstep(max(0.0, 1.0 - antialiasDist), 1.0, rad); - gl_FragColor = mix(strokeColor, vec4(strokeColor.rgb, 0.0), step); - } + pointFeatureFragment(rad); } diff --git a/src/webgl/pointFeatureSprite.vert b/src/webgl/pointFeatureSprite.vert index e9069c0674..ee0da0f3d3 100644 --- a/src/webgl/pointFeatureSprite.vert +++ b/src/webgl/pointFeatureSprite.vert @@ -1,45 +1,13 @@ /* pointFeature sprite vertex shader */ -#ifdef GL_ES - precision highp float; -#endif -attribute vec3 pos; -attribute float radius; -attribute vec3 fillColor; -attribute vec3 strokeColor; -attribute float fillOpacity; -attribute float strokeWidth; -attribute float strokeOpacity; -attribute float fill; -attribute float stroke; -uniform float pixelWidth; -uniform float aspect; -uniform mat4 modelViewMatrix; -uniform mat4 projectionMatrix; -varying vec4 fillColorVar; -varying vec4 strokeColorVar; -varying float radiusVar; -varying float strokeWidthVar; -// non-sprite has ither definitions. +$pointFeatureVS void main(void) { - strokeWidthVar = strokeWidth; - fillColorVar = vec4(fillColor, fillOpacity); - strokeColorVar = vec4(strokeColor, strokeOpacity); - // No stroke or fill implies nothing to draw - if (stroke < 1.0 || strokeWidth <= 0.0 || strokeOpacity <= 0.0) { - strokeColorVar.a = 0.0; - strokeWidthVar = 0.0; - } - if (fill < 1.0 || radius <= 0.0 || fillOpacity <= 0.0) - fillColorVar.a = 0.0; - /* If the point has no visible pixels, skip doing computations on it. */ - if (fillColorVar.a == 0.0 && strokeColorVar.a == 0.0) { - gl_Position = vec4(2, 2, 0, 1); + radiusVar = pointFeaturePrep(); + if (radiusVar == 0.0) { return; } - radiusVar = radius; // for sprite gl_Position = (projectionMatrix * modelViewMatrix * vec4(pos, 1.0)).xyzw; gl_PointSize = 2.0 * (radius + strokeWidthVar); diff --git a/src/webgl/pointFeatureVS.glsl b/src/webgl/pointFeatureVS.glsl new file mode 100644 index 0000000000..a9cbf1e213 --- /dev/null +++ b/src/webgl/pointFeatureVS.glsl @@ -0,0 +1,39 @@ +/* pointFeature common vertex shader */ + +#ifdef GL_ES + precision highp float; +#endif +attribute vec3 pos; +attribute float radius; +attribute vec3 fillColor; +attribute vec3 strokeColor; +attribute float fillOpacity; +attribute float strokeWidth; +attribute float strokeOpacity; +attribute float fill; +attribute float stroke; +uniform mat4 modelViewMatrix; +uniform mat4 projectionMatrix; +varying vec4 fillColorVar; +varying vec4 strokeColorVar; +varying float radiusVar; +varying float strokeWidthVar; + +float pointFeaturePrep() { + strokeWidthVar = strokeWidth; + fillColorVar = vec4(fillColor, fillOpacity); + strokeColorVar = vec4(strokeColor, strokeOpacity); + // No stroke or fill implies nothing to draw + if (stroke < 1.0 || strokeWidth <= 0.0 || strokeOpacity <= 0.0) { + strokeColorVar.a = 0.0; + strokeWidthVar = 0.0; + } + if (fill < 1.0 || radius <= 0.0 || fillOpacity <= 0.0) + fillColorVar.a = 0.0; + /* If the point has no visible pixels, skip doing computations on it. */ + if (fillColorVar.a == 0.0 && strokeColorVar.a == 0.0) { + gl_Position = vec4(2, 2, 0, 1); + return 0.0; + } + return radius; +} diff --git a/webpack.base.config.js b/webpack.base.config.js index 410046d70f..ccbe2462ef 100644 --- a/webpack.base.config.js +++ b/webpack.base.config.js @@ -135,9 +135,12 @@ module.exports = { ] }, { test: /\.(glsl|vs|fs|vert|frag)$/, - use: [ - 'shader-loader' - ] + use: [{ + loader: 'shader-loader', + options: { + glsl: { chunkPath: 'src/webgl' } + } + }] }, { test: /vgl\.js$/, use: [