javascript – WebGL Drawback: `textSubImage2D` inconsistent perfomance

javascript – WebGL Drawback: `textSubImage2D` inconsistent perfomance

[ad_1]

I’ve an issue when creating texture with WebGL. Factor that I don’t perceive is that the primary name with texSubImage2D with a canvas has name drawImage consumps extra time (10ms in picture under) than different name and I’m battling it. Can anybody clarify why it occur? Thanks.

P/s: the aim I am doing this as a result of I attempt changing texImage2D (synchronous operate) into multi texSubImage2D in numerous time to enhance efficiency.

Time log

class LoadTextureWebGL {
    public async loadTexture(tempKey: string, url: string) {
        const htmlImage = await new Promise<HTMLImageElement>((resolve, reject) => {
            const picture = new Picture()
            picture.onerror = () => {
                reject()
            }
            picture.onload = () => {
                resolve(picture)
            }
            picture.src = url
        })

        const texture = await this.createGLTextureFromImage(htmlImage)
    }

    non-public async createGLTextureFromImage(picture: HTMLImageElement) {
        // Create a brand new canvas factor
        const canvasGl = doc.createElement('canvas')

        // Get a WebGL context
        const gl =
            canvasGl.getContext('webgl') ||
            (canvasGl.getContext('experimental-webgl') as WebGLRenderingContext)

        if (!gl) {
            throw new Error(
                'Unable to get WebGL context. Your browser or machine might not help it.'
            )
        }

        // const renderer = this.recreation.renderer as Phaser.Renderer.WebGL.WebGLRenderer
        // const gl = renderer.gl

        const minFilter: quantity = gl.NEAREST
        const magFilter: quantity = gl.NEAREST
        let wrap: quantity = gl.CLAMP_TO_EDGE

        const width = picture.width
        const peak = picture.peak

        const pow = Phaser.Math.Pow2.IsSize(width, peak)

        if (pow) {
            wrap = gl.REPEAT
        }

        const pma = true
        const flipY = false

        // Step 1: Create a brand new WebGLTexture object
        console.time('createTexture')
        const texture = gl.createTexture()
        console.timeEnd('createTexture')

        if (!texture) {
            console.error('createGLTextureFromImage: Did not create WebGL texture')
            return null
        }

        // Step 2: Activate a texture unit
        console.time('activeTexture')
        gl.activeTexture(gl.TEXTURE0)
        const oldTexture = gl.getParameter(gl.TEXTURE_BINDING_2D)
        console.timeEnd('activeTexture')

        // Step 3: Bind the feel object
        console.time('bindTexture')
        gl.bindTexture(gl.TEXTURE_2D, texture)
        console.timeEnd('bindTexture')

        // Step 4: Set the feel parameters
        console.time('texParameteri')
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter)
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter)
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap)
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap)

        gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, pma)
        gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipY)
        console.timeEnd('texParameteri')

        // Create a short lived canvas
        const canvas2D = doc.createElement('canvas')
        const context = canvas2D.getContext('second')

        if (!context) {
            console.error('createGLTextureFromImage: Did not get 2D context')
            return null
        }

        console.time('texImage2D')
        // Initialize the feel to the proper measurement
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, peak, 0, gl.RGBA, gl.UNSIGNED_BYTE, null)

        console.time('texSubImage2DWithBlankCanvas')
        gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 100, gl.RGBA, gl.UNSIGNED_BYTE, canvas2D)
        console.timeEnd('texSubImage2DWithBlankCanvas')

        // Assuming you need to cut up the picture into 10 components vertically
        const partHeight = picture.peak / 10
        for (let i = 0; i < 10; i++) {
            // Set the scale of the canvas to match the scale of the half
            canvas2D.width = picture.width
            canvas2D.peak = partHeight

            // Draw the a part of the picture onto the canvas
            context.drawImage(
                picture,
                0,
                i * partHeight,
                picture.width,
                partHeight,
                0,
                0,
                canvas2D.width,
                canvas2D.peak
            )
            console.time('texSubImage2D')
            // Add the half to the feel
            gl.texSubImage2D(
                gl.TEXTURE_2D,
                0,
                0,
                i * partHeight,
                gl.RGBA,
                gl.UNSIGNED_BYTE,
                canvas2D
            )
            console.timeEnd('texSubImage2D')
        }
        console.timeEnd('texImage2D')

        // Step 6: Generate the mipmap
        if (pow) {
            console.time('generateMipmap')
            gl.generateMipmap(gl.TEXTURE_2D)
            console.timeEnd('generateMipmap')
        }

        // Step 6: Rebind the outdated texture
        if (oldTexture) {
            gl.bindTexture(gl.TEXTURE_2D, oldTexture)
        }

        return texture
    }
}
```

[ad_2]

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply