Lỗi khởi động đối tượng nhanh OpenGL


8

Tôi có một số mã lặp qua một tập hợp các đối tượng và biểu hiện các thể hiện của các đối tượng đó. Danh sách các đối tượng cần được hiển thị được lưu trữ dưới dạng std :: map>, trong đó một đối tượng của lớp GridResource chứa các đỉnh và chỉ mục với dữ liệu thực tế và một đối tượng của classMeshRenderer xác định điểm trong không gian mà lưới sẽ là kết xuất tại.

Mã kết xuất của tôi như sau:

glDisable(GL_BLEND);
    glEnable(GL_CULL_FACE);
    glDepthMask(GL_TRUE);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);

    for (std::map<MeshResource*, std::vector<MeshRenderer*> >::iterator it = renderables.begin(); it != renderables.end(); it++)
    {
        it->first->setupBeforeRendering();
        cout << "<";
        for (unsigned long i =0; i < it->second.size(); i++)
        {
            //Pass in an identity matrix to the vertex shader- used here only for debugging purposes; the real code correctly inputs any matrix.
            uniformizeModelMatrix(Matrix4::IDENTITY);
            /**
             * StartHere fix rendering problem.
             * Ruled out:
             *  Vertex buffers correctly.
             *  Index buffers correctly.
             *  Matrices correct?
             */
            it->first->render();
        }
        it->first->cleanupAfterRendering();
    }

    geometryPassShader->disable();
    glDepthMask(GL_FALSE);
    glDisable(GL_CULL_FACE);
    glDisable(GL_DEPTH_TEST);

Hàm trong MeshResource xử lý việc thiết lập đồng phục như sau:

void MeshResource::setupBeforeRendering()
{
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    glEnableVertexAttribArray(3);
    glEnableVertexAttribArray(4);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
    glBindBuffer(GL_ARRAY_BUFFER, vboID);

    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); // Vertex position
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 12); // Vertex normal
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 24); // UV layer 0
    glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 32); // Vertex color
    glVertexAttribPointer(4, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 44); //Material index
}

Mã làm cho đối tượng là thế này:

void MeshResource::render()
{
    glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}

Và mã làm sạch là đây:

void MeshResource::cleanupAfterRendering()
{
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    glDisableVertexAttribArray(3);
    glDisableVertexAttribArray(4);
}

Kết quả cuối cùng của việc này là tôi nhận được một màn hình đen, mặc dù phần cuối của đường dẫn kết xuất của tôi sau mã kết xuất (về cơ bản chỉ là vẽ trục và đường thẳng trên màn hình) hoạt động chính xác, vì vậy tôi khá chắc chắn rằng đó không phải là vấn đề với đi qua đồng phục. Tuy nhiên, nếu tôi thay đổi mã một chút để mã kết xuất gọi thiết lập ngay trước khi kết xuất, như vậy:

void MeshResource::render()
{
    setupBeforeRendering();
    glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}

Chương trình hoạt động như mong muốn. Tuy nhiên, tôi không muốn phải làm điều này vì mục đích của tôi là thiết lập dữ liệu đỉnh, vật liệu, v.v. một lần cho mỗi loại đối tượng và sau đó hiển thị mỗi phiên bản chỉ cập nhật thông tin chuyển đổi.

Đồng bộ hóaModelMatrix hoạt động như sau:

void RenderManager::uniformizeModelMatrix(Matrix4 matrix)
{
    glBindBuffer(GL_UNIFORM_BUFFER, globalMatrixUBOID);
    glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Matrix4), matrix.ptr());
    glBindBuffer(GL_UNIFORM_BUFFER, 0);
}

Tôi có một thiết lập gần như giống hệt nhau để hiển thị các mô hình của tôi. Ngoại trừ lệnh gọi kết xuất của tôi liên kết bộ đệm và đặt con trỏ thuộc tính mỗi lần. Bạn đang chạy vào vấn đề hiệu suất với điều này? Nó chạy rất nhanh đối với tôi.
MichaelHouse

Tôi đã không gặp phải vấn đề về hiệu năng trừ khi tôi có hàng trăm đối tượng giống hệt nhau trên màn hình, nhưng tôi vẫn không thể hiểu được chuyện gì đang xảy ra ở đây và thật tuyệt khi tìm hiểu lý do tại sao mã không hoạt động như mong đợi.
HJ Media Studios

1
Chúng ta chỉ cần thu hút sự chú ý của @NicolBolas, anh ấy là chuyên gia openGL thường trú.
MichaelHouse

Có thể là một ý tưởng tốt để sử dụng offsetofkhi chỉ định các thuộc tính đỉnh
JBeurer

Câu trả lời:


2

