Дивні білі обриси навколо моделі


19

Я працюю над грою в XNA 4, і нещодавно я перейшов на реалізацію відкладеного затінення, слідуючи цьому посібнику . Зараз на моїх моделях з’являються дивні білі контури, і я не впевнений, що це спричиняє. Я подумав, що це може бути недостатньою точністю до нормальної цілі візуалізації або цілі глибини відображення, але збільшення їх до 64 біт (Rgba64) замість 32 (Color) не допомогло. Я також подумав, що це може бути якась проблема з дзеркальним розрахунком, тому я спробував встановити окуляр на 0, але це теж не допомогло. Налагодження пікселя в PIX показує, що розсіяне значення обчислюється як майже біле для цього пікселя. Будь-які ідеї? Я включив картинку проблеми нижче, її легше побачити в повному розмірі.

Піксельний шейдер:

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
    input.ScreenPosition.xy /= input.ScreenPosition.w;

    float2 texCoord = 0.5f * (float2(input.ScreenPosition.x, -input.ScreenPosition.y) + 1) - halfPixel;

    float4 normalData = tex2D(normalSampler, texCoord);

    //Transform normal back into [-1, 1] range
    float3 normal = normalize(2.0f * normalData.xyz - 1.0f);

    float specularPower = normalData.a;
    float specularHardness = tex2D(colorSampler, texCoord).a * 255;
    float depthVal = tex2D(depthSampler, texCoord).r;

    //Compute screen-space position
    float4 position = float4(input.ScreenPosition.xy, depthVal, 1.0f);

    //Transform to world space
    position = mul(position, InvertViewProjection);
    position /= position.w;

    //Surface-to-light vector
    float3 lightVector = lightPosition - position;

    float3 projectedTexCoords = position - lightPosition;
    projectedTexCoords = mul(projectedTexCoords, float3x3(
                            float3(-1, 0, 0),
                            float3(0, 1, 0),
                            float3(0, 0, 1)));

    float distanceToLight = length(lightVector) / lightRadius;
    float shadow = ShadowContribution(projectedTexCoords, distanceToLight);

    float attenuation = saturate(1.0f - distanceToLight);

    lightVector = normalize(lightVector);

    //Compute diffuse light
    float normalDotLight = max(0, dot(normal, lightVector));
    float3 diffuseLight = normalDotLight * Color.rgb;

    float3 reflectionVector = normalize(reflect(-lightVector, normal));
    float3 directionToCamera = normalize(cameraPosition - position);
    float specularLight = specularPower * pow(saturate(dot(reflectionVector, directionToCamera)), specularHardness);

    return shadow * attenuation * lightIntensity * float4(diffuseLight.rgb, specularLight);
}

Редагувати : Вибачте за JPG, завантажувач stackexchange зробив це самостійно. Рой Т: Я насправді посилався на ваше перетворення XNA4 підручника для частин, які змінилися з XNA3. Оскільки я не вніс жодних великих змін у код, я подумав, що, можливо, ця помилка існувала в оригіналі, але просто неможливо побачити стільки вогнів, що рухаються навколо, тому я видалив усе, крім одного світла, і помилка з’явилася знову (дивіться біля ліктя ящірки)

Ось вміст GBuffer для моєї сцени:

Колірний буфер: Буфер глибини: Звичайний буфер: Остаточний рендер:

Edit2 :

Я починаю підозрювати, що проблема CombineFinal.fx, коли вона відбирає кольорову карту. Це обчислення для правильно кольорового пікселя поруч із білим пікселем:

diffuseColor        : (0.435, 0.447, 0.412)
diffuseLight        : (1.000, 1.000, 0.902)
light               : (1.000, 1.000, 0.902, 0.000)
PixelShaderFunction : (0.435, 0.447, 0.371, 1.000)
specularLight       : 0.000

І це вихід з неправильно забарвленого білого пікселя безпосередньо поруч із ним:

diffuseColor        : (0.824, 0.792, 0.741)
diffuseLight        : (1.000, 1.000, 0.902)
light               : (1.000, 1.000, 0.902, 0.000)
PixelShaderFunction : (0.824, 0.792, 0.669, 1.000)
specularLight       : 0.000

DiffuseColor - єдина відмінність, і цей колір взято безпосередньо з кольорової карти. Можливо, є невелика помилка в обчисленні координати текстури для вибірки?

Просвітлення:


4
Будь ласка, не jpeg стискає знімок екрана, показуючи тонкий графічний глюк. Люди захочуть бачити проблему в ідеальному відтворенні.
aaaaaaaaaaaa

Ну, стиснення jpeg насправді дозволяє виправити досить непогано, я думаю, лише один піксель і лише тоді, коли певні речі об’єднуються (велика різниця в глибині Z і освітлення (досить) велике на всіх пікселях). Удачі, відкладене надання є досить технічним.
Валмонд

2
Не впевнений, чи допомагає це, але ви використовуєте дуже стару версію коду / підручника, фактичний код / ​​підручник Каталіни Зіми зараз знаходиться за адресою: catalinzima.com/tutorials/deferred-rendering-in-xna та санкціонований XNA4.0 тут розміщена версія: roy-t.nl/index.php/2010/12/28/…
Roy T.

Крім того, як завжди при налагодженні відкладеної візуалізації, чи могли ви розміщувати знімки екрана з усіх буферів? Це, мабуть, у буфері освітлення, але це може бути щось інше.
Рой Т.

Мій інстинкт полягає в тому, що це буде проблема з тим, як частина алгоритму обробляє рівно кут на 90 градусів, але мені доведеться пограти з одою після роботи, щоб переглянути її далі.
Jordaan Mylonas

Відповіді:


4

Я мав цей білий контур або "ореол" навколо моїх моделей, коли я почав самостійно відкладати візуалізацію. Проблема полягала в тому, що значення зміщення текстури для накладання цілей візуалізації було встановлено неправильно. Для зміщення деяких текстур потрібно було встановити +0,5 пікселів замість –0,5 пікселів.

Лише після виправлення значень деяких зміщень текстури контури пішли. Швидше за все, це в одному з освітлювальних шейдерів.

Редагувати: до речі, я також дізнався з підручника Каталіна Зіми, який є відгалуженням вашого прикладу, тому він повинен працювати.


Так, це було все. Я змінив його на + halfPixel для всіх вибірок координат у світловій шейдері, і ореол зараз відсутній.
Теланор

0

Я не впевнений, що саме відбувається, але ще кілька речей, щоб перевірити:

  1. Переконайтеся, що у вас відключена фільтрація текстури під час відбору проб G-буферів - не білінарних, анізотропних чи нічого.

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


Я пішов і змінив усе, що стосується GBuffer, на POINT (я припускаю, що відключає фільтрацію?), І його все одно те саме. Що стосується вашого другого пункту, чи не виведення GBuffer безпосередньо було б точно таким же: зробіть шейдер, який просто виводить дані? Чи можете ви детальніше зупинитися на цьому?
Теланор

Ну, як ви створили знімки екрана G-буфера вище? Я припускаю, що ви викликаєте якусь вбудовану функцію API, щоб копіювати пікселі один на один з G-буфера на екран (задній буфер)? (Я не знаю XNA, тому я не знаю, як би це називалося.) Я говорю, порівняйте висновок вбудованої функції копіювання "один на один" з виходом піксельного шейдера, написаного для виконання копія "один на один" ... таким чином ви можете бути впевнені, що координати текстури є правильними, і ви дійсно отримуєте вибірку "один на один".
Натан Рід
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.