SKYFORGE: Технологии рендеринга 
Сергей Макеев, технический директор
План 
! Что такое Skyforge? 
! Графические технологии, использованные при 
разработке графического движка Skyforge 
! Physically Based Shading 
! Deferred Shading 
! Reversed Depth buffer 
! Выводы 
! Q&A
Skyforge для программиста 
! Fantasy + Sci-fi 
! Свой движок 
! Nextgen графика в MMO 
! Стилизованная реальность 
! Огромные открытые локации 
! Материалы и освещение максимально естественны 
! 4 графических программиста
Physically Based Shading
Зачем ? 
! Зачем нужен шейдинг, основанный на физике? 
! Более реалистичная и сведенная картинка – меньше 
настраивать 
! Материалы и свет разделены – меньше настраивать 
! Меньше параметров в материале – меньше настраивать 
! Соблюдается закон сохранения энергии – меньше 
настраивать 
! Физически корректно не значит фотореалистично 
(см. работы Disney, Pixar и т.д.)
Физика процесса 
! В реальной жизни поверхность не гладкая 
! Поверхность объектов состоит из множества маленьких 
неровностей. Эти неровности настолько маленькие, что не видны 
невооруженным глазом 
! Размер микронеровностей больше длины волны и они влияют на 
отражение света от поверхности
Бумага под электронным микроскопом
Бумага под электронным микроскопом
Микрогеометрия поверхности 
! Часть света отражается от поверхности 
! Часть проникает внутрь поверхности и 
переизлучается или поглощается
Микрогеометрия поверхности 
! Мы оперируем на уровне пикселей 
! Нужно учитывать отраженный и переизлученный свет
BRDF 
! BRDF 
! Bidirectional 
! Reflection 
! Distribution 
! Function 
! Цель: рассчитать количество энергии, излучаемой в сторону наблюдателя, 
при заданном входящем излучении 
! В теории, многомерная функция - 3D, 4D, 6D 
! На практике, мы будем рассматривать функцию от двух параметров
Рассеянный свет (diffuse) 
! Можно пренебречь точкой входа и выхода луча 
! Считаем, что весь рассеянный свет 
распределяется равномерно
Рассеянный свет (diffuse) 
! Функция для расчета рассеянного света 
! l – направление света 
! v – направление взгляда (не используется в данной модели) 
! albedo – векторный параметр, который определяет сколько энергии рассеивается, а сколько поглощается материалом 
! n – нормаль поверхности 
! Деление на PI закон сохранения энергии 
! Всем известный dot ( N, L ) 
! dot ( N, L ) это cos между векторами N, L
Рассеянный свет (diffuse) 
! Площадь проекции зависит от угла падения 
! И равна cos(N, L)
Рассеянный свет (diffuse) 
! На поверхность попадает меньше энергии в 
зависимости от угла падения
Отраженный свет (specular) 
! Отражение света 
! Направление отражения меняется 
из-за микрограней
Отраженный свет (specular) 
! Отражение света 
! Менее гладкая поверхность
Микрогеометрия поверхности 
! Microfacet theory 
! Моделирует поверхность как множество 
микрограней 
! Каждая микрогрань - идеально отражающее 
зеркало 
! Нам нужна сумма вклада каждой микрограни в 
освещение (интеграл) 
! Слишком много вычислений, чтобы решить 
численно
Microfacet BRDF 
! Функция для расчета отраженного света (microfacet theory) 
! D – функция распределения нормали. Определяет, как микрограни распределены вдоль 
направления h (от этой функции меняется форма блика) 
! F – формула Френеля 
! G – функция затенения микрогранями друг друга 
! l – направление света 
! v – направление взгляда 
! n – нормаль поверхности 
! h – вектор между векторами l and v (half vector)
Half vector 
! Half vector, вектор между L и V 
! Физический смысл half vector 
! Фильтрация микрограней, которые вносят вклад в BRDF 
! h = m значит микрогрань отражает свет, видимый наблюдателю
Microfacet BRDF 
! Функция для расчета отраженного света (microfacet theory) 
! D – функция распределения нормали. Определяет, как микрограни распределены вдоль 
направления h (от этой функции меняется форма блика) 
! F – формула Френеля 
! G – функция затенения микрогранями друг друга 
! l – направление света 
! v – направление взгляда 
! n – нормаль поверхности 
! h – вектор между векторами l and v (half vector)
Распределение микрограней 
! Степень косинуса в качестве функции 
распределения микрограней (Blinn-Phong) 
! Степень 0.25 .. 65536
Microfacet BRDF 
! Функция для расчета отраженного света (microfacet theory) 
! D – функция распределения нормали. Определяет, как микрограни распределены вдоль 
направления h (от этой функции меняется форма блика) 
! F – формула Френеля 
! G – функция затенения микрогранями друг друга 
! l – направление света 
! v – направление взгляда 
! n – нормаль поверхности 
! h – вектор между векторами l and v (half vector)
Френель 
!ло
Френель
Френель 
! Аппроксимация Шлика 
! f0 – можно получить из IOR (Index of refraction)
Френель 
! Френель: задает, сколько света будет поглощено, а сколько 
отражено под разными углами 
! Физический смысл f0: процент света, отраженный от 
материала под прямым углом 
! Обычное значение f0 для диэлектриков 2% - 5% 
! Металлы рассеивают мало света, в основном отражают
Microfacet BRDF 
! Функция для расчета отраженного света (microfacet theory) 
! D – функция распределения нормали. Определяет, как микрограни распределены вдоль 
направления h (от этой функции меняется форма блика) 
! F – формула Френеля 
! G – функция затенения микрогранями друг друга 
! l – направление света 
! v – направление взгляда 
! n – нормаль поверхности 
! h – вектор между векторами l and v (half vector)
Microfacet BRDF 
! Пример того, какая часть света скрывается микрогранями
Видимость микрограней 
! Используем простейшую функцию видимости
Отраженный свет (specular) 
! Функция отраженного света 
! Соответствует normalized Blinn-Phong model
Изменение параметров 
! Изменение F0 ( IOR ) 
! Изменение шероховатости
Сохранение энергии 
! Закон сохранения энергии 
! Количество отраженного света <= 1 
! Т.е. рассеянный + отраженный свет <= 1 
! Из этого следует: яркость и площадь блика от 
источника света связаны
Шероховатость 100%
Шероховатость 80%
Шероховатость 50%
Шероховатость 30%
Шероховатость 10%
Интенсивность света 
! Интенсивность света обратно пропорциональна квадрату 
расстояния до источника света 
! Хорошо подходит для точечных источников, не имеющих 
объема 
! Мы хотим источник света, у которого есть размер (area light) 
! Стремится к нулю, но никогда его не достигает
Интенсивность света 
! Нужно учесть два радиуса 
! Rinner – размер источника 
! Router – дистанция, на которой вкладом в освещение 
можно пренебречь
Интенсивность света 
! Наша функция затухания 
! Константа внутри Rinner 
! На дистанции Router равна 0 
float GetAttenuation(float distance, float lightInnerR, float invLightOuterR) 
{ 
float d = max(distance, lightInnerR); 
return saturate(1.0 - pow(d * invLightOuterR, 4.0)) / (d * d + 1.0); 
}
Интенсивность света 
! График затухания света
Модель материала 
! Модель материала 
! Base color 
! Albedo для диэлектрика 
! Векторная часть F0 для проводника 
! Normal (нормаль поверхности, макро) 
! Roughness (шероховатость поверхности, микро) 
! Fresnel F0 (практически всегда константа для 
диэлектрика, скалярная часть F0 для металла) 
! Metal (маска: металл или диэлектрик)
Base color ( Albedo )
Base color ( Albedo )
Normal map
Gloss (Roughness)
Specular ( F0 / IOR )
Metal
Пример материала
Пример материала
Пример материала
Пример материала
Пример материала
Пример материала
Deferred Shading
Deferred shading 
! Плюсы 
! Геометрия отделена от освещения 
! Много источников света 
! Нет комбинаторного взрыва в шейдерах 
! Минусы 
! Bandwidth 
! Источники света с тенями по-прежнему дорогие 
! Сложность с разными BRDF 
! Поддержка прозрачности
Deferred shading 
! Skyforge Gbuffer layout (2xRGBA8, 1xRGB10A2, 1xD24S8) 
! 96 bits + 24 bits + 8 bits = 128 bits per pixel
Финальный результат
Base color
Нормали (world space)
Шероховатость
Fresnel reflectance (F0)
Metallic
HDR: Global Illumination + Emissive
Ambient occlusion
Без локального освещения и волюметриков
Финальный результат
Tips & Tricks
Реконструкция позиции 
! Алгоритмам освещения нужна позиция 
! world space 
! shadow space 
! view space 
! и т.д. 
! В Gbuffer хранится только глубина 
! используем INTZ (DX9) 
! гиперболическое распределение " 
! Нужна реконструкция позиции из глубины
Реконструкция позиции 
! Преобразуем depth буфер в линейный 
! INTZ в R32F 
! Сразу после заполнения Gbuffer 
// Функция для преобразования глубины с гиперболическим распределением в линейную 
float ConvertHyperbolicDepthToLinear(float hyperbolicDepth) 
{ 
return ((zNear / (zNear-zFar)) * zFar) / (hyperbolicDepth - (zFar / (zFar-zNear))); 
}
Подобие треугольников 
! Треугольник P1, P2, P3 
подобен треугольнику P1, P4, P5
Подобие треугольников 
! Треугольник P1, P2, P3
Подобие треугольников 
! Треугольник P1, P4, P5
Реконструкция позиции 
! Вершинный шейдер 
! Считаем треугольник P1, P2, P3 в вершинном шейдере 
! Передаем отрезок P1, P3 в пиксельный шейдер 
! Пиксельный шейдер 
! Получаем интерполированный вектор P1,P3 (rayDir) через интерполятор 
! Считываем линейную глубину 
! position = cameraPosition + rayDir * linearDepth 
! Очень быстро: mad + интерполятор 
! Можно реконструировать позицию в любом удобном пространстве. 
world, view, shadow и т.д. 
! HLSL код в бонус слайдах
Reversed Depth Buffer
Большая дальность видимости
Большая дальность видимости
Большая дальность видимости
Большая дальность видимости
Reversed Depth Buffer 
! Reversed depth buffer 
near = 1 
far = 0 
! Работает с fixed point depth, формат D24S8 
! Нужно инвертировать D3DRS_ZFUNC 
D3DCMP_GREATEREQUAL 
! Всегда инвертируйте матрицу проекции 
Некорректно инвертировать на стадии viewport’а или в шейдере
Матрица проекции
Матрица проекции 
! Как получается глубина? 
! float4 p = mul( float4( pos, 1 ), mtxProjection ); 
! float depth = p.z / p.w;
Сравнение методов 
! Z near = 0.5 
! Z far = 50000.0
Сравнение методов 
! Стандартный метод 
! Reversed depth buffer
Сравнение методов 
! Стандартный метод 
! Reversed depth buffer
Numeric error – стандартный метод
Numeric error – reversed depth buffer
Numeric error – reversed depth buffer
Reversed depth buffer : выводы 
! D24 легко покрывает дальность в 50 км 
! Reverse depth подходит для любого движка 
! Лучше закладывать с самого начала проекта 
! Извлечение плоскостей фрустума из матрицы 
! Bias у теней 
! и т.д. 
! При возможности используйте float depth буфер
Заключение 
! Nextgen графика в MMO уже реальность 
! Все меньше отличий от 
ААА консольных тайтлов 
! Физичный шейдинг упрощает 
производство контента 
! Нам нужны графические программисты !
СПАСИБО ЗА ВНИМАНИЕ! 
ВОПРОСЫ? 
s.makeev@corp.mail.ru
Bonus
Реконструкция позиции: Vertex shader 
// Часть матрицы проекции 
float tanHalfVerticalFov; // invProjection.11; 
float tanHalfHorizontalFov; // invProjection.00; 
// Базис камеры в пространстве реконструкции 
float3 camBasisUp; 
float3 camBasisSide; 
float3 camBasisFront; 
// postProjectiveSpacePosition в homogeneous projection space 
float3 CreateRay(float4 postProjectiveSpacePosition) 
{ 
float3 leftRight = camBasisSide * -postProjectiveSpacePosition.x * tanHalfHorizontalFov; 
float3 upDown = camBasisUp * postProjectiveSpacePosition.y * tanHalfVerticalFov; 
float3 forward = camBasisFront; 
return (forward + leftRight + upDown); 
} 
void VertexShader(float4 inPos, out float4 outPos : POSITION, out float3 rayDir : TEXCOORD0) 
{ 
outPos = inPos; 
rayDir = CreateRay(inPos); 
}
Реконструкция позиции: Pixel shader 
// Позиция камеры в пространстве реконструкции 
float3 camPosition; 
float4 PixelShader(float3 rayDir : TEXCOORD0) : COLOR0 
{ 
... 
float linearDepth = tex2D(linearDepthSampler, uv).r; 
float3 position = camPosition + rayDir * linearDepth; 
... 
} 
// Функция для преобразования глубины с гиперболическим распределением в линейную 
float ConvertHyperbolicDepthToLinear(float hyperbolicDepth) 
{ 
return ((zNear / (zNear-zFar)) * zFar) / (hyperbolicDepth - (zFar / (zFar-zNear))); 
}

