用于独立于api的顶点处理的良好代码结构是什么? [英] What is a good code structure for api-independent vertex processing?

查看:93
本文介绍了用于独立于api的顶点处理的良好代码结构是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前正在使用C#开发3D媒体引擎,我遇到了一个小难题.我已经弄清楚了我的借出循环,有了一个很棒的插件体系结构和内容管理系统,甚至还计划了一个物料管道.然后,引擎计划使用DirectX和OpenGL(通过渲染器"插件),以及两个API的可编程管道.

Currently working on a 3D media engine using C# and I have come across a little conundrum. I have my rending loop figured out, I got a great plug-in architecture and content management system and even a material pipeline all planned out. Then engine is planned to use DirectX and OpenGL (via 'renderer' plug-ins), along with both APIs' programmable pipe-line.

无论如何,在本周初,我开始研究引擎抽象层以处理顶点(我已经对此感到恐惧了几周了).众所周知,图形API之间的顶点处理根本不相关或不相同.有点相关;),但是不一样.在OpenGL中,处理顶点非常简单明了,您可以创建自定义顶点结构,将其发送到GPU,然后让着色器处理其余部分.这对于灵活的图形管线来说是完美的,不需要OpenGL知道每个顶点包含哪些元素.另一方面,DirectX要求我们为每个顶点结构创建声明,然后将它们发送到GPU.

Anyways, at the beginning of this week I started on working on the engines abstract layer for processing vertices (I have been dreading this for weeks now). And as some of you know, vertex handling between graphic APIs' is not at all related or the same. Well kinda related ;), but not the same. In OpenGL handling vertices is very straight-forward, you create the custom vertex structure, send it to the GPU and then let your shaders handle the rest. This is perfect for a flexible graphics pipe-line, OpenGL is not required to know what elements are contained with each vertex. DirectX on the other-hand requires us to create declarations for each vertex structure and then send them to the GPU.

问题是我不知道要传递哪种类型的顶点结构,并且我绝对希望避免创建抽象层,该抽象层涉及通过枚举和一些抽象的'VertexDeclaration'类来声明顶点的每个元素;这会引起一些问题:

The issue is that I will not know what type of vertex structure is being passed and I would definitely like to avoid creating the abstraction layer that involves declaring each element of a vertex through enumerations and some abstract 'VertexDeclaration' class; this would cause some issues:

1)至少可以说,获得顶点元素将是一件痛苦的事情.我可以使用一些'VertexSemantic'并请求顶点'a-z'的位置,但是当为诸如骨骼动画之类的东西处理很多顶点时,会产生很多开销.

1) Getting vertex elements will be a pain to say the least. I could use some 'VertexSemantic' and ask for the positions of vertex 'a - z', but when processing a lot of vertices for something like skeletal animation, it can have a lot of overhead.

2)考虑到引擎的主要关注点是新手",因此不太友好.我希望用户能够创建自定义的顶点和网格缓冲区,而不必声明大量的对象,这会浪费宝贵的开发时间.

2) Not very user-friendly considering the engines' main focus is 'newbies'. I would like for users to be able to create custom vertices and mesh buffers, without having to declare a ton of objects, consuming valuable development time.

3)还有?

现在,我可以对属性做一些事情,然后在DirectX渲染器中为顶点结构创建声明.例如,继续创建一些枚举:

Now I could do something with attributes and then create declarations for vertex structures inside the DirectX renderer. For instance, go ahead and create some 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
}

现在,我可以创建一个属性,用户可以将其应用于其顶点结构中每个元素的字段":

Now I can create an attribute that users can apply to the 'fields' of each element in their vertex structure:

    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
    }

自定义顶点结构的示例:

An example of what a custom vertex structure could look like:

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
}

这很好.在DirectX插件(渲染器)中,我可以创建一个实用程序类,该类可以为每种结构类型创建语义,然后缓存数据,因此不必为每个顶点重新创建声明.

This would be nice. In the DirectX plug-in (renderer) I could just create a utility class that can create the semantics for each structure type and then cache the data so the declarations don't have to be recreated for each vertex.

我什至可以在ELementUsage中添加一个NONE枚举值,这样自定义值就可以用于……意味着,但是它们只能在OpenGL中使用,因为DirectX要求您标记每个顶点...除非存在我缺少的东西.

