我怀疑我没有正确地将粒子位置呈现给我的FBO,或者在渲染时正确地采样这些位置,尽管这可能不是我代码的实际问题,不可否认。
我有一个完整的jsfiddle在这里: http://jsfiddle.net/p5mdv/53/
代码概述:
初始化:创建一个随机粒子在x,y,z位置的数组
创建纹理采样位置数组(例如,对于2个粒子,第一个粒子在0,0,下一个在0.5,0)
创建一个帧缓冲对象和两个粒子位置纹理(一个用于输入,一个用于输出)
创建一个全屏四边形(-1,-1到1,1)
粒子模拟:
使用粒子程序渲染一个全屏四边形(绑定帧缓冲区,将视口设置为粒子位置纹理的尺寸,绑定输入纹理,并从- 1,1到1,1绘制一个四边形)。输入和输出纹理每帧交换
粒子片段着色器在当前片段位置(gl_fragcoordinate .xy)采样粒子纹理,做一些修改,并写出修改后的位置
粒子呈现:
使用纹理采样位置的顶点缓冲区绘制
顶点着色器使用采样位置对粒子位置纹理进行采样,然后使用视图投影矩阵对它们进行变换
使用精灵纹理(gl.POINTS)绘制粒子
问题:
我在粒子模拟步骤中正确设置了FBO的视口吗?也就是说,我是否正确地渲染了一个全屏四边形?
// 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);
我是否正确设置纹理坐标来采样粒子位置?
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 }
相关的着色器:
粒子模拟片段着色器:
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;
}
粒子渲染顶点着色器:
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;
}
让我知道是否有更好的方法去调试这个,如果没有别的。我正在使用webgl-debug来查找gl错误并记录我可以到控制台的内容。
您的quad正面对着远离视图,所以我尝试添加gl.disable(gl.CULL_FACE),仍然没有结果。
然后我注意到,当用画布调整窗口面板的大小时,它实际上显示了一个黑色的方形粒子。因此,渲染循环似乎不是很好。
如果你看一下控制台日志,它无法加载粒子图像,它还说FBO大小是512x1,这是不好的。
一些函数声明不存在,如getTexSize。(? !)
代码需要排序和分组,如果你已经在使用控制台,一定要检查它。
找到问题了
gl_FragCoord是从[0,0]到[screenwidth, screenheight],我错误地认为它是从[0,0]到[1,1]。
我必须传入宽度和高度的着色器变量,然后在从纹理采样之前规范化样本坐标。