如何在两种纹理之间交替?
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中)?