Javascript WebGL可渲染纹理未渲染。渲染警告:绑定到纹理单元0的纹理不可渲染

Javascript WebGL可渲染纹理未渲染。渲染警告:绑定到纹理单元0的纹理不可渲染,javascript,opengl-es,textures,webgl,Javascript,Opengl Es,Textures,Webgl,我在一个web查看器中工作,它有许多渲染到同一页面的着色器程序。我正在添加另一个程序,该程序使用纹理渲染四边形。四边形渲染效果很好。纹理是我的问题所在 Mesh.prototype.initTexture = function(ctx) { this.texture = this.ctx.createTexture(); this.texture.image = new Image(); // ctx.bindTexture(this.ctx.TEXTURE_2D,

我在一个web查看器中工作,它有许多渲染到同一页面的着色器程序。我正在添加另一个程序,该程序使用纹理渲染四边形。四边形渲染效果很好。纹理是我的问题所在

Mesh.prototype.initTexture = function(ctx) {

    this.texture = this.ctx.createTexture();
    this.texture.image = new Image();

    // ctx.bindTexture(this.ctx.TEXTURE_2D, this.texture);
    // ctx.texImage2D(this.ctx.TEXTURE_2D, 0, this.ctx.RGBA, 1, 1, 0, this.ctx.RGBA, this.ctx.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255])); // red

    mesh.texture.image.onload = function () {
        //Upon callback, 'this' is different, so we use the global variable for now
        mesh.handleLoadedTexture(mesh.texture,mesh.texture.image);
    }

    this.texture.image.src = "/path/to/images/nehe.gif";

}
这是我的initTexture函数。我可以取消注释加载红方块(la)的两行,然后纹理渲染为红色,不再弹出错误,但我的纹理从未加载。纹理本身是我从LearningWebGL下载的可渲染纹理。我下载了一个演示表单,该表单在我的本地主机上运行良好,与此项目并行

这是handleLoadedTexture函数

Mesh.prototype.handleLoadedTexture = function(texture, image) {

    mesh.ctx.bindTexture(mesh.ctx.TEXTURE_2D, texture);
    mesh.ctx.pixelStorei(mesh.ctx.UNPACK_FLIP_Y_WEBGL, true);
    mesh.ctx.texImage2D(mesh.ctx.TEXTURE_2D, 0, mesh.ctx.RGBA, this.ctx.RGBA, mesh.ctx.UNSIGNED_BYTE, image);
    mesh.ctx.texParameteri(mesh.ctx.TEXTURE_2D, mesh.ctx.TEXTURE_MAG_FILTER, mesh.ctx.NEAREST);
    mesh.ctx.texParameteri(mesh.ctx.TEXTURE_2D, mesh.ctx.TEXTURE_MIN_FILTER, mesh.ctx.NEAREST);
    mesh.ctx.generateMipmap(mesh.ctx.TEXTURE_2D);
    mesh.ctx.bindTexture(mesh.ctx.TEXTURE_2D, null);
}
然后,我们在整个渲染管道中拥有调用此渲染的块:

if (mesh != null) {
    mesh = new Mesh();
    ctx.useProgram(meshShader);
    // I set the camera and projection matrices here
    glCheck();
    if(!mesh.vbo) {
        mesh.loadGL(ctx);
    }
    if(!mesh.texture){
        mesh.initTexture(ctx);
    }
    mesh.render(meshShader);
    glCheck();
}
那里没有什么太革命性的东西

渲染功能:

Mesh.prototype.render = function(program) {
    assert(this.vbo != null, "VBO is null");
    assert(this.tcbo != null, "TCBO is null");

    // Arguments here are (index, size, type, normalized(bool), stride, offset)
    this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.vbo);
    this.ctx.vertexAttribPointer(program.a.vertex, this.sizevertices, this.ctx.FLOAT, false, 0, 0);

    this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, this.tcbo);
    this.ctx.vertexAttribPointer(program.a.textureCoordinate, this.sizetexco, this.ctx.FLOAT, false, 0, 0);

    this.ctx.activeTexture(this.ctx.TEXTURE0);
    this.ctx.bindTexture(this.ctx.TEXTURE_2D, this.texture);
    this.ctx.uniform1i(program.uSampler, 0);

    this.ctx.drawArrays(this.ctx.TRIANGLE_STRIP, 0, this.numvertices);
    render.glCheck();
}
顶点着色器:

