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
IconLayer (png) render artifacts #2169
Comments
can you add your original png and the final rendering effects here? |
hey @jianhuang01, We've come across this issue as well, so hopefully this will help: const iconMapping = {
default: {
x: 0,
y: 0,
width: 80,
height: 80,
},
}
const iconLayer = new IconLayer({
id: `icon-layer`,
pickable: true,
iconMapping,
iconAtlas: 'locations-spritesheet-white.png',
getIcon: () => 'default',
getSize: 80,
sizeScale: 5,
data: layersData,
opacity: 1,
}); White sprite-sheet, only using the first sprite: When we add in the second sprite for Any ideas? |
You can also see it happening on the IconLayer deck.gl example here: https://deck.gl/#/examples/core-layers/icon-layer It's noticeable when the markers overlap: Maybe something to do with alpha blending? |
@wooly Are those sprites using the alpha channel to fade off at the edges? |
@tsherif they're using the alpha channel to anti-alias the circle edges, yep. |
It looks like the icon layer does sample the texture alpha. The issue might be that deck.gl doesn't premultiply its output alphas (some discussion here of why this is an issue). |
@wooly Can you try adding the following to your icon layer constructor props: parameters: {
depthMask: false
} |
@tsherif didn't make any discernible difference, unfortunately. |
Happens also to me. |
I found the issue in my case. I upgraded to the latest Example: new IconLayer({ ...yourProps, loadOptions: {
image: {
type: 'image'
}
}}) |
@BowlingX Good that you were able to pinpoint this. It is unexpected. ImageBitmap is the recommended format for loading images on modern browsers, but based on your findings it looks like there is potential issue with transparency when converted to texture. I googled a bit but could not find more information on this. For completeness, can you provide browser information? If you have time, you could also try the following and see if it makes a difference:
For information on that, see createImageBitmap |
@ibgreen I tried this option already and it did not fix the issue, unfortunately. The only thing that helped was to change the type to |
@ibgreen I think we want The option doesn't seem to have any effect either way in Chrome, but works in FireFox. |
That sounds good. We could perhaps set it as a default option in the image loader? https://github.com/visgl/loaders.gl/blob/master/modules/images/src/image-loader.js#L36 |
@ibgreen ImageBitmap's options do not work in Chrome. Setting a default won't solve this issue. |
I've just run into this as well and I can confirm what @Pessimistress says about When looking at what Chrome renders with renderdoc I can see that the texture holding the icons is indeed premultiplied (e.g. fully transparent pixels have value RGBA: 0x00000000). I think icon-layer.js#L208 should call draw with custom parameters, e.g. something like: this.state.model
.setUniforms(
Object.assign({}, uniforms, {
iconsTexture,
iconsTextureDim: [iconsTexture.width, iconsTexture.height],
sizeScale: sizeScale * (sizeUnits === 'pixels' ? viewport.metersPerPixel : 1),
sizeMinPixels,
sizeMaxPixels,
billboard,
alphaCutoff
})
)
.draw({
parameters: {
blendFunc: [GL.ONE, GL.ONE_MINUS_SRC_ALPHA]
}
}); |
Thanks @cneumann for the insight! Can confirm that this solves the problem: new IconLayer({
...
parameters: {
blendFunc: [1, 771] // GL.ONE, GL.ONE_MINUS_SRC_ALPHA
},
loadOptions: {
imagebitmap: {
premultiplyAlpha: 'none'
}
}
}) We can change |
Just to be sure: if you change the blend function in this way you do want premultiplied alpha, so the option should be Also, great to know I can pass parameters this way to the layer, I had actually cloned IconLayer and hacked it's draw call to include the alternate blend function :) |
Hmm, you are correct; although changing the option does not seem to make any difference. It looks like Chrome's bitmap color is always premultiplied regardless. I can confirm the the option is indeed passed to |
Ok, this seems to be a rabbithole. I suppose ImageBitmaps are supposed to be in a format that is particularly efficient for rendering, maybe the implementation is allowed this freedom. Maybe try loading as Image instead of ImageBitmap then. Less performant but correct results... Something along these lines? new IconLayer({ ...yourProps, loadOptions: {
image: {
type: 'image'
}
}}) |
Edit: no, the option is not passed to |
Update: an issue is fixed in new IconLayer({
...
loadOptions: {
imagebitmap: {
premultiplyAlpha: 'none'
}
}
}) I plan to make |
Fixed in 8.3.0-beta.2 |
I use IconLayer with png sprite.
Icons render with a small glitch, something like a gray border or shadow but originally they have only a white border.
The text was updated successfully, but these errors were encountered: