2010-02-03 38 views
12

Hiện đang làm việc trên một phương tiện truyền thông 3D bằng cách sử dụng C# và tôi đã gặp một câu hỏi nhỏ. Tôi có vòng lặp rending của tôi đã tìm ra, tôi có một kiến ​​trúc plug-in tuyệt vời và hệ thống quản lý nội dung và thậm chí cả một đường ống dẫn vật liệu đã được lên kế hoạch. Sau đó, động cơ được lên kế hoạch sử dụng DirectX và OpenGL (thông qua plug-in 'renderer'), cùng với cả hai đường ống có thể lập trình của API.Cấu trúc mã tốt cho xử lý đỉnh độc lập api là gì?

Dù sao thì, vào đầu tuần này, tôi bắt đầu làm việc trên lớp trừu tượng của động cơ để xử lý các đỉnh (Tôi đã dò tìm điều này trong nhiều tuần nay). Và như một số bạn biết, việc xử lý đỉnh giữa các API đồ họa 'không hề có liên quan hoặc giống nhau. Vâng kinda liên quan;), nhưng không giống nhau. Trong các đỉnh xử lý OpenGL rất thẳng về phía trước, bạn tạo cấu trúc đỉnh tùy chỉnh, gửi nó tới GPU và sau đó để các trình đổ bóng của bạn xử lý phần còn lại. Điều này là hoàn hảo cho một đường ống đồ họa linh hoạt, OpenGL không bắt buộc phải biết những gì các yếu tố được chứa với mỗi đỉnh. Mặt khác, DirectX yêu cầu chúng tôi tạo các khai báo cho mỗi cấu trúc đỉnh và sau đó gửi chúng đến GPU.

Vấn đề là tôi sẽ không biết loại cấu trúc đỉnh nào đang được chuyển và tôi chắc chắn muốn tránh tạo lớp trừu tượng liên quan đến việc khai báo từng phần tử của đỉnh thông qua liệt kê và một số lớp 'VertexDeclaration' trừu tượng; điều này sẽ gây ra một số vấn đề:

1) Bắt các yếu tố đỉnh sẽ là một nỗi đau để nói rằng ít nhất. Tôi có thể sử dụng một số 'VertexSemantic' và yêu cầu các vị trí của đỉnh 'a - z', nhưng khi xử lý rất nhiều đỉnh cho một cái gì đó giống như hoạt hình xương, nó có thể có rất nhiều chi phí.

2) Không thân thiện với người dùng khi xem trọng tâm chính của động cơ là 'người mới'. Tôi muốn cho người dùng có thể tạo ra các đỉnh tùy chỉnh và bộ đệm lưới, mà không cần phải khai báo một tấn các đối tượng, tiêu tốn thời gian phát triển có giá trị.

3) nhiều hơn?

Bây giờ tôi có thể làm điều gì đó với các thuộc tính và sau đó tạo các khai báo cho các cấu trúc đỉnh bên trong trình kết xuất DirectX. Ví dụ, đi trước và tạo ra một số enums:

// for getting the format layout of the element 
public enum ElementFormat 
{ 
    Float, Float2, Float3, Byte, etc, etc 
} 
// for determining the 'usage' 
// (here is 'another' where DirectX limits vertex structures ><) 
public enum ElementUsage 
{ 
    Position, Normal, Color, TextureCoord, etc, etc 
} 

Bây giờ tôi có thể tạo ra một thuộc tính mà người dùng có thể áp dụng đối với các 'lĩnh vực' của mỗi yếu tố trong cấu trúc đỉnh của họ:

public class VertexElementAttribute : Attribute 
    { 
     #region Properties 
     /// <summary> 
     /// Gets the total size (in bytes) of the element. 
     /// </summary> 
     public int Size 
     { 
      get; 
      set; 
     } 
     /// <summary> 
     /// Gets the number of values contained with-in the element. 
     /// </summary> 
     public int Count 
     { 
      get; 
      set; 
     } 
     /// <summary> 
     /// Gets the type semantic of the element. 
     /// </summary> 
     public ElementType Type 
     { 
      get; 
      set; 
     } 
     /// <summary> 
     /// Gets the usage semantic of the element. 
     /// </summary> 
     public ElementUsage Usage 
     { 
      get; 
      set; 
     } 
     #endregion 

     #region Init 
     /// <summary> 
     /// Creates a new vertex element attribute. 
     /// </summary> 
     /// <param name="count">The number of values contained within the element.</param> 
     /// <param name="size">The total size (in bytes) of the element.</param> 
     /// <param name="type">The type semantic of the element.</param> 
     /// <param name="usage">The usage semantic of the element.</param> 
     public VertexElementAttribute(int count, int size, ElementType type, ElementUsage usage) 
     { 
      Count = count; 
      Size = size; 
      Type = type; 
      Usage = usage; 
     } 
     #endregion 
    } 

Một ví dụ về cấu trúc đỉnh tùy chỉnh có thể trông như thế nào:

public struct VertexPositionColor 
{ 
    [VertexElement(3, sizeof(Vector3), ElementType.FLOAT3, ElementUsage.POSITION)] 
    public Vector3 Xyz; 
    [VertexElement(4, sizeof(Color), ElementType.FLOAT4, ElementUsage.COLOR)] 
    public Color Rgba; 

    ... etc 
} 

Điều này sẽ rất tuyệt. Trong trình cắm thêm DirectX (trình kết xuất đồ họa), tôi có thể tạo một lớp tiện ích có thể tạo ngữ nghĩa cho từng loại cấu trúc và sau đó lưu trữ dữ liệu để các khai báo không phải được tạo lại cho mỗi đỉnh.