varying vec2 vTextureCoord;

attribute vec3 vertex;
attribute vec2 textureCoordinate;

//other unrelated uniforms

void main(void) {

//position settings omitted
    vTextureCoord = textureCoordinate;
}
片段着色器:

precision mediump float;

varying vec2 vTextureCoord;

uniform sampler2D uSampler;

void main(void) {
    gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}
也许整件事最好有个合适的旗子

// when creating mesh
mesh.texInit = false;
加载时:

Mesh.prototype.initTexture = function(ctx) {

    this.texture = this.ctx.createTexture();
    this.texture.image = new Image();

    // ctx.bindTexture(this.ctx.TEXTURE_2D, this.texture);
    // ctx.texImage2D(this.ctx.TEXTURE_2D, 0, this.ctx.RGBA, 1, 1, 0, this.ctx.RGBA, this.ctx.UNSIGNED_BYTE, new Uint8Array([255, 0, 0, 255])); // red

    mesh.texture.image.onload = function () {
        //Upon callback, 'this' is different, so we use the global variable for now
        mesh.handleLoadedTexture(mesh.texture,mesh.texture.image);
        mesh.texInit = true;
        // note ^ here
    }
    this.texture.image.src = "/path/to/images/nehe.gif";
}
和用于渲染:

if(mesh.texInit) { doMagic(); } // aka render

我想知道您在
initTexture
函数中引用的是哪个
mesh
——您提供的代码中肯定没有定义它

也许你想写

this.texture.image.onload = function....
您已经了解到函数内部的
与外部的
不同。但我想你需要使用另一个变量,而不是全局变量,比如:

that = this;
this.texture.image.onload = function () {
    that.handleLoadedTexture(mesh.texture,mesh.texture.image);
}

调用
mesh.ctx.generateMipmap(mesh.ctx.TEXTURE_2D)没有意义如果要使用最近邻缩小过滤器。你所做的就是无缘无故地将纹理数据的大小增加33%。嗯,我明白了。我想说的是,这条线是在这个问题上挥舞的剩余部分。我删除了那条线,但加载纹理的结果是相同的。谢谢你提供的信息!您确定调用了
handleLoadedTexture
?你(用Chrome的WebGL检查器)检查过纹理是否已加载到WebGL吗?@virtualnobi完全忽略了这一事实。美好的我仍然建议使用标志来检查某些内容,这比将完整对象与某些值进行比较要好。@AbstractAlgorithm我不确定您的意思-我指的是一些基本的调试检查,以确保执行正确的代码并将纹理传输到WebGL空间…正确!我并没有添加那个代码,这是非常棒的锅炉板的东西,但我可以添加它,如果你愿意的话。在代码中,
mesh
是一个全局定义的变量,我最初将其设置为
null
。加载其他对象后,我进入js控制台并执行
mesh=1
。在这一点上,
如果(!mesh){…
得到评估。我对js也是相当陌生的,但是如果我能做一些像
that=this
这样的事情,那会很好。这是建立上下文的标准过程吗?还有另一种可能性,即一个
bind
函数修复函数的执行上下文,但是(我认为)在这里更容易使用局部变量。只需谷歌“Javascript绑定函数”然后选择你最信任的站点…啊,那么添加一个标志,表明纹理已经初始化?我试过一次,但我打赌我错过了一些东西。我愿意打赌,只有当它有机会使用纹理渲染时,它还没有准备好。我明天会尝试并报告。谢谢!!是的,只要使用标志就知道我如果你已经完全完成了创建
WebGLTexture
对象的工作。这比将整个对象与某个值进行比较要好得多。说它是如何运行的。嗯,仍然没有。纹理仍然是我的临时1x1红色。我在对象实例化中添加了
mesh.texinit=false
。我确保了逻辑工作,即纹理仅为应用于纹理加载:
if(mesh.texinit==false){mesh.initTexture(ctx);}
此外,我在控制台中检查了
mesh.texinit
logs
true
mesh.texture.image.height
logs
256
。这次运行中没有出现错误。您的注释将我设置在正确的路径上。我的逻辑覆盖了我的对象,相当于:```if(mesh!=null){mesh=new mesh();…}```太尴尬了。我修好了,它的负载非常好。谢谢你的帮助!
that = this;
this.texture.image.onload = function () {
    that.handleLoadedTexture(mesh.texture,mesh.texture.image);
}