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

GODOT->UNITY: помогите разобраться с буффером глубины. (2 стр)

Страницы: 1 2
#15
0:57, 11 сен 2023

Инвертирование оси делается для матрицы проекции

#16
23:23, 11 сен 2023

В общем-то получилось сделать эффект, но почему-то текстура глубины не рендерится камерой редактора.
Или рендерится неверно.
Повесил такой скрипт:

[ExecuteInEditMode]
public class CameraDepthOn : MonoBehaviour {

    void OnEnable() {
        Camera.main.depthTextureMode |= DepthTextureMode.Depth;
    }
}

Текстуру глубины читаю так:

fixed4 frag(v2f i) : SV_Target{
                float2 SCREEN_UV = i.screenPos.xy / i.screenPos.w;
                float depth = LinearEyeDepth( tex2D(_CameraDepthTexture, SCREEN_UV).r );

В итоге текстура глубины выглядит так (везде текстура глубины GameView):

333 | GODOT->UNITY: помогите разобраться с буффером глубины.

Замучился с текстурой глубины, не могу понять почему камера редактора не рендерит свою текстуру глубины.
Не знаете как рендерить текстуры глубины для камеры редактора. Иначе нельзя видеть эффект в режиме редактора...

#17
19:57, 12 сен 2023

Не получилось в итоге перенести годотовский шейдер.
Вот есть этот шейдер, сейчас по шагам его разберу:

// ЧИТАЕМ ГЛУБИНУ, С НЕЙ ПРОБЛЕМ НЕТ, В ШЕЙДЕРЕ ЮНИТИ ТУТ ВСЕ ХОРОШО:
float depth = textureLod(depth_tex, SCREEN_UV, 0.0).r;

// Здесь координаты с экрана (от (-1,-1) до (1,1)) переводим в пространство камеры (NDC(ClipSpace) => ViewSpace))
vec4 upos = INV_PROJECTION_MATRIX * vec4(SCREEN_UV * 2.0 - 1.0, depth, 1.0);
// upos в пространстве камеры (СОВПАДАЕТ С ТЕМ ЧТО В UNITY)
// upos выглядит в юнити и годот одинаково на Direct11, OGL3/ES/Vulcan

// [url=https://docs.unity3d.com/ScriptReference/Camera-worldToCameraMatrix.html]***Согласно инструкциям от юнити:[/url]
// View matrix это Camera.worldToCameraMatrix
// INV_VIEW_MATRIX  = Camera.main.cameraToWorldMatrix; <= тогда это инверсная, использую ее
// Так мы позицию из пространства камеры переводим в мировое пространство (ТАК ЭТО В ГОДОТЕ):
vec4 wpos = INV_VIEW_MATRIX * (upos / upos.w);//<<<

Если геометрия с шейдером стоит в (0,0,0), вращения в 0, то wpos визуально как и в годоте.
А вот если вращать или двигать обект, то появляются расхождения. Вот как это выглядит:
GU | GODOT->UNITY: помогите разобраться с буффером глубины.


Если показывать на схеме, то мы с конца (красная стрелка) пришли к WorldPos благодаря глубине и координатам экрана:
00 | GODOT->UNITY: помогите разобраться с буффером глубины.

В теории все хорошо, Мануал годота говорит in mat4 INV_VIEW_MATRIX - View space to world space transform.
То есть вью матрица та, что надо.
Мануал юнити тоже говорит(***), что вью матрица та, что надо.
На предыдущем шаге значения юнити и годота совпадали, но после того как мы помножили инверсную вью-матрицу на (upos / upos.w), в годоте получили один результат, а в юнити другой.

Не знаю в чем проблема, целый день прыгаю с бубном возле матриц пытаясь понять почему в юнити не удается перевести координаты. Перепробовал, наверно, вообще все. В чем может быть проблема?
Если кому интересно, могу проекты скинуть.

#18
21:06, 12 сен 2023

Слушай, а скинь мне, я попробую перенести, любопытно

#19
22:20, 12 сен 2023

Исходный проект годота и юнити.

#20
5:03, 13 сен 2023

Может проще написать что в итоге надо сделать?
Что этот шейдер делает?

#21
8:19, 13 сен 2023

atomic
> Может проще написать что в итоге надо сделать?
> Что этот шейдер делает?

Достаточно обычная математика, проблема в технической части.
Есть текстура глубины и нужно по ней найти worldPosition.
На основе этого worldPosition на объектах нужно отрендерить декали. Я использую реймач, worldPosition помогает рендерить декали корректно.

#22
12:15, 13 сен 2023

Alerr
> Есть текстура глубины и нужно по ней найти worldPosition.

// Получаем линейную глубину
float depth = LinearEyeDepth( SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv) );

