如何在两种纹理之间交替?

Posted

技术标签:

【中文标题】如何在两种纹理之间交替?【英文标题】:How to alternate between two textures? 【发布时间】:2016-08-07 20:54:01 【问题描述】:

我正在尝试绘制纹理,以便渲染不断叠加。 我正在使用两个纹理和两个帧缓冲区。 texture[0] 附加到 framebuffer[0],texture[1] 附加到 framebuffer[1]。

    var gl = webgl.context;

    gl.useProgram(this.program);

    gl.bindTexture(gl.TEXTURE_2D, this.texture[this.pingpong]);
    this.pingpong = (this.pingpong==0?1:0);
    var pp = this.pingpong;

    gl.bindFramebuffer(gl.FRAMEBUFFER, this.frameBuffer[pp]);

    gl.drawArrays(gl.TRIANGLES, 0, 6);              //primitiveType, offset, count

    gl.bindTexture(gl.TEXTURE_2D, this.texture[pp]);        //bind to the texture we just drew to
    gl.bindFramebuffer(gl.FRAMEBUFFER, null);               //render the above texture to the canvas

    gl.drawArrays(gl.TRIANGLES, 0, 6);

问题是我没有看到之前的渲染被保存到纹理中。 我认为 bindframebuffer() 会使它渲染到纹理。 我的片段着色器:

precision mediump float;                                    // fragment shaders don't have a default precision so we need to pick one. mediump is a good default

    varying vec2 v_texCoord;                                    // the texCoords passed in from the vertex shader.

    uniform vec2 u_resolution;                                  // a uniform
    uniform vec2 u_mouse;

    uniform sampler2D u_image;                              // this isn't set, so it will default to 0 (the current active texture)
void main()        

        vec4 texColor = texture2D(u_image, v_texCoord);         // Look up a color from the texture.

        vec2 coord = vec2(gl_FragCoord.x,u_resolution.y-gl_FragCoord.y);

        vec4 color = step(distance(coord,u_mouse),100.0)*vec4(1,0,0,1) + step(100.0,distance(coord,u_mouse))*texColor;


        gl_FragColor = color;                   // gl_FragColor is a special variable a fragment shader is responsible for setting
    

u_image 设置为默认 0,即活动纹理。

有什么我忽略的吗?为什么以前的渲染不会相互叠加?它只是显示最新的渲染,就好像纹理没有被改变一样。

这是顶点着色器:

precision mediump float;

    attribute vec2 a_position;                                  // an attribute will receive data from a buffer
    attribute vec2 a_texCoord;
    varying vec2 v_texCoord;                                    // a varying 
    uniform vec2 u_resolution;                                  // a uniform
    uniform vec2 u_mouse;
    uniform float u_flip;

    // all shaders have a main function
    void main() 
        v_texCoord = a_texCoord;                                // pass the texCoord to the fragment shader.The GPU will interpolate this value between points

        vec2 zeroToOne = a_position / u_resolution;     // convert the position from pixels to 0.0 to 1.0
        vec2 zeroToTwo = zeroToOne * 2.0;               // convert from 0->1 to 0->2
        vec2 clipSpace = zeroToTwo - 1.0;                   // convert from 0->2 to -1->+1 (clipspace)

        // gl_Position is a special variable a vertex shader is responsible for setting
        gl_Position = vec4(clipSpace * vec2(1, u_flip), 0, 1);
    

【问题讨论】:

你能解释一下你期望着色器做什么吗?在鼠标光标周围画一个红色(+ 来自另一个纹理的颜色)圆圈? 是的,当我移动鼠标时,它会在鼠标光标周围画一个红色圆圈。我希望它保留以前的绘制,但由于某种原因它没有这样做,所以我只得到一个红色圆圈,而不是鼠标移动的一系列圆圈。我正在使用两个纹理和两个帧缓冲区,我认为它们可以用来绘制圆,然后在它们之间交替,以便保留以前的图形,但它不起作用。我不明白为什么。 我担心的是纹理似乎没有保留它们的数据。如果我在绑定帧缓冲区时绘制到它们,然后当我绑定纹理以获取颜色时,它应该具有先前渲染的图像,对吗?然而,当我阅读它们的颜色时,它似乎没有之前呈现的内容——它只是空白。 如果我尝试这样做,它看起来一样 - 只是鼠标周围有一个红色圆圈。 我用顶点着色器代码更新了帖子,以防有人看到错误? 【参考方案1】:

我试图模仿你在做什么:

loop.flexStep = function()
    gl.clear(gl.COLOR_BUFFER_BIT);

    pingPong.pingPong().applyPass( //pingPong() just swaps the FBOs and return the current FBO being draw to
        "outColor += src0 * 0.98;",
        pingPong.otherTexture() // the src0 texture
    );
    points.drawPoint([mouse.x, mouse.y, 0 ]);
    points.renderAll(camera); 

    screenBuffer.applyPass(
        "outColor = src0;",
        pingPong.resultFBO  // src0
    );
;

这是它的样子(gl.POINTS 而不是圆形):

这里是 gl 命令:

您应该首先检查您的帧缓冲区是否设置正确。由于那部分没有显示出来,很难说。

还要考虑分离你的着色器。您应该在 pingpong 阶段使用一个着色器来将先前纹理的结果复制/更改为当前 pingPong FBO 纹理。另一个着色器用于将新内容绘制到当前的 pingPong FBO 纹理。

【讨论】:

谢谢 - 我设法找到了问题。它没有选择正确的纹理坐标,还不得不解决一些翻转问题。 很高兴您解决了问题。如果你想使用乒乓缓冲区来实现其他有趣的效果,我认为你应该考虑实现我上面概述的结构。 我会试着理解你的结构——我对 webgl 比较陌生,我很难识别你表单中的模式。它似乎比我目前能够处理的要先进一些。也许你可以给我一个关于你建议的结构类型的好教程或演练? 基本思想是,在每一帧上: 1) 将所需的效果应用到乒乓缓冲区(在你的情况下,它只是复制,在我的情况下,它会使先前图像的结果变暗,可以是百万种不同的东西,例如模糊、颜色变化等)。 2) 将新内容绘制到 pingpong 缓冲区。 3) 将乒乓缓冲区的内容复制到屏幕缓冲区。【参考方案2】:

问题似乎在于获取错误的纹理坐标并翻转纹理。 它现在按预期工作。

这是更新的顶点/片段着色器:

this.vertex = `
    precision mediump float;

    attribute vec2 a_position;                                  // an attribute will receive data from a buffer
    attribute vec2 a_texCoord;
    varying vec2 v_texCoord;                                    // a varying 
    uniform vec2 u_resolution;                                  // a uniform
    uniform vec2 u_mouse;
    uniform float u_flip;

    // all shaders have a main function
    void main() 
        v_texCoord = a_texCoord / u_resolution;                             // pass the texCoord to the fragment shader.The GPU will interpolate this value between points

        vec2 zeroToOne = a_position / u_resolution;     // convert the position from pixels to 0.0 to 1.0
        vec2 zeroToTwo = zeroToOne * 2.0;               // convert from 0->1 to 0->2
        vec2 clipSpace = zeroToTwo - 1.0;                   // convert from 0->2 to -1->+1 (clipspace)

        // gl_Position is a special variable a vertex shader is responsible for setting
        gl_Position = vec4(clipSpace * vec2(1, u_flip), 0, 1);
    

`;

this.fragment = ` 

    precision mediump float;                                    // fragment shaders don't have a default precision so we need to pick one. mediump is a good default

    varying vec2 v_texCoord;                                    // the texCoords passed in from the vertex shader.

    uniform vec2 u_resolution;                                  // a uniform
    uniform vec2 u_mouse;
    uniform float u_flip;

    uniform sampler2D u_image;                              // this isn't set, so it will default to 0 (the current active texture)
    uniform sampler2D u_texture0;
    uniform sampler2D u_texture1;

    void main()        

        vec4 texColor = texture2D(u_image, v_texCoord);         // Look up a color from the texture.

        vec2 coord = vec2(gl_FragCoord.x, step(0.0,u_flip)*gl_FragCoord.y + step(u_flip,0.0)*(u_resolution.y-gl_FragCoord.y) );

        vec4 color = step(distance(coord,u_mouse),100.0)*vec4(1,0,0,1) + step(100.0,distance(coord,u_mouse))*texColor;


        gl_FragColor = color;                   // gl_FragColor is a special variable a fragment shader is responsible for setting
    

`;

【讨论】:

以上是关于如何在两种纹理之间交替?的主要内容,如果未能解决你的问题,请参考以下文章

如何在两种公钥格式之间进行转换,一种是“BEGIN RSA PUBLIC KEY”,另一种是“BEGIN PUBLIC KEY”

如何在两种模式之间打印行,包括或排他(在sed,AWK或Perl中)?

Atitit 如何创新 创新只有在两种条件下发生:自由效率。

Qtablewidget设置颜色交替

如何在 html 文件之间交替并在它们之间发送数据?

Spark Read Json:如何读取在整数和结构之间交替的字段