Инвертирование оси делается для матрицы проекции
В общем-то получилось сделать эффект, но почему-то текстура глубины не рендерится камерой редактора.
Или рендерится неверно.
Повесил такой скрипт:
[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):
Замучился с текстурой глубины, не могу понять почему камера редактора не рендерит свою текстуру глубины.
Не знаете как рендерить текстуры глубины для камеры редактора. Иначе нельзя видеть эффект в режиме редактора...
Не получилось в итоге перенести годотовский шейдер.
Вот есть этот шейдер, сейчас по шагам его разберу:
// ЧИТАЕМ ГЛУБИНУ, С НЕЙ ПРОБЛЕМ НЕТ, В ШЕЙДЕРЕ ЮНИТИ ТУТ ВСЕ ХОРОШО: 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 визуально как и в годоте.
А вот если вращать или двигать обект, то появляются расхождения. Вот как это выглядит:
Если показывать на схеме, то мы с конца (красная стрелка) пришли к WorldPos благодаря глубине и координатам экрана:
В теории все хорошо, Мануал годота говорит in mat4 INV_VIEW_MATRIX - View space to world space transform.
То есть вью матрица та, что надо.
Мануал юнити тоже говорит(***), что вью матрица та, что надо.
На предыдущем шаге значения юнити и годота совпадали, но после того как мы помножили инверсную вью-матрицу на (upos / upos.w), в годоте получили один результат, а в юнити другой.
Не знаю в чем проблема, целый день прыгаю с бубном возле матриц пытаясь понять почему в юнити не удается перевести координаты. Перепробовал, наверно, вообще все. В чем может быть проблема?
Если кому интересно, могу проекты скинуть.
Слушай, а скинь мне, я попробую перенести, любопытно
Может проще написать что в итоге надо сделать?
Что этот шейдер делает?
atomic
> Может проще написать что в итоге надо сделать?
> Что этот шейдер делает?
Достаточно обычная математика, проблема в технической части.
Есть текстура глубины и нужно по ней найти worldPosition.
На основе этого worldPosition на объектах нужно отрендерить декали. Я использую реймач, worldPosition помогает рендерить декали корректно.
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) );
marggob
Спасибо, но у меня тоже этот результат получаетсяя. Когда камерой кручу,
то WorldSpace искажается (цвета меняются) как на скринах справа:
Насколько понимаю этого не должно быть. Напрмер в годоте этого нет (скрины слева).
Откуда берется это искажение?
Нашел недавно гит от разработчика юнити, там написано:
// 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 цвета искажаются. Этого же не должно быть, нет?
Alerr
Написанный мной метод я использую постоянно в постэффектах. Он всегда отрабатывает корректно. Ни разу не было каких-то косяков или вывертов непонятных. Где-то что-то вы делаете не правильно или ни в том порядке.
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:
Секунду, похоже Ваш код работает...
Alerr
> Секунду, похоже Ваш код работает...
Естественно работает. Многократно проверено и перепроверено. )))
marggob
>Естественно работает. Многократно проверено и перепроверено. )))
В общем большое Вам спасибо!
Можете разжевать что тут делаете: (SCREEN_UV * 2 - 1 - p13_31) / p11_22 ?
Alerr
> Можете разжевать что тут делаете
Ну, честно говоря я уже не помню. Да и код-то я брал готовый откуда-то. Хоть и разбирал что и для чего там делается, но уже всё вылетело из головы за ненадобностью. ))))
Но по логике там что-то связанное с Viewport Rect и FOV. Но могу и ошибаться.
Тема в архиве.