Tôi đang cố gắng tạo một công cụ trò chơi 2D bằng OpenGL ES 2.0 (iOS bây giờ). Tôi đã viết lớp Ứng dụng trong Mục tiêu C và một RendererGLES20 riêng chứa trong C ++. Không có cuộc gọi cụ thể GL được thực hiện bên ngoài trình kết xuất. Nó đang hoạt động hoàn hảo.
Nhưng tôi có một số vấn đề thiết kế khi sử dụng shader. Mỗi shader có các thuộc tính và đồng phục riêng cần được đặt ngay trước lệnh gọi rút thăm chính (glDrawArrays trong trường hợp này). Ví dụ, để vẽ một số hình học tôi sẽ làm:
void RendererGLES20::render(Model * model)
{
// Set a bunch of uniforms
glUniformMatrix4fv(.......);
// Enable specific attributes, can be many
glEnableVertexAttribArray(......);
// Set a bunch of vertex attribute pointers:
glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, m->pCoords);
// Now actually Draw the geometry
glDrawArrays(GL_TRIANGLES, 0, m->vertexCount);
// After drawing, disable any vertex attributes:
glDisableVertexAttribArray(.......);
}
Như bạn có thể thấy mã này là vô cùng cứng nhắc. Nếu tôi sử dụng một shader khác, giả sử hiệu ứng gợn, tôi sẽ cần phải truyền thêm đồng phục, attribs đỉnh, v.v. Nói cách khác, tôi sẽ phải thay đổi mã nguồn kết xuất RendererGLES20 chỉ để kết hợp với shader mới.
Có cách nào để làm cho đối tượng shader hoàn toàn chung chung không? Giống như Điều gì xảy ra nếu tôi chỉ muốn thay đổi đối tượng đổ bóng và không lo lắng về việc biên dịch lại nguồn trò chơi? Bất kỳ cách nào để làm cho trình kết xuất không biết về đồng phục và thuộc tính, v.v.? Mặc dù chúng ta cần truyền dữ liệu cho đồng phục, đâu là nơi tốt nhất để làm điều đó? Lớp người mẫu? Là lớp mô hình nhận thức về đồng phục và thuộc tính cụ thể của shader?
Chương trình sau đây Lớp diễn viên:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
Lớp trình điều khiển mô hình: lớp ModelContoder {class IShader * shader; int textureId; vec4 tint; phao alpha; cấu trúc Vertex * vertexArray; };
Lớp shader chỉ chứa đối tượng shader, biên dịch và liên kết các thường trình con, v.v.
Trong lớp Game Logic tôi thực sự kết xuất đối tượng:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
Xin lưu ý rằng mặc dù Diễn viên mở rộng ISceneNode, tôi vẫn chưa bắt đầu triển khai SceneGraph. Tôi sẽ làm điều đó ngay khi tôi giải quyết vấn đề này.
Bất kỳ ý tưởng làm thế nào để cải thiện điều này? Mẫu thiết kế liên quan vv?
Cảm ơn bạn đã đọc câu hỏi.