-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
Fix rendering images with nearest sampling and 2^n size #11162
Changes from 12 commits
b7bb196
73b2487
49f45e0
bebd455
0dcfc2c
19896ce
57d18b8
0b81246
69dbf01
976b8e1
f21aba4
144e4c6
c98c5a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,18 +52,16 @@ class Texture { | |
|
||
update(image: TextureImage, options: ?{premultiply?: boolean, useMipmap?: boolean}, position?: { x: number, y: number }) { | ||
const {width, height} = image; | ||
const resize = (!this.size || this.size[0] !== width || this.size[1] !== height) && !position; | ||
const {context} = this; | ||
const {gl} = context; | ||
|
||
this.useMipmap = Boolean(options && options.useMipmap); | ||
gl.bindTexture(gl.TEXTURE_2D, this.texture); | ||
|
||
context.pixelStoreUnpackFlipY.set(false); | ||
context.pixelStoreUnpack.set(1); | ||
context.pixelStoreUnpackPremultiplyAlpha.set(this.format === gl.RGBA && (!options || options.premultiply !== false)); | ||
|
||
if (resize) { | ||
if (!position && (!this.size || this.size[0] !== width || this.size[1] !== height)) { | ||
this.size = [width, height]; | ||
|
||
if (image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof HTMLVideoElement || image instanceof ImageData || (ImageBitmap && image instanceof ImageBitmap)) { | ||
|
@@ -81,23 +79,20 @@ class Texture { | |
} | ||
} | ||
|
||
if (this.useMipmap && this.isSizePowerOfTwo()) { | ||
this.useMipmap = Boolean(options && options.useMipmap && this.isSizePowerOfTwo()); | ||
if (this.useMipmap) { | ||
gl.generateMipmap(gl.TEXTURE_2D); | ||
} | ||
} | ||
|
||
bind(filter: TextureFilter, wrap: TextureWrap, minFilter: ?TextureFilter) { | ||
bind(filter: TextureFilter, wrap: TextureWrap) { | ||
const {context} = this; | ||
const {gl} = context; | ||
gl.bindTexture(gl.TEXTURE_2D, this.texture); | ||
|
||
if (minFilter === gl.LINEAR_MIPMAP_NEAREST && !this.isSizePowerOfTwo()) { | ||
minFilter = gl.LINEAR; | ||
} | ||
|
||
if (filter !== this.filter) { | ||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter); | ||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter || filter); | ||
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, (this.useMipmap && filter === gl.LINEAR) ? gl.LINEAR_MIPMAP_NEAREST : filter); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 That's the correct fallback a filtering request on LINEAR. For NEAREST, if we request texture.bind(NEAREST, ...) I would still expect as a user of this class to fallback to NEAREST_MIPMAP_NEAREST (nearest within the mip level and nearest between mip levels). It seems that most of our use cases need to stay non-linear between mip level as a default (we're not using trilinear, but we could extend that when we need it for some cases, e.g. LINEAR_MIPMAP_LINEAR), so we can stick to that for now but still hint the requested filter for within the mip (e.g. filter_MIPMAP_NEAREST). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In practice what that means as a fallback in this case:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! Happy to add the condition for nearest with mipmap. In practice I don't think this is ever happening, but not a bad idea to future-proof it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's a possible combination when a user chooses nearest as a paint properties with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That makes sense! I noticed that code path didn't run in my example, but it should now correctly use mipmaps when it is called. (Repeating textures?) |
||
this.filter = filter; | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"version": 8, | ||
"metadata": { | ||
"test": { | ||
"width": 256, | ||
"height": 256 | ||
} | ||
}, | ||
"center": [34.5, 54.5], | ||
"zoom": 6, | ||
"sources": { | ||
"image": { | ||
"type": "image", | ||
"coordinates": [[34, 55], [35, 55], [35, 54], [34, 54]], | ||
"url": "local://image/256.png" | ||
} | ||
}, | ||
"layers": [ | ||
{ | ||
"id": "image", | ||
"type": "raster", | ||
"source": "image", | ||
"paint": { | ||
"raster-fade-duration": 0, | ||
"raster-resampling": "nearest" | ||
} | ||
} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1 on removing the extra parameter as it really simplifies use of that class (basically infers that from the option request to use mipmaps).