// Получаем координаты в пространстве камеры
float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);
float2 p13_31 = float2(unity_CameraProjection._13, unity_CameraProjection._23);
float3 positionCS = float3((i.uv * 2 - 1 - p13_31) / p11_22, 1) * depth;

// Получаем мировые координаты
float3 positionWS = mul( unity_CameraToWorld, float4(positionCS, 1) );  
#23
13:09, 13 сен 2023

marggob
Спасибо, но у меня тоже этот результат получаетсяя. Когда камерой кручу,
то WorldSpace искажается (цвета меняются) как на скринах справа:
GU | GODOT->UNITY: помогите разобраться с буффером глубины.

Насколько понимаю этого не должно быть. Напрмер в годоте этого нет (скрины слева).

Откуда берется это искажение?

Нашел недавно гит от разработчика юнити, там написано:

// world, view, projection matrices
var world = obj.transform.localToWorldMatrix;
var view = cam.worldToCameraMatrix;
var proj = cam.projectionMatrix;

// the actual projection matrix used in shaders
// is actually massaged a bit to work across all platforms
// (different Z value ranges etc.)
var gpuProj = GL.GetGPUProjectionMatrix (proj, false);
var gpuMV = view * world; // UNITY_MATRIX_MV
var gpuMVP = gpuProj * view * world; // UNITY_MATRIX_MVP

Я, конечно, еще раз попробовал, но результат тот же самый. wPos цвета искажаются. Этого же не должно быть, нет?

#24
14:40, 13 сен 2023

Alerr
Написанный мной метод я использую постоянно в постэффектах. Он всегда отрабатывает корректно. Ни разу не было каких-то косяков или вывертов непонятных. Где-то что-то вы делаете не правильно или ни в том порядке.

#25
14:49, 13 сен 2023

marggob
> Написанный мной метод я использую постоянно в постэффектах. Он всегда отрабатывает корректно.
Я его почти буквально тупо взял и вставил.

v2f vert (appdata v) {
    v2f o;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.screenPos = ComputeScreenPos(o.vertex);
}

fragment:
float2 SCREEN_UV = i.screenPos.xy / i.screenPos.w;

//=======================================================
// Получаем линейную глубину
float depth = LinearEyeDepth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, SCREEN_UV));

// Получаем координаты в пространстве камеры
float2 p11_22 = float2(unity_CameraProjection._11, unity_CameraProjection._22);
float2 p13_31 = float2(unity_CameraProjection._13, unity_CameraProjection._23);
float3 positionCS = float3((SCREEN_UV * 2 - 1 - p13_31) / p11_22, 1) * depth;

// Получаем мировые координаты
float3 positionWS = mul(unity_CameraToWorld, float4(positionCS, 1));
return float4(positionWS, 1);
//=======================================================

Update:
Секунду, похоже Ваш код работает...

#26
14:53, 13 сен 2023

Alerr
> Секунду, похоже Ваш код работает...

+ Показать

Естественно работает. Многократно проверено и перепроверено. )))

#27
16:27, 13 сен 2023

marggob
>Естественно работает. Многократно проверено и перепроверено. )))
В общем большое Вам спасибо!

Можете разжевать что тут делаете: (SCREEN_UV * 2 - 1 - p13_31) / p11_22 ?

#28
20:26, 14 сен 2023

Alerr
> Можете разжевать что тут делаете
Ну, честно говоря я уже не помню. Да и код-то я брал готовый откуда-то. Хоть и разбирал что и для чего там делается, но уже всё вылетело из головы за ненадобностью. ))))
Но по логике там что-то связанное с Viewport Rect и FOV. Но могу и ошибаться.

Страницы: 1 2
ПрограммированиеФорумГрафика

Тема в архиве.