Спрайт виводить розмито зі швидкістю


9

Після додавання швидкості до своєї гри я відчуваю, що мої текстури смикаються. Я думав, що це лише мої очі, поки я нарешті не зафіксував це на скріншоті:

введіть тут опис зображення

Ліворуч - це те, що відображається в моїй грі; праворуч - оригінал спрайта, обклеєний. (Це скріншот із Photoshop, збільшений у 6 разів.)

Помітьте, що краї зведені - це виглядає майже як піксельне візуалізація. Насправді, якби я не змусив своїх спрайтів (які мають позицію та швидкість як інти) малювати за допомогою цілих значень, я б поклявся, що MonoGame малює зі значеннями з плаваючою комою. Але це не так.

Що може бути причиною того, що ці речі з’являються розмитими? Це не відбувається без застосованої швидкості.

Якщо бути точним, у мого SpriteComponentкласу є Vector2 Positionполе. Коли я телефоную Draw, я по суті використовую new Vector2((int)Math.Round(this.Position.X), (int)Math.Round(this.Position.Y))для позиції.

Я мав помилку раніше, коли навіть стаціонарні об'єкти будуть тремтіти - це було через те, що я використовував прямий Positionвектор і не округляв значення до ints. Якщо я використовую Floor/ Ceilingзамість круглої, спрайт тоне / наближається (одна різниця в пікселях в будь-якому випадку), але все одно малює розмитою.


1
Чи може це бути пов’язано з застосованим фільтруванням текстур?
OriginalDaemon

У вас є код для вашого шейдера? Деякі люди додають половину пікселя на обох осях, щоб пікселі були в центрі. Не впевнений, хоча, я думаю, що це лише DirectX.
Вільям Маріагер

3
Деактивація фільтрації - це не вирішення проблеми.
Архів

1
Візуалізація нічого не знає про вашу швидкість, тому будь-яка позиція, розмір або що-небудь інше ви переходите до SpriteBatch.Draw - це інше, або помилка була перед тим, як ви додали швидкість. Як ви називаєте SpriteBatch.Drew саме?
Архів

1
@ ashes999 Ви налагодили цей виклик і перевірили цей.X, this.Y та this.origin? На що встановлено це.origin? В основному жодним чином інший результат відтворення не відрізняється, коли цей виклик Draw є однаковим.
Архів

Відповіді:


3

Ну, це бентежить.

Виявляється, я малював не цілі позиції, а плаваючі позиції. Арчі вказав мені правильний шлях своїм коментарем@ashes999 did you debug this call and checked this.X, this.Y and this.origin?

Щойно я додав сліду твердження, я помітив, що нічого не простежується. Виявляється, мій SpriteComponentклас правильно використав цілі цілі значення, але мій SpriteSheetComponentвсе-таки використаний float значення з raw Vector2 Position.

Хоча я не намагався фільтрувати текстуру та затискати текстуру, я підозрював, що це не правильна зміна, оскільки я малював 2D-зображення на тій же ширині та висоті, що й вихідне зображення (без масштабування).


1
Готово, радий, що ти знайшов його!
Архів

2

XNA використовує DirectX9, який використовує центр пікселя як своє місцезнаходження. Це помітно при використанні перевантажень класу малювання на основі Vector2. Я вважаю, що віднімання (.5, .5) має вирішити вашу проблему.

Більше інформації тут.


Я технічно цього не можу зробити, тому що я передаю в Vector2 int, intаргументи. Крім того, речі виглядають ідеально, коли я не маю жодних предметів у русі.
ashes999

Що ви маєте на увазі під об'єктом в русі? XNA не має поняття руху, він малює речі там, де ви також це скажете. Серія стаціонарних знімків. Спробуйте також використовувати перевантаження прямокутника, оскільки ви все одно округляєте до прямокутника.
ClassicThunder

У мене є власна реалізація швидкості. SpriteComponentмає Vector2положення, яке збільшується як плаває залежно від швидкості; коли я малюю, я створюю нові Vector2з цілими (округлими) версіями моїх positionX і Y. Це не проблема, оскільки нерухомі об'єкти без швидкості здаються нормальними.
ashes999

Отже, ваше висловлювання, що у вас є вектор позиції p і вектор швидкості v, додайте їх, таких як p + = v, а потім створіть копію p, використовуючи округлені значення. І що це значення yeild відрізняється від того, що має місце, яке є таким же, як і попереднє p + = v, незважаючи на те, що виклики нічиї були однаковими? Тому що це не має сенсу.
ClassicThunder

Так, це теж говорить @Archy. Дозвольте мені налагодити і ще раз перевірити. Я додаю p += vпід час Updateі відтворюю за допомогою new Vector2((int)Math.Round(p.X), (int)Math.Round(p.Y))).
зола999

2

Візуалізація нічого не знає про вашу швидкість, тому будь-яка позиція, розмір або що-небудь інше ви переходите до SpriteBatch.Draw - це інше, або помилка була перед тим, як ви додали швидкість. Як ви називаєте SpriteBatch.Drew саме?

Ви налагодили цей виклик і перевірили цей.X, this.Y та this.origin? На що встановлено це.origin? В основному жоден спосіб, коли результат візуалізації зі швидкістю відрізняється, коли цей виклик Draw є однаковим.


1

Проблема, ймовірно, увімкнена фільтрування текстур. Якщо ви не впевнені, що це означає, розгляньте ситуацію, коли у вас є зображення шириною 2 пікселів: перший піксель чорний, другий піксель - білий. Якщо ви збільшите масштаб цієї текстури, якщо фільтрування текстури ввімкнено, ви побачите, що вона розмивається, а область між чорним та білим пікселями використовує градієнт сірий колір.

Класичний приклад ігор з фільтруванням і без нього - Super Mario 64, який фільтрував, а Doom цього не робив.

Якщо ви не використовуєте швидкість, ваш Sprite, ймовірно, розташований так, що центр текстури знаходиться в точці зразка, що XNA (або будь-яка основна api використовується) захоплює колір. Коли ви рухаєтесь зі швидкістю поплавця, то положення вашого Sprite змінюється, тому точка зразка може не вирівнюватися безпосередньо з центром пікселя, тому кінцевим результатом є те, що колір, що є середнім значенням найближчих пікселів, використовується для візуалізації.

Ви можете переконатися, що фільтрування увімкнено, просто зробивши Sprite справді великим на екрані. Якщо це розмито, то це питання.

Якщо у вас повинна бути ідеальна піксель точність при візуалізації, вам потрібно мати значення float для збереженої десь позиції, але використовувати цілі значення для позиції об'єкта, який ви рендерінгу ... або, звичайно, ви можете просто вимкнути фільтрування якщо ваша гра не потрібна.

Ви також можете прочитати це .


Як я вже згадував у своєму запитанні, я вже використовую цілі числа для свого місцезнаходження та вихідного розміру зображення під час дзвінка Draw. Тож я не впевнений, як це могло бути, але я спробую відобразити масштабне і побачу, чи допоможе відключення фільтрування текстур.
ashes999

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.