Аппаратное копирование XNA: сетка отображается не полностью

Я реализовал базовый метод создания экземпляров модели оборудования в коде XNA, следуя этому короткому руководству: http://www.float4x4.net/index.php/2011/07/hardware-instancing-for-pc-in-xna-4-with-textures/

Я создал нужный шейдер (но без текстурного атласа, но только с одной текстурой) и пытаюсь использовать этот метод для рисования простого дерева, созданного с помощью 3DS Max 2013 и экспортированного в формат FBX.

Результаты, которые я вижу, оставили меня без понятия о том, что происходит.

Дерево без ствола, по некоторым причинам

Когда я не использовал методы создания экземпляров, а просто вызывал Draw на сетке (для каждого дерева на уровне), было показано все дерево:

Правильный рендеринг, но не экземпляр (может быть очень медленным на нескольких сотнях объектов на уровень

Я абсолютно уверен, что Модель содержит только одну сетку, а сетка содержит только одну сетку.

Я использую метод Vertex Extraction, используя метод "GetData<>()" Vertex и Index Buffer модели, и корректное количество вершин и индексов, следовательно, отображается правильное количество примитивов. Правильные текстурные координаты и Нормы для освещения также извлекаются, что видно по части дерева, которая отображается.

Также части дерева также находятся на своих правильных местах.

Они просто пропускают около 1000 или около того многоугольников, совершенно без причины, что когда-либо. У меня есть точки останова на каждом этапе извлечения вершин и генерации параметров шейдера, и я не могу на всю жизнь понять, что я делаю неправильно.

Функция преобразования вершины моего шейдера:

VertexShaderOutput VertexShaderFunction2(VertexShaderInput IN, float4x4 instanceTransform : TEXCOORD1)
{
        VertexShaderOutput output;

        float4 worldPosition = mul(IN.Position, transpose(instanceTransform));
        float4 viewPosition = mul(worldPosition, View);
        output.Position = mul(viewPosition, Projection);
        output.texCoord = IN.texCoord;
        output.Normal = IN.Normal;

        return output;
}

Связывание вершин и генерация индексного буфера:

instanceBuffer = new VertexBuffer(Game1.graphics.GraphicsDevice, Core.VertexData.InstanceVertex.vertexDeclaration, counter, BufferUsage.WriteOnly);
            instanceVertices = new Core.VertexData.InstanceVertex[counter];

            for (int i = 0; i < counter; i++)
            {
                instanceVertices[i] = new Core.VertexData.InstanceVertex(locations[i]);
            }

            instanceBuffer.SetData(instanceVertices);

            bufferBinding[0] = new VertexBufferBinding(vBuffer, 0, 0);
            bufferBinding[1] = new VertexBufferBinding(instanceBuffer, 0, 1);

Метод извлечения вершин, используемый для получения всей информации о вершинах (эта часть, я уверен, работает правильно, поскольку я использовал ее раньше, чтобы загружать тестовые геометрические фигуры в уровни, такие как блоки, сферы и т. Д., Для тестирования различных шейдеров и построения ограничивающих рамок вокруг них, используя извлекаются данные вершин, и это все правильно):

public void getVertexData(ModelMeshPart part)
        {
            modelVertices = new VertexPositionNormalTexture[part.NumVertices];
            rawData = new Vector3[modelVertices.Length];
            modelIndices32 = new uint[rawData.Length];
            modelIndices16 = new ushort[rawData.Length];

            int stride = part.VertexBuffer.VertexDeclaration.VertexStride;

            VertexPositionNormalTexture[] vertexData = new VertexPositionNormalTexture[part.NumVertices];
            part.VertexBuffer.GetData(part.VertexOffset * stride, vertexData, 0, part.NumVertices, stride);

            if (part.IndexBuffer.IndexElementSize == IndexElementSize.ThirtyTwoBits)
                part.IndexBuffer.GetData<uint>(modelIndices32);
            if (part.IndexBuffer.IndexElementSize == IndexElementSize.SixteenBits)
                part.IndexBuffer.GetData<ushort>(modelIndices16);

            for (int i = 0; i < modelVertices.Length; i++)
            {
                rawData[i] = vertexData[i].Position;
                modelVertices[i].Position = rawData[i];
                modelVertices[i].TextureCoordinate = vertexData[i].TextureCoordinate;
                modelVertices[i].Normal = vertexData[i].Normal;
                counter++;
            }
        }

Это код рендеринга для пакета объектов (деревья в данном конкретном случае):

public void RenderHW()
        {
            Game1.graphics.GraphicsDevice.RasterizerState = rState;

            treeBatchShader.CurrentTechnique.Passes[0].Apply();
            Game1.graphics.GraphicsDevice.SetVertexBuffers(bufferBinding);
            Game1.graphics.GraphicsDevice.Indices = iBuffer;
            Game1.graphics.GraphicsDevice.DrawInstancedPrimitives(PrimitiveType.TriangleList, 0, 0, treeMesh.Length, 0, primitive , counter);

            Game1.graphics.GraphicsDevice.RasterizerState = rState2;
        }

Если у кого-то есть идеи, где даже начинать искать ошибки, просто опубликуйте все идеи, которые приходят на ум, так как я совершенно ошеломлен тем, что происходит.

Это даже опровергает весь мой предыдущий опыт, когда я что-то испортил в шейдерном коде или генерации вершин, вы бы получили на экране абсолютный беспорядок - многочисленные графические артефакты, такие как вытянутые треугольники, возникающие там, где должна быть сетка, но один наконечник тянется назад до (0,0,0), черная текстура, неправильное позиционирование (часто за пределами скайбокса или ниже ландшафта), неправильное масштабирование...

Это нечто иное, почти как если бы оно работало - видимая часть дерева правильна в каждом аспекте (местоположение, вращение, масштаб, текстура, затенение), за исключением того, что часть отсутствует. Что делает меня более странным, так это то, что отсутствующая часть, по-видимому, логически сегментирована: отсутствуют только примитивы ствола дерева, а некоторые опускаются с самых низких ветвей дерева, в результате чего все остальные примитивы отображаются правильно без каких-либо артефактов. По сути, они... правильно отсутствуют.

1 ответ

Решаемые. Конечно, это была единственная часть, я был уверен на 100%, что это было правильно, хотя это было не так.

        modelIndices32 = new uint[rawData.Length];
        modelIndices16 = new ushort[rawData.Length];

Измените это на:

        modelIndices32 = new uint[part.IndexBuffer.IndexCount];
        modelIndices16 = new ushort[part.IndexBuffer.IndexCount];

Теперь мне нужно просто выяснить, почему 3 вызова отрисовки рендерит 300 деревьев медленнее, чем 300 вызовов отрисовки, рендеринг 1 дерева каждый (то есть, почему я потратил весь день на создание новой проблемы).

Другие вопросы по тегам