KiQ писал: А допустим, кто-то захочет прикрутить в TriAPI шейдеры, логичнее для этого использовать какой-то универсальный язык, по типу того, что был в системе материалов в третьей кваке, а затем уже компилировать в зависимости от выбранного рендера.
А нету таких языков. Вот байт-код универсальный есть, да. SPIR-V называется. Но он в OpenGL поддерживается только в самых крайних версиях.
SNMetamorph я не совсем о том гвоорил. Я имел в виду, что самому разработать упрощённый шейдерный язык с конечным значением основных комманд и два транслятора, в GLSL и что там в директе используется
KiQ
Так я не понял, чем вас Cg не устраивает?
В Volatile шейдеры при сборке компилируются сразу в большое число профилей, часть из которых D3D, а часть GL. Соответственно, простые эффекты будут работать на условной GeForceFX, ну а сложные используют всё преимущество полноценного ветвления, неразвёртываемых циклов и других радостей модели 3+.
XaeroX помню ещё пытался с Cg водичкой для халфы разобраться, и как-то сразу мне оно не зашло именно тем, что это C for graphics. Отсюда и издержки синтаксиса и в целом некая перегруженность. Я же имел в виду некий высокоуровневый универсальный язык, который может транслироваться в API-зависимые конструкции. В общем, скриптинг для шейдеров. Старый GLSL был к этому приближен, потом в него тоже ввели кучу нагромождений типа чтобы отвязать от фиксированного пайплайна. В итоге да, контроль есть, а удобства уже такого нет. Все эти раскладки переменных и т.д, которые нужно делать вручную. Это мне напомнило переход от LWJGL2 к LWJGL3. Да, дали значительно больше контроля, но теперь вместо условного Display.create() нужно прописывать по сути те же обёртки над GL, так и спрашивается, на кой чёрт такой фреймворк, который заставляет делать пользователя то же самое, только переименованными методами?
Вопрос к XaeroX - гуглил "oblique frustum with inversed depth" и ничего толком не нашел, кроме, походу, твоей работы по линеаризации глубины в шейдере при юзании oblique frustum с инвертированной глубиной (потому что сам по себе oblique frustum там портит глубину и потому Unigine от него отказались)
К чему это я - не подскажешь как подправить оригинальный код Эрика для модификации матрицы проекции если эта самая матрица уже с инвертированной глубиной ?
У меня в рендере юзается инвертированный депс, и я пытаюсь запилить зеркало, если оно попадает во фрустум - отражаю камеру и рисую в рендертаргет, потом шлепаю на это зеркало.
Хочу клипать все по этому зеркалу чтоб не рисовалось то что за ним, и потому подумаю использовать oblique frustum, но кривизна рук и бедность мозга не позволяет получить результат.
0r@ngE писал: потому что сам по себе oblique frustum там портит глубину и потому Unigine от него отказались
Ничего он не портит, что за глупости? Прекрасно она линеаризуется, что я в статье и показал.
Собственно, я и писал статью для тех, кто пугается "порчи" глубины и не хочет закапываться в матан.
Цитата:
0r@ngE писал: не подскажешь как подправить оригинальный код Эрика для модификации матрицы проекции если эта самая матрица уже с инвертированной глубиной ?
К сожалению, у меня нет необходимых формул, но полагаю, что ты можешь проделать те же выкладки, что в статье, с учётом отличий в матрице проекции. Они вроде не критичные.
XaeroX писал: К сожалению, у меня нет необходимых формул, но полагаю, что ты можешь проделать те же выкладки, что в статье, с учётом отличий в матрице проекции. Они вроде не критичные.
Проблема в том, что я сделал, но ничего не клипается, объекты за плоскостью зеркала рисуются, а не должны по идее.
code:
// See: Oblique frustum: Eric Lengyel
static void ClipProjectionMatrix(const Matrix& matView, Matrix& matProj, const Plane& inClipPlane)
{
Plane transformedPlane = matView.TransformPlane(inClipPlane);
Vector clipPlane(transformedPlane.Normal());
clipPlane.SetScalar(3, -transformedPlane.Distance());
// Calculate the clip-space corner point opposite the clipping plane
// as (Sgn(clipPlane.x), Sgn(clipPlane.y), 1, 1) and
// transform it into camera space by multiplying it
// by the inverse of the projection matrix
float m0 = matProj.GetScalar(0, 0);
float m5 = matProj.GetScalar(1, 1);
float m8 = matProj.GetScalar(2, 0);
float m9 = matProj.GetScalar(2, 1);
float m10 = matProj.GetScalar(2, 2);
float m14 = matProj.GetScalar(3, 2);
Vector q
(
(Sgn(clipPlane.GetScalar(0)) + m8) / m0,
(Sgn(clipPlane.GetScalar(1)) + m9) / m5,
1.0f,
(1.0f - m10) / m14
);
// Calculate the scaled plane vector
Vector c = clipPlane * (1.0f / clipPlane.Dot4(q));
// Replace the third row of the projection matrix
matProj.SetScalar(0, 2, -c.GetScalar(0));
matProj.SetScalar(1, 2, -c.GetScalar(1));
matProj.SetScalar(2, 2, -c.GetScalar(2));
matProj.SetScalar(3, 2, c.GetScalar(3));
}
0r@ngE
Для начала рекомендую вернуть обычную (не инвертированную) матрицу проекции и убедиться, что oblique clipping в принципе работает. А уж потом можно будет доработать для инверсии.
XaeroX писал: Для начала рекомендую вернуть обычную (не инвертированную) матрицу проекции и убедиться, что oblique clipping в принципе работает. А уж потом можно будет доработать для инверсии.
Да вот сижу откручиваю инвертированную глубину назад чтоб проверить.
Цитата:
Дядя Миша писал: При правильной реализации это автоматически получается.
В смысле? Мы модифицируем near plane чтоб оно клипалось, ибо clip planes умерли вместе с fixed pipeline. В этом и есть смысле oblique frustum. Проблема в том чтоб адаптировать его для проекционной матрицы которая построена для инвертированной глубины (считай far и near поменяны местами)
Открутил inversed depth (он тут у меня везде прибит гвоздями), вернул оригинальную функцию и теперь все клипается как положено.
Отличия моего кода от оригинального от Эрика только в том, что у него там OpenGL, и потому clip space depth в [-1;1] а у меня Vulkan и [0;1]
code:
// See: Oblique frustum: Eric Lengyel
static void ClipProjectionMatrix(const Matrix& matView, Matrix& matProj, const Plane& inClipPlane)
{
Plane transformedPlane = matView.TransformPlane(inClipPlane);
Vector clipPlane(transformedPlane.Normal());
clipPlane.SetScalar(3, -transformedPlane.Distance());
// Calculate the clip-space corner point opposite the clipping plane
// as (Sgn(clipPlane.x), Sgn(clipPlane.y), 1, 1) and
// transform it into camera space by multiplying it
// by the inverse of the projection matrix
float m0 = matProj.GetScalar(0, 0);
float m5 = matProj.GetScalar(1, 1);
float m8 = matProj.GetScalar(2, 0);
float m9 = matProj.GetScalar(2, 1);
float m10 = matProj.GetScalar(2, 2);
float m14 = matProj.GetScalar(3, 2);
Vector q
(
(Sgn(clipPlane.GetScalar(0)) + m8) / m0,
(Sgn(clipPlane.GetScalar(1)) + m9) / m5,
-1.0f,
(1.0f + m10) / m14
);
// Calculate the scaled plane vector
Vector c = clipPlane * (1.0f / clipPlane.Dot4(q));
// Replace the third row of the projection matrix
matProj.SetScalar(0, 2, c.GetScalar(0));
matProj.SetScalar(1, 2, c.GetScalar(1));
matProj.SetScalar(2, 2, c.GetScalar(2));
matProj.SetScalar(3, 2, c.GetScalar(3));
}
Задача в том, чтоб ее адаптировать под inversed depth (который уже в matProj), и вот тут я чот буксую к сожалению.
Подумал раз ты в Volatile Engine это сделал, может подскажешь