Conversation
…custom layer immediate mode example -expose more variables for this purpose in prerender and render methods
stepankuzmin
left a comment
There was a problem hiding this comment.
Looks good to me, but worth another look from @mapbox/gl-js 👍
| import type {ProjectionSpecification} from '../../style-spec/types.js'; | ||
|
|
||
| type CustomRenderMethod = (gl: WebGLRenderingContext, matrix: Array<number>, projection: ?ProjectionSpecification, projectionToMercatorMatrix: ?Array<number>, projectionToMercatorTransition: ?number) => void; | ||
| type CustomRenderMethod = (gl: WebGLRenderingContext, matrix: Array<number>, projection: ?ProjectionSpecification, projectionToMercatorMatrix: ?Array<number>, projectionToMercatorTransition: ?number, centerInMercator: ?Array<number>, pixelsPerMeterRatio: ?number) => void; |
There was a problem hiding this comment.
Adding more parameter gives me another reason to point out this suggestion: #12182 (comment) to clean this interface before we publish it publicly.
Or, if we could eliminate most of these parameters per below comment altogether that would be even more ideal to reduce a bit of the complexity for the user; e.g. remove the need to pass along globeToMercMatrix, transition, centerInMercator, and pixelsPerMeterRatio.
| void main() { | ||
| vec4 p = u_projection * u_globeToMercMatrix * vec4(a_pos_ecef, 1.); | ||
| p /= p.w; | ||
| if (u_globeToMercatorTransition > 0.) { | ||
| vec4 merc = u_projection * vec4(a_pos_merc, 1.); | ||
|
|
||
| vec4 merc = vec4(a_pos_merc, 1.); | ||
| merc.xy = (merc.xy - u_centerInMerc) * u_pixelsPerMeterRatio + u_centerInMerc; | ||
| merc.z *= u_pixelsPerMeterRatio; | ||
|
|
||
| merc = u_projection * merc; |
There was a problem hiding this comment.
@astojilj @akoylasar Are there mechanisms that we could adopt to include related code/functions to facilitate these conversions for the user? I imagine that this isn't trivial knowledge for them to successfully implement the conversions. As a user I would only want to care about my custom layer implementation (creating data in each of these world coordinates + projecting it).
My main concern is that this requires quite a bit of understanding of the internal workings of mapbox-gl. What I would want to care as a developer using globe custom layers is the following:
- creating ECEF coordinates for globe
- creating mercator coordinates for mercator
- projecting each of these without thinking about internal details
The most minimal custom layer code I'd imagine someone would write:
gl_Position = custom_layer_project(a_pos_ecef, a_pos_merc);Then, our internal boilerplate code would be injected and have the following:
uniform mat4 u_projection;
uniform mat4 u_globeToMercMatrix;
uniform float u_globeToMercatorTransition;
uniform vec2 u_centerInMerc;
uniform float u_pixelsPerMeterRatio;
vec4 project_custom_layer(vec3 pos_ecef, vec3 pos_merc) {
vec4 projected_position = u_projection * u_globeToMercMatrix * vec4(a_pos_ecef, 1.);
projected_position /= projected_position.w;
if (u_globeToMercatorTransition > 0.) {
vec4 merc = u_projection * vec4(a_pos_merc, 1.);
vec4 merc = vec4(a_pos_merc, 1.);
merc.xy = (merc.xy - u_centerInMerc) * u_pixelsPerMeterRatio + u_centerInMerc;
merc.z *= u_pixelsPerMeterRatio;
merc = u_projection * merc;
merc /= merc.w;
projected_position = mix(projected_position, merc, u_globeToMercatorTransition);
}
return projected_position;
}The above shader code would be injected by default, and uniforms could be setup on our side prior to call onAdd and updated prior to the render function.
By hiding some of that complexity, we would also not have have to carry so many parameters to the render function.
There was a problem hiding this comment.
More thoughts on the shader code injection point, the header shader code could be simply added as
this.globeProgram = createProgram(gl, mapboxgl.getGlobeVertexHeader().concat(globeVertCode), fragCode); And uniforms uploaded with a specific function taking in the program id
mapboxgl.updateCustomGlobeShader(this.globeProgram)and I think that would cover it?
Then, render interface becomes:
render (gl, projectionMatrix, projection)instead of:
render (gl, projectionMatrix, projection, globeToMercMatrix, transition, centerInMercator, pixelsPerMeterRatio)|
Discussed with @akoylasar , let's merge this PR and continue on the discussion from #12544 (comment) in the other PR. |
This PR extends the
prerenderandrendermethods for the custom layer when globe projection is in use. The new API exposes variables that can be used to also fix the issue described in #12182 (comment).after:
after-.mov
Launch Checklist
@mapbox/map-design-team@mapbox/static-apisif this PR includes style spec API or visual changes@mapbox/gl-nativeif this PR includes shader changes or needs a native portmapbox-gl-jschangelog:<changelog></changelog>