Есть ли более быстрая альтернатива использованию текстур в XNA? - PullRequest
6 голосов
/ 20 мая 2010

Я пишу программу для редактирования карт для 2D-игр с использованием XNA.Создание Texture2D для всех плиток, необходимых для карты, занимает слишком много времени.

Существуют ли альтернативы использованию текстур для рисования с использованием XNA?

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

В настоящее время программа содержит всепотенциальные текстуры в памяти как растровые объекты.Есть ли способ просто нарисовать растровый объект на экране в XNA?Я искал, но не могу найти информацию по этому вопросу.Этот подход позволил бы избежать создания текстур в целом, однако любые оттенки или эффекты, которые я должен был бы применить непосредственно к растровому изображению.

Ответы [ 7 ]

2 голосов
/ 03 июня 2010

Есть ли причина, по которой вы не рассматривали возможность загрузки изображения один раз, а затем передачи координат смещения x и y в пиксельный шейдер?

Вы бы в основном настроили C # так:

myGraphicsDevice.Textures[0] = whateverYourGiantMapTextureIs;

foreach(MapChunk chunk in mapChunks) {
    myShader.Effect.Parameters["xOffset"] = chunk.XOffset;
    myShader.Effect.Parameters["yOffset"] = chunk.YOffset;

    myGraphicsDevice.DrawIndexedPrimitives( your chunk drawing code here );
}

И затем код шейдера выглядит так:

float4x4 World; 
float4x4 View; 
float4x4 Projection;

float xOffset;
float yOffset;

sampler TextureSampler; 

struct VS_INPUT { 
    float4 Position : POSITION0; 
    float4 Color    : COLOR0;
};

VS_INPUT Transform(VS_INPUT Input) { 
    VS_INPUT Output; 

    float4 worldPosition = mul(Input.Position, World); 
    float4 viewPosition = mul(worldPosition, View); 
    Output.Position = mul(viewPosition, Projection); 
    Output.Color = Input.Color;

    return Output; 
} 

float4 ColorTexture(VS_INPUT Input) : COLOR0{ 
    return Input.Color.rgba * tex2D(TextureSampler, float2(xOffset, yOffset));
} 

technique TransformColorTexture { 
    pass P0 { 
        VertexShader = compile vs_2_0 Transform(); 
        PixelShader = compile ps_2_0 ColorTexture(); 
    } 
}

Код шейдера может нуждаться в некоторой подгонке к существующему коду, но в противном случае он должен сработать.

2 голосов
/ 06 февраля 2013

Использование одной текстуры на плитку не очень эффективно. Тем более, что это означает, что вы не можете выполнять пакетирование (в любом реальном смысле).

Если по какой-то причине вам НУЖНО иметь их в качестве отдельных текстур в вашем контент-проекте (проще редактировать одну плитку и т. Д.), Вы можете довольно легко скомпилировать их в карты листов после загрузки. Как вы делаете это в основном:

1: загрузить количество плиток (скажем, 40 32 * 32 плиток)

2: Определите хороший размер текстуры для карты тайла: корень квадратный из 40 равен 6. что-то, поэтому мы округляем до 7. 7 * 32 - это 224, что хорошо, но 256 лучше, поэтому давайте сделаем текстуру 256x256. (вы можете сделать код, который выяснит это на лету)

3: создайте Rendertarget2D нужного размера.

4: активировать цель визуализации.

5: рендеринг тайлов на цели рендера:

int x, y = 0;
foreach (var tile in allTiles)
{
    RenderTile(tile, x*32, y*32);
    x++;

    if (x >= 8)
    {
        x = 0;
        y++;
    }
}

Для бетч-рендеринга у вас есть буфер вершин с 4 * 40 вершинами. каждый набор из 4 имеет значение, указывающее индекс четырехугольника, которому он принадлежит (0,1,2 и т. д.). В вашем шейдере у вас есть массив матриц [40] для расположения плиток, а также массив tileIndex (int [40]) для определения того, какую плитку рендерить из карты тайлов.

Извините, но сейчас у меня нет времени написать весь код шейдера: s

Другой трюк, который я использовал в наших играх, - это предварительный рендеринг уровня на большие плитки (640x360), что значительно уменьшает количество вызовов на ничью, особенно при работе с 5+ слоями плиток из разных наборов плиток. , Единственное, что он не работает с динамическими плитками (анимированными плитками и т. Д.), Но вы можете пометить их и визуализировать их нормально, если хотите ...

1 голос
/ 26 мая 2010

Поскольку вам нужно использовать пользовательский формат изображения, если вы хотите (для скорости), вы можете попытаться написать собственные импортеры и процессоры конвейера контента для XNA (http://msdn.microsoft.com/en-us/library/bb447754.aspx), но это может быть излишним для вас. нужно сделать.

Я вижу, вы хотите создать графический интерфейс как можно проще, даже если эти проблемы вынуждают вас использовать язык, такой как C ++, чтобы вы могли использовать DirectX. В Visual C ++ вы все равно сможете воспользоваться визуальным макетом Windows Forms , если вы используете Visual Studio.

0 голосов
/ 02 июня 2010

Вы пытаетесь нарисовать их всех одним потоком выполнения?

Попробуйте многопоточность вашей игры. Потоки в C # довольно просты и поддерживаются XNA.

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

0 голосов
/ 31 мая 2010

К сожалению, насколько я знаю, в XNA нет способа напрямую нарисовать растровое изображение на экране;это требует, чтобы все было сопоставлено с объектами текстуры, которые по умолчанию буферизируются на видеокарте.Похоже, вы говорите о большом количестве плиток, хотя, если они не будут все соответствовать максимально допустимой текстуре (я не могу вспомнить, было ли это 1024 или 4096 квадратов ...) - вы пытались иметьнебуферизованная текстура для скоростных целей?Другой альтернативой может быть ленивая загрузка ваших наборов плиток в текстуры, чтобы пользователю не приходилось ждать их загрузки - для редактора использование ярко-розового запасного цвета обычно допустимо во время загрузки.

Кроме того, есть ли что-нибудь по своей сути, чтобы написать свой инструмент в XNA?Поскольку кажется, что вы пишете инструмент отдельно от самого игрового движка, вы можете найти некоторые очень приемлемые решения в WPF, включая рисование непосредственно из BitmapSources и некоторые утилиты для вашего пользовательского интерфейса.

0 голосов
/ 23 мая 2010

Если несколько плиток используют одну и ту же текстуру, достаточно будет загрузить ее только один раз.

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

0 голосов
/ 20 мая 2010

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

Я прочитал это и ваш другой пост о текстурах. Если они представляют собой готовые изображения, которые вы хотите использовать в своей игре, не могли бы вы просто включить их в папку содержимого и сослаться на них? Это позволяет XNA компилировать текстуры в формате xnb, и у вас не должно быть проблем, которые вы объясняете.

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

...