2011-01-29 2 views
2

У меня есть игровой объект, который управляет несколькими объектами спрайтов. Каждый из спрайтов немного перекрывает друг друга, и рисование их выглядит просто отлично, когда они имеют 100% непрозрачность. Если я задаю непрозрачность, то это будет 50%, то есть когда все идет в банк, потому что любая перекрывающаяся область не будет непрозрачной на 50% из-за нескольких слоев.Проблема XNA Layered Sprite

EDIT: Ой! По какой-то причине я думал, что не могу загружать изображения. Во всяком случае ....

http://postimage.org/image/2fhcmn6s/ -> Вот оно. Думаю, мне нужно больше репутации для правильного включения.

Слева направо:
1. Несколько спрайтов, непрозрачность 100%. Большой!
2. Оба являются 50%, но обратите внимание, как область перекрытия отличает их как два спрайта.
3. Это желаемое поведение. Они непрозрачны на 50%, но с точки зрения составного изображения.

Каков наилучший способ уменьшить эту проблему? Является ли цель рендеринга хорошей идеей? Что делать, если у меня есть сотни этих «мульти-спрайтов»?

Надеюсь, что это имеет смысл. Благодаря!

+0

Вы на самом деле не сказал, что эффект, который вы хотите достичь. Что происходит с вашими 50% непрозрачными спрайтами, когда они перекрываются, и что вам не нравится? Если текст не удастся вам, скриншот будет полезен. – Olhovsky

+0

Он все еще не на 100% точно знает, какой эффект вы ищете. Тем не менее, я добавил ответ, основанный на том, какой эффект я думаю, что вы, возможно, собираетесь.Дайте мне знать, правильно ли я это понял. – Olhovsky

ответ

2

Метод 1:

Если вы заботитесь об индивидуальном непрозрачности каждого спрайта, а затем сделать изображение на фоне к RenderTarget текстуры одного и того же размера, используя 50% или что-то помутнение вы хотите спрайт на фоне. Затем нарисуйте эту rendertarget со 100% непрозрачностью.

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

Метод 2:

Если вы не заботитесь о настройке индивидуальной непрозрачности каждого спрайта, то вы можете просто сделать все спрайты 100% непрозрачности к RenderTarget. Затем нарисуйте эту цель на вашем фоне с непрозрачностью 50%.


проблемы производительности:

Я упомянул два примера подходило к rendertargets, каждый для другого эффекта.

Метод 1:

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

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

Метод 2:

Вам не нужна разная непрозрачность на каждый спрайт. В этом случае вы можете почти наверняка уйти с помощью всего 2 вызовов, независимо от размера спрайта. Просто загрузите все призывы спрайтов (со 100% непрозрачностью), чтобы привлечь к rendertarget. Это один призыв к розыгрышу. Теперь нарисуйте эту rendertarget поверх фонового изображения с желаемой непрозрачностью (например, 50% непрозрачность), и все спрайты будут иметь эту непрозрачность. Этот случай проще реализовать.

+0

Я думаю, что для достижения эффекта, который он выполняет, вам нужно будет нарисовать спрайты, составляющие «составной» спрайт, в рендерную цель с непрозрачностью 100%. А затем нарисуйте эту рендерную цель с непрозрачностью 50%. Однако использование таких целей рендеринга может быть не идеальным по производительности. –

+0

Да, мне нравится идея сначала рисовать все спрайты с целью рендеринга. Это проще и эффективнее. Однако, если он хочет иметь другую непрозрачность для каждого спрайта, то это не сработает, и он застрял, рисуя каждый спрайт в отдельную цель рендеринга. – Olhovsky

+0

Да, мне также нравится идея рендеринга. Это была моя первая интуиция, но я не был уверен в ее фактической эффективности. Если бы мне нужно было нарисовать 200 композитных спрайтов, например, это не было бы большим хитом производительности? –

0

Первым, на что напомнили мои примеры изображений, является проблема «глубина-буфер и полупрозрачная поверхность».

В 3D-игре вы должны отсортировать полупрозрачные поверхности с обратной стороны и нарисовать их только после того, как вы отобрали остальную часть вашей сцены - все с включенным чтением и записью глубины. Если вы этого не сделаете, вы в конечном итоге получите свое изображение, когда вы, как правило, хотите получить изображение с просвечиванием стекла поверх того, что стоит за ним.

Но вы хотите -ий изображения - с некоторыми прозрачными поверхностями затеняя другие одни - так что вы можете просто намеренно вызвать эту проблему глубины!

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

Для достижения этой цели в XNA 4.0 вам необходимо пройти, чтобы SpriteBatch.Begin, а DepthStencilState с его DepthBufferFunction набором для CompareFunction.Less (по умолчанию это менее чем или равный к) и DepthBufferEnable и DepthBufferWriteEnable набора к истине.

Возможно взаимодействие с параметром layerDepth спрайта (я не могу вспомнить, как он по умолчанию задает глубину).

Вы может также необходимо использовать BasicEffect в качестве шейдера для вашего спрайта партии - в частности, таким образом Вы можете установить матрицу проекции с соответствующими ближними и дальними самолетов. This article объясняет, как это сделать. И вам также может понадобиться очистить буфер глубины перед раздачей.

Наконец, вам нужно нарисовать свои спрайты в правильном порядке - сначала с помощью простого эльфа.

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

0

Сначала вы должны попробовать материал в ответе Андрея, но если это не сработает, вы все равно можете отобразить все спрайты (при условии, что все они имеют одинаковую непрозрачность) на RenderTarget (2D) со 100% непрозрачностью, а затем визуализируйте RenderTarget на экран с 50%.

Нечто подобное в XNA 4.0:

RenderTarget2D rt = new RenderTarget2D(graphicsDevice, 
             graphicsDevice.PresentationParameters.BackBufferWidth, 
             graphicsDevice.PresentationParameters.BackBufferHeight); 
GraphicsDevice.SetRenderTarget(rt); 
//Draw sprites 
GraphicsDevice.SetRenderTarget(null); 
//Then draw rt (also a Texture2D) with 50% opacity. For example: 
spriteBatch.Begin(); 
spriteBatch.Draw(rt, Vector2.Zero, Color.FromArgb(128, Color.White)); 
spriteBatch.End();