{"record":{"id":"b77d2facfdd82b41","repo":"BabylonJS/Babylon.js","slug":"hdr-prefiltering-is-not-available-in-webgl-1-you","errorCode":null,"errorMessage":"HDR prefiltering is not available in WebGL 1., you can use real time filtering instead.","messagePattern":"HDR prefiltering is not available in WebGL 1\\., you can use real time filtering instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/dev/core/src/Materials/Textures/Filtering/hdrFiltering.ts","lineNumber":221,"sourceCode":"     * @param texture Texture to filter\r\n     * @returns true if the filter is ready\r\n     */\r\n    public isReady(texture: BaseTexture) {\r\n        return texture.isReady() && this._effectWrapper.effect.isReady();\r\n    }\r\n\r\n    /**\r\n     * Prefilters a cube texture to have mipmap levels representing roughness values.\r\n     * Prefiltering will be invoked at the end of next rendering pass.\r\n     * This has to be done once the map is loaded, and has not been prefiltered by a third party software.\r\n     * See http://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf for more information\r\n     * @param texture Texture to filter\r\n     * @returns Promise called when prefiltering is done\r\n     */\r\n    // eslint-disable-next-line @typescript-eslint/naming-convention\r\n    public async prefilter(texture: BaseTexture): Promise<void> {\r\n        if (!this._engine._features.allowTexturePrefiltering) {\r\n            throw new Error(\"HDR prefiltering is not available in WebGL 1., you can use real time filtering instead.\");\r\n        }\r\n\r\n        this._effectRenderer = new EffectRenderer(this._engine);\r\n        this._effectWrapper = this._createEffect(texture);\r\n\r\n        await this._effectWrapper.effect.whenCompiledAsync();\r\n\r\n        this._prefilterInternal(texture);\r\n        this._effectRenderer.dispose();\r\n        this._effectWrapper.dispose();\r\n    }\r\n}\r\n","sourceCodeStart":203,"sourceCodeEnd":234,"githubUrl":"https://github.com/BabylonJS/Babylon.js/blob/0592b347b8a4ee0236089ea86a749cacfdb266d8/packages/dev/core/src/Materials/Textures/Filtering/hdrFiltering.ts#L203-L234","documentation":"HDRFilter's prefilter() generates pre-filtered mip levels for an HDR environment texture so it can be used for IBL. The library throws this when the engine does not support texture prefiltering, which Babylon.js signals via Engine._features.allowTexturePrefiltering (false on WebGL 1 / WebGPU not being used and engine feature unsupported). The message suggests falling back to real-time HDR filtering (HDRFilter without prefiltering) instead.","triggerScenarios":"Calling hdrFilter.prefilter(texture) on an engine where _features.allowTexturePrefiltering is false — i.e., a WebGL1Engine or a WebGL2 context without the required capabilities that Babylon uses to decide prefiltering support.","commonSituations":"App runs on WebGL 1 (older browsers/devices, forced WebGL1 fallback); engine created with default options on hardware lacking float texture rendering support; loading .hdr/.env files for PBR on legacy mobile browsers.","solutions":["Create the engine with WebGL 2 (default in recent Babylon versions) and verify engine._features.allowTexturePrefiltering === true before calling prefilter()","If WebGL 1 must be supported, do not call prefilter(); use the real-time HDR filtering path (filteringStrength / runtime filtering) so filtering happens per-frame","Use a pre-baked .env file (converted via the Babylon sandbox/Ibl baker) instead of runtime prefiltering of an .hdr texture","Upgrade Babylon.js / ensure WebGPU engine is used where supported"],"exampleFix":"// before\nconst hdrFilter = new HDRFilter(engine, cubeMapSize);\nawait hdrFilter.prefilter(hdrTexture);\n// after\nif (engine._features.allowTexturePrefiltering) {\n    const hdrFilter = new HDRFilter(engine, cubeMapSize);\n    await hdrFilter.prefilter(hdrTexture);\n} else {\n    // WebGL 1 fallback: load a pre-baked .env or rely on real-time filtering\n    const envTexture = CubeTexture.CreateFromPrefilteredData('environment.env', scene);\n}","handlingStrategy":"fallback","validationCode":"if (!engine._features.allowTexturePrefiltering) {\n    // WebGL 1 or unsupported engine: skip prefiltering, use real-time filtering or .env\n    return CubeTexture.CreateFromPrefilteredData('environment.env', scene);\n}","typeGuard":"function canPrefilter(engine: AbstractEngine): boolean {\n    return engine._features.allowTexturePrefiltering === true;\n}","tryCatchPattern":"try {\n    await hdrFilter.prefilter(texture);\n} catch (e) {\n    if (String(e?.message).includes('HDR prefiltering')) {\n        texture = CubeTexture.CreateFromPrefilteredData('environment.env', scene); // fallback\n    } else {\n        throw e;\n    }\n}","preventionTips":["Check engine._features.allowTexturePrefiltering before any prefilter() call","Detect WebGL 1 early in bootstrap and plan the .env/real-time filtering path","Prefer shipping pre-baked .env textures so runtime prefiltering is never required","Test on lowest supported target (old iOS/Android WebView) where WebGL 1 is common"],"tags":["webgl1","hdr","prefiltering","engine-capability","pbr"],"backgroundTag":"unsupported-webgl-feature","analyzedSha":"0592b347b8a4ee0236089ea86a749cacfdb266d8","analyzedAt":"2026-08-30T15:11:20.442Z","schemaVersion":2},"datasetVersion":"2026-08-30T18:17:15.746Z"}