Skyforge rendering tech (KRI 2014)

  • 1.
    SKYFORGE: Технологии рендеринга Сергей Макеев, технический директор
  • 2.
    План ! Чтотакое Skyforge? ! Графические технологии, использованные при разработке графического движка Skyforge ! Physically Based Shading ! Deferred Shading ! Reversed Depth buffer ! Выводы ! Q&A
  • 4.
    Skyforge для программиста ! Fantasy + Sci-fi ! Свой движок ! Nextgen графика в MMO ! Стилизованная реальность ! Огромные открытые локации ! Материалы и освещение максимально естественны ! 4 графических программиста
  • 12.
  • 13.
    Зачем ? !Зачем нужен шейдинг, основанный на физике? ! Более реалистичная и сведенная картинка – меньше настраивать ! Материалы и свет разделены – меньше настраивать ! Меньше параметров в материале – меньше настраивать ! Соблюдается закон сохранения энергии – меньше настраивать ! Физически корректно не значит фотореалистично (см. работы Disney, Pixar и т.д.)
  • 14.
    Физика процесса !В реальной жизни поверхность не гладкая ! Поверхность объектов состоит из множества маленьких неровностей. Эти неровности настолько маленькие, что не видны невооруженным глазом ! Размер микронеровностей больше длины волны и они влияют на отражение света от поверхности
  • 15.
  • 16.
  • 17.
    Микрогеометрия поверхности !Часть света отражается от поверхности ! Часть проникает внутрь поверхности и переизлучается или поглощается
  • 18.
    Микрогеометрия поверхности !Мы оперируем на уровне пикселей ! Нужно учитывать отраженный и переизлученный свет
  • 19.
    BRDF ! BRDF ! Bidirectional ! Reflection ! Distribution ! Function ! Цель: рассчитать количество энергии, излучаемой в сторону наблюдателя, при заданном входящем излучении ! В теории, многомерная функция - 3D, 4D, 6D ! На практике, мы будем рассматривать функцию от двух параметров
  • 20.
    Рассеянный свет (diffuse) ! Можно пренебречь точкой входа и выхода луча ! Считаем, что весь рассеянный свет распределяется равномерно
  • 21.
    Рассеянный свет (diffuse) ! Функция для расчета рассеянного света ! l – направление света ! v – направление взгляда (не используется в данной модели) ! albedo – векторный параметр, который определяет сколько энергии рассеивается, а сколько поглощается материалом ! n – нормаль поверхности ! Деление на PI закон сохранения энергии ! Всем известный dot ( N, L ) ! dot ( N, L ) это cos между векторами N, L
  • 22.
    Рассеянный свет (diffuse) ! Площадь проекции зависит от угла падения ! И равна cos(N, L)
  • 23.
    Рассеянный свет (diffuse) ! На поверхность попадает меньше энергии в зависимости от угла падения
  • 24.
    Отраженный свет (specular) ! Отражение света ! Направление отражения меняется из-за микрограней
  • 25.
    Отраженный свет (specular) ! Отражение света ! Менее гладкая поверхность
  • 26.
    Микрогеометрия поверхности !Microfacet theory ! Моделирует поверхность как множество микрограней ! Каждая микрогрань - идеально отражающее зеркало ! Нам нужна сумма вклада каждой микрограни в освещение (интеграл) ! Слишком много вычислений, чтобы решить численно
  • 27.
    Microfacet BRDF !Функция для расчета отраженного света (microfacet theory) ! D – функция распределения нормали. Определяет, как микрограни распределены вдоль направления h (от этой функции меняется форма блика) ! F – формула Френеля ! G – функция затенения микрогранями друг друга ! l – направление света ! v – направление взгляда ! n – нормаль поверхности ! h – вектор между векторами l and v (half vector)
  • 28.
    Half vector !Half vector, вектор между L и V ! Физический смысл half vector ! Фильтрация микрограней, которые вносят вклад в BRDF ! h = m значит микрогрань отражает свет, видимый наблюдателю
  • 29.
    Microfacet BRDF !Функция для расчета отраженного света (microfacet theory) ! D – функция распределения нормали. Определяет, как микрограни распределены вдоль направления h (от этой функции меняется форма блика) ! F – формула Френеля ! G – функция затенения микрогранями друг друга ! l – направление света ! v – направление взгляда ! n – нормаль поверхности ! h – вектор между векторами l and v (half vector)
  • 30.
    Распределение микрограней !Степень косинуса в качестве функции распределения микрограней (Blinn-Phong) ! Степень 0.25 .. 65536
  • 31.
    Microfacet BRDF !Функция для расчета отраженного света (microfacet theory) ! D – функция распределения нормали. Определяет, как микрограни распределены вдоль направления h (от этой функции меняется форма блика) ! F – формула Френеля ! G – функция затенения микрогранями друг друга ! l – направление света ! v – направление взгляда ! n – нормаль поверхности ! h – вектор между векторами l and v (half vector)
  • 32.
  • 33.
  • 34.
    Френель ! АппроксимацияШлика ! f0 – можно получить из IOR (Index of refraction)
  • 35.
    Френель ! Френель:задает, сколько света будет поглощено, а сколько отражено под разными углами ! Физический смысл f0: процент света, отраженный от материала под прямым углом ! Обычное значение f0 для диэлектриков 2% - 5% ! Металлы рассеивают мало света, в основном отражают
  • 36.
    Microfacet BRDF !Функция для расчета отраженного света (microfacet theory) ! D – функция распределения нормали. Определяет, как микрограни распределены вдоль направления h (от этой функции меняется форма блика) ! F – формула Френеля ! G – функция затенения микрогранями друг друга ! l – направление света ! v – направление взгляда ! n – нормаль поверхности ! h – вектор между векторами l and v (half vector)
  • 37.
    Microfacet BRDF !Пример того, какая часть света скрывается микрогранями
  • 38.
    Видимость микрограней !Используем простейшую функцию видимости
  • 39.
    Отраженный свет (specular) ! Функция отраженного света ! Соответствует normalized Blinn-Phong model
  • 40.
    Изменение параметров !Изменение F0 ( IOR ) ! Изменение шероховатости
  • 41.
    Сохранение энергии !Закон сохранения энергии ! Количество отраженного света <= 1 ! Т.е. рассеянный + отраженный свет <= 1 ! Из этого следует: яркость и площадь блика от источника света связаны
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
    Интенсивность света !Интенсивность света обратно пропорциональна квадрату расстояния до источника света ! Хорошо подходит для точечных источников, не имеющих объема ! Мы хотим источник света, у которого есть размер (area light) ! Стремится к нулю, но никогда его не достигает
  • 48.
    Интенсивность света !Нужно учесть два радиуса ! Rinner – размер источника ! Router – дистанция, на которой вкладом в освещение можно пренебречь
  • 49.
    Интенсивность света !Наша функция затухания ! Константа внутри Rinner ! На дистанции Router равна 0 float GetAttenuation(float distance, float lightInnerR, float invLightOuterR) { float d = max(distance, lightInnerR); return saturate(1.0 - pow(d * invLightOuterR, 4.0)) / (d * d + 1.0); }
  • 50.
    Интенсивность света !График затухания света
  • 51.
    Модель материала !Модель материала ! Base color ! Albedo для диэлектрика ! Векторная часть F0 для проводника ! Normal (нормаль поверхности, макро) ! Roughness (шероховатость поверхности, микро) ! Fresnel F0 (практически всегда константа для диэлектрика, скалярная часть F0 для металла) ! Metal (маска: металл или диэлектрик)
  • 53.
    Base color (Albedo )
  • 54.
    Base color (Albedo )
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
    Deferred shading !Плюсы ! Геометрия отделена от освещения ! Много источников света ! Нет комбинаторного взрыва в шейдерах ! Минусы ! Bandwidth ! Источники света с тенями по-прежнему дорогие ! Сложность с разными BRDF ! Поддержка прозрачности
  • 67.
    Deferred shading !Skyforge Gbuffer layout (2xRGBA8, 1xRGB10A2, 1xD24S8) ! 96 bits + 24 bits + 8 bits = 128 bits per pixel
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
    Реконструкция позиции !Алгоритмам освещения нужна позиция ! world space ! shadow space ! view space ! и т.д. ! В Gbuffer хранится только глубина ! используем INTZ (DX9) ! гиперболическое распределение " ! Нужна реконструкция позиции из глубины
  • 80.
    Реконструкция позиции !Преобразуем depth буфер в линейный ! INTZ в R32F ! Сразу после заполнения Gbuffer // Функция для преобразования глубины с гиперболическим распределением в линейную float ConvertHyperbolicDepthToLinear(float hyperbolicDepth) { return ((zNear / (zNear-zFar)) * zFar) / (hyperbolicDepth - (zFar / (zFar-zNear))); }
  • 81.
    Подобие треугольников !Треугольник P1, P2, P3 подобен треугольнику P1, P4, P5
  • 82.
    Подобие треугольников !Треугольник P1, P2, P3
  • 83.
    Подобие треугольников !Треугольник P1, P4, P5
  • 84.
    Реконструкция позиции !Вершинный шейдер ! Считаем треугольник P1, P2, P3 в вершинном шейдере ! Передаем отрезок P1, P3 в пиксельный шейдер ! Пиксельный шейдер ! Получаем интерполированный вектор P1,P3 (rayDir) через интерполятор ! Считываем линейную глубину ! position = cameraPosition + rayDir * linearDepth ! Очень быстро: mad + интерполятор ! Можно реконструировать позицию в любом удобном пространстве. world, view, shadow и т.д. ! HLSL код в бонус слайдах
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
    Reversed Depth Buffer ! Reversed depth buffer near = 1 far = 0 ! Работает с fixed point depth, формат D24S8 ! Нужно инвертировать D3DRS_ZFUNC D3DCMP_GREATEREQUAL ! Всегда инвертируйте матрицу проекции Некорректно инвертировать на стадии viewport’а или в шейдере
  • 91.
  • 92.
    Матрица проекции !Как получается глубина? ! float4 p = mul( float4( pos, 1 ), mtxProjection ); ! float depth = p.z / p.w;
  • 93.
    Сравнение методов !Z near = 0.5 ! Z far = 50000.0
  • 94.
    Сравнение методов !Стандартный метод ! Reversed depth buffer
  • 95.
    Сравнение методов !Стандартный метод ! Reversed depth buffer
  • 96.
    Numeric error –стандартный метод
  • 97.
    Numeric error –reversed depth buffer
  • 98.
    Numeric error –reversed depth buffer
  • 99.
    Reversed depth buffer: выводы ! D24 легко покрывает дальность в 50 км ! Reverse depth подходит для любого движка ! Лучше закладывать с самого начала проекта ! Извлечение плоскостей фрустума из матрицы ! Bias у теней ! и т.д. ! При возможности используйте float depth буфер
  • 100.
    Заключение ! Nextgenграфика в MMO уже реальность ! Все меньше отличий от ААА консольных тайтлов ! Физичный шейдинг упрощает производство контента ! Нам нужны графические программисты !
  • 101.
    СПАСИБО ЗА ВНИМАНИЕ! ВОПРОСЫ? s.makeev@corp.mail.ru
  • 102.
  • 103.
    Реконструкция позиции: Vertexshader // Часть матрицы проекции float tanHalfVerticalFov; // invProjection.11; float tanHalfHorizontalFov; // invProjection.00; // Базис камеры в пространстве реконструкции float3 camBasisUp; float3 camBasisSide; float3 camBasisFront; // postProjectiveSpacePosition в homogeneous projection space float3 CreateRay(float4 postProjectiveSpacePosition) { float3 leftRight = camBasisSide * -postProjectiveSpacePosition.x * tanHalfHorizontalFov; float3 upDown = camBasisUp * postProjectiveSpacePosition.y * tanHalfVerticalFov; float3 forward = camBasisFront; return (forward + leftRight + upDown); } void VertexShader(float4 inPos, out float4 outPos : POSITION, out float3 rayDir : TEXCOORD0) { outPos = inPos; rayDir = CreateRay(inPos); }
  • 104.
    Реконструкция позиции: Pixelshader // Позиция камеры в пространстве реконструкции float3 camPosition; float4 PixelShader(float3 rayDir : TEXCOORD0) : COLOR0 { ... float linearDepth = tex2D(linearDepthSampler, uv).r; float3 position = camPosition + rayDir * linearDepth; ... } // Функция для преобразования глубины с гиперболическим распределением в линейную float ConvertHyperbolicDepthToLinear(float hyperbolicDepth) { return ((zNear / (zNear-zFar)) * zFar) / (hyperbolicDepth - (zFar / (zFar-zNear))); }