Вычислить шейдерную форму, оптимизированную неправильно? - PullRequest
0 голосов
/ 19 декабря 2018

Получение местоположения однородных «однородных сферных сфер [10]» (через glGetUniformLocation (программа, имя)).Возвратите -1, даже если в программе есть другие униформы (frustum_planes), которые работают.

Формы frustum_planes и сферы также используются в тех же местах, что делает странным, что присутствует только одна из двух.

Есть идеи, что может пойти не так?

Шейдер

#version 460 core
// Required by compute shaders apparently
// Process one object per shader invocation (optimisation?)
layout (local_size_x = 1) in;

struct Sphere {
    vec3 center;
    float radius;
};

uniform Sphere spheres[10];

// Plane defined as: Ax + By + Cz = D
uniform vec4 frustum_planes[6];

uint test(Sphere obj, vec4 plane) {
    const float distance = plane.x * obj.center.x + plane.y * obj.center.y + plane.z * obj.center.z + plane.w;
    if (distance < -obj.radius) {
        return 0; // Negative halfspace
    }
    return 1; // Positive halfspace or on the plane
}

/// Same as the OpenGL provided struct: DrawElementsIndirectCommand
struct DrawCommand {
    uint count; // Num elements (vertices)
    uint instanceCount; // Number of instances to draw (a.k.a primcount)
    uint firstIndex; // Specifies a byte offset (cast to a pointer type) into the buffer bound to GL_ELEMENT_ARRAY_BUFFER to start reading indices from.
    uint baseVertex; // Specifies a constant that should be added to each element of indices​ when chosing elements from the enabled vertex arrays.
    uint baseInstance; // Specifies the base instance for use in fetching instanced vertex attributes.
    // 20 bytes
    uint padding0;
    uint padding1;
    uint padding2;
    // 32 bytes (multiple of 16)
};

// One draw command per object 
// Command buffer backed by Shader Storage Object Buffer (SSBO)
layout(std140, binding = 0) writeonly buffer DrawCommandsBlock {
    DrawCommand draw_commands[];
};

void main() {
    const uint idx = gl_GlobalInvocationID.x;

    uint inside = 0; 
    for (int i = 0; i < 6; i++) {
        inside += test(spheres[idx], frustum_planes[i]) << i;
    }

    const uint INSIDE_ALL_PLANES = 63; // = 0b111111;
    const bool visible = inside == INSIDE_ALL_PLANES;
    draw_commands[idx].count = 25350; // sphere.indices.size();
    draw_commands[idx].instanceCount = visible ? 1 : 0; // This is the trick right here
    draw_commands[idx].baseInstance = 0;
    draw_commands[idx].baseVertex = 0;
    draw_commands[idx].padding0 = 0; // Avoid optimisation 
    draw_commands[idx].padding1 = 0;
    draw_commands[idx].padding2 = 0;
}

Рабочий вызов glGetUniformLocation

glGetUniformLocation(gl_state.cull_shader.gl_program, "spheres[0].center");

main.cpp

  glUseProgram(gl_state.cull_shader.gl_program);
  if (glGetUniformLocation(gl_state.cull_shader.gl_program, "frustum_planes") == -1) {
    std::cerr << "Work!" << std::endl;
  }
  if (glGetUniformLocation(gl_state.cull_shader.gl_program, "spheres") == -1) {
    std::cerr << "Does not work?!" << std::endl;
  }
  glUniform4fv(glGetUniformLocation(gl_state.cull_shader.gl_program, "spheres"), NUM_OBJECTS, &bounding_volumes[0].pos.x);
  glUniform4fv(glGetUniformLocation(gl_state.cull_shader.gl_program, "frustum_planes"), 6, glm::value_ptr(frustum[0]));
  glDispatchCompute(NUM_OBJECTS, 1, 1);
  glMemoryBarrier(GL_COMMAND_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT); // Buffer objects affected by this bit are derived from the GL_DRAW_INDIRECT_BUFFER binding. 

1 Ответ

0 голосов
/ 19 декабря 2018

Невозможно запросить расположение униформ, которые не являются базовыми типами или массивами базовых типов. OpenGL Wiki заявляет:

API самоанализа часто заставляют одно определение «переменной» в GLSL выглядеть так, как если бы это было несколько переменных.Это делается для переменных, которые не являются базовыми типами или массивами базовых типов (обратите внимание, что в GLSL «базовые типы» включают в себя векторные и матричные типы).

...

Вместо этого каждыйподэлемент структуры, который является базовым типом, является видимым.

Это означает, что вы не можете запрашивать spheres (или spheres[0]).Что вам нужно сделать, это запросить каждого члена каждой структуры в отдельности.Чтобы получить местоположение первого центра Сферы, вам нужно запросить spheres[0].center.

Обратите внимание, что запрос frustum_planes работает, как и ожидалось, потому что это массив vec4 (который являетсябазовый тип).

...