使用WebGL渲染全屏四边形

时间:2014-06-08 09:54:43

标签: webgl framebuffer quad

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

我尝试过创建像这样的全屏四核

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);

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

2 个答案:

答案 0 :(得分:4)

一旦你了解了如何使用Vertex Buffers和着色器,这真的不是什么大问题。然后,您可以轻松编写实用程序功能来执行此操作。这是我通常使用的一个,如果您正在寻找参考:

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,而无需乘以投影矩阵。

答案 1 :(得分:0)

为什么需要相机来渲染全屏四边形?渲染全屏四边形几乎是您在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