Trước hết, OpenGL chứa đầy những điều kỳ lạ nên lỗi trình điều khiển, tuy nhiên không chắc là như vậy, vẫn là một lựa chọn - xem xét thử nghiệm ứng dụng trên các thiết lập khác nhau (nVidia so với AMD, trình điều khiển cũ hơn) và các sửa đổi mã nhỏ khác. Ví dụ: bạn có thể bắt đầu bằng cách xóa "glBindBuffer (GL_UNIFORM_BUFFER, 0);" dòng - nó dường như không làm gì hữu ích.

Vì mọi thứ ở đây có vẻ đúng, nên vấn đề có lẽ không phải ở đây. Có hai tùy chọn: gDEBugger và chuyển qua mã trong trình gỡ lỗi C ++. Dường như một cái gì đó đang được thiết lập lại ngay trước khi vẽ. Trong gDEBugger, có một tính năng "lịch sử cuộc gọi" có thể giúp bạn xem các cuộc gọi nào được thực hiện trước cuộc gọi rút thăm và theo thứ tự nào.

Nhân tiện, tôi thực sự khuyên bạn nên bọc mọi cuộc gọi trả về lỗi bằng một macro để kiểm tra tất cả các lỗi có thể xảy ra và ném chúng. Nó phải là một macro để hỗ trợ gỡ lỗi mở rộng (in tệp, dòng và chính dòng mã bị lỗi) có thể bị vô hiệu hóa trong các bản dựng phát hành. Nếu một số quy tắc bí mật bị phá vỡ, thiết lập như vậy sẽ cảnh báo bạn về điều đó ngay lập tức.


5
Tôi sẽ tránh liên kết đến trang web Gremedy. Phiên bản gDEBugger đó là cổ xưa, không được hỗ trợ và rất có lỗi. developer.amd.com/tools/heterogeneous-computing/amd-gdebugger là phiên bản hỗ trợ AMD cập nhật, với sự hỗ trợ của Windows và Linux (không có OS X, không may). Ngoài ra còn có một số công cụ gỡ lỗi / hoàn hảo GL tuyệt vời khác trên trang web của AMD, chưa kể đến các công cụ mà NVIDIA và Intel cung cấp.
Sean Middleditch

0

Tôi khá chắc chắn rằng thuộc tính sẽ liên kết với bộ đệm hiện tại vì vậy không có lý do gì để làm lại doanh nghiệp này với các thuộc tính mỗi khung trừ khi bạn xây dựng lại bộ đệm mỗi lần ....

Vì vậy, bạn có thể nên làm theo cách này hay cách khác - hoặc để nó hoặc xây dựng lại toàn bộ mọi thứ.


0

TL; DR: Lỗi trình điều khiển.

Trong các thử nghiệm của tôi tính đến ngày hôm nay (tháng 10 năm 2016) bộ đệm đồng phục không được hỗ trợ đúng cách bởi hầu hết các trình điều khiển ngoài kia.

Một số người không tôn trọng glUniformBlockBindingmột số không cập nhật dữ liệu thống nhất ( glBufferSubDataglBufferData) một cách chính xác, trong đó các bản sao nội bộ của bộ đệm / GPU được lưu trong bộ đệm của các bộ đệm nói trên không được giữ mạch lạc.


Cách tôi hiểu nó (và cách Nvidia cũng hiểu nó)

  • Liên kết / Ánh xạ đối tượng bộ đệm thống nhất của bạn vào một bảng toàn cầu được chia sẻ bởi tất cả các trình đổ bóng bên trong trình điều khiển / GPU OpenGL bằng cách sử dụng glBindBufferBasehoặc glBindBufferRange.
  • Ánh xạ bộ đệm đồng nhất của shader truy cập vào một mục vào bảng toàn cầu đó bằng cách sử dụng glUniformBlockBinding(shader_id, shader_ubo_index, global_ubo_index);cài đặt này là cho mỗi chương trình đổ bóng , không được chia sẻ trên toàn cầu.

Lưu ý: global_ubo_index KHÔNG phải là tên của đối tượng bộ đệm thống nhất mà là một chỉ mục trong bảng toàn cầu đó.

"Sự phức tạp" này (là một tính năng tuyệt vời để chia sẻ UBO giữa các shader khác nhau, chẳng hạn như giá trị ánh sáng) dường như là điều mà hầu hết các trình điều khiển OpenGL gặp phải. Để công bằng, từ ngữ trong tài liệu OpenGL không phải là từ rõ ràng nhất có thể.

Tôi đã phải dùng đến việc sử dụng đồng phục cũ đơn giản cho những người lái xe khác.

Cả hai ảnh chụp màn hình sử dụng các đối tượng bộ đệm thống nhất, hai trình điều khiển khác nhau:

Lỗi đệm đồng phục


Những trình điều khiển bạn đã kiểm tra với? Nền tảng gì?
bất thường
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.