Я пишу фрагмент кода, который будет проверять все точки данных на объем столкновения, используя вычислительный шейдер. Если точка находится внутри объема столкновения, она меняет метку на 1, в противном случае она остается равной 0.
Мой подход состоит в том, чтобы иметь два буфера, один из которых содержит все вершины, а другой буфер содержит все метки в порядке вершин. Затем в каждой рабочей группе вычислительный шейдер будет обрабатывать точку с индексом X и соответствующим образом устанавливать метку с индексом X.
Однако результат странный, он изменил некоторые метки на 1, но не те, которые находятся внутри поля столкновения, он разбросан вокруг каждой части целых точек данных... Я почти уверен, что обнаружение столкновения и ограничивающие поля переданы в с шейдерами все в порядке, они работают во всех других частях программы с тем же форматом точек, может ли это быть из-за того, что порядок выполнения рабочей группы вычислительных шейдеров совершенно случайный?
Я очень благодарен всем, кто может взглянуть на это... это был мой кошмар последние 3 дня...
Сначала в моем коде C++ я выделял и назначал буферы следующим образом:
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo); // vertices
glGenBuffers(1, &cbo); // colors
glGenBuffers(1, &lbo); // labels
glGenBuffers(1, &ssvbo); // shader storage vbo for compute shader
glGenBuffers(1, &sslbo); // shader storage lbo for compute shader
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssvbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(float) * vertices.size() * 3, &vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, sslbo);
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(int) * labels.size(), &labels[0], GL_STATIC_DRAW);
glBindVertexArray(vao);
// Vertices
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * vertices.size() * 3, &vertices[0], GL_STATIC_DRAW); // xyz
// set attribute for the first argument
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); // pos
glBindBuffer(GL_ARRAY_BUFFER, cbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * colors.size() * 3, &colors[0], GL_STATIC_DRAW); // rgb
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0); //color
glBindBuffer(GL_ARRAY_BUFFER, lbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(int) * labels.size(), &labels[0], GL_STATIC_DRAW);
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 1, GL_INT, GL_FALSE, sizeof(GLint), (GLvoid*)0); // label
// illustration : 1 1 1 1 1 1 1
// name: |pos | clr | label
// location: | 0 | 1 | 2
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
И вот как я запускаю программу вычислительного шейдера,
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m->ssvbo);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 5, m->sslbo);
glUseProgram(compute_label_program);
GLint vNormals = glGetUniformLocation(compute_label_program, "normals");
GLint vPts = glGetUniformLocation(compute_label_program, "pts");
glUniform3fv(vNormals, 6, &norms[0].x);
glUniform3fv(vPts, 8, &pt[0].x);
glDispatchCompute(static_cast<int>(m->vertices.size()) / WORK_GROUP_SZ + 1, 1, 1);
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
// now, assume the above code changed the labels in sslbo, copy the sslbo,ssvbo values back to client
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m->sslbo);
m->labels.clear();
m->labels.resize(m->vertices.size());
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(int) * m->vertices.size(), &m->labels[0]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, m->ssvbo);
m->vertices.clear();
m->vertices.resize(m->labels.size());
glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(point) * m->vertices.size(), &m->vertices[0]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
// re-upload labels buffer
m->UpdateBuffers();
А это код вычислительного шейдера,
#version 430 compatibility
#extension GL_ARB_compute_shader : enable
#extension GL_ARB_shader_storage_buffer_object : enable
layout (std140, binding = 4) readonly buffer Position
{
vec3 pos[];
};
layout (std140, binding = 5) writeonly buffer Label
{
int label[];
};
layout (local_size_x = 128, local_size_y = 1, local_size_z = 1) in;
uniform vec3 normals[6];
uniform vec3 pts[8];
bool Oobb(in vec3 norms[6], in vec3 pt[8], in vec3 po)
{
// some collision checking code
}
void main()
{
uint gid = gl_GlobalInvocationID.x;
if(Oobb(normals, pts, pos[gid].xyz))
label[gid] = 1;
}