Странный белый контур вокруг модели

19

Я работаю над игрой в XNA 4 и недавно переключился на реализацию отложенного затенения, следуя этому руководству . Странный белый контур появляется на моих моделях сейчас, и я не уверен, что является причиной этого. Я подумал, что это может быть недостаточная точность для обычной цели рендеринга или цели рендеринга глубины, но увеличение их до 64 бит (Rgba64) вместо 32 (цвет) не помогло. Я также подумал, что это может быть какая-то проблема с расчетом зеркальности, поэтому я попытался установить зеркально на 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, и этот цвет берется непосредственно из карты цветов. Возможно, есть небольшая ошибка в вычислении координаты текстуры для выборки?

Пропуск освещения:

Telanor
источник
4
Пожалуйста, не сжимайте jpeg скриншот, показывающий тонкий графический сбой. Люди захотят увидеть проблему в идеальном воспроизведении.
aaaaaaaaaaaa
Что ж, сжатие в формате jpeg на самом деле позволяет довольно хорошо просвечивать, я думаю, только один пиксель и только когда определенные вещи воссоединены (большой различие по глубине Z и освещение (довольно) высоко для всех пикселей). Удачи, отложенный рендеринг довольно технический.
Вальмонд,
2
Не уверен , если это поможет, но вы используете очень старую версию кода / учебник, Каталин Zi в реальном коде / учебник сейчас на сайте : catalinzima.com/tutorials/deferred-rendering-in-xna и санкционированный XNA4.0 версия находится здесь: roy-t.nl/index.php/2010/12/28/…
Рой Т.
Также как всегда с отладкой отложенного рендеринга, вы могли бы публиковать скриншоты из всех буферов? Это, вероятно, в буфере освещения, но это может быть что-то еще.
Рой Т.
Мой инстинкт заключается в том, что проблема заключается в том, как часть алгоритма обрабатывает угол ровно в 90 градусов, но мне придется поработать с одой после работы, чтобы разобраться в ней.
Джордаан Милонас

Ответы:

4

У меня также был этот белый контур или «ореол» вокруг моих моделей, когда я начинал на своем собственном отложенном рендере. Проблема заключалась в том, что значение смещения текстуры для наложения целей рендеринга было настроено неправильно. Для некоторых текстур необходимо установить +0,5 пикселей для смещения вместо -0,5 пикселей.

Только после настройки значений некоторых смещений текстуры контуры исчезли. Скорее всего это в одном из осветительных шейдеров.

Редактировать: кстати, я также узнал из учебника Каталина Зимы, который является ответвлением от вашего примера, поэтому он должен работать.

ChrisC
источник
Да, это было это. Я изменил его на + halfPixel для всей выборки координат в легком шейдере, и ореол исчез.
Теланор
0

Я не уверен точно, что происходит, но пару вещей, чтобы перепроверить:

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

  2. Я вижу, вы добавляете половинное смещение к координатам текстуры; перепроверьте, что это правильно. Я не достаточно знаком с XNA, чтобы знать, каким должно быть правильное смещение, но вы должны иметь возможность проверить его, написав шейдер, который сэмплирует один из G-буферов и просто выводит сэмпл. Затем переключайтесь между этим и отображайте G-буфер прямо на экране. Если вы получили правильное смещение, вы не должны видеть различий, даже ни одного пикселя.

Натан Рид
источник
Я пошел и изменил все, что связано с GBuffer на POINT (я предполагаю, что отключает фильтрацию?), И он все тот же. Что касается вашего второго пункта, не будет ли вывод GBuffer напрямую таким же: создать шейдер, который просто выводит данные? Не могли бы вы подробнее остановиться на этом?
Теланор
Ну, как вы сгенерировали скриншоты G-буфера выше? Я предполагаю, что вы вызываете какую-то встроенную функцию API, чтобы скопировать пиксели один-к-одному из G-буфера на экран (задний буфер)? (Я не знаю XNA, поэтому не знаю, как он будет называться.) Я говорю, сравните выходные данные встроенной функции копирования один-к-одному с выходными данными пиксельного шейдера, написанного для копия один-к-одному ... таким образом, вы можете быть уверены, что координаты текстуры точно верны, и вы действительно получаете выборку один к одному.
Натан Рид