【问题标题】:Rendering a fullscreen quad using WebGL使用 WebGL 渲染全屏四边形
【发布时间】:2014-06-08 09:54:43
【问题描述】:

我有一个渲染场景的帧缓冲区,现在我想将它渲染到“全屏”四边形。如何设置我的相机以及我应该在我的顶点着色器中放置什么以便将帧缓冲区的纹理渲染到整个屏幕。

我尝试过创建这样的全屏四边形

var gl = this.gl;
var quad_vertex_buffer = gl.createBuffer();
var quad_vertex_buffer_data = new Float32Array([ 
    -1.0, -1.0, 0.0,
     1.0, -1.0, 0.0,
    -1.0,  1.0, 0.0,
    -1.0,  1.0, 0.0,
     1.0, -1.0, 0.0,
     1.0,  1.0, 0.0]);
gl.bufferData(quad_vertex_buffer, quad_vertex_buffer_data, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, quad_vertex_buffer);
gl.vertexAttribPointer(this.shaderProgram.vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
//gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.drawArrays(gl.TRIANGLES,0, 6);

但它仍然使一切变黑。我可以遵循任何想法或示例/教程?

【问题讨论】:

    标签: webgl framebuffer


    【解决方案1】:

    这真的没什么大不了的,一旦你了解了如何使用顶点缓冲区和着色器。然后你可以很容易地编写一个实用函数来完成它。如果您正在寻找参考,这是我通常使用的一个:

    drawFullScreenQuad : function(shaderProgram) {
    
        if (!shaderProgram)
        {
            utils.warning("Missing the shader program!");
            return;
        }
    
        // Only created once
        if (this.screenQuadVBO == null)
        {
            var verts = [
                // First triangle:
                 1.0,  1.0,
                -1.0,  1.0,
                -1.0, -1.0,
                // Second triangle:
                -1.0, -1.0,
                 1.0, -1.0,
                 1.0,  1.0
            ];
            this.screenQuadVBO = this.gl.createBuffer();
            this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.screenQuadVBO);
            this.gl.bufferData(this.gl.ARRAY_BUFFER, new Float32Array(verts), this.gl.STATIC_DRAW);
        }
    
        // Bind:
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.screenQuadVBO);
        this.gl.enableVertexAttribArray(shaderProgram.vertexAttributes.vertexPositionNDC);
        this.gl.vertexAttribPointer(shaderProgram.vertexAttributes.vertexPositionNDC, 2, this.gl.FLOAT, false, 0, 0);
    
        // Draw 6 vertexes => 2 triangles:
        this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
    
        // Cleanup:
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);
    },
    

    然后你可以像我一样在顶点着色器中即时计算纹理坐标:

    顶点着色器:

    precision lowp float;
    
    // xy = vertex position in normalized device coordinates ([-1,+1] range).
    attribute vec2 vertexPositionNDC;
    
    varying vec2 vTexCoords;
    
    const vec2 scale = vec2(0.5, 0.5);
    
    void main()
    {
        vTexCoords  = vertexPositionNDC * scale + scale; // scale vertex attribute to [0,1] range
        gl_Position = vec4(vertexPositionNDC, 0.0, 1.0);
    }
    

    片段着色器:

    precision mediump float;
    
    uniform sampler2D colorMap;
    varying vec2 vTexCoords;
    
    void main()
    {
        gl_FragColor = texture2D(colorMap, vTexCoords);
    }
    

    需要注意的重点是归一化设备坐标 (NDC) 中的顶点,因此您只需将 [-1,1] 范围内的顶点传递并直接将它们转发到gl_Position,而无需乘以投影矩阵。

    【讨论】:

    • 我在this.gl.enableVertexAttribArray(shaderProgram.vertexAttributes.vertexPositionNDC); 上收到了Error: program.vertexAttributes is undefined 我忘记了什么?
    • @JeroenvanLangen, shaderProgram 是用户定义的类型,不是 WebGL 内置的,所以你需要自己定义。截取的代码并不完整,只是为了演示。
    • 一个,tnx。我刚刚开始检查 webgl。我做了一些 dx11,但它仍然是一个变化..
    • 仅供参考:NDC 在透视划分之后(参见 GL 规范)。你是说剪辑空间坐标吗?
    • @gman,是的,你是对的。我总是习惯于弄错术语。那确实是剪辑空间,而不是 ndc。
    【解决方案2】:

    为什么需要相机来渲染全屏四边形?渲染一个全屏四边形几乎是您在 WebGL 中可以做的最简单的事情。鉴于您已经设置的缓冲区,只需使用这样的着色器

    顶点着色器:

    attribute vec4 v_position;
    
    void main() {
      gl_Position = v_position;
    }     
    

    片段着色器:

    precision mediump float;
    
    void main() {
       gl_FragColor = vec4(0,1,0,1); // green
    }
    

    你应该得到一个绿屏。

    但代码中存在一些错误。您需要在尝试将数据放入其中之前绑定缓冲区。您需要通过绑定点引用缓冲区,而不是缓冲区对象。

    旧的(不正确的)

    gl.bufferData(quad_vertex_buffer, quad_vertex_buffer_data, gl.STATIC_DRAW);
    gl.bindBuffer(gl.ARRAY_BUFFER, quad_vertex_buffer);
    

    新的(正确的)

    gl.bindBuffer(gl.ARRAY_BUFFER, quad_vertex_buffer);
    gl.bufferData(gl.ARRAY_BUFFER, quad_vertex_buffer_data, gl.STATIC_DRAW);
    

    例子:

    const vs = `
        attribute vec4 v_position;
    
        void main() {
          gl_Position = v_position;
        }     
    `;
    
    const fs = `
        precision mediump float;
    
        void main() {
           gl_FragColor = vec4(0,1,0,1); // green
        }
    `;
    
    var gl = document.querySelector("canvas").getContext("webgl");
    var shader_program = twgl.createProgram(gl, [vs, fs]);
    gl.useProgram(shader_program);
    var vertexPositionAttribute = gl.getAttribLocation(shader_program, "v_position");
    var quad_vertex_buffer = gl.createBuffer();
    var quad_vertex_buffer_data = new Float32Array([ 
        -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
        -1.0,  1.0, 0.0,
        -1.0,  1.0, 0.0,
         1.0, -1.0, 0.0,
         1.0,  1.0, 0.0]);
    gl.bindBuffer(gl.ARRAY_BUFFER, quad_vertex_buffer);
    gl.bufferData(gl.ARRAY_BUFFER, quad_vertex_buffer_data, gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vertexPositionAttribute)
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
    <canvas></canvas>

    另一个使用简单模式的示例来显示它的工作原理

    const vs = `
        attribute vec4 v_position;
    
        void main() {
          gl_Position = v_position;
        }     
    `;
    
    const fs = `
        precision mediump float;
    
        void main() {
           gl_FragColor = vec4(fract(gl_FragCoord.xy / vec2(16., 32.)),0,1); 
        }
    `;
    
    var gl = document.querySelector("canvas").getContext("webgl");
    var shader_program = twgl.createProgram(gl, [vs, fs]);
    gl.useProgram(shader_program);
    var vertexPositionAttribute = gl.getAttribLocation(shader_program, "v_position");
    var quad_vertex_buffer = gl.createBuffer();
    var quad_vertex_buffer_data = new Float32Array([ 
        -1.0, -1.0, 0.0,
         1.0, -1.0, 0.0,
        -1.0,  1.0, 0.0,
        -1.0,  1.0, 0.0,
         1.0, -1.0, 0.0,
         1.0,  1.0, 0.0]);
    gl.bindBuffer(gl.ARRAY_BUFFER, quad_vertex_buffer);
    gl.bufferData(gl.ARRAY_BUFFER, quad_vertex_buffer_data, gl.STATIC_DRAW);
    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
    gl.enableVertexAttribArray(vertexPositionAttribute)
    gl.drawArrays(gl.TRIANGLES, 0, 6);
    <script src="https://twgljs.org/dist/4.x/twgl.min.js"></script>
    <canvas></canvas>

    我建议你阅读一些WebGL tutorials。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 2015-01-12
      • 1970-01-01
      相关资源
      最近更新 更多