首页 > 解决方案 > 渲染管道在 WebGL 1 中有效,但在 WebGL 2 中无效

问题描述


更新


@gman 已经回答了这个问题。启动时需要调用 gl.getExtension('EXT_color_buffer_float') 。


问题是在 WebGL2 下调用gl.checkFramebufferStatus(gl.FRAMEBUFFER)不会返回。gl.FRAMEBUFFER_COMPLETE我在打电话之前打了这个电话gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4)

以下是任一版本的常见顺序。区别在于createTexture()readTexture()。这些特定于 WebGL 的版本。

一般流程:

gl.useProgram(program);
var texShape = getTextureShape(programInfo.outputTensor);
var outputTexture = this.textureManager.getOrCreateTexture(programInfo.outputTensor);
this.gpuContext.attachFramebuffer(outputTexture, texShape.width, texShape.height);
var inputTextures = this.createTextures(programInfo.textureData);
this.bindAttributes(buildArtifact.attribLocations);
this.bindUniforms(buildArtifact.uniformLocations, programInfo.uniformData);
this.bindTextures(buildArtifact.uniformLocations, inputTextures);
if (!this.gpuContext.isFramebufferReady()) {
    throw new Error("Framebuffer is not ready");
}
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
this.copyToOutput(outputTexture, programInfo.outputTensor);

attachFramebuffer:普通

GpuContext.prototype.attachFramebuffer = function (texture, width, height) {
    var gl = this.gl;
    gl.activeTexture(gl.TEXTURE0 + (this.maxTextureImageUnits - 1));
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
    gl.framebufferTexture2D(gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D,
        texture,
        0); 
    gl.viewport(0, 0, width, height);
};

创建纹理:WebGL 1.0:

GpuContext.prototype.createTexture = function (width, height, data) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    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);
    // TODO: remove this override
    var type = gl.FLOAT;
    var buffer = null;
    if (data) {
        buffer = new Float32Array(data.length * 4);
        data.forEach(function (value, index) { return buffer[index * 4] = value; });
    }
    // Pixel format and data for the texture
    gl.texImage2D(gl.TEXTURE_2D, // Target, matches bind above.
        0,
        gl.RGBA,
        width,
        height,
        0,
        gl.RGBA,
        type,
        buffer);
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};

读取纹理:WebGL 1.0:

GpuContext.prototype.readTexture = function (texture, width, height) {
    var gl = this.gl;
    var buffer = new Float32Array(width * height * 4);
    var format = gl.RGBA;
    var type = gl.FLOAT;
    // bind texture to framebuffer
    gl.framebufferTexture2D(gl.FRAMEBUFFER,
        gl.COLOR_ATTACHMENT0,
        gl.TEXTURE_2D,
        texture,
        0);
    if (!this.isFramebufferReady()) {
        throw new Error("Framebuffer is not ready after attaching texture");
    }
    gl.readPixels(0, // x-coord of lower left corner
        0, // y-coord of lower left corner
        width, // width of the block
        height, // height of the block
        format, // Format of pixel data.
        type, // Data type of the pixel data, must match makeTexture
        buffer); // Load pixel data into buffer
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    return buffer.filter(function (value, index) { return index % 4 === 0; });
};

WebGL 2.0 覆盖:

WebGL2GpuContext.prototype.createTexture = function (width, height, data) {
    var gl = this.gl;
    var texture = gl.createTexture();
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    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);

    var internalFormat = WebGL2RenderingContext.R32F;
    var format = WebGL2RenderingContext.RED;
    var type = gl.FLOAT;
    gl.texImage2D(gl.TEXTURE_2D, 
        0, 
        internalFormat, 
        width, 
        height, 
        0, 
        format, 
        type, 
        data); 
    gl.bindTexture(gl.TEXTURE_2D, null);
    return texture;
};
WebGL2GpuContext.prototype.readTexture = function (texture, width, height) {
    var gl = this.gl;
    var buffer = new Float32Array(width * height);
    var format = WebGL2RenderingContext.RED;
    var type = gl.FLOAT;
    gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
        gl.framebufferTexture2D(gl.FRAMEBUFFER, 
        gl.COLOR_ATTACHMENT0, 
        gl.TEXTURE_2D, 
        texture, 
        0); 
    if (!this.isFramebufferReady()) {
        throw new Error("Framebuffer is not ready after attaching texture");
    }
    gl.readPixels(0, 
        0, 
        width, 
        height, 
        format, 
        type, 
        buffer); 
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    return buffer;
};

标签: javascriptwebglwebgl2

解决方案


推荐阅读