Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / SSR (Screen Space Reflections) - проблемы, артефакты

SSR (Screen Space Reflections) - проблемы, артефакты

Страницы: 1 2 3 4 Следующая »
DEN 3DПостоялецwww11 окт. 201812:58#0
Всем привет!

Реализовал SSR, по вот этой статье: https://habr.com/post/244367/

Проблема в следующем - для простых объектов типа - ровные стены, куб, цилиндр - отражения
строятся вполне хорошо, без артефактов.. Но для более сложных объектов типа сферы - есть артефакты.
Подумал, что не точно находится пересечение отражённого луча и добавил уточнение по бинарному поиску,
но что-то результат совсем не стал от этого лучше.. Не хуже, но и не лучше..

Код главного пиксельного шейдера (шейдер под библиотеку BGFX, поэтому местами синтаксис немного отличается от
HLSL/GLSL):

$input v_texCoord0

#include "../../Common.sh"

uniform mat4 viewProj;
uniform mat4 invViewProj;
uniform vec4 cameraPosition;
uniform vec4 edgeFactorPower;
uniform vec4 reflectionDistanceFadeFactor;

SAMPLER2D(s_depthTexture, 0);
SAMPLER2D(s_normalTexture, 1);
SAMPLER2D(s_colorTexture, 2);

vec3 getWorldSpacePosition(vec2 UV, float depth)
{
    vec4 position;
 
    position.x = UV.x * 2.0 - 1.0;
    position.y = -(UV.y * 2.0 - 1.0);
    position.z = depth;
    position.w = 1.0;
 
    position = mul(invViewProj, position);
 
    position.xyz /= position.w;

    return position.xyz;
}

vec2 getUV(vec3 position)
{
    vec4 pVP = mul(viewProj, vec4(position, 1.0));
    pVP.xy = vec2(0.5, 0.5) + vec2(0.5, -0.5) * pVP.xy / pVP.w;
    return pVP.xy;
}

#define MAX_RM_STEPS 30
#define L_FACTOR 0.1
#define BS_STEPS 5

vec2 BinarySearch(vec3 dir, vec3 hitCoord, out vec3 finalHitCoord)
{
    vec2 UV;

    for (int i = 0; i < BS_STEPS; i++)
    {
        UV = getUV(hitCoord);
        float d = texture2D(s_depthTexture, UV).x;
        vec3 pos = getWorldSpacePosition(UV, d);

        float dDepth = hitCoord.z - pos.z;

        dir *= 0.5;
        if(dDepth > 0.0)
            hitCoord += dir;
        else
            hitCoord -= dir;
    }
 
    finalHitCoord = hitCoord;

    return UV;
}

vec2 RayMarch(vec3 position, vec3 dir, out float distance)
{
    vec3 hitCoord;
    vec2 UV;

    float L = L_FACTOR;

    float dist = 0.0;

    [loop]
    for (int i = 0; i < MAX_RM_STEPS; i++)
    {
        vec3 vDir = dir * L;
        hitCoord = position + vDir;

        UV = getUV(hitCoord);
        float d = texture2D(s_depthTexture, UV).x;
        vec3 newPosition = getWorldSpacePosition(UV, d);

        dist = length(hitCoord - newPosition);

        L = length(position - newPosition);
    }

    vec3 reflectionHitCoord;

    vec2 finalUV =  BinarySearch(dir * dist, hitCoord, reflectionHitCoord);
    distance = length(position - reflectionHitCoord);

    return finalUV;
}

void main()
{
    const float fresnel_multiplier = 2.8;
    const float fresnel_pow = 2.0;

    float depth = texture2D(s_depthTexture, v_texCoord0).x;

    vec3 position = getWorldSpacePosition(v_texCoord0, depth);

    vec3 viewDir = normalize(position - cameraPosition.xyz);

    vec3 normal = normalize(texture2D(s_normalTexture, v_texCoord0).xyz * 2.0 - 1.0);

    vec3 reflectDir = normalize(reflect(viewDir, normal));

    float fresnel = fresnel_multiplier * pow(1.0 + dot(viewDir, normal), fresnel_pow);

    float dist;
    vec2 vCoords = RayMarch(position, reflectDir, dist);

    float distFactor = 1.0 - saturate(dist * reflectionDistanceFadeFactor.x);

    vec2 vCoordsEdgeFact = vec2(1.0, 1.0) - pow(saturate(abs(vCoords.xy - vec2(0.5, 0.5)) * 2.0), edgeFactorPower.x);
    float fScreenEdgeFactor = saturate(min(vCoordsEdgeFact.x, vCoordsEdgeFact.y));

    float reflectionMultiplier = fresnel * saturate(reflectDir.z) * fScreenEdgeFactor;

    reflectionMultiplier = clamp(reflectionMultiplier, 0.0, 1.0);

    gl_FragColor = vec4(texture2D(s_colorTexture, vCoords).rgb * reflectionMultiplier, 0.0);
}

Скриншоты для наглядности:

ssr arf 1 | SSR (Screen Space Reflections) - проблемы, артефакты
SSR arf 2 | SSR (Screen Space Reflections) - проблемы, артефакты
SSR arf 3 | SSR (Screen Space Reflections) - проблемы, артефакты
SSR arf 4 | SSR (Screen Space Reflections) - проблемы, артефакты
SSR arf 5 | SSR (Screen Space Reflections) - проблемы, артефакты

Прошу помочь; уверен, что кто-то делал SSR и сталкивался с этими проблемами.

