Войти
UnityФорумПрограммирование

Рендеринг FPS-оружия в Unity? [РЕШЕНО]

Страницы: 1 2 Следующая »
#0
16:45, 25 фев 2016

Хае! Уже довольно давно топчусь вокруг этого вопроса.
В юньке есть трудности с рендерингом оружия от первого лица. Классические способы не помогают - при ZTest Always не только оружие, но и руки начинают рендериться друг поверх друга, а при попытке рендеринга оружия второй камерой с очисткой буфера глубины теряем все тени, и пушка в подземелье начинает сиять как на солнце.

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

PS: опускание оружия при контакте со стеной не предлагать - так делают только педики :D

#1
16:49, 25 фев 2016

В третьем думе применяется такой хак матрицы проекции (код из моего проекта, но суть та же):

void Camera::EnterDepthHack( float depth ) {
    // store initial matrix
    if( !mInDepthHack ) {
        mDepthHackMatrix = mProjection;
    }
    mInDepthHack = true;
    // modify matrix
    mProjection._43 -= depth;
}

void Camera::LeaveDepthHack() {
    // restore matrix
    mInDepthHack = false;
    mProjection = mDepthHackMatrix;
}

Используется так:

if( needOverlay ) {
  camera->EnterDepthHack( depth );
}
node->Draw( camera );
if( needOverlay ) {
  camera->LeaveDepthHack();
}

Тут надо поиграться со значением depth. Оно обычно небольшое - 0,05 - 0,15. Код выше приведен для DX, хз как в юнити матрицы трактуются.

#2
17:00, 25 фев 2016

E-Cone
> опускание оружия при контакте со стеной не предлагать - так делают только
> педики

Так сделано в Крайзисе

#3
17:07, 25 фев 2016

>так делают только педики
выходит, все люди с оружием в реальной жизни - педики. что ж... доля правды в этом есть.

#4
17:28, 25 фев 2016

Сплющи оружие в вертексном шэйдере.

#5
22:16, 25 фев 2016

mr.DIMAS, спасибище! Всё заработало)
Я беру worldToCameraMatrix главной камеры, отнимаю depth от Z из 3 строки матрицы и зафигачиваю ее в качестве глобальной шейдерной матрицы "_viewModelMatrix".
На оружии стоит кастомный шейдер, который вместо стандартной UNITY_MATRIX_MVP строит свою MVP с измененной матрицей.

float4x4 mvp = mul( mul( UNITY_MATRIX_P, _viewModelMatrix), _Object2World );
o.pos = mul(mvp, v.vertex);

вместо

o.pos = mul(UNITY_MATRIX_MVP, v.vertex);

Наверное перемножение P и V все-таки следует делать в скрипте, а то у меня там по 6-10 объектов так отрисовываются..

В итоге и ствол не проваливается, и тенюшки рисуются. Позитив! =)

Изображение

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

innuendo, Mr F, это была шутка юмора) меня просто бесит, когда игроку не позволяют стрелять, прижавшись к стене.

Battle Angel Alita, а теперь представь себе, как будет выглядеть рукопожатие главгероя с другим NPC при сплющивании)

#6
12:05, 26 фев 2016

Так-с, я малость косякнул - не с той матрицей работал :D
Вот так вроде правильно:
в скрипте:

void OnPreRender() {
    Matrix4x4 P = cam.projectionMatrix;
    Vector4 invec = P.GetRow (1); invec.Scale( new Vector4 (1, -1, 1, 1));
    P.SetRow (1, invec);
    Shader.SetGlobalMatrix ("_P", P);
  }

в шейдере:

float4x4 mvp = mul( mul( _P, UNITY_MATRIX_V), _Object2World );
o.vertex = mul(mvp, v.vertex);

Тут я просто инвертировал матрицу проекции по Y, чтобы пушка не рисовалась вверх ногами, и всё заработало даже без сдвига..

#7
12:09, 26 фев 2016

а всего то надо было пушке глубину отключить

#8
12:18, 26 фев 2016

E-Cone
> Как я понимаю, этот метод основан на том, что мы обманываем камеру, заставляя
> ее думать, что она вместе с моделью находится позади игрока
То решение, что предложил mr.DIMAS - просто подтягивает глубину чуть чуть на нас. А по твоему коду не понятно, что ты делаешь, но скейл Vector4 (1, -1, 1, 1) явно лишний.

#9
12:18, 26 фев 2016

Misanthrope, попробуй отключи, лол. Будешь наблюдать руки сквозь ствол

#10
12:21, 26 фев 2016

E-Cone
> Будешь наблюдать руки сквозь ствол
а если бы не руки, то прокатило бы?

#11
12:23, 26 фев 2016

Misanthrope
> а если бы не руки, то прокатило бы?
Не прокатило бы. Ствол не выпуклый примитив, и просто куллингом не отделаться.

#12
12:29, 26 фев 2016

MrShoor, если взять матрицу проекции камеры и передать ее напрямик в шейдер, оружие будет рисоваться вверх ногами - для этого и инвертирую Y.

Первоначальный способ работает только возле нулевых координат. Если отойти подальше, пушка плавно растворится в воздухе. Второй способ пока работает как надо. Возможно там не только Y, но и Z инвертированы, из-за чего юнька думает, что рендерит пушку за спину игроку и таким образом опять же записывает в Z-буфер самые близкие значения.

#13
12:36, 26 фев 2016

Battle Angel Alita
>Сплющи оружие в вертексном шэйдере.
это как ?

#14
13:10, 26 фев 2016

E-Cone
> MrShoor, если взять матрицу проекции камеры и передать ее напрямик в шейдер,
> оружие будет рисоваться вверх ногами - для этого и инвертирую Y.
Странная у тебя матрица. Почему вверх ногами то?

codingmonkey
> это как ?
Out.Pos.z /= Out.Pos.w;
Out.Pos.z *= 0.1;
Out.Pos.z *= Out.Pos.w;

Страницы: 1 2 Следующая »
UnityФорумПрограммирование

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