WebGL: Particle engine using FBO, how to correctly write and sample particle positions from a texture?

匿名 (未验证) 提交于 2019-12-03 10:10:24

问题:

I suspect I'm not correctly rendering particle positions to my FBO, or correctly sampling those positions when rendering, though that may not be the actual problem with my code, admittedly.

I have a complete jsfiddle here: http://jsfiddle.net/p5mdv/53/

A brief overview of the code:

Initialization:

  1. Create an array of random particle positions in x,y,z

  2. Create an array of texture sampling locations (e.g. for 2 particles, first particle at 0,0, next at 0.5,0)

  3. Create a Frame Buffer Object and two particle position textures (one for input, one for output)

  4. Create a full-screen quad (-1,-1 to 1,1)

Particle simulation:

  1. Render a full-screen quad using the particle program (bind frame buffer, set viewport to the dimensions of my particle positions texture, bind input texture, and draw a quad from -1,-1 to 1,1). Input and output textures are swapped each frame.

  2. Particle fragment shader samples the particle texture at the current fragment position (gl_FragCoord.xy), makes some modifications, and writes out the modified position

Particle rendering:

  1. Draw using the vertex buffer of texture sampling locations

  2. Vertex shader uses the sampling location to sample the particle position texture, then transforms them using view projection matrix

  3. Draw the particle using a sprite texture (gl.POINTS)

Questions:

  1. Am I correctly setting the viewport for the FBO in the particle simulation step? I.e. am I correctly rendering a full-screen quad?

    // 6 2D corners = 12 vertices  var vertexBuffer = new Float32Array(12);  // -1,-1 to 1,1 screen quad vertexBuffer[0] = -1; vertexBuffer[1] = -1;  vertexBuffer[2] = -1; vertexBuffer[3] = 1;  vertexBuffer[4] = 1; vertexBuffer[5] = 1;  vertexBuffer[6] = -1; vertexBuffer[7] = -1;  vertexBuffer[8] = 1; vertexBuffer[9] = 1;  vertexBuffer[10] = 1; vertexBuffer[11] = -1;  // Create GL buffers with this data g.particleSystem.vertexObject = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, g.particleSystem.vertexObject); gl.bufferData(gl.ARRAY_BUFFER, vertexBuffer, gl.STATIC_DRAW);  ...  gl.viewport(0, 0,          g.particleSystem.particleFBO.width,         g.particleSystem.particleFBO.height);  ...  // Set the quad as vertex buffer gl.bindBuffer(gl.ARRAY_BUFFER, g.screenQuad.vertexObject); gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);  // Draw! gl.drawArrays(gl.TRIANGLES, 0, 6);
  2. Am I correctly setting the texture coordinates to sample the particle positions?

    for(var i=0; i<numParticles; i++) {     // Coordinates of particle within texture (normalized)     var texCoordX = Math.floor(i % texSize.width) / texSize.width;     var texCoordY = Math.floor(i / texSize.width) / texSize.height;      particleIndices[ pclIdx     ] = texCoordX;     particleIndices[ pclIdx + 1 ] = texCoordY;     particleIndices[ pclIdx + 2 ] = 1; // not used in shader }

The relevant shaders:

Particle simulation fragment shader:

precision mediump float;  uniform sampler2D mParticleTex;  void main() {     // Current pixel is the particle's position on the texture     vec2 particleSampleCoords = gl_FragCoord.xy;     vec4 particlePos = texture2D(mParticleTex, particleSampleCoords);      // Move the particle up     particlePos.y += 0.1;     if(particlePos.y > 2.0)     {         // Reset         particlePos.y = -2.0;     }      // Write particle out to texture     gl_FragColor = particlePos; }

Particle rendering vertex shader:

attribute vec4 vPosition;  uniform mat4 u_modelViewProjMatrix;  uniform sampler2D mParticleTex;  void main() {     vec2 particleSampleCoords = vPosition.xy;     vec4 particlePos = texture2D(mParticleTex, particleSampleCoords);     gl_Position = u_modelViewProjMatrix * particlePos;     gl_PointSize = 10.0; }

Let me know if there's a better way to go about debugging this, if nothing else. I'm using webgl-debug to find gl errors and logging what I can to the console.

回答1:

Your quad is facing away from view so I tried adding gl.disable(gl.CULL_FACE), still no result.

Then I noticed that while resizing window panel with canvas it actually shows one black, square-shaped particle. So it seems that rendering loop is not good.

If you look at console log, it fails to load particle image and it also says that FBO size is 512x1 which is not good.

Some function declarations do not exist, as getTexSize. (?!)

Code needs tiding and grouping, and always check console if you're already using it.

Hope this helps a bit.



回答2:

Found the problem.

gl_FragCoord is from [0,0] to [screenwidth, screenheight], I was wrongly thinking it was from [0,0] to [1,1].

I had to pass in shader variables for width and height, then normalize the sample coordinates before sampling from the texture.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!