Skip to content

Commit

Permalink
Change the point shaders so that common code is in shared files.
Browse files Browse the repository at this point in the history
The shader-loader allows importing chunks into other files.  This allows
common code to be placed in a shared file and imported by other files.
There are some restrictions: the common chunks must have filenames
ending in `glsl`, and the glslangValidator doesn't handle these
inclusions on its own.  However, sharing code is of substantial benefit
for reducing maintenance issues, so it is worth this change.

Note that there are other webpack shader loaders (e.g.,
webpack-glsl-loader) that provide similar include functionality but with
a different syntax, as glsl doesn't have its own include statements.  As
such, if we ever switch the shader loader to another one, the import
statements would have to change.
  • Loading branch information
manthey committed Oct 11, 2019
1 parent cff40dc commit 1da3186
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 148 deletions.
5 changes: 3 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
25 changes: 25 additions & 0 deletions scripts/preprocess_glsl.py
Original file line number Diff line number Diff line change
@@ -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)
41 changes: 41 additions & 0 deletions src/webgl/pointFeatureFS.glsl
Original file line number Diff line number Diff line change
@@ -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);
}
}
40 changes: 3 additions & 37 deletions src/webgl/pointFeaturePoly.frag
Original file line number Diff line number Diff line change
@@ -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);
}
40 changes: 6 additions & 34 deletions src/webgl/pointFeaturePoly.vert
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
41 changes: 4 additions & 37 deletions src/webgl/pointFeatureSprite.frag
Original file line number Diff line number Diff line change
@@ -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);
}
38 changes: 3 additions & 35 deletions src/webgl/pointFeatureSprite.vert
Original file line number Diff line number Diff line change
@@ -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);
Expand Down
39 changes: 39 additions & 0 deletions src/webgl/pointFeatureVS.glsl
Original file line number Diff line number Diff line change
@@ -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;
}
9 changes: 6 additions & 3 deletions webpack.base.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand Down

0 comments on commit 1da3186

Please sign in to comment.