OpenGL Transform обратная связь сделана правильно на Android

Я изо всех сил пытался создать рабочую обратную связь обратной связи на Android. До сих пор наиболее близкая проблема, с которой я столкнулся, была похожа на этот недооцененный вопрос: https://stackru.com/questions/41066101/transform-feedback-altering-render-result

Что я хочу создать:

Рендеринг из буфера объекта вершины в обратную связь преобразования. Затем выполните рендеринг из буфера обратной связи преобразования с помощью финального чертежного шейдера.

Как я понимаю всю эту концепцию:

Я понимаю, как программа связана с изменениями (я следовал этому примеру: https://gist.github.com/hpp/d2d26adc5987002eb520) На Android вы должны предоставить "фиктивный" фрагментный шейдер, в противном случае программа связывает потерпит неудачу без сообщения.

После того, как у вас есть связанная программа, это следующие шаги: (код в java)

  1. Создать VBO для чтения данных из

    int[] vbo = new int[1];
    glGenBuffers(1, vbo, 0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glBufferData(GL_ARRAY_BUFFER, bufferLength, data, GL_STATIC_READ);
    
  2. Создать буфер обратной связи преобразования

    int[] tbo = new int[1];
    glGenBuffers(1, tbo, 0);
    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo[0]);
    glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferLength, null, GL_DYNAMIC_COPY);
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo[0]);
    
  3. Каждый раз, когда я хотел бы сделать свои вычисления, я называю что-то вроде этого:

    glUseProgram(calculationShaderProgram);
    // For all input variables:
    glEnableVertexAttribArray(inputAttrib);
    glVertexAttribPointer(...
    
    // To bind the transform feedback buffer as the destination
    glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfo[0]);
    
    glEnable(GL_RASTERIZER_DISCARD);
    glBeginTransformFeedback(GL_POINTS);
    glDrawArrays(GL_POINTS, 0, vertexCount);
    glEndTransformFeedback();
    glDisable(GL_RASTERIZER_DISCARD);
    
    glFinish(); // I know this is slow to call, but for simplicity's sake
    
  4. После этого я смогу нарисовать содержимое буфера:

    glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo[0]);
    
    glUseProgram(drawShaderProgram);
    // For all input variables:
    glEnableVertexAttribArray(inputAttrib);
    glVertexAttribPointer(...
    
    // Set uniforms ...
    glDrawArrays(GL_POINTS, 0, vertexCount); // There is no glDrawTransformFeedback on android
    

Теперь мои вопросы:

  • Есть ли что-то по сути неправильно в этом процессе?
  • Есть ли какая-то причина, по которой часть вычислений портит экран моего устройства, даже если я ничего не рисую? (Он показывает случайные цвета или значки, обновляемые Android, такие как батарея и сеть)
  • Использует ли объект массива вершин то же самое с GL_TRANSFORM_FEEDBACK_BUFFER, как и с GL_ARRAY_BUFFER?

1 ответ

Это заняло некоторое время, но вот решение. Я оставлю это здесь, потому что эти части не были объяснены должным образом ни в одной доступной книге, связанной с OpenGL.

  1. При рисовании из буфера обратной связи преобразования (шаг 4 выше), не имеет значения, работает ли он как буфер обратной связи преобразования, вы должны привязать его как GL_ARRAY_BUFFER, точно так же, как вы рисовали бы из объекта буфера вершин.

    glBindBuffer(GL_ARRAY_BUFFER, tbo[0]);
    
  2. При использовании кадрового буфера по умолчанию,

    glBindFrameBuffer(GL_FRAMEBUFFER, 0);
    

    или нет настройки вообще, вы не можете использовать

    glEnable(GL_RASTERIZER_DISCARD);
    // Draw to Transform feedback
    // ...
    glDisable(GL_RASTERIZER_DISCARD);
    

    (на шаге 3) без предварительного вызова

    glClear(GL_COLOR_BUFFER_BIT);
    

    в противном случае вы увидите случайные узоры в качестве фона. Одного glClear перед каждым циклом отрисовки недостаточно.

Другие вопросы по тегам