Благодарю.

SuslikМодераторwww11 окт. 201813:11#1
DEN 3D
откуда ты вообще взял такую схему реймарчинга? в смысле с чего оно вообще должно сходиться?  бинарный поиск нужен, чтобы уточнить решение, он никак не поможет его исправить, если оно неправильно. поэтому отключай и отлаживай без него. у тебя ошибка в том, что луч просто пропускает особенности. рекомендую для начала реализовать самую простую схему, где шаг по лучу фиксирован, потом уже выделываться с непостоянным шагом.


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

Правка: 11 окт. 2018 13:12

DEN 3DПостоялецwww11 окт. 201813:23#2
Suslik
Схему реймарчинга взял из вышеупомянутой статьи: https://habr.com/post/244367/

В статье код выглядит так:

float3 currentRay = 0;

float3 nuv = 0;
float L = LFactor;

for(int i = 0; i < 10; i++)
{
    currentRay = texelPosition + reflectDir * L;

    nuv = GetUV(currentRay); // проецирование позиции на экран
    float n = GetDepth(nuv.xy); // чтение глубины из DepthMap по UV

    float3 newPosition = GetPosition2(nuv.xy, n);
    L = length(texelPosition - newPosition);
}

И автор объясняет его следующим образом: "В моем варианте мы берем некоторое начальное приближение L и динамически меняем его исходя из расстояния между нашим текселем и позицией, которую мы “восстановили”.

Про общий свет пока не заморачиваюсь, сейчас главное SSR отладить.

SuslikМодераторwww11 окт. 201813:35#3
DEN 3D
такая схема и будет сходиться только для простых случаев вроде вертикальных плоскостей. чем сложнее depth buffer, тем больше артефактов она будет давать. например, напрочь будет пропускать отражения тонких горизонтальных объектов в полу. по этой же причине у самого автора на фоне правого ящика хреновина отражается криво, с такими же артефактами, как у тебя:
Изображение

ещё раз — рекомендую сначала реализовать самую простую схему с реймарчингом с постоянным шагом, потом уже её улучшать.

Правка: 11 окт. 2018 13:39

DEN 3DПостоялецwww11 окт. 201813:54#4
Suslik
Спасибо, понял.. Можешь порекоммендовать ссылки
на хорошие имплементации SSR с нормальным рэймарчингом?
Только не в составе движков...
SuslikМодераторwww11 окт. 201814:01#5
DEN 3D
я не видел ни одной реализации, которая была бы настолько хорошей, что её можно взять себе и забыть. все делают screenspace raymarching по-разному не от хорошей жизни, а потому что идеального решения всё ещё нет. бери и сам экспериментируй, начать можно с гугла по запросу "screenspace raymarching". некоторые реализации можно посмотреть на шейдертое(например, по запросу parallax mapping), но там практически всегда используются distance field'ы вместо карты высот вроде depth buffer'а.
DEN 3DПостоялецwww11 окт. 201814:32#6
На самом деле я пробовал и другие варианты.. Но они дают вообще неадекватный результат(
Этот вариант пока самый лучший..
codingmonkeyПостоялецwww11 окт. 201814:44#7
>Этот вариант пока самый лучший..
глянь это
https://blenderartists.org/t/ssr-screen-space-reflections-shader-v0-4/685927
DEN 3DПостоялецwww11 окт. 201817:04#8
codingmonkey
Спасибо! Выглядит интересным) Буду пробовать..
DEN 3DПостоялецwww11 окт. 201821:16#9
codingmonkey
Начал изучать эту реализацию, не понимаю в каком именно пространстве возвращают
координаты функции getViewPosition и getViewCoord? Мне, конечно, через матрицы
привычнее реализация, чем тащить в шейдер кучу параметров камеры - FOVY, Aspect, и.т.д..

Ну и в результате я не понимаю вообще в каком там пространстве координаты))

И ещё там GLSL, а мне надо под DX на HLSL - там могут быть различия и нюансы из-за
разницы систем координат...

DEN 3DПостоялецwww11 окт. 201821:17#10
Например, точно уверен, что под DX вот эта формула будет выглядеть иначе:
-zfar * znear / (zdepth * (zfar - znear) - zfar);
IBetsПостоялецwww12 окт. 201810:20#11
DEN 3D
Попробуй шейдер от KillZone, можешь курить шейдеры CryTek(там реальней разобраться нежели в Unreal)

Правка: 12 окт. 2018 10:21

IBetsПостоялецwww12 окт. 201810:22#12
DEN 3D
Взглянул по беглому и нашел уже ошибку. У тебя UV координаты в DX и GL отличаются убери минус перед 0.5
DanilwПользовательwww12 окт. 201811:21#13
могу ошибаться, но подход описаный в статье "в корне не верный"
использовать рей трейсинг пошаговый(который будет ошибаться и проваливаться из за величины шага) и строить "SDF" из контуров-слишком затратно и не будет работать в реальном времени

>>на хорошие имплементации SSR с нормальным рэймарчингом?
кубемапы спасут мир

если у тебя фотореалистичная сцена строй ее на рей-трейсере целиком(тебеж 1 кадр нужен)
если реал-тайм игра то кубемапы... или тратить пять лет на разработку супер оптимизированного алгоритма (используя cuda и процессор чтоб свести к минимуму потери производительности)

SuslikМодераторwww12 окт. 201811:27#14
Danilw
всё мимо кассы
Страницы: 1 2 3 4 Следующая »

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр