Піксельне ідеальне відображення у візуалізацію з повноекранним чотирма


9

У мене виникають проблеми з рендерінгом купівлі значень. Значення ніколи не закінчуються в тому діапазоні, в якому я їх хочу. В основному я використовую повноекранний квадроцикл і піксельний шейдер для відображення моєї текстури візуалізації, а потім збираюся використовувати координати текстури як основу для деяких обчислень в шейдері. Координати текстур квадратику від (0,0) вгорі зліва до (1,1) в правому нижньому куті ... проблема полягає в тому, що після інтерполяції ці значення не надходять на піксельний шейдер як такий .

Приклад: Я надаю текстуру 4x4, і в цьому випадку шейдер просто виводить координати текстури (u, v) в червоний і зелений канали:

return float4(texCoord.rg, 0, 1);

Я хочу вийти з нього - це текстура, де піксель у верхньому лівому куті - RGB (0,0,0) і, таким чином, чорний, піксель у верхньому правому куті - RGB (255,0,0) і, таким чином, яскравий червоний, а піксель у лівій нижній частині - RGB (0,255,0) - яскраво-зелений.

Однак замість цього я отримую це праворуч:

(пряма квадратіка, без корекції)
пряма візуалізація квадратика, корекція не застосовується

Лівий верхній піксель чорний, але я отримую лише відносно темно-червоний і темно-зелений в інших кутах. Їх значення RGB становлять (191,0,0) та (0,191,0). Я сильно підозрюю, що це стосується місць вибірки квадратика: верхній лівий піксель правильно відбирає лівий верхній кут квадрата і отримує (0,0) як УФ-координати, але інші кутові пікселі не вибирають з інші кути квадратика. Я проілюстрував це на лівому зображенні синім полем, що представляє квадратик, а білі точки - верхні координати вибірки.

Тепер я знаю про зсув напівпікселя, який слід застосувати до своїх координат під час візуалізації квадратиків на екрані в Direct3D9. Подивимося, який результат я отримую від цього:

(чотиримісне відображення із зміщенням половинного пікселя DX9)
чотиризісний виведений із зміщенням половини пікселів

Червоний і зелений стали яскравішими, але все-таки неправильні: 223 - це максимум, який я отримую на каналі червоного або зеленого кольору. Але зараз у мене вже навіть немає чистого чорного, а натомість темний, жовтуватий сірий з RGB (32,32,0)!

Що мені насправді потрібно, буде такий вид рендерінгу:

(цільовий рендер, зменшений розмір квадратика)
чисті чорні, зелені та червоні з правильною інтерполяцією

Схоже, я повинен перемістити праву і нижню межу мого квадрата рівно на один піксель вгору і вліво, порівняно з першою цифрою. Тоді правий стовпець і нижній ряд пікселів повинні правильно отримувати УФ-координати прямо від межі квадрата:

VertexPositionTexture[] quad = new VertexPositionTexture[]
{
    new VertexPositionTexture(new Vector3(-1.0f,  1.0f, 1f), new Vector2(0,0)),
    new VertexPositionTexture(new Vector3(1.0f - pixelSize.X,  1.0f, 1f), new Vector2(1,0)),
    new VertexPositionTexture(new Vector3(-1.0f, -1.0f + pixelSize.Y, 1f), new Vector2(0,1)),
    new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, -1.0f + pixelSize.Y, 1f), new Vector2(1,1)),
};

Однак це не вийшло, і нижня та права пікселі взагалі не відображалися. Я думаю, що ці піксельні центри вже не вкриті квадратиком, і тому шейдер не оброблятиметься. Якщо я зміню обчислення pixelSize на якусь крихітну суму, щоб зробити квадратик на невеликий розмір більшим, він начебто працює ... принаймні на текстурі 4x4. Він не працює на менших фактурах, і я побоююсь, що це тонко спотворює рівномірний розподіл значень uv на більші текстури:

Vector2 pixelSize = new Vector2((2f / textureWidth) - 0.001f, (2f / textureHeight) - 0.001f);

(Я змінив обчислення pixelSize на 0,001f - для менших текстур, наприклад, 1D таблиці пошуку, це не працює, і я повинен збільшити його до 0,01f або щось більше)

Звичайно, це тривіальний приклад, і я міг би зробити цей розрахунок набагато простіше на процесорі, не турбуючись про відображення УФ-променів у піксельні центри ... все-таки, повинен бути спосіб фактично зробити повноцінним, повним [0, 1] діапазон до пікселів у вікні відтворення !?


Не те, щоб це допомогло, але я маю саме таку проблему.
IUsedToBeAPygmy

1
Не забудьте також відключити лінійну вибірку.
r2d2rigo

Він не схожий на систему координат, яку ви використовуєте, відповідає пікселям екрана - якщо б це було, то виглядає, що ви малюєте тут лише 2 × 2 пікселі. Перша проблема, яку я вирішу, - отримати матриці перегляду проектів і моделей таким чином, що +1 у просторі координат є зміщенням на 1 піксель на екрані.
Сліпп Д. Томпсон

Відповіді:


4

Ваша проблема полягає в тому, що ультрафіолетові випромінювання призначені для координат текстури. Координатна позначка 0,0 - це верхній лівий кут верхнього лівого пікселя текстури, який не є там, де зазвичай потрібно читати текстуру. Для 2D ви хочете прочитати текстуру в середині цього пікселя.

Якщо моя математика права, що вам потрібно зробити, щоб обійтись:

return float4((texCoord.rg - (0.5f/textureSize)) * (textureSize/(textureSize-1)), 0, 1);

Тобто ви віднімаєте відповідний зсув, щоб отримати верхній лівий піксель на 0,0, а потім застосовуєте шкалу, щоб отримати правильний нижній правий.

Те ж саме можна досягти і шляхом розширення координат УФ для геометрії поза діапазоном 0-1.


Щоб детальніше зупинитися на останньому реченні: ви можете застосувати це перетворення до УФ у вершинному буфері для чотирьох кутів квадрата, а потім у піксельній шейдері return float4(texCoord.rg, 0, 1);.
Натан Рід

Я спробував запропоновану вище формулу, і це не спрацювало: у моєму відтворенні 4х4 зразка зверху я отримую 0, 42, 127 і 212 в каналах R і G, зліва направо або зверху вниз. Однак я хотів би, щоб значення від 0 до 255 були рівномірно розташованими кроками (для текстури 4х4, яка була б 0, 85, 170 і 255). Я також намагався змінити координати УФ, але поки не знайшов правильного зміщення.
Маріо

0

Схоже, я повинен перемістити праву і нижню межу мого квадрата рівно на один піксель вгору і вліво, порівняно з першою цифрою.

Майже, але лише половина пікселя. Просто відніміть 0,5 від чотирьох вершин. Наприклад, вам потрібен квадратик 256x256 з однаковою текстурою, ось ваші моменти:

p1 = (-0.5, -0.5)
p2 = (-0.5, 255-0.5)
p3 = (255-0.5, 255-0.5)
p4 = (255-0.5, -0.5)

Або ви можете замість цього додати половину текселя в піксельну шейдер (texCoord.rg + 0.5 * (1.0 / texSize))

Зсув на пів пікселя - відомий факт у DX9. Це та ці статті можуть вам також допомогти.


0

Це, безумовно, викликано лінійною вибіркою. Якщо ви подивитеся на текселі праворуч і нижче повністю чорного верхнього лівого пікселя, ви побачите, що їх у каналах R та / або G їх 63, а 2 з них - 2 у B. Тепер подивіться на каламутно-темно-жовтий ви отримуєте; це 31 в R і G і 1 в B. Це, безумовно, результат усереднення текстових тканин над групою 2x2, тож рішення - встановити фільтр текстури в точку.


-2

Це просто тому, що ви використовуєте texCoords з вершинного виводу, який інтерполюється на жорсткому диску після обробки вершинного шейдера.

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