解决 Failed to execute ‘texSubImage2D‘ on ‘WebGL2RenderingContext‘: Tainted canvases may not be loaded

报这样的错误:

caught DOMException: Failed to execute 'texSubImage2D' on 'WebGL2RenderingContext': Tainted canvases may not be loaded.

或者报这样的错误:

caught DOMException: Failed to execute 'texImage2D' on 'WebGL2RenderingContext': Tainted canvases may not be loaded.

这是由于跨域直接使用Image对象加载图片作为纹理的时候报错的。

解决方案:

用 blob 以二进制文件的方式加载图像纹理数据,然后在生成Image对象,可以直接使用下面的TypeScript代码获取跨域的Image图像数据:


type LoadFunc = (img: HTMLImageElement, imgUrl: string) => void;
class ImgUint {
    private m_listeners: LoadFunc[] = [];
    url: string = "";
    img: HTMLImageElement = null;
    loaded = false;
    constructor() { }
    addListener(listener: LoadFunc): void {
        let ls = this.m_listeners;
        let i = 0;
        for (; i < ls.length; ++i) {
            if (ls[i] == listener) {
                break;
            }
        }
        if (i >= ls.length) {
            ls.push(listener);
        }
    }
    removeListener(listener: LoadFunc): void {

        let ls = this.m_listeners;
        for (let i = 0; i < ls.length; ++i) {
            if (ls[i] == listener) {
                ls.splice(i, 1);
                break;
            }
        }
    }
    dispatch(): void {

        if(this.loaded) {

            let ls = this.m_listeners;
            this.m_listeners = [];
            for (let i = 0; i < ls.length; ++i) {
                ls[i](this.img, this.url);
            }
        }
    }
}
export default class ImageResLoader {
    private m_map: Map = new Map();
    constructor() { }

    load(url: string, onload: LoadFunc): void {

        if (url != "") {

            let initUrl = url;
            let map = this.m_map;

            url = url != "" ? url : "static/assets/box.jpg";

            if (map.has(initUrl)) {
                let punit = map.get(url);
                if (punit.loaded) {
                    onload(punit.img, punit.url);
                } else {
                    punit.addListener(onload);
                }
            }

            let img = new Image();

            let unit = new ImgUint();
            unit.img = img;
            unit.url = initUrl;
            unit.addListener(onload);

            map.set(initUrl, unit);
            
            const request = new XMLHttpRequest();
            request.open("GET", url, true);
            request.responseType = "blob";
            request.onload = (e) => {
                img.onload = (evt: any): void => {
                    unit.loaded = true;
                    unit.dispatch();
                }
                let pwin: any = window;
                img.src = (pwin.URL || pwin.webkitURL).createObjectURL(request.response);
            };
            request.onerror = e => {
                console.error("load error binary image buffer request.status: ", request.status, "url:", url);
            };
            request.send(null);
        }
    }
}

当然你也可以用其他数据流的方式,例如socket直接度数据流。
 

你可能感兴趣的:(Web,WebGL/WebGPU,3D引擎,java,开发语言,3d,web)