From 94b8cf6af3b615936615ca90d13d0470599273a0 Mon Sep 17 00:00:00 2001 From: Olivier Guyot Date: Tue, 22 Oct 2019 13:39:07 +0200 Subject: [PATCH] Webgl / add support for a time operator in literal styles This required adding `u_time` as one of the default uniforms provided by the webgl helper. --- src/ol/webgl/Helper.js | 11 ++++++++++- src/ol/webgl/ShaderBuilder.js | 8 ++++++-- test/spec/ol/webgl/helper.test.js | 12 +++++++++--- test/spec/ol/webgl/shaderbuilder.test.js | 6 ++++++ 4 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/ol/webgl/Helper.js b/src/ol/webgl/Helper.js index 04c6eee152..288babfcfa 100644 --- a/src/ol/webgl/Helper.js +++ b/src/ol/webgl/Helper.js @@ -42,7 +42,8 @@ export const ShaderType = { export const DefaultUniform = { PROJECTION_MATRIX: 'u_projectionMatrix', OFFSET_SCALE_MATRIX: 'u_offsetScaleMatrix', - OFFSET_ROTATION_MATRIX: 'u_offsetRotateMatrix' + OFFSET_ROTATION_MATRIX: 'u_offsetRotateMatrix', + TIME: 'u_time' }; /** @@ -355,6 +356,12 @@ class WebGLHelper extends Disposable { * @private */ this.shaderCompileErrors_ = null; + + /** + * @type {number} + * @private + */ + this.startTime_ = Date.now(); } /** @@ -548,6 +555,8 @@ class WebGLHelper extends Disposable { this.setUniformMatrixValue(DefaultUniform.OFFSET_SCALE_MATRIX, fromTransform(this.tmpMat4_, offsetScaleMatrix)); this.setUniformMatrixValue(DefaultUniform.OFFSET_ROTATION_MATRIX, fromTransform(this.tmpMat4_, offsetRotateMatrix)); + + this.setUniformFloatValue(DefaultUniform.TIME, (Date.now() - this.startTime_) * 0.001); } /** diff --git a/src/ol/webgl/ShaderBuilder.js b/src/ol/webgl/ShaderBuilder.js index 7860ab8e46..f03b7e7e91 100644 --- a/src/ol/webgl/ShaderBuilder.js +++ b/src/ol/webgl/ShaderBuilder.js @@ -66,6 +66,8 @@ export function parse(value, attributes, attributePrefix) { attributes.push(v[1]); } return attributePrefix + v[1]; + case 'time': + return 'u_time'; // math operators case '*': return `(${p(v[1])} * ${p(v[2])})`; @@ -328,8 +330,8 @@ export class ShaderBuilder { * Generates a symbol vertex shader from the builder parameters, * intended to be used on point geometries. * - * Three uniforms are hardcoded in all shaders: `u_projectionMatrix`, `u_offsetScaleMatrix` and - * `u_offsetRotateMatrix`. + * Three uniforms are hardcoded in all shaders: `u_projectionMatrix`, `u_offsetScaleMatrix`, + * `u_offsetRotateMatrix`, `u_time`. * * The following attributes are hardcoded and expected to be present in the vertex buffers: * `vec2 a_position`, `float a_index` (being the index of the vertex in the quad, 0 to 3). @@ -348,6 +350,7 @@ export class ShaderBuilder { uniform mat4 u_projectionMatrix; uniform mat4 u_offsetScaleMatrix; uniform mat4 u_offsetRotateMatrix; +uniform float u_time; ${this.uniforms.map(function(uniform) { return 'uniform ' + uniform + ';'; }).join('\n')} @@ -393,6 +396,7 @@ ${this.varyings.map(function(varying) { */ getSymbolFragmentShader() { return `precision mediump float; +uniform float u_time; ${this.uniforms.map(function(uniform) { return 'uniform ' + uniform + ';'; }).join('\n')} diff --git a/test/spec/ol/webgl/helper.test.js b/test/spec/ol/webgl/helper.test.js index 9e3bd65583..11f8c7eb20 100644 --- a/test/spec/ol/webgl/helper.test.js +++ b/test/spec/ol/webgl/helper.test.js @@ -1,4 +1,4 @@ -import WebGLHelper from '../../../../src/ol/webgl/Helper.js'; +import WebGLHelper, {DefaultUniform} from '../../../../src/ol/webgl/Helper.js'; import { create as createTransform, rotate as rotateTransform, @@ -11,9 +11,9 @@ import {FLOAT} from '../../../../src/ol/webgl.js'; const VERTEX_SHADER = ` precision mediump float; - uniform mat4 u_projectionMatrix; uniform mat4 u_offsetScaleMatrix; uniform mat4 u_offsetRotateMatrix; + uniform float u_time; attribute float a_test; uniform float u_test; @@ -25,9 +25,9 @@ const VERTEX_SHADER = ` const INVALID_VERTEX_SHADER = ` precision mediump float; - uniform mat4 u_projectionMatrix; uniform mat4 u_offsetScaleMatrix; uniform mat4 u_offsetRotateMatrix; + uniform float u_time; bla uniform float u_test; @@ -123,6 +123,12 @@ describe('ol.webgl.WebGLHelper', function() { expect(h.getCanvas().height).to.eql(160); }); + it('has processed default uniforms', function() { + expect(h.uniformLocations_[DefaultUniform.OFFSET_ROTATION_MATRIX]).not.to.eql(undefined); + expect(h.uniformLocations_[DefaultUniform.OFFSET_SCALE_MATRIX]).not.to.eql(undefined); + expect(h.uniformLocations_[DefaultUniform.TIME]).not.to.eql(undefined); + }); + it('has processed uniforms', function() { expect(h.uniforms_.length).to.eql(4); expect(h.uniforms_[0].name).to.eql('u_test1'); diff --git a/test/spec/ol/webgl/shaderbuilder.test.js b/test/spec/ol/webgl/shaderbuilder.test.js index 98c2012824..5ade1799fc 100644 --- a/test/spec/ol/webgl/shaderbuilder.test.js +++ b/test/spec/ol/webgl/shaderbuilder.test.js @@ -45,6 +45,7 @@ describe('ol.webgl.ShaderBuilder', function() { uniform mat4 u_projectionMatrix; uniform mat4 u_offsetScaleMatrix; uniform mat4 u_offsetRotateMatrix; +uniform float u_time; attribute vec2 a_position; attribute float a_index; @@ -85,6 +86,7 @@ void main(void) { uniform mat4 u_projectionMatrix; uniform mat4 u_offsetScaleMatrix; uniform mat4 u_offsetRotateMatrix; +uniform float u_time; uniform float u_myUniform; attribute vec2 a_position; attribute float a_index; @@ -122,6 +124,7 @@ void main(void) { uniform mat4 u_projectionMatrix; uniform mat4 u_offsetScaleMatrix; uniform mat4 u_offsetRotateMatrix; +uniform float u_time; attribute vec2 a_position; attribute float a_index; @@ -160,6 +163,7 @@ void main(void) { builder.setTextureCoordinateExpression('vec4(' + formatArray([0, 0.5, 0.5, 1]) + ')'); expect(builder.getSymbolFragmentShader()).to.eql(`precision mediump float; +uniform float u_time; varying vec2 v_texCoord; varying vec2 v_quadCoord; @@ -182,6 +186,7 @@ void main(void) { builder.setFragmentDiscardExpression('u_myUniform > 0.5'); expect(builder.getSymbolFragmentShader()).to.eql(`precision mediump float; +uniform float u_time; uniform float u_myUniform; uniform vec2 u_myUniform2; varying vec2 v_texCoord; @@ -209,6 +214,7 @@ void main(void) { it('parses expressions & literal values', function() { expect(parseFn(1)).to.eql('1.0'); expect(parseFn(['get', 'myAttr'])).to.eql('a_myAttr'); + expect(parseFn(['time'])).to.eql('u_time'); expect(parseFn(['+', ['*', ['get', 'size'], 0.001], 12])).to.eql('((a_size * 0.001) + 12.0)'); expect(parseFn(['clamp', ['get', 'attr2'], ['get', 'attr3'], 20])).to.eql('clamp(a_attr2, a_attr3, 20.0)'); expect(parseFn(['stretch', ['get', 'size'], 10, 100, 4, 8])).to.eql('(clamp(a_size, 10.0, 100.0) * ((8.0 - 4.0) / (100.0 - 10.0)) + 4.0)');