gpt4 book ai didi

c++ - D3D11 : Rotating Multiple Triangles

转载 作者:太空狗 更新时间:2023-10-29 21:23:21 25 4
gpt4 key购买 nike

我是 DirectX 的新手,我在理解一些我认为的基础知识时遇到了一些问题。假设我有 10 个三角形,我想以不同的速率旋转每个三角形,以便它们随着时间的推移“旋转”。

到目前为止,我的三角形出现了,但我不太明白如何单独旋转它们。据我所知,我会为每个三角形做这样的事情吗?

  1. 计算旋转矩阵,并将其设置在常量数据中。
  2. 用常量数据更新常量缓冲区。
  3. 用所述数据更新顶点着色器。
  4. DrawPrimitives 以便我的三角形出现在根据步骤 #1 中的矩阵旋转的屏幕上。 (通过顶点着色器)

是吗?好像来来回回很多。我是应该依靠顶点着色器来进行变换,还是有不同的方法在每个“对象”(三角形)的基础上应用旋转?

如果我的问题没有意义,我深表歉意,就像我说的,我认为我遇到了概念/理解问题。

最佳答案

基本上,您有一些模型(在您的例子中是三角形)。

模型是顶点数组:

struct Vertex
{
float3 position;
float3 normal;
float2 texcoord;
float4 color;
// other vertex attributes goes here
};

您在初始化时创建一次顶点(和索引)缓冲区。

std::vector<Vertex> vertices = { /*vertex data goes here*/ };
VertexBuffer vb = renderer->CreateVertexBuffer(&vertices[0], vertices.size());

您的 3D 世界是一组对象,它们是您模型的实例

struct MyObject
{
float3 position;
float3 rotation;
float3 scale;
// other instance attributes goes here (it can be whatever you want)
};

std::vector<MyObject> objects = { /*objects data goes here*/ };

基本上对象的属性是顶点属性的修饰符,所以所有对象都有相同的模型,但在你的世界中看起来不同(在这个例子中它们有不同的位置)。

通常在模型空间中定义的每个顶点的位置(以及法线、切线和副切线)。要将它移动(转换)到世界空间,您可以将每个顶点的 position 乘以当前对象的矩阵。你不想在 CPU 上做,因为它很慢。 Vertex buffer保持不变(当然,你可以改变它,实现变形、曲面 segmentation 等效果,但我们不是这样)。

因此,您在顶点(或几何)着色器中进行变换。而且您必须以某种方式将当前对象的变换(和其他实例属性)的信息发送到顶点着色器。

一种方法是常量缓冲区

假设您在顶点着色器中有 cbuffer:

cbuffer Instance
{
matrix worldMatrix;
// other instance parameters goes here
};

而且你必须用数据填充它。

在绘制每个对象之前,您使用当前的实例数据更新缓冲区(每个对象一次(每帧多次)):

renderer->SetVertexBuffer(vb); // Set needed geometry 
for(int i = 0; i < objects.size(); ++i) // for each object
{
matrix worldMatrix = CalculateWorldMatrix(objects[i]); // prepare data of current object
renderer->UpdateConstantBuffer(&worldMatrix); // Tell shaders about current object's attributes (world matrix in our case)
renderer->Draw(); // or DrawIndexed();
}

对于 n 个对象,您有 n 个绘制调用和 n 个缓冲区更新。

另一种方式是实例缓冲区

您再创建一个顶点缓冲区,它保存的不是顶点数据,而是准备供着色器使用的实例数据。

您计算实例数据并创建实例缓冲区一次:

for(int i = 0; i < objects.size(); ++i) // for each object
{
std::vector<Instance> instances;
instances[i].worldMatrix = CalculateWorldMatrix(objects[i]);
// other instance parameters goes here
}

VertexBuffer instanceBuffer = renderer->CreateVertexBuffer(&instances[0], instances.size());

而且您还必须更改输入布局,因此着色器除了顶点数据之外还需要实例数据。

绘制时,您只需绑定(bind)顶点和实例缓冲区。不需要缓冲区更新(如果你的三角形没有被移动)。不再需要矩阵计算。因此,没有 for 循环,只有一个(!)绘制调用。

    renderer->SetVertexBuffers(2, vb, instanceBuffer); // Set needed model data and instances data
renderer->DrawInstanced(); // or DrawIndexedInstanced();

如果您反对更改它们的参数:位置、颜色等,您只更新实例缓冲区。

当绘制复杂的场景时,您通常会同时使用:常量缓冲区(用于所有或许多对象共享的属性: View 矩阵、投影矩阵等)和实例化(如果您的对象具有相同的模型几何形状,但属性不同), 以发挥他们的优势。

关于c++ - D3D11 : Rotating Multiple Triangles,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18522172/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com