Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { InternalTextureSource, InternalTexture } from "../../../Materials/Textu
import { Texture } from "../../../Materials/Textures/texture.pure";
import { CreateRadianceImageDataArrayBufferViews, GetEnvInfo, UploadEnvSpherical } from "../../../Misc/environmentTextureTools.pure";
import { type IWebRequest } from "../../../Misc/interfaces/iWebRequest";
import { SphericalPolynomial } from "../../../Maths/sphericalPolynomial";
import { type Scene } from "../../../scene.pure";
import { type Nullable } from "../../../types";
import { Constants } from "../../constants";
Expand Down Expand Up @@ -118,34 +119,102 @@ export function RegisterNativeEngineCubeTexture(): void {
);
}
} else {
if (!files || files.length !== 6) {
throw new Error("Cannot load cubemap because 6 files were not defined");
}

// Reorder from [+X, +Y, +Z, -X, -Y, -Z] to [+X, -X, +Y, -Y, +Z, -Z].
const reorderedFiles = [files[0], files[3], files[1], files[4], files[2], files[5]];
// eslint-disable-next-line github/no-then
Promise.all(reorderedFiles.map(async (file) => await this._loadFileAsync(file, undefined, true).then((data) => new Uint8Array(data, 0, data.byteLength))))
if (files && files.length === 6) {
// Reorder from [+X, +Y, +Z, -X, -Y, -Z] to [+X, -X, +Y, -Y, +Z, -Z].
const reorderedFiles = [files[0], files[3], files[1], files[4], files[2], files[5]];
// eslint-disable-next-line github/no-then
.then(async (data) => {
return await new Promise<void>((resolve, reject) => {
this._engine.loadCubeTexture(texture._hardwareTexture!.underlyingResource, data, !noMipmap, true, texture._useSRGBBuffer, resolve, reject);
});
})
// eslint-disable-next-line github/no-then
.then(
() => {
texture.isReady = true;
if (onLoad) {
onLoad();
Promise.all(reorderedFiles.map(async (file) => await this._loadFileAsync(file, undefined, true).then((data) => new Uint8Array(data, 0, data.byteLength))))
// eslint-disable-next-line github/no-then
.then(async (data) => {
return await new Promise<void>((resolve, reject) => {
this._engine.loadCubeTexture(
texture._hardwareTexture!.underlyingResource,
data,
!noMipmap,
true,
texture._useSRGBBuffer,
() => resolve(),
() => reject(new Error("Failed to load native cubemap"))
);
});
})
// eslint-disable-next-line github/no-then
.then(
() => {
texture.isReady = true;
if (onLoad) {
onLoad();
}
},
(error) => {
if (onError) {
onError(`Failed to load cubemap: ${error.message}`, error);
}
}
},
(error) => {
if (onError) {
onError(`Failed to load cubemap: ${error.message}`, error);
);
} else if (files) {
throw new Error("Cannot load cubemap because 6 files were not defined");
} else {
// Single self-contained cubemap container (.dds / .ktx / .ktx2) holding all six
// faces and their mip chain. The native engine decodes it with bimg and, when
// polynomials are requested, returns the spherical harmonics it computed from the
// top mip (native cannot read cube faces back from the GPU to derive them lazily).
const onContainerLoaded = (data: ArrayBufferView) => {
this._engine.loadCubeTexture(
texture._hardwareTexture!.underlyingResource,
[data],
!noMipmap,
true,
texture._useSRGBBuffer,
(sphericalPolynomialCoefficients?: Float32Array) => {
if (createPolynomials && sphericalPolynomialCoefficients && sphericalPolynomialCoefficients.length === 27) {
const c = sphericalPolynomialCoefficients;
texture._sphericalPolynomial = SphericalPolynomial.FromArray([
[c[0], c[1], c[2]],
[c[3], c[4], c[5]],
[c[6], c[7], c[8]],
[c[9], c[10], c[11]],
[c[12], c[13], c[14]],
[c[15], c[16], c[17]],
[c[18], c[19], c[20]],
[c[21], c[22], c[23]],
[c[24], c[25], c[26]],
]);
}
texture.isReady = true;
if (onLoad) {
onLoad();
}
},
() => {
if (onError) {
onError("Could not load a native cube texture.");
}
}
}
);
);
};

if (buffer) {
onContainerLoaded(buffer);
} else {
const onInternalError = (request?: IWebRequest, exception?: any) => {
if (onError && request) {
onError(request.status + " " + request.statusText, exception);
}
};

this._loadFile(
rootUrl,
(data) => {
onContainerLoaded(new Uint8Array(data as ArrayBuffer, 0, (data as ArrayBuffer).byteLength));
},
undefined,
undefined,
true,
onInternalError
);
}
}
}

this._internalTexturesCache.push(texture);
Expand Down
36 changes: 33 additions & 3 deletions packages/dev/core/src/Engines/Native/nativeInterfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,30 @@ export interface INativeEngine {
getAttributes(shaderProgram: NativeProgram, attributeNames: string[]): number[];

createTexture(): NativeTexture;
initializeTexture(texture: NativeTexture, width: number, height: number, hasMips: boolean, format: number, renderTarget: boolean, srgb: boolean, samples: number): void;
initializeTexture(
texture: NativeTexture,
width: number,
height: number,
hasMips: boolean,
format: number,
renderTarget: boolean,
srgb: boolean,
samples: number,
isCube?: boolean
): void;
loadTexture(texture: NativeTexture, data: ArrayBufferView, generateMips: boolean, invertY: boolean, srgb: boolean, onSuccess: () => void, onError: () => void): void;
loadRawTexture(texture: NativeTexture, data: ArrayBufferView, width: number, height: number, format: number, generateMips: boolean, invertY: boolean): void;
updateTextureData(
texture: NativeTexture,
data: ArrayBufferView,
xOffset: number,
yOffset: number,
width: number,
height: number,
faceIndex: number,
lod: number,
invertY: boolean
): void;
loadRawTexture2DArray(
texture: NativeTexture,
data: Nullable<ArrayBufferView>,
Expand All @@ -74,7 +95,15 @@ export interface INativeEngine {
generateMipMaps: boolean,
invertY: boolean
): void;
loadCubeTexture(texture: NativeTexture, data: Array<ArrayBufferView>, generateMips: boolean, invertY: boolean, srgb: boolean, onSuccess: () => void, onError: () => void): void;
loadCubeTexture(
texture: NativeTexture,
data: Array<ArrayBufferView>,
generateMips: boolean,
invertY: boolean,
srgb: boolean,
onSuccess: (sphericalPolynomial?: Float32Array) => void,
onError: () => void
): void;
loadCubeTextureWithMips(texture: NativeTexture, data: Array<Array<ArrayBufferView>>, invertY: boolean, srgb: boolean, onSuccess: () => void, onError: () => void): void;
getTextureWidth(texture: NativeTexture): number;
getTextureHeight(texture: NativeTexture): number;
Expand All @@ -100,7 +129,8 @@ export interface INativeEngine {
height: number,
generateStencilBuffer: boolean,
generateDepthBuffer: boolean,
samples: number
samples: number,
layer?: number
): NativeFramebuffer;

getRenderWidth(): number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ export class NativeRenderTargetWrapper extends RenderTargetWrapper {
private __framebuffer: Nullable<NativeFramebuffer> = null;
// eslint-disable-next-line @typescript-eslint/naming-convention
private __framebufferDepthStencil: Nullable<NativeFramebuffer> = null;
// Per-face framebuffers for cube render targets (index = cube face 0..5).
// eslint-disable-next-line @typescript-eslint/naming-convention
private __framebuffers: Nullable<NativeFramebuffer[]> = null;

public get _framebuffer(): Nullable<NativeFramebuffer> {
return this.__framebuffer;
Expand All @@ -23,6 +26,21 @@ export class NativeRenderTargetWrapper extends RenderTargetWrapper {
this.__framebuffer = framebuffer;
}

public get _framebuffers(): Nullable<NativeFramebuffer[]> {
return this.__framebuffers;
}

public set _framebuffers(framebuffers: Nullable<NativeFramebuffer[]>) {
if (this.__framebuffers) {
for (const framebuffer of this.__framebuffers) {
this._engine._releaseFramebufferObjects(framebuffer);
}
}
this.__framebuffers = framebuffers;
// Keep _framebuffer pointing at face 0 so single-target code paths still work.
this.__framebuffer = framebuffers ? framebuffers[0] : null;
}

public get _framebufferDepthStencil(): Nullable<NativeFramebuffer> {
return this.__framebufferDepthStencil;
}
Expand All @@ -40,7 +58,13 @@ export class NativeRenderTargetWrapper extends RenderTargetWrapper {
}

public override dispose(disposeOnlyFramebuffers = false): void {
this._framebuffer = null;
if (this.__framebuffers) {
// Releases all six per-face framebuffers (face 0 is aliased by __framebuffer, so
// clear that alias here without releasing it again).
this._framebuffers = null;
} else {
this._framebuffer = null;
}
this._framebufferDepthStencil = null;

super.dispose(disposeOnlyFramebuffers);
Expand Down
Loading
Loading