I am looking to render some output to an openlayers map using the vertexShader & fragmentShader from the WebGL options. The long term goal is something like the effect at windy.com.
I have created a CustomWebGLPointsLayer (extending ol/layer/WebGLPoints) & specified some simple shaders to control for position & color. With my CustomWebGLPointsLayer, data points are being placed in the center of the map resulting in a triangle (top left, top right, center) on the map. This triangle also ignores the color(s) I am attempting to set.
Questions are:
- How can I get these points rendered appropriately?
- How can I get the dynamic color to work correctly?
Repo is here if you want to play with the code.
CustomWebGLPointsLayer instantiation:
class CustomWebGLPointsLayer extends WebGLPointsLayer {
createRenderer() {
return new WebGLPointsLayerRenderer(this, {
// "attributes" are passed into the shaders
attributes: [
{
name: 'a_coords',
callback: function(feature) {
// Array of XY positions per feature to pass to the vertexShader.
const coordinatesArr = [
feature.values_[0],
feature.values_[1],
];
return coordinatesArr;
}
},
{
name: 'a_color',
callback: function(feature) {
// Create an array of some colors & select one at random
const colorsArr = {
"red": `[1.0, 0.0, 0.0]`,
"green": `[0.0, 1.0, 0.0]`,
"blue": `[0.0, 0.0, 1.0]`,
};
const obj = Object.keys(colorsArr);
const randomColor = obj[Math.floor(Math.random() * obj.length)];
const vec3_color = colorsArr[randomColor];
return vec3_color;
}
}
],
vertexShader:
`
// Specify the precision level to use with floats in this shader.
precision mediump float;
// Declare attributes; these values are passed into GLSL from JavaScript
attribute vec2 a_coords;
attribute vec3 a_color;
// Declare varyings; these values will be passed along to the fragmentShader
varying vec3 v_color;
void main() {
gl_Position = vec4(a_coords, 0.0, 0.0); // Set the position
v_color = vec3(a_color); // set the value of v_color <-- This doesn't work?
}
`,
// This should paint all fragments the value of v_color
fragmentShader: `
precision mediump float;
// Declare varyings; these values have been passed along from the vertexShader
varying vec3 v_color;
void main() {
gl_FragColor = vec4(v_color, 0.5); // Set the color dynamically - DOESN'T WORK
// gl_FragColor = vec4(1.0, 0.0, 1.0, 0.5); // pink; WORKS!
// gl_FragColor = vec4(1, 0, 0, 0.5); // red; WORKS! (testing ints, not floats)
}
`
})
}
};
And the map
const map = new Map({
layers: [
new Tile({ source: new OSM() }),
// new WebGLPointsLayer({ // Use this if you want to see the points rendered statically
new CustomWebGLPointsLayer({
source: new VectorSource({ features: featuresArr }),
style: {
symbol: {
symbolType: "triangle",
size: 16,
color: "red",
rotation: ["*", ["get", "deg"], Math.PI / 180],
rotateWithView: true,
},
},
}),
],
target: "map",
view: new View({center: [0, 0],zoom: 0,}),
});
Thanks!