-
Notifications
You must be signed in to change notification settings - Fork 28
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How should we size the canvas for best experience and render? #159
Comments
Alternate idea I haven't implemented:
|
Digging deeper I've realized that so far neither solution satisfies requirement “Resolution setting” is user defined setting of the expected image export. In Solution 1, it’s observed that the viewport changes when the user resizes the container. It’s also observed that locking the container size results in a fixed viewport at any resolution setting, and this results in the expected rendered resolution because the DPI is changing. In Solution 2 it’s observed that the viewport changes when resolution setting is changed because DPI is fixed, and the container changes to export the expected rendered resolution. It’s also observed that locking the resolution setting and setting any container size results in a fixed viewport because the rendered resolution is exactly set to the resolution setting, the container is scaled with CSS transform, and DPI is fixed. So it seems the only way to keep the viewport bounds fixed in the current system is to not change the container size. Next I'm going to investigate if I can change DPI while maintaining a viewport - if I can, I'm interested in understanding why because the frameworks pass that into webgl and I'd like to have more direct control if I can. |
I'm happy to see changing I want a better solution than changing Low DPI (expecting blurry)High DPI |
@ibgreen I've been watching the code that runs when resizing the canvas or changing DPI and I have more (but not all) confidence a shared drawing buffer resolution is controlled by our frameworks rather than mapbox. Deck's AnimationLoop constantly checks for canvas size/DPI changes and calls luma's resizeGLContext. Luma floors the resolution, which partly explains why I'm seeing slightly unexpected resolutions. I'd like to have a new feature on resizeGLContext / AnimationLoop that allows me to directly set the inner canvas width/height and ignore DPI. The viewport uses the canvas client width/height to set the viewport bounds - I'll either need to set the canvas to something constant or directly set the viewport size somewhere. Edit: In the mean time I'm going to hack together a proof that our frameworks have control of the mapbox gl context resolution. |
Today I took a slight tangent to see if we could render both deck and mapbox to a non-default framebuffer that we define. While it was easy to do with deck, I don't think it is possible in mapbox right now. Implementation in 26dbd2f. DeckRender allows the target framebuffer to be overridden, The Painter in mapbox doesn't appear to have it where I expected it, |
I'm trying to create a canvas with these properties:
So far we've implemented this two ways with different results. Each only satisfy 2 of the 3 requirements.
Solution A:
window.devicePixelRatio = factor
Through an understanding of deck/mapbox internals we've determined the framebuffer size is set as a function
window.devicePixelRatio
and canvas css size. If we control these variables, we can indirectly control the framebuffer size. This sometimes works as expected, but also may result in an inaccurate height in the export depending on the container's size. The issue results in images with this resolution discrepancy:Here is where we set the
devicePixelRatio
which will internally be used by deck.gl and mapbox-gl-js to set the framebuffer size. Note: The issue also occurred before we rounded to the nearest even.hubble.gl/examples/worldview/src/features/map/Map.js
Line 59 in 31f5db5
The canvas is styled to fit a container, and the container is set to an explicit size.
hubble.gl/examples/worldview/src/features/map/Map.js
Lines 134 to 143 in 31f5db5
Note: The deck width/height props are set explicitly to the expected dimensions. But these are not used to set framebuffer size.
hubble.gl/examples/worldview/src/features/map/Map.js
Lines 156 to 157 in 31f5db5
Current Conclusion
Resolution error is introduced when framebuffer size is derived in deck.gl and mapbox by multiplying their container size by
devicePixelRatio
. There doesn't appear to be an interface for explicitly setting framebuffer width/height in both libraries.At some container sizes this solution works as expected, but further investigation is needed to ensure the output is always the expected resolution.
So far we've observed this solution works as expected when:
2.
is relaxed: when the scale factor is 1.0 and the container size matches the resolution.Solution B:
transform: scale(${factor})
If we apply a scale factor to the deck/mapbox canvas as a CSS transform we can fit a canvas of any size into a container of any size. Deck and mapbox were designed to be explicitly sized, so standard methods can be used to get actual framebuffer matching our desired resolution. However,
window.devicePixelRatio = 1
is necessary to ensure retina (or other HiDPI) displays do not effect the framebuffer size.In this example we set
window.devicePixelRatio = 1
, a random container size, the same view state. We switch between 1080p or 4K resolution. See the framebuffer size in the images as "Canvas Internal Size".Current Conclusion
It is very common to resize a video and expect the same boundary given a viewState, so this method is not viable unless there is a way to set the viewState and the bounds of the viewport. Currently we do not have a get/setBounds function for our viewports which works at any perspective.
The text was updated successfully, but these errors were encountered: