Берсеркер
2357 постов
Карма: 221
#1791 02 февраля 2026 в 20:02
Привет RaideR!
Формат текстур поменялся, ретекстурю сейчас, увеличиваю размер текстур в 2..3 раза по каждой оси, добавляю PBR-текстуры (чтобы отличать металл от пластика или дерева).
Старая система освещения была как в IdTech4 (Doom III), сейчас современная PBR.
Частично беру текстуры от уважаемого камрада GT-Agressor.

Вот что получается:















Машина несла меня через неведомые районы Галактики сквозь пространство математической реальности быстрее скорости света. (C) Фред Саберхаген.
RaideR
6 постов
Карма: 0
#1792 21 февраля 2026 в 03:00
Вау, Berserker!
Эти металлические материалы!
Эти рельефы!
Эта тесселяция (PBR)!
Всё выглядит просто потрясающе!
Освещение — изысканное!
:D !!!

Ну что ж, надеюсь, ты всё это прочитаешь, Berserker — получилось довольно объёмно… :C

На мой взгляд, текстуры пола на карте Q3DM1 Arena Gate немного отошли от серо-коричневого оттенка и теперь выглядят слишком белыми. Полагаю, что узор текстуры отличается от оригинального ванильного варианта, но это лишь небольшая деталь — в целом всё по-прежнему выглядит великолепно.

Пользуясь случаем, оставлю несколько предложений по улучшению:
-В моей текущей сборке Quake 3 Berserker текстуры оружия выглядят слишком отражающими, почти как полированное зеркало. Не знаю, исправил ли ты это в текстурах оружия, которые показываешь на своих скриншотах.
-Большинство текстур оружия должны иметь металлический/матовый тип материала, за -исключением BFG 10K — у неё как раз уместна зеркальная полировка.
-Было бы здорово добавить функцию weapon sway — ощущение просто великолепное, Quake 3 Arena становится намного более «живым» и органичным с этой особенностью.

Я сам скомпилировал сборку Quake 3 Arena 1.32b и реализовал Weapon Sway, вот смотри:
https://www.youtube.com/watch?v=474SJNbBKAI

Реализация кода weapon sway:
cg_weapons.c

==============
CG_CalculateWeaponPosition
==============
*/
static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
float scale;
int delta;
float fracsin;
….
….
….
// Organic Weapon Sway (spring gzdoom universal weapon sway style)
// Organic Weapon Sway v3 (stable)
{
vec3_t delta;
float targetX, targetY;
float stiffness = 1.0f;
float damping = 24.0f;
float scale = 4.5f;
float dt = cg.frametime * 0.001f;

if (dt <= 0.0f)
dt = 0.001f;

int i;


for (i = 0; i < 3; i++) {
delta[i] = cg.refdefViewAngles[i] - cg.lastViewAngles[i];

if (delta[i] > 180) delta[i] -= 360;
if (delta[i] < -180) delta[i] += 360;
}

// suavizar input (reduce efecto parabólico)
float inputSmooth = 0.8f;

cg.weaponSwayInput[0] =
cg.weaponSwayInput[0] * (1.0f - inputSmooth) + (-delta[YAW] * scale) * inputSmooth;

cg.weaponSwayInput[1] =
cg.weaponSwayInput[1] * (1.0f - inputSmooth) + (delta[PITCH] * scale) * inputSmooth;

targetX = cg.weaponSwayInput[0];
targetY = cg.weaponSwayInput[1];

// Spring force
cg.weaponSwayVelocity[0] += (targetX - cg.weaponSway[0]) * stiffness * dt;
cg.weaponSwayVelocity[1] += (targetY - cg.weaponSway[1]) * stiffness * dt;

// Damping
cg.weaponSwayVelocity[0] *= (1.0f - damping * dt);
cg.weaponSwayVelocity[1] *= (1.0f - damping * dt);

// Integrate
cg.weaponSway[0] += cg.weaponSwayVelocity[0];
cg.weaponSway[1] += cg.weaponSwayVelocity[1];

// Safety clamp
if (cg.weaponSway[0] > 10) cg.weaponSway[0] = 10;
if (cg.weaponSway[0] < -10) cg.weaponSway[0] = -10;
if (cg.weaponSway[1] > 10) cg.weaponSway[1] = 10;
if (cg.weaponSway[1] < -10) cg.weaponSway[1] = -10;

origin[0] += cg.weaponSway[0] * 0.05f;
angles[YAW] += cg.weaponSway[0] * 1.7f;
origin[1] += cg.weaponSway[1] * 0.5f;
angles[PITCH] += cg.weaponSway[1] * 1.0f;

VectorCopy(cg.refdefViewAngles, cg.lastViewAngles);
}


Это отвечает за:
-targetOffset
-скорость
-ускорение
-ограничение (clamp)

cg_local.h
Добавить внутрь
cg_t
(переменные состояния клиента).
#define MAX_PREDICTED_EVENTS 16
typedef struct {


vec3_t lastViewAngles;
vec3_t weaponSway;

// weapon sway
vec3_t lastViewAngles;
vec3_t weaponSway;
vec3_t weaponSwayVelocity;
vec3_t weaponSwayInput;
vec3_t weaponMoveSway; //Я пока ещё не реализовал это, реализую в ближайшем будущем.


Итог:
В результате sway в моей версии Quake 3 1.32b получился как смесь:
-Очень лёгкого параболического стиля движения sway из Quake 2
-В сочетании со стилем мода Universal Weapon Sway для GZDoom (UZDoom)
https://forum.zdoom.org/viewtopic.php?t=68255
https://github.com/Boondorl/Universal-Weapon-Sway


Old DirectInput and MouseInput code Quake 3 Vanilla bug:
В vanilla-коде обработки ввода мыши в Quake 3 Arena есть логическая ошибка, связанная с кнопками (я двигаюсь вперёд и назад с помощью левой и правой кнопок мыши).
Похоже, что в Windows 10 / Windows 11 с DirectInput события обрабатываются или гарантируются некорректно.

В ванильном Quake 3 Arena в коде обработки ввода мыши присутствует логическая ошибка блокировки, связанная с состояниями кнопок (в моём случае движение вперёд/назад назначено на левую и правую кнопки мыши).
В среде Windows 10 / Windows 11 при использовании DirectInput события ButtonUp / ButtonDown не всегда обрабатываются корректно и детерминированно при следующих условиях:
-одновременное нажатие нескольких клавиш клавиатуры и нескольких кнопок мыши
-высокий polling rate у мыши и клавиатуры

Кнопки мыши логически остаются в состоянии «MouseClick Down», хотя физически кнопка мыши уже не нажата.

Это приводит к тому, что одна из двух кнопок (левая или правая) «залипает», и приходится нажимать её снова, чтобы логическое состояние кнопки сбросилось.
Предполагаю, что проблема связана со старой API DirectInput времён Windows 98 / Windows XP, которую внутренне использует ванильный Quake 3. Она работает крайне нестабильно в среде Windows 10 / Windows 11.

В ioquake3, Quake 3 Spearmint и Quake3e эта проблема не наблюдается. Полагаю, что они используют API SDL2 с новым кодом обработки ввода мыши.

К сожалению, Quake 3 Berserker наследует всю эту проблему из mouse input code ванильного Quake 3.

Насколько мне известно, схема in_mouse в ванильном Quake 3 следующая:
-in_mouse 1 → Win32 mouse (старый метод, очень плохо работает в Win10/Win11)
-in_mouse 0 → мышь отключена
-in_mouse -1 → RawInput (некорректно реализован для Win10/Win11)
-in_mouse -2 → DirectInput (самый стабильный режим для Win10/Win11)

В ванильном Quake 3:
Кнопки мыши обрабатываются как события, а не как состояния.
Если событие ButtonUp теряется → кнопка остаётся «нажатой» навсегда.

Отсутствует:
-timeout
-перекрёстная валидация
-опрос реального состояния кнопок (state polling)
-принудительная очистка состояния

Однако я самостоятельно применил простой патч «Anti-stuck» к своей сборке 1.32b, не меняя сам mouse input code, и теперь кнопки мыши работают идеально и больше не залипают!

В результате возможны залипания состояний кнопок или некорректная синхронизация событий ввода.

cl_input.c
-Я добавил в начало файла следующее:
static int lastInputTime = 0;

-Я добавил следующее в блок CL_CreateCmd:
int i;

-И я добавил следующее внутри блока usercmd_t CL_CreateCmd( void ):
// Win10 mouse button stuck fix
if (cls.realtime - lastInputTime > 200) {
for (i = 0; i < 16; i++) {
in_buttons[i].active = qfalse;
in_buttons[i].down[0] = 0;
in_buttons[i].down[1] = 0;
}

in_forward.active = qfalse;
in_back.active = qfalse;
in_left.active = qfalse;
in_right.active = qfalse;
}

lastInputTime = cls.realtime;


Краткое резюме по cl_input.c
Этот небольшой патч принудительно обеспечивает согласованность состояний кнопок.
Я очищаю флаги (active) всех 16 действий в Quake 3.
Если в течение 200 мс не было «реального» ввода, фантомные кнопки очищаются.
-не ломает клавиатуру
-не ломает мышь
-не влияет на нормальный геймплей
CL_CreateCmd() состояния текущего кадра уже консолидированы.
-Я не вмешиваюсь во внутреннюю обработку кнопок.

Это всего лишь патч, который выполняет своего рода «sanity reset» для mouse code, чтобы предотвратить залипание кнопок.

Auto BunnyJump, как в Quake Live и Quake Champions:
Я знаю, что это спорная тема: одни категорически против, другие поддерживают, поскольку играть с auto bunnyjump более приятно и комфортно.

Но я понимаю, что у разработчиков есть очевидные причины отказаться от этой функции (в зависимости от концепции source-порта).

Разработчики, которые выступают против, говорят, что это нарушит совместимость с модами, такими как Defrag (что вполне понятно).

Также есть разработчики, которые поддерживают добавление этой функции как серверной опции, например через cvar вида:
sv_bunnyjump 0/1

Таким образом, те, кто хотят запускать сервер с auto bunnyjump, смогут позволить игрокам наслаждаться этой замечательной возможностью.

Ну а вот моя реализация. Со своей стороны я хочу сделать это на стороне клиента (clientside). Пока я ещё не добавил cvar вида cl_bunnyjump 0/1, но планирую реализовать её в ближайшее время.

bg_pmove.c

PM_CheckJump
=============
*/
static qboolean PM_CheckJump( void ) {
// if ( pm->ps->pm_flags & PMF_RESPAWNED ) {
// return qfalse; // don't allow jump until all buttons are up
// }

if ( pm->cmd.upmove < 10 ) {
// not holding jump
return qfalse;
}

// SOLO permitir salto si estamos en el suelo
if (pm->ps->groundEntityNum == ENTITYNUM_NONE) {
return qfalse;
}

// must wait for jump to be released
// if ( pm->ps->pm_flags & PMF_JUMP_HELD ) {
// clear upmove so cmdscale doesn't lower running speed
// pm->cmd.upmove = 0;
// return qfalse;
// }

pml.groundPlane = qfalse; // jumping away
pml.walking = qfalse;

pm->ps->pm_flags |= PMF_JUMP_HELD;
pm->ps->groundEntityNum = ENTITYNUM_NONE;
pm->ps->velocity[2] = JUMP_VELOCITY;

PM_AddEvent( EV_JUMP );

if ( pm->cmd.forwardmove >= 0 ) {
PM_ForceLegsAnim( LEGS_JUMP );
pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
} else {
PM_ForceLegsAnim( LEGS_JUMPB );
pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
}

return qtrue;
}


И в PM_GroundTrace я добавил следующее:
pm->ps->pm_flags &= ~PMF_JUMP_HELD;


В итоге получилось так:
static void PM_GroundTrace( void ) {
vec3_t point;
trace_t trace;

point[0] = pm->ps->origin[0];
point[1] = pm->ps->origin[1];
point[2] = pm->ps->origin[2] - 0.25;



if ( pm->ps->groundEntityNum == ENTITYNUM_NONE ) {
// just hit the ground
if ( pm->debugLevel ) {
Com_Printf("%i:Land\n", c_pmove);
}
// КЛЮЧЕВОЕ: разрешить auto-jump при касании земли.
pm->ps->pm_flags &= ~PMF_JUMP_HELD;

PM_CrashLand();

// И я закомментировал это, чтобы отключить задержку после приземления (landing cooldown).
// don't do landing time if we were just going down a slope
// if ( pml.previous_velocity[2] < -200 ) {
// don't allow another jump for a little while
// pm->ps->pm_flags |= PMF_TIME_LAND;
// pm->ps->pm_time = 250;
// }
PM_AddTouchEnt( trace.entityNum );
}


Проект по рестекстуризации
И раз уж вы улучшаете текстуры с помощью ремастеринговых материалов, было бы просто великолепно немного доработать оружие из Quake Champions — эти 3D-модели были экспортированы в Quake 3 Arena!
https://www.moddb.com/mods/quake-champions-weapons-for-q3a

Идея в том, чтобы текстуры выглядели матовыми, но при этом металлическими, прочными и слегка изношенными.
Мне кажется, что сами текстуры уже хорошо проработаны, им просто не хватает соответствующих шейдеров, чтобы сделать их максимально похожими на версию из Quake Champions.

Quake 3 Berserker с моделями оружия из Quake Champions:
Кроме того, я создал мод для настройки ванильной перспективы с FOV 100.
https://drive.google.com/file/d/1ESiW8XNNrYEQ7fLHCL9tu9eDx83mN_v4/view?usp=sharing

Результат:









Референс металлических материалов напрямую из движка Quake Champions (Saber Engine):








BFK 10K пока ещё не экспортировали
:C

Полагаю, модели они взяли отсюда:
https://knockout.chat/thread/9182/1

А ещё я сделал такой же мод, чтобы скорректировать оригинальную перспективу с углом обзора 100 для оригинального оружия; оно выглядит красиво и очень хорошо.
https://drive.google.com/file/d/12Vd0KkGRhywH9Jf-9efEY0feXZRXsFUs/view?usp=sharing












Возможно, чтобы избежать необходимости вносить множество изменений для каждого значения угла обзора, хорошей идеей было бы реализовать нечто подобное тому, что есть в Serious Sam 2, где угол обзора не влияет на отображение HUD оружия, но, полагаю, это очень сложная задача.

Здесь я показываю, как модели из Quake Champions выглядят в ванильном Quake 3 Arena 1.32b.
https://www.youtube.com/watch?v=pzqASCPhq_M

А здесь я показываю, как модели из Quake Champions выглядят в Quake 3 Berserker.
https://www.youtube.com/watch?v=FdqcMklEg3o

Совместимость с модом ZTM Flexible HUD
https://github.com/clover-moe/flexible-hud-for-ioq3
https://clover.moe/flexible-hud-for-ioq3/

Или, по крайней мере, реализовать нечто подобное, чтобы включить:
-Растягивание HUD
-Масштабирование HUD

ZTM Flexible HUD


Quake 3 Berserker HUD


И наконец — улучшение производительности, как это сделано в Quake3e
https://github.com/ec-/Quake3e

Например, на карте House Of The Rising Sun FPS сильно падают, когда добавляешь ботов — вплоть до провалов до ~60 FPS.
https://lvlworld.com/review/id:2278

Вот сравнение:
Quake 3 Berserker


Quake3e


Такое снижение производительности наблюдается и в других существующих портах исходного кода:
-Quake 3 Spearmint
-ioquake3

В Quake3e этого нет. Возможно, в будущем вы могли бы рассмотреть возможность внедрения улучшений, сделанных ec- в Quake3Berserker?

Эй-эй! Какое же увлекательное путешествие в мир расследований и составления отчетов у меня получилось! ха-ха-ха!

Я чувствую, что Quake 3 Berserker станет лучшим портом из всех благодаря всем этим возможностям.