I could even add a NONE enumeration value to ELementUsage so that custom values may be used for what ever means... but then again they would only work in OpenGL because DirectX requires you to mark each vertex... unless there is something I am missing.

我的问题:

是否有更好的方法(除了使用Attirbutes以外)? 有没有一种方法可以避免在DirectX中使用VertexDeclarations? 关于我的"问题,您可能不了解任何事情吗?

Is there a better way to go about this (besides using the attirbutes)? Is there a way to avoid using VertexDeclarations in DirectX? Is there any thing you may not understand about 'my' question?

使用属性的问题是从每个顶点获取元素数据.假设我想获取网格缓冲区中每个顶点的位置.因为我使用了属性,所以我不能只做'vertex.Position',我将不得不创建一个实用程序方法,该方法可以从顶点结构中提取字段引用,例如'Utility.GetElement(vertex,ElementUsage.POSITION)' .此方法将需要使用反射来首先找到属性,然后将引用返回到字段值. (我认为)无法设置该值?

An issue with using attributes would be getting element data from each vertex. Say I wanted to get the positions of each vertex in a mesh buffer. Since I went with attributes, I can't just do 'vertex.Position', I would have to create a utility method that could extract a field reference from a vertex structure, like 'Utility.GetElement(vertex, ElementUsage.POSITION)' . This method would need to use reflection to first find the attribute, then return the reference to the field value. Setting the value would not even (i think) be possible?

另一种方法是创建一个IElement接口并实现每个元素(Positon,Normal等).接口可能具有Name属性,我可以直接在继承的元素结构内返回该属性,例如PositionElements的Name属性将仅返回"Positon".

Another way would be to create an IElement interface and implement each element (Positon, Normal, etc). The interface could have Name property that I can return directly inside the inherited element structure, like the PositionElements' Name property would just return "Positon".

接下来,我可以将IElement数组保留在Vertex结构的内部,该结构包含诸如AddElement(IElement),GetElement(字符串名称),GetElement(int索引),Insert,Replace等方法.我将实现DirectX已知的所有元素以便渲染器插件可以解析顶点结构以创建顶点声明数组.

Next I could hold the array of IElement indside a Vertex struct that contains methods like AddElement(IElement), GetElement(string name), GetElement(int index), Insert, Replace, etc. I would implement all elements known to DirectX so that the renderer plug-in could parse a vertex structure to create an array of vertex declarations.

问题是我不确定数组'[]'是否可以用作顶点元素数据.例如,数组包含的其他哪些字节(如果有)会阻止我将Vertex结构(包含IElement数组)直接传递给DirectX,然后传递给GPU?

The issue with this is that I am not sure if an array '[]' can be used as vertex element data. Like, what other bytes does an array contain (if any) that would hinder me from passing the Vertex struct (contains the IElement array) directly to DirectX, then to the GPU?

以这种方式实施对于我所需要的是绝对完美的.另一个问题是IElement(元素)的继承类型是一个类,还是元素值必须是值类型?

Implementing it this way would be absolutely perfect for what I need it for. Another question is could the inheriting types of IElement (the elements) be a class, or do element values have to be value-types?

推荐答案

我做过Directx或opengl已有很长的时间了,所以请带着一点建议,但我记得做过 这样的东西.

It has been a long time since I've done any directx or opengl, so take my advice with a grain of salt, but I remember doing something like this a while ago.

我认为我做了这样的事情:

I think I did something like this:

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);

您将拥有一个图形流,该图形流是一组应用了用法的类型化数据集.由此可以生成适当的顶点格式.该API可让您一次更改单个元素或上传并替换整个顶点缓冲区.

You'd have a graphics stream which was a set of typed data sets with a usage applied. From this you can generate an appropriate vertex format. The API would let you change individual elements or upload and replace the entire vertex buffer in one go.

最大的缺点是,您的顶点结构中没有一种表示列"的结构.

The biggest downside is that you don't have one structure that represents a "column" in your vertex structure.

我不知道这是否是您要找的东西.为什么这样的设计不合适?

I don't know if this is the kind of thing you're looking for. Why would a design like this not be appropriate?

这篇关于用于独立于api的顶点处理的良好代码结构是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