1

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.

4

2 回答 2

1

发现了问题。

gl_FragCoord 是从 [0,0] 到 [screenwidth, screenheight],我错误地认为它是从 [0,0] 到 [1,1]。

我必须传入宽度和高度的着色器变量,然后在从纹理采样之前标准化样本坐标。

于 2013-06-13T21:35:05.270 回答
1

你的四边形背对着视线,所以我尝试添加 gl.disable(gl.CULL_FACE),仍然没有结果。

然后我注意到,在使用画布调整窗口面板大小时,它实际上显示了一个黑色的方形粒子。所以看起来渲染循环不好。

如果您查看控制台日志,它无法加载粒子图像,并且还说 FBO 大小为 512x1,这不好。

有些函数声明不存在,如 getTexSize。(?!)

代码需要整理和分组,如果您已经在使用它,请务必检查控制台。

希望这个对你有帮助。

于 2013-06-04T11:32:38.443 回答