2

我们目前正在研究 GPU 粒子系统。我的实现有问题,似乎缓冲区没有更新或绘制。

如果有任何帮助,我将不胜感激!

粒子系统初始化

Particle Particles[MaxParticles];

Particles[0].Type = 0;
Particles[0].Pos = glm::vec3(12.f, 14.f, 17.f);// getCamPos();
Particles[0].Vel = glm::vec3(0.0f, 0.0341f, 0.0f);
Particles[0].LifetimeMillis = 0.0f;

currTransFeedBuffer = 1;
currVertBuffer = 0;

glGenTransformFeedbacks(2, transFeedBackBuffers);
glGenBuffers(2, particleBuffers);

for (unsigned int i = 0; i < 2; i++) {
    glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transFeedBackBuffers[i]);
    glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[i]);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Particles), Particles, GL_DYNAMIC_DRAW);
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, particleBuffers[i]);
}

粒子系统更新

particleShader.useShader();


auto m_deltaTimeMillisLocation      = glGetUniformLocation(particleShader.programHandle, "gDeltaTimeMillis");
auto m_timeLocation                     = glGetUniformLocation(particleShader.programHandle, "gTime");
auto m_launcherLifetimeLocation         = glGetUniformLocation(particleShader.programHandle, "gLauncherLifetime");
auto m_shellLifetimeLocation                = glGetUniformLocation(particleShader.programHandle, "gShellLifetime");
auto m_secondaryShellLifetimeLocation   = glGetUniformLocation(particleShader.programHandle, "gSecondaryShellLifetime");

glUniform1f(m_deltaTimeMillisLocation, (float)delta);
glUniform1f(m_timeLocation, (float)glfwGetTime());
glUniform1f(m_launcherLifetimeLocation, 10.f);
glUniform1f(m_shellLifetimeLocation, 3.f);
glUniform1f(m_secondaryShellLifetimeLocation, 1.5f);

glEnable(GL_RASTERIZER_DISCARD);

glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[currVertBuffer]);
glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transFeedBackBuffers[currTransFeedBuffer]);

cout << "update bind buffer " << "particleBuffers" << " -> " << currVertBuffer << endl;
cout << "update bind TF " << "transFeedBackBuffers" << " -> " << currTransFeedBuffer << endl;

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);

glVertexAttribPointer(0, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), 0);                          // type
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)4);         // position
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)16);        // velocity
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(Particle), (const GLvoid*)28);          // lifetime

glBeginTransformFeedback(GL_POINTS);

if (firstParticles) {
    glDrawArrays(GL_POINTS, 0, 1);

    firstParticles = false;
}
else {
    glDrawTransformFeedback(GL_POINTS, transFeedBackBuffers[currVertBuffer]);
}

glEndTransformFeedback();

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);

glDisable(GL_RASTERIZER_DISCARD);

我没有在Draw 调用上花费太多时间。我最初的计划是绘制实例,这需要更多的研究,这就是为什么我试图让粒子模拟首先运行。

    shader->useShader();
    glBindBuffer(GL_ARRAY_BUFFER, particleBuffers[currTransFeedBuffer]);
glDrawTransformFeedback(GL_POINTS,transFeedBackBuffers[currTransFeedBuffer]);

    GLuint temp = currVertBuffer;
    currVertBuffer = currTransFeedBuffer;
    currTransFeedBuffer = temp;

我在调试这段代码时也遇到了麻烦,我用过

glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, transFeedBackBuffers[currTransFeedBuffer]); 
GLfloat feedback[20];
glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, sizeof(feedback), feedback);
cout << currTransFeedBuffer << "-------------"<< endl;
for (int i = 0; i < 20; i++) {
    cout << feedback[i] << " - ";
}
cout << endl;

要检查缓冲区数据,它似乎总是我在 init 中设置的一个元素,没有改变。

着色器类

Shader::Shader(const string& vertexShader, const string& geoShader, const string& fragmentShader)
: programHandle(0){
programHandle = glCreateProgram();

if (programHandle == 0) {
    cerr << "ERROR: Failed to create programm" << endl;
    system("PAUSE");
    exit(EXIT_FAILURE);
}

GLuint vertexHandle;
GLuint fragmentHandle;
GLuint geoHandle;

loadShader(vertexShader, GL_VERTEX_SHADER, vertexHandle);
loadShader(geoShader, GL_GEOMETRY_SHADER, geoHandle);
loadShader(fragmentShader, GL_FRAGMENT_SHADER, fragmentHandle);

glAttachShader(programHandle, vertexHandle);
glAttachShader(programHandle, fragmentHandle);
glAttachShader(programHandle, geoHandle);

const GLchar* Varyings[4];
Varyings[0] = "Type1";
Varyings[1] = "Position1";
Varyings[2] = "Velocity1";
Varyings[3] = "Age1";

glTransformFeedbackVaryings(programHandle, 4, Varyings, GL_INTERLEAVED_ATTRIBS);

glLinkProgram(programHandle);

}

垂直着色器

#version 330                                                                        

layout (location = 0) in float Type;                                                
layout (location = 1) in vec3 Position;                                             
layout (location = 2) in vec3 Velocity;                                             
layout (location = 3) in float Age;                                                 

out float Type0;                                                                    
out vec3 Position0;                                                                 
out vec3 Velocity0;                                                                 
out float Age0;                                                                     

void main()                                                                         
{                                                                                   
    Type0 = Type;                                                                   
    Position0 = Position;                                                           
    Velocity0 = Velocity;                                                           
    Age0 = Age;                                                                     
}

几何着色器

#version 330                                                                        

layout(points) in;                                                                  
layout(points) out;                                                                 
layout(max_vertices = 30) out;                                                      

in float Type0[];                                                                   
in vec3 Position0[];                                                                
in vec3 Velocity0[];                                                                
in float Age0[];                                                                    

out float Type1;                                                                    
out vec3 Position1;                                                                 
out vec3 Velocity1;                                                                 
out float Age1;                                                                     

#define PARTICLE_TYPE_LAUNCHER 0.0f                                                 

vec3 GetRandomDir(float TexCoord)                                                   
{                                                                                   
     return vec3(0.5, 0.5, 0.5);                                                                     
}                                

void main() {

        float Age = Age0[0] + gDeltaTimeMillis;

        Type1       = PARTICLE_TYPE_LAUNCHER;                                             
        Position1   = Position0[0];                                                   
        Velocity1   = Velocity0[0];                                                   
        Age1        = Age;                                                                 
        EmitVertex();                                                               
        EndPrimitive(); 

}   

也许我的隧道视野已经很强大了,但是我自己研究了很多 tuts、线程和示例,我没有弄错!我希望有人可以帮助我,问候!

4

0 回答 0