WebGL:使用FBO的粒子引擎,如何从纹理正确写入和采样粒子位置? [英] WebGL: Particle engine using FBO, how to correctly write and sample particle positions from a texture?

查看:108
本文介绍了WebGL:使用FBO的粒子引擎,如何从纹理正确写入和采样粒子位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我怀疑我没有正确地将粒子位置渲染到我的FBO上,或者渲染时没有正确采样这些位置,尽管这可能不是我代码的实际问题.

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.

我在这里有一个完整的jsfiddle : http://jsfiddle.net/p5mdv /53/

代码的简要概述:

初始化:

  1. 在x,y,z中创建随机粒子位置的数组

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

创建一个纹理采样位置数组(例如,对于2个粒子,第一个粒子在0,0,下一个在0.5,0)

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

创建一个帧缓冲区对象和两个粒子位置纹理(一个用于输入,一个用于输出)

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

创建全屏四边形(-1,-1到1,1)

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

颗粒模拟:

  1. 使用粒子程序渲染全屏四边形(绑定帧缓冲区,将视口设置为我的粒子位置纹理的尺寸,绑定输入纹理,并绘制从-1,-1到1,1的四边形).输入和输出纹理每帧交换一次.

  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.

粒子片段着色器在当前片段位置(gl_FragCoord.xy)采样粒子纹理,进行一些修改,并写出修改后的位置

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

粒子渲染:

  1. 使用纹理采样位置的顶点缓冲区绘制

  1. Draw using the vertex buffer of texture sampling locations

顶点着色器使用采样位置对粒子位置纹理进行采样,然后使用视图投影矩阵对其进行转换

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

使用精灵纹理(gl.POINTS)绘制粒子

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

问题:

  1. 我是否在粒子模拟步骤中正确设置了FBO的视口? IE.我可以正确渲染全屏四边形吗?

  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);

  • 我是否正确设置了纹理坐标以对粒子位置进行采样?

  • 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
    }
    

  • 相关的着色器:

    粒子模拟片段着色器:

    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错误,并将可以记录的内容记录到控制台.

    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.

    推荐答案

    发现了问题.

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

    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.

    这篇关于WebGL:使用FBO的粒子引擎,如何从纹理正确写入和采样粒子位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