В настоящее время мы работаем над системой частиц GPU. Что-то в моей реализации не так, похоже, что буферы не обновляются и не обращаются к ним.
Буду очень признателен за любую помощь!
Система частиц init:
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 call. Мой первоначальный план состоял в том, чтобы рисовать инстансы, мне нужно больше исследований для этого, поэтому я попытался запустить симуляцию частиц в первую очередь.
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;
}
GeometryShader:
#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();
}
Может быть, мое туннельное зрение уже слишком сильное, но я работал над множеством примеров, тем и примеров, я не понимаю, в чем дело!
Я надеюсь, что кто-то может помочь мне, привет!
Задача ещё не решена.
Других решений пока нет …