@@ -23,6 +23,11 @@ let memoizedImages: HTMLImageElement[] | undefined = undefined;
23
23
*/
24
24
let facesKey : string | undefined = undefined ;
25
25
26
+ interface ImageLoadingPromiseReturnValue {
27
+ image : HTMLImageElement ;
28
+ key : CubemapFaceNames ;
29
+ }
30
+
26
31
/**
27
32
* Loads a cubemap texture from a set of image URLs.
28
33
*
@@ -63,7 +68,6 @@ export function loadCubemapTexture({ gl, faces, onReady, forceRefresh }: LoadCub
63
68
facesKey = JSON . stringify ( faces ) ;
64
69
65
70
const texture = gl . createTexture ( ) ;
66
- gl . bindTexture ( gl . TEXTURE_CUBE_MAP , texture ) ;
67
71
68
72
if ( ! faces ) {
69
73
console . warn ( "[CubemapLayer][loadCubemapTexture]: Faces are null" ) ;
@@ -77,63 +81,80 @@ export function loadCubemapTexture({ gl, faces, onReady, forceRefresh }: LoadCub
77
81
return ;
78
82
}
79
83
80
- const promises = Object . entries ( faces as CubemapFaces ) . map ( ( [ key , face ] ) => {
81
- return new Promise < HTMLImageElement > ( ( resolve , reject ) => {
84
+ const imageLoadingPromises = Object . entries ( faces ) . map ( ( [ key , face ] ) => {
85
+ return new Promise < ImageLoadingPromiseReturnValue > ( ( resolve , reject ) => {
86
+ const keyEnum = key as CubemapFaceNames ;
82
87
if ( face === undefined ) {
83
- console . warn ( `[CubemapLayer][loadCubemapTexture]: Face ${ key } is undefined` ) ;
88
+ reject ( new Error ( `[CubemapLayer][loadCubemapTexture]: Face ${ key } is undefined` ) ) ;
84
89
return ;
85
90
}
86
- const glCubemapTarget = getGlCubemapTarget ( gl , key as CubemapFaceNames ) ;
87
91
88
- if ( glCubemapTarget ) {
89
- const level = 0 ;
90
- const internalFormat = gl . RGBA ;
91
- const format = gl . RGBA ;
92
- const type = gl . UNSIGNED_BYTE ;
92
+ const image = new Image ( ) ;
93
93
94
- const image = new Image ( ) ;
94
+ image . crossOrigin = "anonymous" ;
95
95
96
- image . crossOrigin = "anonymous" ;
96
+ const handleLoad = ( ) => {
97
+ resolve ( { image, key : keyEnum } ) ;
98
+ } ;
97
99
98
- const handleLoad = ( ) => {
99
- gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
100
- gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MIN_FILTER , gl . LINEAR ) ;
101
- gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_WRAP_S , gl . CLAMP_TO_EDGE ) ;
102
- gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_WRAP_T , gl . CLAMP_TO_EDGE ) ;
100
+ image . src = face ;
103
101
104
- gl . texImage2D ( glCubemapTarget , level , internalFormat , format , type , image ) ;
102
+ // in case the image is loaded from the cache.
103
+ if ( image . complete && image . naturalWidth > 0 ) {
104
+ handleLoad ( ) ;
105
+ } else {
106
+ image . onload = handleLoad ;
107
+ }
105
108
106
- resolve ( image ) ;
107
- } ;
109
+ image . onerror = ( ) => {
110
+ reject ( new Error ( `[CubemapLayer][loadCubemapTexture]: Error loading image ${ face } ` ) ) ;
111
+ } ;
112
+ } ) ;
113
+ } ) ;
114
+
115
+ void Promise . all ( imageLoadingPromises )
116
+ . then ( ( imagesAndFaceKeys ) => {
117
+ for ( let i = 0 ; i < imagesAndFaceKeys . length ; i ++ ) {
118
+ const lod = 0 ;
119
+ const internalFormat = gl . RGBA ;
120
+ const format = gl . RGBA ;
121
+ const type = gl . UNSIGNED_BYTE ;
108
122
109
- image . src = face ;
123
+ const { image, key } = imagesAndFaceKeys [ i ] ?? { } ;
110
124
111
- // in case the image is loaded from the cache.
112
- if ( image . complete && image . naturalWidth > 0 ) {
113
- handleLoad ( ) ;
114
- } else {
115
- image . onload = handleLoad ;
125
+ if ( ! image || ! key ) {
126
+ console . warn ( `[CubemapLayer][loadCubemapTexture]: Image or key is null` ) ;
127
+ continue ;
116
128
}
117
129
118
- image . onerror = ( ) => {
119
- reject ( new Error ( `[CubemapLayer][loadCubemapTexture]: Error loading image ${ face } ` ) ) ;
120
- } ;
130
+ const glCubemapTarget = getGlCubemapTarget ( gl , key ) ;
131
+
132
+ gl . bindTexture ( gl . TEXTURE_CUBE_MAP , texture ) ;
133
+
134
+ gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
135
+ gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MIN_FILTER , gl . LINEAR ) ;
136
+ gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_WRAP_S , gl . CLAMP_TO_EDGE ) ;
137
+ gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_WRAP_T , gl . CLAMP_TO_EDGE ) ;
138
+
139
+ gl . texImage2D ( glCubemapTarget , lod , internalFormat , format , type , image ) ;
121
140
}
122
- } ) ;
123
- } ) ;
124
141
125
- void Promise . all ( promises ) . then ( ( images ) => {
126
- gl . bindTexture ( gl . TEXTURE_CUBE_MAP , texture ) ;
127
- gl . generateMipmap ( gl . TEXTURE_CUBE_MAP ) ;
142
+ gl . bindTexture ( gl . TEXTURE_CUBE_MAP , texture ) ;
143
+ gl . generateMipmap ( gl . TEXTURE_CUBE_MAP ) ;
128
144
129
- gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MIN_FILTER , gl . LINEAR_MIPMAP_LINEAR ) ;
130
- gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
145
+ gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MIN_FILTER , gl . LINEAR_MIPMAP_LINEAR ) ;
146
+ gl . texParameteri ( gl . TEXTURE_CUBE_MAP , gl . TEXTURE_MAG_FILTER , gl . LINEAR ) ;
131
147
132
- onReady ( texture , images ) ;
148
+ const imageElements = imagesAndFaceKeys . map ( ( image ) => image . image ) ;
133
149
134
- memoizedImages = images ;
135
- memoizedTexture = texture ;
136
- } ) ;
150
+ onReady ( texture , imageElements ) ;
151
+
152
+ memoizedImages = imageElements ;
153
+ memoizedTexture = texture ;
154
+ } )
155
+ . catch ( ( error ) => {
156
+ console . error ( `[CubemapLayer][loadCubemapTexture]: Error loading cubemap texture` , error ) ;
157
+ } ) ;
137
158
}
138
159
139
160
function getGlCubemapTarget ( gl : WebGLRenderingContext | WebGL2RenderingContext , key : CubemapFaceNames ) : number {
0 commit comments