fix issue #124: Texture and MipMap types #227
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Why
Issue #124 discusses a desire to have concrete types for the
imageandmipmapsfields ofTHREE.Texture.This is made difficult by the fact that Three.js appears to occasionally use the
imagesfield not as an actual source of image data, but as a metadata field to store width/height information about composite texture types likeTHREE.CubeTexture.For the
mipmapsfield, all of the loaders in the examples code end up returning anImageDatastructure, but in some cases likeTHREE.VideoTexture, themipmapsfield could contain anHTMLVideoElement. In general, Three.js does some checking on the type of theTHREE.Texturebefore choosing whether to use theimagefield or one of themipmapsarray elements for a call to various texture loading functions in WebGL, some of which are capable of loading anyTexImageSource. Indeed, it appears it's kept as such to also support manually generating mipmaps, e.g. by resizing images via rendering to a Canvas.What
For all of the Loader types in the examples folder, I've updated their returned mipmaps fields to be
ImageData[]instead ofobject[].For the base
THREE.Texturetype, I started by defining a number of utility types that describe all the extant ways that theimagefield appears to be used in Three.js. I then used these to create optional type parameters toTHREE.Texture. Subclasses ofTHREE.Texturecan then specify values for those type parameters, e.g.THREE.VideoTexturespecifies that the image type isHTMLVideoElement.One curious thing is that there actually aren't a lot of restrictions on the types of images you put in
THREE.Textures. For example,THREE.VideoTexturecould contain anHTMLCanvasElement. AllTHREE.VideoTexturedoes is run an animation loop to setneedsUpdatewithout the user having to do so in their own code. You could conceivably useTHREE.VideoTexturewith a canvas object that you intend to draw to continuously, saving you from having to write an animation loop to update the texture. Similarly,THREE.CanvasTexturedoesn't really care if you give it a canvas or not, all it does is setneedsUpdateto true.But in those cases, I opted to be explicit in the typing of the textures. If someone were to want to do some shenanigans like that, they can always just cast to
any.Finally, I also updated the type signatures for
THREE.WebGLRenderTargetand its subclasses, so that theirtexturefields could also be typed more explicitly.I'm submitting this as a draft PR because I'm not really sure of the ergonomics of this. The tests pass, I even managed to write a few that prove out the general concept in type checking. But I'm not really sure how useful the generic
THREE.Texturetype with the default type parameters will be when dealing with textures loaded from model loaders. Well, at the very least, it gives you more guidance on how to go about type filtering on those values, but I'm curious to see what others think.Checklist
master, next goesdev)