WebGL - เป็นไปได้ไหมที่จะส่ง gl ไปยังฟังก์ชัน img.onload

ในโปรแกรม WebGL ของฉันที่ฉันเขียนใน ES6 ฉันมีคลาสชื่อ Texture

ในตอนแรกจะวาดพื้นผิวเป็น 1 พิกเซลสีแดง เมื่อรูปภาพโหลดแล้ว ฉันต้องการแทนที่พิกเซลสีแดงด้วยรูปภาพ

ฉันติดขัดเล็กน้อยเนื่องจากไม่แน่ใจว่าวิธีที่ดีที่สุดสำหรับสิ่งนี้เนื่องจากขณะนี้เกิดข้อผิดพลาดและไม่ได้ผล:

Uncaught TypeError: ไม่สามารถดำเนินการ 'texImage2D' บน 'WebGLRenderingContext': ไม่พบฟังก์ชันที่ตรงกับลายเซ็นที่ให้ไว้

ฉันเดาได้ดีที่สุดว่าสิ่งนี้เกิดขึ้นเนื่องจาก JavaScript เป็นแบบอะซิงโครนัส ดังนั้นเมื่อรูปภาพโหลดแล้ว gl หายไป หรือบางทีฉันอาจคิดผิดเกี่ยวกับเรื่องนี้

การช่วยให้เข้าใจสิ่งนี้และ/หรือแนวทางแก้ไขจะได้รับการชื่นชมอย่างมาก

export default class Texture {
    constructor(gl, src) {
        // create texture then bind it
        this.texture = gl.createTexture();
        gl.bindTexture(gl.TEXTURE_2D, this.texture);

        // texture settings for the texture
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
        gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);

        // create it as a red pixel first so it can be quickly drawn then replaced with the actual image
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255]));

        // active the texture
        gl.activeTexture(gl.TEXTURE0);

        // load the image
        this.img = new Image();
        this.img.src = src;

        // replace the red pixel with the texture once it is loaded
        this.img.onload = function() {
            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
        }
    }
}

ฉันลองสิ่งนี้แล้ว:

this.img.onload = function(gl) {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
}

แต่มันเกิดข้อผิดพลาดนี้:

Uncaught TypeError: t.texImage2D ไม่ใช่ฟังก์ชัน


person Edward    schedule 06.04.2018    source แหล่งที่มา
comment
สิ่งนี้มีประโยชน์ไหม? stackoverflow.com/questions/49187705/   -  person gman    schedule 07.04.2018
comment
@gman นี่เป็นข้อมูลเกี่ยวกับวิธีการทำงานจริง ๆ ขอบคุณ!   -  person Edward    schedule 09.04.2018


คำตอบ (2)


คุณกำลังสร้างขอบเขตใหม่ภายในฟังก์ชัน วิธีที่ง่ายที่สุดในการป้องกันใน ES6 คือฟังก์ชันลูกศร:

this.img.onload = () => {
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.img);
}
person Sebastian Speitel    schedule 06.04.2018
comment
นี่มันสมบูรณ์แบบ ฉันจะยอมรับคำตอบของคุณเมื่อทำได้ และฉันจะอ่านฟังก์ชันลูกศร - person Edward; 06.04.2018

คำหลัก this ภายในฟังก์ชัน onload ของคุณไม่ตรงกับบริบท this ที่คุณคาดหวัง วิธีหนึ่งคือใช้ฟังก์ชันลูกศรเหมือนในคำตอบของ Sebastian Speitel

คุณยังสามารถบันทึกการอ้างอิงลงในตัวแปร self ซึ่งเป็นรูปแบบทั่วไป:

var self = this;
this.img.onload = function() {
        gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, self.img);
}

ฟังก์ชันใดๆ ก็ตามสามารถเข้าถึงตัวแปรจากขอบเขตภายนอกได้ นั่นคือสาเหตุที่ self สามารถเข้าถึงได้ภายใน this.img.onload

person Tomasz Bubała    schedule 06.04.2018
comment
ฉันเพิ่งทดสอบสิ่งนี้และมันก็ใช้งานได้เช่นกัน ขอบคุณสำหรับคำอธิบาย ฟังก์ชันลูกศรเป็นวิธีแก้ปัญหาที่ฉันชอบสำหรับสิ่งนี้ แต่การทราบข้อมูลนี้มีประโยชน์อย่างแน่นอนเนื่องจากฉันกำลังอยู่ระหว่างการเรียนรู้ ES6 - person Edward; 06.04.2018
comment
ใช่ เลือกใช้ ES6 ถ้าทำได้ ฟังก์ชันลูกศรไม่มี this เป็นของตัวเอง This เชื่อมโยงกับบริบทที่สร้างขึ้น ซึ่งมีประโยชน์ในหลาย ๆ สถานการณ์ - เช่นเดียวกับของคุณ :) - person Tomasz Bubała; 06.04.2018