Tôi thậm chí có thể thêm giá trị NONE liệt kê vào ELementUsage để giá trị tùy chỉnh có thể được sử dụng cho những gì có nghĩa ... nhưng sau đó lại chỉ hoạt động trong OpenGL vì DirectX yêu cầu bạn đánh dấu từng đỉnh ... trừ khi có là thứ tôi đang thiếu.

(Các) câu hỏi của tôi:

Có cách nào tốt hơn để thực hiện việc này (ngoài việc sử dụng attirbutes) không? Có cách nào để tránh sử dụng VertexDeclarations trong DirectX không? Có điều gì bạn có thể không hiểu về câu hỏi 'của tôi' không?

CHỈNH SỬA:

Sự cố khi sử dụng thuộc tính sẽ lấy dữ liệu phần tử từ mỗi đỉnh. Nói rằng tôi muốn có được vị trí của mỗi đỉnh trong một bộ đệm lưới. Vì tôi đã đi với các thuộc tính, tôi không thể chỉ làm 'vertex.Position', tôi sẽ phải tạo ra một phương thức tiện ích có thể trích xuất một tham chiếu trường từ một cấu trúc đỉnh, như 'Utility.GetElement (vertex, ElementUsage.POSITION)' . Phương thức này sẽ cần sử dụng sự phản chiếu để tìm thấy thuộc tính đầu tiên, sau đó trả về tham chiếu đến giá trị trường. Thiết lập giá trị thậm chí sẽ không (tôi nghĩ) có thể?

Một cách khác là tạo giao diện IElement và triển khai từng phần tử (Positon, Normal, v.v.). Giao diện có thể có thuộc tính Name mà tôi có thể quay trở lại trực tiếp bên trong cấu trúc phần tử thừa kế, như thuộc tính NameElements 'Name sẽ chỉ trả về "Positon".

Tiếp theo, tôi có thể giữ mảng IElement bên cạnh một cấu trúc Vertex chứa các phương thức như AddElement (IElement), GetElement (tên chuỗi), GetElement (int index), Insert, Replace, v.v. DirectX để trình kết xuất trình cắm thêm có thể phân tích một cấu trúc đỉnh để tạo ra một mảng các khai báo đỉnh.

Vấn đề với điều này là tôi không chắc chắn nếu một mảng '[]' có thể được sử dụng làm dữ liệu phần tử đỉnh. Giống như, những byte khác có một mảng chứa (nếu có) sẽ cản trở tôi vượt qua cấu trúc Vertex (chứa mảng IElement) trực tiếp đến DirectX, sau đó đến GPU?

Triển khai theo cách này sẽ hoàn toàn hoàn hảo cho những gì tôi cần. Một câu hỏi khác là các kiểu kế thừa của IElement (các phần tử) có phải là một lớp hay các giá trị phần tử có phải là các kiểu giá trị không?

+2

Tôi khuyên bạn nên xem xét cách XNA thực hiện điều đó. – Foole

+0

Tôi có, nó sử dụng một cái gì đó tương tự như directX ... không có sự khác biệt thực sự. Một khi tôi đã tìm ra cho trình kết xuất DirectX của chúng tôi, Xna sẽ dễ dàng như vậy. Tôi sẽ nhìn lại bất cứ điều gì tôi đã bỏ lỡ, cảm ơn :). –

+0

Nhìn vào Xna và nó tương tự như DirectX: (.. vì vậy không có sự giúp đỡ ở đó. –

Trả lời

1

Đã lâu rồi kể từ khi tôi thực hiện bất kỳ điều khoản trực tiếp nào, vì vậy hãy lấy lời khuyên của tôi với một hạt muối, nhưng tôi nhớ đã làm một cái gì đó như thế này một thời gian trước đây.

Tôi nghĩ rằng tôi đã làm một cái gì đó như thế này:

var graphicsStream = new GraphicsStream(); 

var elements = graphicsStream.Create<Vector3>(Usage.Position); 
graphicsStream.Create<Color>(Usage.Color); 
graphicsStream.Create<Quaternion>(Usage.Fribble); 

elements.SetData(new[] { new Vector3(), new Vector3() }); 

var vertexFormat = graphicsStream.GetFormat(); 
graphicsStream.Validate(); // ensure all the streams have the same length 

// get a particular element by type 
var p = graphicsStream.GetData(Usage.Position, 1); 

Bạn muốn có một dòng đồ họa mà là một tập hợp các tập hợp dữ liệu đánh máy với việc sử dụng áp dụng. Từ đó bạn có thể tạo ra một định dạng đỉnh thích hợp. API sẽ cho phép bạn thay đổi các phần tử riêng lẻ hoặc tải lên và thay thế toàn bộ bộ đệm đỉnh trong một lần.

Nhược điểm lớn nhất là bạn không có một cấu trúc đại diện cho "cột" trong cấu trúc đỉnh của bạn.

Tôi không biết đây có phải là thứ bạn đang tìm kiếm không. Tại sao một thiết kế như thế này không phù hợp?

+0

Đã quá lâu rồi tôi biết, nhưng câu trả lời của bạn là chính xác và mẫu của bạn có thể dễ dàng được điều chỉnh để phù hợp với chính tôi .... Không rằng nó cần thiết nữa xD. Dù sao cũng cảm ơn. –

+0

Bạn được chào đón =) – jonnii

1

Bạn có thể xem cách OGRE xử lý việc này. Cụ thể là The render system documentation về VertexElement và cũng là vertex buffer classes. OGRE là C++ nhưng tôi chắc chắn bạn sẽ có thể nhận được các mẫu thiết kế dễ dàng chuyển đổi thành C#.

Các vấn đề liên quan