如何在mapbox GL JS自定义样式层中使用u_time
How to use u_time in mapbox GL JS custom style layer
我想在 fragmentSource 中添加时间到 mapbox 着色器,但是当我添加 uniform float u_time;
三角形不渲染。这里有一个fiddlehttps://jsfiddle.net/benderlio/o4xc5hw7/33/
var fragmentSource =`
uniform float u_time;
void main() {
gl_FragColor = vec4(sin(1.0*u_time),0.0,1.0,1);
}`
见OpenGL ES Shading Language 1.00 Specification - 4.5.3 Default Precision Qualifiers:
The fragment language has no default precision qualifier for floating point types. Hence for float, floating
point vector and matrix variable declarations, either the declaration must include a precision qualifier or
the default float precision must have been previously declared.
由于统一变量具有浮点类型,因此您必须向片段着色器添加精度限定符。如果您未指定精度限定符,则会导致编译错误(例如,_No precision qualifier for (float)).
要么添加默认精度限定符:
precision mediump float;
uniform float u_time;
或者向统一变量添加显式精度限定符:
uniform mediump float u_time;
我建议验证着色器是否已成功编译 (gl.getShaderParameter
/gl.getShaderInfoLog
) 以及程序是否已链接 (gl.getProgramParameter
/gl.getProgramInfoLog
)。例如:
// create a vertex shader
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(vertexShader));
// create a fragment shader
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(fragmentShader));
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
alert(gl.getProgramInfoLog(this.program));
mapboxgl.accessToken = 'pk.eyJ1IjoiYmVuZGVybGlkemUiLCJhIjoiY2pud3c0MnN1MDdraTN4cXBraDR3MHdyaCJ9.OsQLWGIWOutuIXCHgT8coQ';
var map = (window.map = new mapboxgl.Map({
container: 'map',
zoom: 3,
center: [7.5, 58],
style: 'mapbox://styles/mapbox/light-v10',
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
}));
// create a custom style layer to implement the WebGL content
var highlightLayer = {
id: 'highlight',
type: 'custom',
// method called when the layer is added to the map
// https://docs.mapbox.com/mapbox-gl-js/api/#styleimageinterface#onadd
onAdd: function(map, gl) {
// create GLSL source for vertex shader
var vertexSource =
`
uniform mat4 u_matrix;
attribute vec2 a_pos;
void main() {
gl_Position = u_matrix * vec4(a_pos, 0.0, 1);
}`;
// create GLSL source for fragment shader
var fragmentSource =
`
precision mediump float;
uniform float u_time;
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}`;
// create a vertex shader
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(vertexShader));
// create a fragment shader
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(fragmentShader));
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
alert(gl.getProgramInfoLog(this.program));
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
// define vertices of the triangle to be rendered in the custom style layer
var helsinki = mapboxgl.MercatorCoordinate.fromLngLat({
lng: 25.004,
lat: 60.239
});
var berlin = mapboxgl.MercatorCoordinate.fromLngLat({
lng: 13.403,
lat: 52.562
});
var kyiv = mapboxgl.MercatorCoordinate.fromLngLat({
lng: 30.498,
lat: 50.541
});
// create and initialize a WebGLBuffer to store vertex and color data
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
helsinki.x,
helsinki.y,
berlin.x,
berlin.y,
kyiv.x,
kyiv.y
]),
gl.STATIC_DRAW
);
},
// method fired on each animation frame
// https://docs.mapbox.com/mapbox-gl-js/api/#map.event:render
render: function(gl, matrix) {
gl.useProgram(this.program);
gl.uniformMatrix4fv(
gl.getUniformLocation(this.program, 'u_matrix'),
false,
matrix
);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.aPos);
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
}
};
// add the custom style layer to the map
map.on('load', function() {
map.addLayer(highlightLayer);
});
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.js'></script>
<div id='map'></div>
我想在 fragmentSource 中添加时间到 mapbox 着色器,但是当我添加 uniform float u_time;
三角形不渲染。这里有一个fiddlehttps://jsfiddle.net/benderlio/o4xc5hw7/33/
var fragmentSource =`
uniform float u_time;
void main() {
gl_FragColor = vec4(sin(1.0*u_time),0.0,1.0,1);
}`
见OpenGL ES Shading Language 1.00 Specification - 4.5.3 Default Precision Qualifiers:
The fragment language has no default precision qualifier for floating point types. Hence for float, floating point vector and matrix variable declarations, either the declaration must include a precision qualifier or the default float precision must have been previously declared.
由于统一变量具有浮点类型,因此您必须向片段着色器添加精度限定符。如果您未指定精度限定符,则会导致编译错误(例如,_No precision qualifier for (float)).
要么添加默认精度限定符:
precision mediump float;
uniform float u_time;
或者向统一变量添加显式精度限定符:
uniform mediump float u_time;
我建议验证着色器是否已成功编译 (gl.getShaderParameter
/gl.getShaderInfoLog
) 以及程序是否已链接 (gl.getProgramParameter
/gl.getProgramInfoLog
)。例如:
// create a vertex shader
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(vertexShader));
// create a fragment shader
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(fragmentShader));
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
alert(gl.getProgramInfoLog(this.program));
mapboxgl.accessToken = 'pk.eyJ1IjoiYmVuZGVybGlkemUiLCJhIjoiY2pud3c0MnN1MDdraTN4cXBraDR3MHdyaCJ9.OsQLWGIWOutuIXCHgT8coQ';
var map = (window.map = new mapboxgl.Map({
container: 'map',
zoom: 3,
center: [7.5, 58],
style: 'mapbox://styles/mapbox/light-v10',
antialias: true // create the gl context with MSAA antialiasing, so custom layers are antialiased
}));
// create a custom style layer to implement the WebGL content
var highlightLayer = {
id: 'highlight',
type: 'custom',
// method called when the layer is added to the map
// https://docs.mapbox.com/mapbox-gl-js/api/#styleimageinterface#onadd
onAdd: function(map, gl) {
// create GLSL source for vertex shader
var vertexSource =
`
uniform mat4 u_matrix;
attribute vec2 a_pos;
void main() {
gl_Position = u_matrix * vec4(a_pos, 0.0, 1);
}`;
// create GLSL source for fragment shader
var fragmentSource =
`
precision mediump float;
uniform float u_time;
void main() {
gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);
}`;
// create a vertex shader
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexSource);
gl.compileShader(vertexShader);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(vertexShader));
// create a fragment shader
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentSource);
gl.compileShader(fragmentShader);
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
alert(gl.getShaderInfoLog(fragmentShader));
// link the two shaders into a WebGL program
this.program = gl.createProgram();
gl.attachShader(this.program, vertexShader);
gl.attachShader(this.program, fragmentShader);
gl.linkProgram(this.program);
if (!gl.getProgramParameter(this.program, gl.LINK_STATUS))
alert(gl.getProgramInfoLog(this.program));
this.aPos = gl.getAttribLocation(this.program, 'a_pos');
// define vertices of the triangle to be rendered in the custom style layer
var helsinki = mapboxgl.MercatorCoordinate.fromLngLat({
lng: 25.004,
lat: 60.239
});
var berlin = mapboxgl.MercatorCoordinate.fromLngLat({
lng: 13.403,
lat: 52.562
});
var kyiv = mapboxgl.MercatorCoordinate.fromLngLat({
lng: 30.498,
lat: 50.541
});
// create and initialize a WebGLBuffer to store vertex and color data
this.buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
helsinki.x,
helsinki.y,
berlin.x,
berlin.y,
kyiv.x,
kyiv.y
]),
gl.STATIC_DRAW
);
},
// method fired on each animation frame
// https://docs.mapbox.com/mapbox-gl-js/api/#map.event:render
render: function(gl, matrix) {
gl.useProgram(this.program);
gl.uniformMatrix4fv(
gl.getUniformLocation(this.program, 'u_matrix'),
false,
matrix
);
gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
gl.enableVertexAttribArray(this.aPos);
gl.vertexAttribPointer(this.aPos, 2, gl.FLOAT, false, 0, 0);
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3);
}
};
// add the custom style layer to the map
map.on('load', function() {
map.addLayer(highlightLayer);
});
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v1.4.0/mapbox-gl.js'></script>
<div id='map'></div>