From 6b9248be7e12d4962b70ce5c89ea7410e9da22ec Mon Sep 17 00:00:00 2001 From: OneMorePseudoCoder <73041211+OneMorePseudoCoder@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:11:40 +0300 Subject: [PATCH] Changes 21.02.24 -Support usage of multiple spawn_loadout sections in character descriptions (https://github.com/OpenXRay/xray-16/pull/1590) -Support for linear space rendering in R4 renderer (https://github.com/OpenXRay/xray-16/pull/1576) -Fixed "Naruto run" -Fog affects npc vision -Smopth peak -Landscape render phase (IXRAY) -Volumetric light optimization (fixed light flickering by Graff46) -Fixed visual memory manager formula -Optimazed light renderer (https://github.com/OpenXRay/xray-16/pull/1600/files) -Fixed HOM cache (dsh2dsh) -Fixed CKinematics::LL_SetBoneVisible (Anomaly) --- .../scripts/visual_memory_manager.script | 4 +- res/gamedata/shaders/r3/yuv2rgb.ps | Bin 0 -> 829 bytes res/gamedata/shaders/r5/yuv2rgb.ps | Bin 741 -> 829 bytes src/Layers/xrRender/FTreeVisual.cpp | 35 +--- src/Layers/xrRender/HOM.cpp | 36 ++-- src/Layers/xrRender/Shader.cpp | 5 +- src/Layers/xrRender/Shader.h | 1 + src/Layers/xrRender/SkeletonCustom.cpp | 43 +++-- .../blenders/Blender_BmmD_deferred.cpp | 26 ++- src/Layers/xrRender/blenders/uber_deffer.cpp | 25 +-- src/Layers/xrRender/dxRainRender.cpp | 14 +- src/Layers/xrRender/r__dsgraph_build.cpp | 7 + src/Layers/xrRender/r__dsgraph_render.cpp | 42 ++++ src/Layers/xrRender/r__dsgraph_structure.h | 2 + src/Layers/xrRender/r__dsgraph_types.h | 5 +- src/Layers/xrRender/r__occlusion.cpp | 23 ++- src/Layers/xrRender/xrRender_console.cpp | 10 +- src/Layers/xrRender/xrRender_console.h | 3 + src/Layers/xrRenderDX11/dx11HW.cpp | 40 ++-- src/Layers/xrRenderDX11/dx11HW.h | 1 + src/Layers/xrRenderDX11/dx11Texture.cpp | 179 +----------------- src/Layers/xrRenderDX11/dx11TextureUtils.cpp | 1 + src/Layers/xrRenderPC_R4/r4_rendertarget.h | 10 + .../r4_rendertarget_phase_combine.cpp | 4 +- src/Layers/xrRenderPC_R4/r4_shaders.cpp | 3 + src/Layers/xrRender_R2/r2.cpp | 4 +- src/Layers/xrRender_R2/r2.h | 2 + src/Layers/xrRender_R2/r2_R_lights.cpp | 68 +++---- src/Layers/xrRender_R2/r2_R_render.cpp | 7 + src/Layers/xrRender_R2/r2_rendertarget.cpp | 27 ++- src/Layers/xrRender_R2/r2_types.h | 2 + src/xrCore/FS.cpp | 17 +- src/xrCore/FileSystem.cpp | 38 +--- src/xrCore/LocatorAPI.cpp | 3 +- src/xrCore/_matrix.h | 5 +- src/xrEngine/xr_collide_form.cpp | 22 +-- src/xrGame/ActorAnimation.cpp | 12 +- src/xrGame/Actor_Movement.cpp | 44 ++--- src/xrGame/ai_obstacle.cpp | 2 +- src/xrGame/alife_object.cpp | 107 ++++++----- src/xrGame/visual_memory_manager.cpp | 24 ++- src/xrGame/visual_memory_params.cpp | 2 + src/xrGame/visual_memory_params.h | 2 + src/xrMaterialSystem/GameMtlLib.cpp | 1 + src/xrMaterialSystem/GameMtlLib_Engine.cpp | 1 + 45 files changed, 400 insertions(+), 509 deletions(-) create mode 100644 res/gamedata/shaders/r3/yuv2rgb.ps diff --git a/res/gamedata/scripts/visual_memory_manager.script b/res/gamedata/scripts/visual_memory_manager.script index 8d4c0f2306f..d8d0e46bf44 100644 --- a/res/gamedata/scripts/visual_memory_manager.script +++ b/res/gamedata/scripts/visual_memory_manager.script @@ -4,7 +4,7 @@ -- called from engine -- This occurs during the visible check. If value >= visiblity_threshold then object is considered visible -- warning npc and who can be nil sometimes -function get_visible_value(npc, who, time_delta, time_quant, luminocity, velocity_factor, velocity, distance, object_distance, always_visible_distance) +function get_visible_value(npc, who, time_delta, time_quant, luminocity, velocity_factor, velocity, distance, object_distance, always_visible_distance, fog_factor) distance = distance <= 0 and 0.00001 or distance luminocity = luminocity <= 0 and 0.0001 or luminocity @@ -12,5 +12,5 @@ function get_visible_value(npc, who, time_delta, time_quant, luminocity, velocit -- luminocity = luminocity + 0.35 -- end - return time_delta / time_quant * luminocity * (1 + velocity_factor * velocity) * (distance - object_distance) / distance + return time_delta / time_quant * luminocity * (1 + velocity_factor * velocity) * (distance - object_distance) / (distance - always_visible_distance) * fog_factor end \ No newline at end of file diff --git a/res/gamedata/shaders/r3/yuv2rgb.ps b/res/gamedata/shaders/r3/yuv2rgb.ps new file mode 100644 index 0000000000000000000000000000000000000000..7806ec41cbb8bc1141263568c7662d21be6df742 GIT binary patch literal 829 zcmaJ*VBJyB#F(w8L6CzK`#7>v&gKXeu`0w7k4FxnVOVgg7 zb9#Dj+i^BeR*wn}=6Rat8Gk-ttQ|*ieKqpV#({r(cJ2jZZ*<{}uSSwyRBHo0@RWuNGbAFNe+)Lrq(R=l5i%pr+mCGC!m@KyIznRMH|GZA z))ZrI0R1|2V7A2|_l6-1I27FO3u(EL0bPp=)0GysrvsBM2_4@^x+Zt~JxO$w9-Aa= zVHr9w-4gge0%FO&G|69Z*A_iVTI_!BSW@Tzd!ak+b@tnfm+e9@p*VBJyB#F(w8L6CzK`#7>v&gKXeu`0w7k4FxnVOVgg7 zb9#Dj+i^BeR*wn}=6Rat8Gk-ttQ|*ieKqpV#({r(cJ2jZZ*<{}uSSwyRBHo0@RWuNGbAFNe+)Lrq(R=l5i%pr+mCGC!m@KyIznRMH|GZA z))ZrI0R1|2V7A2|_l6-1I27FO3u(EL0bPp=)0GysrvsBM2_4@^x+Zt~JxO$w9-Aa= zVHr9w-4gge0%FO&G|69Z*A_iVTI_!BSW@Tzd!ak+b@tnfm+e9@p!{42I9$8iOPrS#?)63&(wO(?KUcy*x(&Kx6 zR(=)RhMMyriDFpbIsbB(pq|8QdddwFYjfq6Xi`>~mWN%g;;B6JEE3#TgoMgbQR{1d zjYVzjdk~YhlKbhLdgV1T&^6sar=sc#*m~O}hz%~#v7BJcgF;WblDKv#PD!AP5#Y}z zfnVq`f{EOk2D88^dic48Wy+iJz$G$jNk_iKh*X7JzQ-rQRrk>97`hgB{J^bc($XYL zKAG06Zd1qg(jlYKyJn%Y_dv+iwVwsl%#ao8XQt6fPll-6OpkIy4rumW8_2p&G|;1= zPVTSQv2Gz`Me3;>(g0q&#Y0s%R7tX49I05h3(); - new_buffer->Create(vertices_size); - - auto vert_new = static_cast(new_buffer->Map()); - const auto vert_orig = static_cast(p_rm_Vertices->Map(vBase, vertices_size, true)); // read-back - CopyMemory(vert_new, vert_orig, vertices_size); - - for (size_t i = 0; i < vCount; ++i) - { - //vert_new->P.mul(xform.j); - ++vert_new; - } - - new_buffer->Unmap(true); - p_rm_Vertices->Unmap(false); - _RELEASE(p_rm_Vertices); - p_rm_Vertices = new_buffer; - vBase = 0; - }*/ - // Geom rm_geom.create(vFormat, *p_rm_Vertices, *p_rm_Indices); @@ -114,7 +89,7 @@ struct FTreeVisual_setup Fvector4 wave; Fvector4 wind; - FTreeVisual_setup(): dwFrame(0), scale(0) {} + FTreeVisual_setup(): dwFrame(0), scale(M_MIN_SCALE) {} void calculate() { @@ -123,23 +98,21 @@ struct FTreeVisual_setup const float tm_rot = PI_MUL_2 * Device.fTimeGlobal / ps_r__Tree_w_rot; // Calc wind-vector3, scale - wind.set(_sin(tm_rot), 0, _cos(tm_rot), 0); wind.normalize(); #if RENDER!=R_R1 const auto& env = g_pGamePersistent->Environment().CurrentEnv; const float fValue = env.m_fTreeAmplitudeIntensity; - wind.mul(fValue); // dir1*amplitude + wind.mul(fValue); #else - wind.mul(ps_r__Tree_w_amp); // dir1*amplitude + wind.mul(ps_r__Tree_w_amp); #endif scale = 1.f / float(FTreeVisual_quant); // setup constants - wave.set( - ps_r__Tree_Wave.x, ps_r__Tree_Wave.y, ps_r__Tree_Wave.z, Device.fTimeGlobal * ps_r__Tree_w_speed); // wave + wave.set(ps_r__Tree_Wave.x, ps_r__Tree_Wave.y, ps_r__Tree_Wave.z, Device.fTimeGlobal * ps_r__Tree_w_speed); // wave wave.div(PI_MUL_2); } }; diff --git a/src/Layers/xrRender/HOM.cpp b/src/Layers/xrRender/HOM.cpp index 8438b10689d..01f562a1ddf 100644 --- a/src/Layers/xrRender/HOM.cpp +++ b/src/Layers/xrRender/HOM.cpp @@ -11,8 +11,6 @@ #include "xrEngine/GameFont.h" #include "xrEngine/PerformanceAlert.hpp" -float psOSSR = .001f; - ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// @@ -155,15 +153,11 @@ void CHOM::Render_DB(CFrustum& base) // Update projection matrices on every frame to ensure valid HOM culling float view_dim = occ_dim_0; #if defined(USE_DX9) || defined(USE_DX11) - Fmatrix m_viewport = {view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - view_dim / 2.f + 0 + 0, view_dim / 2.f + 0 + 0, 0.0f, 1.0f}; - Fmatrix m_viewport_01 = {1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.f / 2.f + 0 + 0, 1.f / 2.f + 0 + 0, 0.0f, 1.0f}; + Fmatrix m_viewport = {view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, view_dim / 2.f + 0 + 0, view_dim / 2.f + 0 + 0, 0.0f, 1.0f}; + Fmatrix m_viewport_01 = {1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.f / 2.f + 0 + 0, 1.f / 2.f + 0 + 0, 0.0f, 1.0f}; #elif defined(USE_OGL) - Fmatrix m_viewport = {view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, -view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - view_dim / 2.f + 0 + 0, view_dim / 2.f + 0 + 0, 0.0f, 1.0f}; - Fmatrix m_viewport_01 = {1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, -1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, - 1.f / 2.f + 0 + 0, 1.f / 2.f + 0 + 0, 0.0f, 1.0f}; + Fmatrix m_viewport = {view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, -view_dim / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, view_dim / 2.f + 0 + 0, view_dim / 2.f + 0 + 0, 0.0f, 1.0f}; + Fmatrix m_viewport_01 = {1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, -1.f / 2.f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.f / 2.f + 0 + 0, 1.f / 2.f + 0 + 0, 0.0f, 1.0f}; #else # error No graphics API selected or enabled! #endif @@ -344,11 +338,15 @@ BOOL CHOM::visible(const Fbox2& B, float depth) const BOOL CHOM::visible(vis_data& vis) const { - if (Device.dwFrame < vis.hom_frame) - return TRUE; // not at this time :) if (!bEnabled) return TRUE; // return - everything visible + if (vis.hom_tested == Device.dwFrame) + return vis.hom_frame > vis.hom_tested; + + if (Device.dwFrame < vis.hom_frame) + return TRUE; // not at this time :) + ScopeStatTimer scopeStats(stats.Total, stats.TotalTimerLock); // Now, the test time comes @@ -357,20 +355,8 @@ BOOL CHOM::visible(vis_data& vis) const // 1. The object was visible, but we must to re-check it - test | frame-new, tested-???, hom_res = true; // 2. New object slides into view - delay test| frame-old, tested-old, hom_res = ???; const u32 frame_current = Device.dwFrame; - // u32 frame_prev = frame_current-1; - const BOOL result = _visible(vis.box, m_xform_01); - u32 delay = 1; - if (result) - { - // visible - delay next test - delay = ::Random.randI(5 * 2, 5 * 5); - } - else - { - // hidden - shedule to next frame - } - vis.hom_frame = frame_current + delay; + vis.hom_frame = result ? frame_current + ::Random.randI(5 * 2, 5 * 5) : frame_current; vis.hom_tested = frame_current; return result; } diff --git a/src/Layers/xrRender/Shader.cpp b/src/Layers/xrRender/Shader.cpp index 3a12aff9535..d0ef4102029 100644 --- a/src/Layers/xrRender/Shader.cpp +++ b/src/Layers/xrRender/Shader.cpp @@ -20,6 +20,7 @@ void resptrcode_shader::create(LPCSTR s_shader, LPCSTR s_textures, LPCSTR s_cons { _set(RImplementation.Resources->Create(s_shader, s_textures, s_constants, s_matrices)); } + void resptrcode_shader::create(IBlender* B, LPCSTR s_shader, LPCSTR s_textures, LPCSTR s_constants, LPCSTR s_matrices) { _set(RImplementation.Resources->Create(B, s_shader, s_textures, s_constants, s_matrices)); @@ -36,7 +37,6 @@ void resptrcode_geom::create(const VertexElement* decl, VertexBufferHandle vb, I _set(RImplementation.Resources->CreateGeom(decl, vb, ib)); } - ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// @@ -86,6 +86,7 @@ ShaderElement::ShaderElement() flags.bEmissive = FALSE; flags.bDistort = FALSE; flags.bWmark = FALSE; + flags.bLandscape = FALSE; } BOOL ShaderElement::equal(ShaderElement& S) @@ -100,6 +101,8 @@ BOOL ShaderElement::equal(ShaderElement& S) return FALSE; if (flags.bDistort != S.flags.bDistort) return FALSE; + if (flags.bLandscape != S.flags.bLandscape) + return FALSE; if (passes.size() != S.passes.size()) return FALSE; for (u32 p = 0; p < passes.size(); p++) diff --git a/src/Layers/xrRender/Shader.h b/src/Layers/xrRender/Shader.h index 8a7ad24907e..35c33b781c2 100644 --- a/src/Layers/xrRender/Shader.h +++ b/src/Layers/xrRender/Shader.h @@ -124,6 +124,7 @@ struct ECORE_API ShaderElement : public xr_resource_flagged u32 bEmissive : 1; u32 bDistort : 1; u32 bWmark : 1; + u32 bLandscape : 1; }; Sflags flags; diff --git a/src/Layers/xrRender/SkeletonCustom.cpp b/src/Layers/xrRender/SkeletonCustom.cpp index 59492892ab8..61ebf1a6f54 100644 --- a/src/Layers/xrRender/SkeletonCustom.cpp +++ b/src/Layers/xrRender/SkeletonCustom.cpp @@ -489,26 +489,31 @@ void CKinematics::Release() void CKinematics::LL_SetBoneVisible(u16 bone_id, BOOL val, BOOL bRecursive) { - VERIFY(bone_id < LL_BoneCount()); - u64 mask = u64(1) << bone_id; - visimask.set(mask, val); - if (!visimask.is(mask)) - { - bone_instances[bone_id].mTransform.scale(0.f, 0.f, 0.f); - } - else - { - CalculateBones_Invalidate(); - } - bone_instances[bone_id].mRenderTransform.mul_43( - bone_instances[bone_id].mTransform, (*bones)[bone_id]->m2b_transform); - if (bRecursive) - { - for (xr_vector::iterator C = (*bones)[bone_id]->children.begin(); - C != (*bones)[bone_id]->children.end(); ++C) + VERIFY(bone_id < LL_BoneCount()); + if (bone_id >= LL_BoneCount()) + return; + u64 mask = u64(1) << bone_id; + visimask.set(mask, val); + if (!visimask.is(mask)) + { + bone_instances[bone_id].mTransform.scale(M_MIN_SCALE, M_MIN_SCALE, M_MIN_SCALE); + if (LL_GetData(bone_id).GetParentID() < LL_BoneCount() && LL_GetData(bone_id).GetParentID() != BI_NONE) + bone_instances[bone_id].mTransform.c = LL_GetBoneInstance(LL_GetData(bone_id).GetParentID()).mTransform.c; + } + else + { + CalculateBones_Invalidate(); + } + + bone_instances[bone_id].mRenderTransform.mul_43(bone_instances[bone_id].mTransform, (*bones)[bone_id]->m2b_transform); + + if (bRecursive) + { + for (xr_vector::iterator C = (*bones)[bone_id]->children.begin(); C != (*bones)[bone_id]->children.end(); ++C) LL_SetBoneVisible((*C)->GetSelfID(), val, bRecursive); } - Visibility_Invalidate(); + + Visibility_Invalidate(); } void CKinematics::LL_SetBonesVisible(u64 mask) @@ -525,7 +530,7 @@ void CKinematics::LL_SetBonesVisible(u64 mask) { Fmatrix& A = bone_instances[b].mTransform; Fmatrix& B = bone_instances[b].mRenderTransform; - A.scale(0.f, 0.f, 0.f); + A.scale(M_MIN_SCALE, M_MIN_SCALE, M_MIN_SCALE); B.mul_43(A, (*bones)[b]->m2b_transform); } } diff --git a/src/Layers/xrRender/blenders/Blender_BmmD_deferred.cpp b/src/Layers/xrRender/blenders/Blender_BmmD_deferred.cpp index 9e8ba641059..6d78313604c 100644 --- a/src/Layers/xrRender/blenders/Blender_BmmD_deferred.cpp +++ b/src/Layers/xrRender/blenders/Blender_BmmD_deferred.cpp @@ -80,18 +80,22 @@ void CBlender_BmmD::Compile(CBlender_Compile& C) switch (C.iElement) { case SE_R2_NORMAL_HQ: // deffer + C.SH->flags.bLandscape = true; + C.r_Pass("shadow_direct_base", "shadow_direct_base", FALSE, TRUE, TRUE); + C.r_ColorWriteEnable(false, false, false, false); + C.r_End(); + uber_deffer(C, true, "impl", "impl", false, oT2_Name[0] ? oT2_Name : 0, true); + + C.RS.SetRS(D3DRS_ZFUNC, D3DCMP_EQUAL); + C.r_Sampler("s_mask", mask); C.r_Sampler("s_lmap", C.L_textures[1]); - C.r_Sampler( - "s_dt_r", oR_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); - C.r_Sampler( - "s_dt_g", oG_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); - C.r_Sampler( - "s_dt_b", oB_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); - C.r_Sampler( - "s_dt_a", oA_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); + C.r_Sampler("s_dt_r", oR_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); + C.r_Sampler("s_dt_g", oG_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); + C.r_Sampler("s_dt_b", oB_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); + C.r_Sampler("s_dt_a", oA_Name, false, D3DTADDRESS_WRAP, D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, D3DTEXF_ANISOTROPIC); C.r_Sampler("s_dn_r", strconcat(sizeof(mask), mask, oR_Name, "_bump")); C.r_Sampler("s_dn_g", strconcat(sizeof(mask), mask, oG_Name, "_bump")); @@ -114,7 +118,13 @@ void CBlender_BmmD::Compile(CBlender_Compile& C) C.r_End(); break; case SE_R2_NORMAL_LQ: // deffer + // landscape sorting + C.SH->flags.bLandscape = true; + C.r_Pass("shadow_direct_base", "shadow_direct_base", FALSE, TRUE, TRUE); + C.r_ColorWriteEnable(false, false, false, false); + C.r_End(); uber_deffer(C, false, "base", "impl", false, oT2_Name[0] ? oT2_Name : 0, true); + C.RS.SetRS(D3DRS_ZFUNC, D3DCMP_EQUAL); C.r_Sampler("s_lmap", C.L_textures[1]); C.r_End(); break; diff --git a/src/Layers/xrRender/blenders/uber_deffer.cpp b/src/Layers/xrRender/blenders/uber_deffer.cpp index be7fd73fa8a..14c3e8d4cdc 100644 --- a/src/Layers/xrRender/blenders/uber_deffer.cpp +++ b/src/Layers/xrRender/blenders/uber_deffer.cpp @@ -2,12 +2,11 @@ #include "uber_deffer.h" void fix_texture_name(pstr fn); -void uber_deffer(CBlender_Compile& C, bool hq, LPCSTR _vspec, LPCSTR _pspec, BOOL _aref, LPCSTR _detail_replace, - bool DO_NOT_FINISH) +void uber_deffer(CBlender_Compile& C, bool hq, LPCSTR _vspec, LPCSTR _pspec, BOOL _aref, LPCSTR _detail_replace, bool DO_NOT_FINISH) { // Uber-parse string256 fname, fnameA, fnameB; - xr_strcpy(fname, *C.L_textures[0]); //. andy if (strext(fname)) *strext(fname)=0; + xr_strcpy(fname, *C.L_textures[0]); fix_texture_name(fname); ref_texture _t; _t.create(fname); @@ -166,25 +165,11 @@ void uber_deffer(CBlender_Compile& C, bool hq, LPCSTR _vspec, LPCSTR _pspec, BOO C.r_dx11Texture("s_tdetailBumpX", texDetailBumpX); } } + else if (C.SH->flags.bLandscape) + C.r_Pass(vs, ps, FALSE, TRUE, FALSE); else - { C.r_Pass(vs, ps, FALSE); - } - // C.r_Sampler("s_base", C.L_textures[0], false, D3DTADDRESS_WRAP, - // D3DTEXF_ANISOTROPIC,D3DTEXF_LINEAR, - // D3DTEXF_ANISOTROPIC); - // C.r_Sampler("s_bumpX", fnameB, false, D3DTADDRESS_WRAP, - // D3DTEXF_ANISOTROPIC,D3DTEXF_LINEAR, - // D3DTEXF_ANISOTROPIC); // should be before base bump - // C.r_Sampler("s_bump", fnameA, false, D3DTADDRESS_WRAP, - // D3DTEXF_ANISOTROPIC,D3DTEXF_LINEAR, - // D3DTEXF_ANISOTROPIC); - // C.r_Sampler("s_bumpD", dt, false, D3DTADDRESS_WRAP, - // D3DTEXF_ANISOTROPIC,D3DTEXF_LINEAR, - // D3DTEXF_ANISOTROPIC); - // C.r_Sampler("s_detail", dt, false, D3DTADDRESS_WRAP, - // D3DTEXF_ANISOTROPIC, D3DTEXF_LINEAR, - // D3DTEXF_ANISOTROPIC); + C.r_dx11Texture("s_base", C.L_textures[0]); C.r_dx11Texture("s_bumpX", fnameB); // should be before base bump C.r_dx11Texture("s_bump", fnameA); diff --git a/src/Layers/xrRender/dxRainRender.cpp b/src/Layers/xrRender/dxRainRender.cpp index 30f9a70d5dc..ee97aec1e61 100644 --- a/src/Layers/xrRender/dxRainRender.cpp +++ b/src/Layers/xrRender/dxRainRender.cpp @@ -22,6 +22,18 @@ const int max_particles = 1000; const int particles_cache = 400; const float particles_time = .3f; +namespace +{ + +float srgbToLinear(float c) { return std::pow(c, 2.2f); } + +Fvector3 srgbToLinear(const Fvector3 c) +{ + return Fvector3{srgbToLinear(c.x), srgbToLinear(c.y), srgbToLinear(c.z)}; +} + +} // namespace + dxRainRender::dxRainRender() { IReader* F = FS.r_open("$game_meshes$", "dm" DELIMITER "rain.dm"); @@ -84,7 +96,7 @@ void dxRainRender::Render(CEffect_Rain& owner) // visual const float factor_visual = factor / 2.f + .5f; - const Fvector3 f_rain_color = g_pGamePersistent->Environment().CurrentEnv.rain_color; + const Fvector3 f_rain_color = srgbToLinear(g_pGamePersistent->Environment().CurrentEnv.rain_color); const u32 u_rain_color = color_rgba_f(f_rain_color.x, f_rain_color.y, f_rain_color.z, factor_visual); const float b_radius_wrap_sqr = _sqr((source_radius + .5f)); diff --git a/src/Layers/xrRender/r__dsgraph_build.cpp b/src/Layers/xrRender/r__dsgraph_build.cpp index 06e5b5d5a1e..b973e11d19d 100644 --- a/src/Layers/xrRender/r__dsgraph_build.cpp +++ b/src/Layers/xrRender/r__dsgraph_build.cpp @@ -29,6 +29,7 @@ ICF float CalcSSA(float& distSQ, Fvector& C, dxRender_Visual* V) distSQ = Device.vCameraPosition.distance_to_sqr(C) + EPS; return R / distSQ; } + ICF float CalcSSA(float& distSQ, Fvector& C, float R) { distSQ = Device.vCameraPosition.distance_to_sqr(C) + EPS; @@ -221,6 +222,12 @@ void R_dsgraph_structure::insert_static(dxRender_Visual* pVisual) counter_S++; + if (sh->flags.bLandscape && o.phase == CRender::PHASE_NORMAL) + { + mapLandscape.insert_anyway(distSQ, _MatrixItemS({ SSA, nullptr, pVisual, Fidentity, sh })); + return; + } + for (u32 iPass = 0; iPass < sh->passes.size(); ++iPass) { SPass* pass = sh->passes[iPass]._get(); diff --git a/src/Layers/xrRender/r__dsgraph_render.cpp b/src/Layers/xrRender/r__dsgraph_render.cpp index d6f33d8a7d4..7802001ce26 100644 --- a/src/Layers/xrRender/r__dsgraph_render.cpp +++ b/src/Layers/xrRender/r__dsgraph_render.cpp @@ -406,3 +406,45 @@ void R_dsgraph_structure::render_R1_box(IRender_Sector::sector_id_t sector_id, F } } } + +template +void __fastcall pLandscape_0(u32 context_id, const T& N) +{ + auto& dsgraph = RImplementation.get_context(context_id); + dxRender_Visual* V = N.second.pVisual; + VERIFY(V && V->shader._get()); + dsgraph.cmd_list.set_Element(N.second.se, 0); + const float LOD = calcLOD(N.second.ssa, V->vis.sphere.R); +#ifdef USE_DX11 + dsgraph.cmd_list.LOD.set_LOD(LOD); +#endif + V->Render(dsgraph.cmd_list, LOD, true); +} + +template +void __fastcall pLandscape_1(u32 context_id, const T& N) +{ + auto& dsgraph = RImplementation.get_context(context_id); + dxRender_Visual* V = N.second.pVisual; + VERIFY(V && V->shader._get()); + dsgraph.cmd_list.set_Element(N.second.se, 1); + dsgraph.cmd_list.apply_lmaterial(); + const float LOD = calcLOD(N.second.ssa, V->vis.sphere.R); +#ifdef USE_DX11 + dsgraph.cmd_list.LOD.set_LOD(LOD); +#endif + V->Render(dsgraph.cmd_list, LOD, true); +} + +void R_dsgraph_structure::r_dsgraph_render_landscape(u32 pass, bool bClear) +{ + RCache.set_xform_world(Fidentity); + + if (pass == 0) + mapLandscape.traverse_left_right(context_id, pLandscape_0); + else + mapLandscape.traverse_left_right(context_id, pLandscape_1); + + if (bClear) + mapLandscape.clear(); +} \ No newline at end of file diff --git a/src/Layers/xrRender/r__dsgraph_structure.h b/src/Layers/xrRender/r__dsgraph_structure.h index aaf34015d32..a282706fc5a 100644 --- a/src/Layers/xrRender/r__dsgraph_structure.h +++ b/src/Layers/xrRender/r__dsgraph_structure.h @@ -60,6 +60,7 @@ struct R_dsgraph_structure R_dsgraph::mapSorted_T mapHUDEmissive; #endif + R_dsgraph::mapLandscape_T mapLandscape; xr_vector Sectors; xr_vector Portals; CPortalTraverser PortalTraverser; @@ -188,6 +189,7 @@ struct R_dsgraph_structure void render_wmarks(); void render_distort(); void render_R1_box(IRender_Sector::sector_id_t sector_id, Fbox& _bb, int _element); + void r_dsgraph_render_landscape(u32 pass, bool bClear); void build_subspace(); }; diff --git a/src/Layers/xrRender/r__dsgraph_types.h b/src/Layers/xrRender/r__dsgraph_types.h index d79e132eda4..800cddfa091 100644 --- a/src/Layers/xrRender/r__dsgraph_types.h +++ b/src/Layers/xrRender/r__dsgraph_types.h @@ -64,6 +64,7 @@ using mapMatrixPasses_T = mapMatrix_T[SHADER_PASSES_MAX]; // Top level using mapSorted_T = xr_fixed_map; -using mapHUD_T = xr_fixed_map; -using mapLOD_T = xr_fixed_map; +using mapHUD_T = xr_fixed_map; +using mapLOD_T = xr_fixed_map; +using mapLandscape_T = xr_fixed_map; } diff --git a/src/Layers/xrRender/r__occlusion.cpp b/src/Layers/xrRender/r__occlusion.cpp index c6e59e01ecc..137d5714d30 100644 --- a/src/Layers/xrRender/r__occlusion.cpp +++ b/src/Layers/xrRender/r__occlusion.cpp @@ -4,7 +4,9 @@ #include "QueryHelper.h" R_occlusion::R_occlusion(void) { enabled = strstr(Core.Params, "-no_occq") ? FALSE : TRUE; } + R_occlusion::~R_occlusion(void) { occq_destroy(); } + void R_occlusion::occq_create(u32 limit) { pool.reserve(limit); @@ -20,6 +22,7 @@ void R_occlusion::occq_create(u32 limit) } std::reverse(pool.begin(), pool.end()); } + void R_occlusion::occq_destroy() { while (!used.empty()) @@ -27,12 +30,14 @@ void R_occlusion::occq_destroy() ReleaseQuery(used.back().Q); used.pop_back(); } + while (!pool.empty()) { ReleaseQuery(pool.back().Q); pool.pop_back(); } - used.clear(); + + used.clear(); pool.clear(); fids.clear(); } @@ -47,7 +52,7 @@ u32 R_occlusion::occq_begin(u32& ID) // Igor: prevent release crash if we issue too many queries if (pool.empty()) { - if ((Device.dwFrame % 40) == 0) + if ((Device.dwFrame % 100) == 0) Msg(" RENDER [Warning]: Too many occlusion queries were issued(>%u)!!!", pool.size()); ID = iInvalidHandle; return 0; @@ -67,14 +72,14 @@ u32 R_occlusion::occq_begin(u32& ID) VERIFY(pool.size()); used.push_back(pool.back()); } + pool.pop_back(); - // CHK_DX (used[ID].Q->Issue (D3DISSUE_BEGIN)); - CHK_DX(BeginQuery(used[ID].Q)); - // Msg ("begin: [%2d] - %d", used[ID].order, ID); + CHK_DX(BeginQuery(used[ID].Q)); return used[ID].order; } + void R_occlusion::occq_end(u32& ID) { ScopeLock lock{ &render_lock }; @@ -86,10 +91,9 @@ void R_occlusion::occq_end(u32& ID) if (ID == iInvalidHandle) return; - // Msg ("end : [%2d] - %d", used[ID].order, ID); - // CHK_DX (used[ID].Q->Issue (D3DISSUE_END)); CHK_DX(EndQuery(used[ID].Q)); } + R_occlusion::occq_result R_occlusion::occq_get(u32& ID) { ScopeLock lock{ &render_lock }; @@ -103,12 +107,9 @@ R_occlusion::occq_result R_occlusion::occq_get(u32& ID) occq_result fragments = 0; HRESULT hr; - // CHK_DX (used[ID].Q->GetData(&fragments,sizeof(fragments),D3DGETDATA_FLUSH)); - // Msg ("get : [%2d] - %d => %d", used[ID].order, ID, fragments); CTimer T; T.Start(); RImplementation.BasicStats.Wait.Begin(); - // while ((hr=used[ID].Q->GetData(&fragments,sizeof(fragments),D3DGETDATA_FLUSH))==S_FALSE) { VERIFY2(ID < used.size(), make_string("_Pos = %d, size() = %d ", ID, used.size())); while ((hr = GetData(used[ID].Q, &fragments, sizeof(fragments))) == S_FALSE) { @@ -121,7 +122,9 @@ R_occlusion::occq_result R_occlusion::occq_get(u32& ID) break; } } + RImplementation.BasicStats.Wait.End(); + #if defined(USE_DX9) || defined(USE_DX11) if (hr == D3DERR_DEVICELOST) fragments = 0xffffffff; diff --git a/src/Layers/xrRender/xrRender_console.cpp b/src/Layers/xrRender/xrRender_console.cpp index 3fa52ffaaff..67c5163e774 100644 --- a/src/Layers/xrRender/xrRender_console.cpp +++ b/src/Layers/xrRender/xrRender_console.cpp @@ -105,16 +105,17 @@ const xr_token qwater_reflection_quality_token[] = }; u32 ps_r3_msaa = 0; // = 0; -const xr_token qmsaa_token[] = {{"st_opt_off", 0}, {"2x", 1}, {"4x", 2}, {"8x", 3}, - {nullptr, 0}}; +const xr_token qmsaa_token[] = {{"st_opt_off", 0}, {"2x", 1}, {"4x", 2}, {"8x", 3}, {nullptr, 0}}; u32 ps_r3_msaa_atest = 0; // = 0; -const xr_token qmsaa__atest_token[] = { - {"st_opt_off", 0}, {"st_opt_atest_msaa_dx10_0", 1}, {"st_opt_atest_msaa_dx10_1", 2}, {nullptr, 0}}; +const xr_token qmsaa__atest_token[] = {{"st_opt_off", 0}, {"st_opt_atest_msaa_dx10_0", 1}, {"st_opt_atest_msaa_dx10_1", 2}, {nullptr, 0}}; u32 ps_r3_minmax_sm = 3; // = 0; const xr_token qminmax_sm_token[] = {{"off", 0}, {"on", 1}, {"auto", 2}, {"autodetect", 3}, {nullptr, 0}}; +u32 ps_r3_rendering_space = 0; // = 0; +const xr_token rendering__space_token[] = {{"gamma", 0}, {"linear", 1}, {nullptr, 0}}; + // “Off” // “DX10.0 style [Standard]” // “DX10.1 style [Higher quality]” @@ -1097,6 +1098,7 @@ void xrRender_initconsole() //CMD3(CCC_Mask, "r3_msaa_alphatest", &ps_r2_ls_flags, (u32)R3FLAG_MSAA_ALPHATEST); CMD3(CCC_Token, "r3_msaa_alphatest", &ps_r3_msaa_atest, qmsaa__atest_token); CMD3(CCC_Token, "r3_minmax_sm", &ps_r3_minmax_sm, qminmax_sm_token); + CMD3(CCC_Token, "r3_rendering_space", &ps_r3_rendering_space, rendering__space_token); // Allow real-time fog config reload #if (RENDER == R_R3) || (RENDER == R_R4) diff --git a/src/Layers/xrRender/xrRender_console.h b/src/Layers/xrRender/xrRender_console.h index d8008a948f3..3410deb83df 100644 --- a/src/Layers/xrRender/xrRender_console.h +++ b/src/Layers/xrRender/xrRender_console.h @@ -29,6 +29,9 @@ extern ECORE_API const xr_token qmsaa__atest_token[]; extern ECORE_API u32 ps_r3_minmax_sm; // = 0; extern ECORE_API const xr_token qminmax_sm_token[]; +extern ECORE_API u32 ps_r3_rendering_space; // = 0; +extern ECORE_API const xr_token rendering__space_token[]; + extern ENGINE_API int ps_r__Supersample; extern ECORE_API int ps_r__LightSleepFrames; diff --git a/src/Layers/xrRenderDX11/dx11HW.cpp b/src/Layers/xrRenderDX11/dx11HW.cpp index 5de6bf437fa..737339901b2 100644 --- a/src/Layers/xrRenderDX11/dx11HW.cpp +++ b/src/Layers/xrRenderDX11/dx11HW.cpp @@ -262,15 +262,9 @@ bool CHW::CreateSwapChain(HWND hwnd) sd.BufferDesc.Height = Device.dwHeight; // TODO: DX11: implement dynamic format selection - constexpr DXGI_FORMAT formats[] = - { - //DXGI_FORMAT_R16G16B16A16_FLOAT, // Do we even need this? - //DXGI_FORMAT_R10G10B10A2_UNORM, // D3DX11SaveTextureToMemory fails on this format - DXGI_FORMAT_R8G8B8A8_UNORM, - }; + sd.BufferDesc.Format = selectBackBufferFormat(); // Select back-buffer format - sd.BufferDesc.Format = SelectFormat(D3D_FORMAT_SUPPORT_DISPLAY, formats); Caps.fTarget = dx11TextureUtils::ConvertTextureFormat(sd.BufferDesc.Format); // Buffering @@ -319,16 +313,9 @@ bool CHW::CreateSwapChain2(HWND hwnd) // Back buffer desc.Width = Device.dwWidth; desc.Height = Device.dwHeight; - - constexpr DXGI_FORMAT formats[] = - { - //DXGI_FORMAT_R16G16B16A16_FLOAT, - //DXGI_FORMAT_R10G10B10A2_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM, - }; + desc.Format = selectBackBufferFormat(); // Select back-buffer format - desc.Format = SelectFormat(D3D11_FORMAT_SUPPORT_DISPLAY, formats); Caps.fTarget = dx11TextureUtils::ConvertTextureFormat(desc.Format); // Buffering @@ -379,6 +366,25 @@ bool CHW::CreateSwapChain2(HWND hwnd) return false; } + +DXGI_FORMAT CHW::selectBackBufferFormat() const +{ + if (ps_r3_rendering_space == 1) + { + constexpr DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM_SRGB}; + + // Select back-buffer format + return SelectFormat(D3D11_FORMAT_SUPPORT_DISPLAY, formats); + } + else + { + constexpr DXGI_FORMAT formats[] = {DXGI_FORMAT_R8G8B8A8_UNORM}; + + // Select back-buffer format + return SelectFormat(D3D11_FORMAT_SUPPORT_DISPLAY, formats); + } +} + bool CHW::ThisInstanceIsGlobal() const { return this == &HW; @@ -429,10 +435,10 @@ void CHW::Reset() DXGI_MODE_DESC& desc = m_ChainDesc.BufferDesc; desc.Width = Device.dwWidth; desc.Height = Device.dwHeight; + desc.Format = selectBackBufferFormat(); CHK_DX(m_pSwapChain->ResizeTarget(&desc)); - CHK_DX(m_pSwapChain->ResizeBuffers( - cd.BufferCount, desc.Width, desc.Height, desc.Format, cd.Flags)); + CHK_DX(m_pSwapChain->ResizeBuffers(cd.BufferCount, desc.Width, desc.Height, desc.Format, cd.Flags)); } void CHW::SetPrimaryAttributes(u32& /*windowFlags*/) diff --git a/src/Layers/xrRenderDX11/dx11HW.h b/src/Layers/xrRenderDX11/dx11HW.h index 9faac490c2d..b573bfd0963 100644 --- a/src/Layers/xrRenderDX11/dx11HW.h +++ b/src/Layers/xrRenderDX11/dx11HW.h @@ -104,6 +104,7 @@ class CHW XRay::Module hD3DCompiler; XRay::Module hDXGI; XRay::Module hD3D; + DXGI_FORMAT selectBackBufferFormat() const; }; extern ECORE_API CHW HW; diff --git a/src/Layers/xrRenderDX11/dx11Texture.cpp b/src/Layers/xrRenderDX11/dx11Texture.cpp index c023c769528..243e5ed192d 100644 --- a/src/Layers/xrRenderDX11/dx11Texture.cpp +++ b/src/Layers/xrRenderDX11/dx11Texture.cpp @@ -8,8 +8,7 @@ constexpr cpcstr NOT_EXISTING_TEXTURE = "ed" DELIMITER "ed_not_existing_texture" void fix_texture_name(pstr fn) { pstr _ext = strext(fn); - if (_ext && (!xr_stricmp(_ext, ".tga") || !xr_stricmp(_ext, ".dds") || !xr_stricmp(_ext, ".bmp") || - !xr_stricmp(_ext, ".ogm"))) + if (_ext && (!xr_stricmp(_ext, ".tga") || !xr_stricmp(_ext, ".dds") || !xr_stricmp(_ext, ".bmp") || !xr_stricmp(_ext, ".ogm"))) { *_ext = 0; } @@ -46,12 +45,7 @@ int get_texture_load_lod(LPCSTR fn) } if (psTextureLOD < 2) - { - //if (enough_address_space_available) return 0; - //else - // return 1; - } else if (psTextureLOD < 4) return 1; else @@ -111,167 +105,6 @@ IC void Reduce(size_t& w, size_t& h, size_t& l, int skip) h = 1; } -/* -ID3DTexture2D* TW_LoadTextureFromTexture -( - ID3DTexture2D* t_from, - D3DFORMAT& t_dest_fmt, - int levels_2_skip, - u32& w, - u32& h - ) -{ - // Calculate levels & dimensions - ID3DTexture2D* t_dest = NULL; - D3DSURFACE_DESC t_from_desc0 ; - R_CHK (t_from->GetLevelDesc (0,&t_from_desc0)); - int levels_exist = t_from->GetLevelCount(); - int top_width = t_from_desc0.Width; - int top_height = t_from_desc0.Height; - Reduce (top_width,top_height,levels_exist,levels_2_skip); - - // Create HW-surface - if (D3DX_DEFAULT==t_dest_fmt) t_dest_fmt = t_from_desc0.Format; - R_CHK (D3DXCreateTexture( - HW.pDevice, - top_width,top_height, - levels_exist,0,t_dest_fmt, - D3DPOOL_MANAGED,&t_dest - )); - - // Copy surfaces & destroy temporary - ID3DTexture2D* T_src= t_from; - ID3DTexture2D* T_dst= t_dest; - - int L_src = T_src->GetLevelCount ()-1; - int L_dst = T_dst->GetLevelCount ()-1; - for (; L_dst>=0; L_src--,L_dst--) - { - // Get surfaces - IDirect3DSurface9 *S_src, *S_dst; - R_CHK (T_src->GetSurfaceLevel (L_src,&S_src)); - R_CHK (T_dst->GetSurfaceLevel (L_dst,&S_dst)); - - // Copy - R_CHK (D3DXLoadSurfaceFromSurface(S_dst,NULL,NULL,S_src,NULL,NULL,D3DX_FILTER_NONE,0)); - - // Release surfaces - _RELEASE (S_src); - _RELEASE (S_dst); - } - - // OK - w = top_width; - h = top_height; - return t_dest; -} - -template -IC void TW_Iterate_1OP -( - ID3DTexture2D* t_dst, - ID3DTexture2D* t_src, - const _It pred - ) -{ - DWORD mips = t_dst->GetLevelCount(); - R_ASSERT (mips == t_src->GetLevelCount()); - for (DWORD i = 0; i < mips; i++) { - D3DLOCKED_RECT Rsrc,Rdst; - D3DSURFACE_DESC desc,descS; - - t_dst->GetLevelDesc (i, &desc); - t_src->GetLevelDesc (i, &descS); - VERIFY (desc.Format==descS.Format); - VERIFY (desc.Format==D3DFMT_A8R8G8B8); - t_src->LockRect (i,&Rsrc,0,0); - t_dst->LockRect (i,&Rdst,0,0); - for (u32 y = 0; y < desc.Height; y++) { - for (u32 x = 0; x < desc.Width; x++) { - DWORD& pSrc = *(((DWORD*)((u8*)Rsrc.pBits + (y * Rsrc.Pitch)))+x); - DWORD& pDst = *(((DWORD*)((u8*)Rdst.pBits + (y * Rdst.Pitch)))+x); - pDst = pred(pDst,pSrc); - } - } - t_dst->UnlockRect (i); - t_src->UnlockRect (i); - } -} -template -IC void TW_Iterate_2OP -( - ID3DTexture2D* t_dst, - ID3DTexture2D* t_src0, - ID3DTexture2D* t_src1, - const _It pred - ) -{ - DWORD mips = t_dst->GetLevelCount(); - R_ASSERT (mips == t_src0->GetLevelCount()); - R_ASSERT (mips == t_src1->GetLevelCount()); - for (DWORD i = 0; i < mips; i++) { - D3DLOCKED_RECT Rsrc0,Rsrc1,Rdst; - D3DSURFACE_DESC desc,descS0,descS1; - - t_dst->GetLevelDesc (i, &desc); - t_src0->GetLevelDesc (i, &descS0); - t_src1->GetLevelDesc (i, &descS1); - VERIFY (desc.Format==descS0.Format); - VERIFY (desc.Format==descS1.Format); - VERIFY (desc.Format==D3DFMT_A8R8G8B8); - t_src0->LockRect (i,&Rsrc0, 0,0); - t_src1->LockRect (i,&Rsrc1, 0,0); - t_dst->LockRect (i,&Rdst, 0,0); - for (u32 y = 0; y < desc.Height; y++) { - for (u32 x = 0; x < desc.Width; x++) { - DWORD& pSrc0 = *(((DWORD*)((u8*)Rsrc0.pBits + (y * Rsrc0.Pitch)))+x); - DWORD& pSrc1 = *(((DWORD*)((u8*)Rsrc1.pBits + (y * Rsrc1.Pitch)))+x); - DWORD& pDst = *(((DWORD*)((u8*)Rdst.pBits + (y * Rdst.Pitch)))+x); - pDst = pred(pDst,pSrc0,pSrc1); - } - } - t_dst->UnlockRect (i); - t_src0->UnlockRect (i); - t_src1->UnlockRect (i); - } -} - -IC u32 it_gloss_rev (u32 d, u32 s) { return color_rgba ( - color_get_A(s), // gloss - color_get_B(d), - color_get_G(d), - color_get_R(d) ); -} -IC u32 it_gloss_rev_base(u32 d, u32 s) { - u32 occ = color_get_A(d)/3; - u32 def = 8; - u32 gloss = (occ*1+def*3)/4; - return color_rgba ( - gloss, // gloss - color_get_B(d), - color_get_G(d), - color_get_R(d) - ); -} -IC u32 it_difference (u32 d, u32 orig, u32 ucomp) { return color_rgba( - 128+(int(color_get_R(orig))-int(color_get_R(ucomp)))*2, // R-error - 128+(int(color_get_G(orig))-int(color_get_G(ucomp)))*2, // G-error - 128+(int(color_get_B(orig))-int(color_get_B(ucomp)))*2, // B-error - 128+(int(color_get_A(orig))-int(color_get_A(ucomp)))*2 ); // A-error -} -IC u32 it_height_rev (u32 d, u32 s) { return color_rgba ( - color_get_A(d), // diff x - color_get_B(d), // diff y - color_get_G(d), // diff z - color_get_R(s) ); // height -} -IC u32 it_height_rev_base(u32 d, u32 s) { return color_rgba ( - color_get_A(d), // diff x - color_get_B(d), // diff y - color_get_G(d), // diff z - (color_get_R(s)+color_get_G(s)+color_get_B(s))/3 ); // height -} -*/ ID3DBaseTexture* CRender::texture_load(LPCSTR fRName, u32& ret_msize) { ret_msize = 0; @@ -288,8 +121,10 @@ ID3DBaseTexture* CRender::texture_load(LPCSTR fRName, u32& ret_msize) // make file name string_path fname; - xr_strcpy(fname, fRName); //. andy if (strext(fname)) *strext(fname)=0; + xr_strcpy(fname, fRName); fix_texture_name(fname); + bool force_srgb = o.linear_space_rendering && !strstr(fname, "_bump") && !strstr(fname, "_mask") && !strstr(fname, "_dudv") && !strstr(fname, "water_normal") && !strstr(fname, "internal_") && !strstr(fname, "_lm.") && !strstr(fname, "level_lods_nm") && !strstr(fname, "lmap#") && !strstr(fname, "ui_magnifier2"); + IReader* S = NULL; if (!FS.exist(fn, "$game_textures$", fname, ".dds") && strstr(fname, "_bump")) goto _BUMP_from_base; @@ -344,10 +179,7 @@ ID3DBaseTexture* CRender::texture_load(LPCSTR fRName, u32& ret_msize) IMG.height = (IMG.height + 3u) & ~0x3u; } - R_CHK2(CreateTextureEx(HW.pDevice, texture.GetImages() + mip_lod, texture.GetImageCount(), IMG, - D3D_USAGE_IMMUTABLE, D3D_BIND_SHADER_RESOURCE, 0, IMG.miscFlags, DirectX::CREATETEX_DEFAULT, - &pTexture2D), fn - ); + R_CHK2(CreateTextureEx(HW.pDevice, texture.GetImages() + mip_lod, texture.GetImageCount(), IMG, D3D_USAGE_IMMUTABLE, D3D_BIND_SHADER_RESOURCE, 0, IMG.miscFlags, force_srgb ? DirectX::CREATETEX_FORCE_SRGB : DirectX::CREATETEX_DEFAULT, &pTexture2D), fn); FS.r_close(S); // OK @@ -358,7 +190,6 @@ ID3DBaseTexture* CRender::texture_load(LPCSTR fRName, u32& ret_msize) _BUMP_from_base: { - // Msg ("! auto-generated bump map: %s",fname); Msg("! Fallback to default bump map: %s", fname); ////////////////// if (strstr(fname, "_bump#")) diff --git a/src/Layers/xrRenderDX11/dx11TextureUtils.cpp b/src/Layers/xrRenderDX11/dx11TextureUtils.cpp index 41fba87b5f2..55e1d395661 100644 --- a/src/Layers/xrRenderDX11/dx11TextureUtils.cpp +++ b/src/Layers/xrRenderDX11/dx11TextureUtils.cpp @@ -26,6 +26,7 @@ TextureFormatPairs TextureFormatList[] = { // D3DFMT_X4R4G4B4 Not available {D3DFMT_A2B10G10R10, DXGI_FORMAT_R10G10B10A2_UNORM}, {D3DFMT_A8B8G8R8, DXGI_FORMAT_R8G8B8A8_UNORM}, // & DXGI_FORMAT_R8G8B8A8_UNORM_SRGB + {D3DFMT_HACK_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB}, // D3DFMT_X8B8G8R8 Not available {D3DFMT_G16R16, DXGI_FORMAT_R16G16_UNORM}, // D3DFMT_A2R10G10B10 Not available diff --git a/src/Layers/xrRenderPC_R4/r4_rendertarget.h b/src/Layers/xrRenderPC_R4/r4_rendertarget.h index a0cde0c26fc..f200c3d5d4a 100644 --- a/src/Layers/xrRenderPC_R4/r4_rendertarget.h +++ b/src/Layers/xrRenderPC_R4/r4_rendertarget.h @@ -407,4 +407,14 @@ class CRenderTarget : public IRender_Target void dbg_addline(Fvector& /*P0*/, Fvector& /*P1*/, u32 /*c*/) {} void dbg_addplane(Fplane& /*P0*/, u32 /*c*/) {} #endif +private: + float toLinearSpace(float c) + { + return RImplementation.o.linear_space_rendering ? std::pow(c, 2.2f) : c; + } + + Fvector4 toLinearSpace(const Fvector4& c) + { + return Fvector4{toLinearSpace(c.x), toLinearSpace(c.y), toLinearSpace(c.z), c.w}; + } }; diff --git a/src/Layers/xrRenderPC_R4/r4_rendertarget_phase_combine.cpp b/src/Layers/xrRenderPC_R4/r4_rendertarget_phase_combine.cpp index f7163af4143..68b75080421 100644 --- a/src/Layers/xrRenderPC_R4/r4_rendertarget_phase_combine.cpp +++ b/src/Layers/xrRenderPC_R4/r4_rendertarget_phase_combine.cpp @@ -216,8 +216,8 @@ void CRenderTarget::phase_combine() RCache.set_c("Ldynamic_color", sunclr); RCache.set_c("Ldynamic_dir", sundir); - RCache.set_c("env_color", envclr); - RCache.set_c("fog_color", fogclr); + RCache.set_c("env_color", toLinearSpace(envclr)); + RCache.set_c("fog_color", toLinearSpace(fogclr)); RCache.set_c("ssao_noise_tile_factor", fSSAONoise); RCache.set_c("ssao_kernel_size", fSSAOKernelSize); diff --git a/src/Layers/xrRenderPC_R4/r4_shaders.cpp b/src/Layers/xrRenderPC_R4/r4_shaders.cpp index 502753906ac..165c7f84ff8 100644 --- a/src/Layers/xrRenderPC_R4/r4_shaders.cpp +++ b/src/Layers/xrRenderPC_R4/r4_shaders.cpp @@ -414,6 +414,9 @@ HRESULT CRender::shader_compile(pcstr name, IReader* fs, pcstr pFunctionName, pc // Minmax SM appendShaderOption(o.minmax_sm, "USE_MINMAX_SM", "1"); + // Linear space rendering if 1, or gamma space if 0 + appendShaderOption(o.linear_space_rendering, "LINEAR_SPACE_RENDERING", "1"); + // Ascii's Screen Space Shaders - SSS preprocessor stuff if (ps_ssfx_rain_1.w > 0) { diff --git a/src/Layers/xrRender_R2/r2.cpp b/src/Layers/xrRender_R2/r2.cpp index 1126689a1d5..d2db9d676b9 100644 --- a/src/Layers/xrRender_R2/r2.cpp +++ b/src/Layers/xrRender_R2/r2.cpp @@ -554,9 +554,9 @@ void CRender::create() o.minmax_sm_screenarea_threshold = 1600 * 1200; #if defined(USE_DX11) - o.tessellation = - HW.FeatureLevel >= D3D_FEATURE_LEVEL_11_0 && ps_r2_ls_flags_ext.test(R2FLAGEXT_ENABLE_TESSELLATION); + o.tessellation = HW.FeatureLevel >= D3D_FEATURE_LEVEL_11_0 && ps_r2_ls_flags_ext.test(R2FLAGEXT_ENABLE_TESSELLATION); o.support_rt_arrays = true; + o.linear_space_rendering = (ps_r3_rendering_space == 1); #else o.support_rt_arrays = false; #endif diff --git a/src/Layers/xrRender_R2/r2.h b/src/Layers/xrRender_R2/r2.h index 52c4a6be11d..cb626dcf5f9 100644 --- a/src/Layers/xrRender_R2/r2.h +++ b/src/Layers/xrRender_R2/r2.h @@ -275,6 +275,8 @@ class CRender final : public D3DXRenderBase // Yohji - New shader support u32 new_shader_support : 1; + + u32 linear_space_rendering : 1; } o; struct RenderR2Statistics diff --git a/src/Layers/xrRender_R2/r2_R_lights.cpp b/src/Layers/xrRender_R2/r2_R_lights.cpp index 4e8b413619d..fb57197330c 100644 --- a/src/Layers/xrRender_R2/r2_R_lights.cpp +++ b/src/Layers/xrRender_R2/r2_R_lights.cpp @@ -32,7 +32,8 @@ void CRender::render_lights(light_Package& LP) L->vis_update(); if (!L->vis.visible) { - source.erase(source.begin() + it); + std::swap(source[it], source.back()); + source.pop_back(); it--; } else @@ -42,25 +43,28 @@ void CRender::render_lights(light_Package& LP) } } - // 2. refactor - infact we could go from the backside and sort in ascending order + // 2. refactor { xr_vector& source = LP.v_shadowed; xr_vector refactored; refactored.reserve(source.size()); const size_t total = source.size(); + std::sort(source.begin(), source.end(), [](light* l1, light* l2) + { + const u32 a0 = l1->X.S.size; + const u32 a1 = l2->X.S.size; + return a0 < a1; // ascending order + }); + for (u16 smap_ID = 0; refactored.size() != total; ++smap_ID) { LP_smap_pool.initialize(RImplementation.o.smapsize); - std::sort(source.begin(), source.end(), [](light* l1, light* l2) - { - const u32 a0 = l1->X.S.size; - const u32 a1 = l2->X.S.size; - return a0 > a1; // reverse -> descending - }); - for (size_t test = 0; test < source.size(); ++test) + + for (auto& L : source) { - light* L = source[test]; + if (!L) + continue; SMAP_Rect R{}; if (LP_smap_pool.push(R, L->X.S.size)) { @@ -69,14 +73,12 @@ void CRender::render_lights(light_Package& LP) L->X.S.posY = R.min.y; L->vis.smap_ID = smap_ID; refactored.push_back(L); - source.erase(source.begin() + test); - --test; + L = nullptr; } } } // save (lights are popped from back) - std::reverse(refactored.begin(), refactored.end()); LP.v_shadowed = std::move(refactored); } @@ -129,43 +131,42 @@ void CRender::render_lights(light_Package& LP) } }; - const auto& flush_lights = [&]() + const auto& flush_lights = [](CRender& render, xr_vector& lights_queue) { for (const auto& [L, task, batch_id] : lights_queue) { VERIFY(task); TaskScheduler->Wait(*task); - auto& dsgraph = get_context(batch_id); + auto& dsgraph = render.get_context(batch_id); const bool bNormal = !dsgraph.mapNormalPasses[0][0].empty() || !dsgraph.mapMatrixPasses[0][0].empty(); - const bool bSpecial = !dsgraph.mapNormalPasses[1][0].empty() || !dsgraph.mapMatrixPasses[1][0].empty() || - !dsgraph.mapSorted.empty(); + const bool bSpecial = !dsgraph.mapNormalPasses[1][0].empty() || !dsgraph.mapMatrixPasses[1][0].empty() || !dsgraph.mapSorted.empty(); if (bNormal || bSpecial) { PIX_EVENT_CTX(dsgraph.cmd_list, SHADOWED_LIGHT); - Stats.s_merged++; + render.Stats.s_merged++; L_spot_s.push_back(L); - Target->phase_smap_spot(dsgraph.cmd_list, L); + render.Target->phase_smap_spot(dsgraph.cmd_list, L); dsgraph.cmd_list.set_xform_world(Fidentity); dsgraph.cmd_list.set_xform_view(L->X.S.view); dsgraph.cmd_list.set_xform_project(L->X.S.project); dsgraph.render_graph(0); if (ps_r2_ls_flags.test(R2FLAG_SUN_DETAILS)) { - if (check_grass_shadow(L, ViewBase)) + if (check_grass_shadow(L, render.ViewBase)) { - Details->fade_distance = -1; // Use light position to calc "fade" - Details->light_position.set(L->position); - Details->Render(dsgraph.cmd_list); + render.Details->fade_distance = -1; // Use light position to calc "fade" + render.Details->light_position.set(L->position); + render.Details->Render(dsgraph.cmd_list); } } L->X.S.transluent = FALSE; if (bSpecial) { L->X.S.transluent = TRUE; - Target->phase_smap_spot_tsh(dsgraph.cmd_list, L); + render.Target->phase_smap_spot_tsh(dsgraph.cmd_list, L); PIX_EVENT_CTX(dsgraph.cmd_list, SHADOWED_LIGHTS_RENDER_GRAPH); dsgraph.render_graph(1); // normal level, secondary priority PIX_EVENT_CTX(dsgraph.cmd_list, SHADOWED_LIGHTS_RENDER_SORTED); @@ -173,9 +174,7 @@ void CRender::render_lights(light_Package& LP) } } else - { - Stats.s_finalclip++; - } + render.Stats.s_finalclip++; L->svis[batch_id].end(); // NOTE(DX11): occqs are fetched here, this should be done on the imm context only RImplementation.release_context(batch_id); @@ -198,6 +197,7 @@ void CRender::render_lights(light_Package& LP) { if (source.empty()) break; + L = source.back(); if (L->vis.smap_ID != sid) break; @@ -206,7 +206,7 @@ void CRender::render_lights(light_Package& LP) if (batch_id == R_dsgraph_structure::INVALID_CONTEXT_ID) { VERIFY(!lights_queue.empty()); - flush_lights(); + flush_lights(*this, lights_queue); continue; } @@ -228,7 +228,7 @@ void CRender::render_lights(light_Package& LP) } lights_queue.emplace_back(data); } - flush_lights(); // in case if something left + flush_lights(*this, lights_queue); // in case if something left cmd_list.Invalidate(); @@ -273,17 +273,19 @@ void CRender::render_lights(light_Package& LP) // if (was_spot_shadowed) -> accum spot shadowed if (!L_spot_s.empty()) { + bool needVolumetric = RImplementation.o.advancedpp && ps_r2_ls_flags.is(R2FLAG_VOLUMETRIC_LIGHTS); + PIX_EVENT(ACCUM_SPOT); + PIX_EVENT(ACCUM_VOLUMETRIC); + for (light* p_light : L_spot_s) { Target->accum_spot(cmd_list, p_light); render_indirect(p_light); - } - PIX_EVENT(ACCUM_VOLUMETRIC); - if (RImplementation.o.advancedpp && ps_r2_ls_flags.is(R2FLAG_VOLUMETRIC_LIGHTS)) - for (light* p_light : L_spot_s) + if (needVolumetric) Target->accum_volumetric(cmd_list, p_light); + } L_spot_s.clear(); } diff --git a/src/Layers/xrRender_R2/r2_R_render.cpp b/src/Layers/xrRender_R2/r2_R_render.cpp index df78c903e70..a0fe5a79499 100644 --- a/src/Layers/xrRender_R2/r2_R_render.cpp +++ b/src/Layers/xrRender_R2/r2_R_render.cpp @@ -163,6 +163,10 @@ void CRender::Render() if (ps_r2_ls_flags.test(R2FLAG_EXP_SPLIT_SCENE)) split_the_scene_to_minimize_wait = TRUE; + // landscape phase + Target->u_setrt(dsgraph.cmd_list, Device.dwWidth, Device.dwHeight, NULL, NULL, NULL, Target->get_base_zb()); + dsgraph.r_dsgraph_render_landscape(0, false); + //******* Main render :: PART-0 -- first #ifdef USE_OGL if (psDeviceFlags.test(rsWireframe)) @@ -178,6 +182,7 @@ void CRender::Render() dsgraph.render_lods(true, true); if (Details) Details->Render(dsgraph.cmd_list); + dsgraph.r_dsgraph_render_landscape(1, true); Target->phase_scene_end(); } else @@ -186,8 +191,10 @@ void CRender::Render() // level, SPLIT Target->phase_scene_begin(); dsgraph.render_graph(0); + dsgraph.r_dsgraph_render_landscape(1, true); Target->disable_aniso(); } + #ifdef USE_OGL if (psDeviceFlags.test(rsWireframe)) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); diff --git a/src/Layers/xrRender_R2/r2_rendertarget.cpp b/src/Layers/xrRender_R2/r2_rendertarget.cpp index 7490a391dfa..5253e792850 100644 --- a/src/Layers/xrRender_R2/r2_rendertarget.cpp +++ b/src/Layers/xrRender_R2/r2_rendertarget.cpp @@ -260,6 +260,8 @@ CRenderTarget::CRenderTarget() const u32 SampleCount = options.msaa ? options.msaa_samples : 1u; const u32 BoundSamples = options.msaa_opt ? 1u : options.msaa_samples; + + const D3DFORMAT mainColorFormat = options.linear_space_rendering ? D3DFMT_HACK_R8G8B8A8_UNORM_SRGB : D3DFMT_A8R8G8B8; #ifdef DEBUG Msg("MSAA samples = %d", SampleCount); @@ -327,7 +329,7 @@ CRenderTarget::CRenderTarget() if (options.mrtmixdepth) { // NV50 - rt_Color.create(r2_RT_albedo, w, h, D3DFMT_A8R8G8B8, SampleCount); + rt_Color.create(r2_RT_albedo, w, h, mainColorFormat, SampleCount); rt_Accumulator.create(r2_RT_accum, w, h, D3DFMT_A16B16G16R16F, SampleCount); } else @@ -358,10 +360,10 @@ CRenderTarget::CRenderTarget() } // generic(LDR) RTs - rt_Generic_0.create(r2_RT_generic0, w, h, D3DFMT_A8R8G8B8, 1); - rt_Generic_1.create(r2_RT_generic1, w, h, D3DFMT_A8R8G8B8, 1); + rt_Generic_0.create(r2_RT_generic0, w, h, mainColorFormat, 1); + rt_Generic_1.create(r2_RT_generic1, w, h, mainColorFormat, 1); #if defined(USE_DX11) || defined(USE_OGL) - rt_Generic.create(r2_RT_generic, w, h, D3DFMT_A8R8G8B8, 1); + rt_Generic.create(r2_RT_generic, w, h, mainColorFormat, 1); #endif if (!options.msaa) { @@ -370,12 +372,10 @@ CRenderTarget::CRenderTarget() } else { - rt_Generic_0_r.create(r2_RT_generic0_r, w, h, D3DFMT_A8R8G8B8, SampleCount); - rt_Generic_1_r.create(r2_RT_generic1_r, w, h, D3DFMT_A8R8G8B8, SampleCount); + rt_Generic_0_r.create(r2_RT_generic0_r, w, h, mainColorFormat, SampleCount); + rt_Generic_1_r.create(r2_RT_generic1_r, w, h, mainColorFormat, SampleCount); } - // Igor: for volumetric lights - // rt_Generic_2.create (r2_RT_generic2,w,h,D3DFMT_A8R8G8B8 ); - // temp: for higher quality blends + if (options.advancedpp) rt_Generic_2.create(r2_RT_generic2, w, h, D3DFMT_A16B16G16R16F, SampleCount); @@ -631,13 +631,10 @@ CRenderTarget::CRenderTarget() // BLOOM { - D3DFORMAT fmt = D3DFMT_A8R8G8B8; // D3DFMT_X8R8G8B8; + D3DFORMAT fmt = mainColorFormat; u32 w = BLOOM_size_X, h = BLOOM_size_Y; - constexpr u32 fvf_build = D3DFVF_XYZRHW | D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) | - D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE2(3); - constexpr u32 fvf_filter = (u32)D3DFVF_XYZRHW | D3DFVF_TEX8 | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEXCOORDSIZE4(1) | - D3DFVF_TEXCOORDSIZE4(2) | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEXCOORDSIZE4(4) | D3DFVF_TEXCOORDSIZE4(5) | - D3DFVF_TEXCOORDSIZE4(6) | D3DFVF_TEXCOORDSIZE4(7); + constexpr u32 fvf_build = D3DFVF_XYZRHW | D3DFVF_TEX4 | D3DFVF_TEXCOORDSIZE2(0) | D3DFVF_TEXCOORDSIZE2(1) | D3DFVF_TEXCOORDSIZE2(2) | D3DFVF_TEXCOORDSIZE2(3); + constexpr u32 fvf_filter = (u32)D3DFVF_XYZRHW | D3DFVF_TEX8 | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEXCOORDSIZE4(1) | D3DFVF_TEXCOORDSIZE4(2) | D3DFVF_TEXCOORDSIZE4(3) | D3DFVF_TEXCOORDSIZE4(4) | D3DFVF_TEXCOORDSIZE4(5) | D3DFVF_TEXCOORDSIZE4(6) | D3DFVF_TEXCOORDSIZE4(7); rt_Bloom_1.create(r2_RT_bloom1, w, h, fmt); rt_Bloom_2.create(r2_RT_bloom2, w, h, fmt); g_bloom_build.create(fvf_build, RImplementation.Vertex.Buffer(), RImplementation.QuadIB); diff --git a/src/Layers/xrRender_R2/r2_types.h b/src/Layers/xrRender_R2/r2_types.h index 78262aabf25..281fd41b88c 100644 --- a/src/Layers/xrRender_R2/r2_types.h +++ b/src/Layers/xrRender_R2/r2_types.h @@ -151,3 +151,5 @@ IC float u_diffuse2s(Fvector3& c) { return u_diffuse2s(c.x, c.y, c.z); } + +#define D3DFMT_HACK_R8G8B8A8_UNORM_SRGB ((D3DFORMAT)666) \ No newline at end of file diff --git a/src/xrCore/FS.cpp b/src/xrCore/FS.cpp index b547650786b..1c65535e4fe 100644 --- a/src/xrCore/FS.cpp +++ b/src/xrCore/FS.cpp @@ -120,8 +120,6 @@ void* FileDownload(pcstr file_name, const int& file_handle, size_t& file_size) const auto r_bytes = _read(file_handle, buffer, file_size); R_ASSERT3(file_size == static_cast(r_bytes), "Can't read from file : ", file_name); - // file_size = r_bytes; - R_ASSERT3(!_close(file_handle), "can't close file : ", file_name); return (buffer); @@ -137,6 +135,7 @@ void* FileDownload(pcstr file_name, size_t* buffer_size) typedef char MARK[9]; IC void mk_mark(MARK& M, const char* S) { strncpy_s(M, sizeof(M), S, 8); } + void FileCompress(pcstr fn, pcstr sign, void* data, size_t size) { MARK M; @@ -240,9 +239,6 @@ void IWriter::w_compressed(void* ptr, size_t count) size_t dest_sz = 0; _compressLZ(&dest, &dest_sz, ptr, count); - // if (g_dummy_stuff) - // g_dummy_stuff (dest,dest_sz,dest); - if (dest && dest_sz) w(dest, dest_sz); xr_free(dest); @@ -257,6 +253,7 @@ void IWriter::w_chunk(u32 type, void* data, size_t size) w(data, size); close_chunk(); } + void IWriter::w_sdir(const Fvector& D) { Fvector C; @@ -273,6 +270,7 @@ void IWriter::w_sdir(const Fvector& D) w_dir(C); w_float(mag); } + // XXX: reimplement to prevent buffer overflows void IWriter::w_printf(const char* format, ...) { @@ -313,6 +311,7 @@ IReader* IReader::open_chunk(u32 ID) else return 0; }; + void IReader::close() { IReader* self = this; @@ -383,6 +382,7 @@ void IReader::r(void* p, size_t cnt) }; IC bool is_term(char a) { return (a == 13) || (a == 10); }; + IC size_t IReader::advance_term_string() { size_t sz = 0; @@ -400,6 +400,7 @@ IC size_t IReader::advance_term_string() } return sz; } + void IReader::r_string(char* dest, size_t tgt_sz) { char* src = (char*)data + Pos; @@ -412,12 +413,14 @@ void IReader::r_string(char* dest, size_t tgt_sz) strncpy_s(dest, tgt_sz, src, sz); dest[sz] = 0; } + void IReader::r_string(xr_string& dest) { char* src = (char*)data + Pos; size_t sz = advance_term_string(); dest.assign(src, sz); } + void IReader::r_stringZ(char* dest, size_t tgt_sz) { char* src = (char*)data; @@ -428,11 +431,13 @@ void IReader::r_stringZ(char* dest, size_t tgt_sz) *dest = 0; Pos++; } + void IReader::r_stringZ(shared_str& dest) { dest = (char*)(data + Pos); Pos += (dest.size() + 1); } + void IReader::r_stringZ(xr_string& dest) { dest = (char*)(data + Pos); @@ -497,7 +502,9 @@ CCompressedReader::CCompressedReader(const char* name, const char* sign) data = (char*)FileDecompress(name, sign, (size_t*)&Size); Pos = 0; } + CCompressedReader::~CCompressedReader() { xr_free(data); }; + CVirtualFileRW::CVirtualFileRW(pcstr cFileName) { #if defined(XR_PLATFORM_WINDOWS) diff --git a/src/xrCore/FileSystem.cpp b/src/xrCore/FileSystem.cpp index e3a0f75969e..4ca7f6d60f3 100644 --- a/src/xrCore/FileSystem.cpp +++ b/src/xrCore/FileSystem.cpp @@ -62,6 +62,7 @@ xr_string EFS_Utils::ChangeFileExt(LPCSTR src, LPCSTR ext) } xr_string EFS_Utils::ChangeFileExt(const xr_string& src, LPCSTR ext) { return ChangeFileExt(src.c_str(), ext); } + //---------------------------------------------------- void MakeFilter(string1024& dest, LPCSTR info, LPCSTR ext) { @@ -120,8 +121,7 @@ UINT_PTR CALLBACK OFNHookProcOldStyle(HWND, UINT, WPARAM, LPARAM) } #endif -bool EFS_Utils::GetOpenNameInternal( - LPCSTR initial, pstr buffer, size_t sz_buf, bool bMulti /*= false*/, LPCSTR offset /*= 0*/, int start_flt_ext /*= -1*/) +bool EFS_Utils::GetOpenNameInternal(LPCSTR initial, pstr buffer, size_t sz_buf, bool bMulti /*= false*/, LPCSTR offset /*= 0*/, int start_flt_ext /*= -1*/) { VERIFY(buffer && (sz_buf > 0)); #if defined(XR_PLATFORM_WINDOWS) @@ -158,21 +158,9 @@ bool EFS_Utils::GetOpenNameInternal( string512 path; xr_strcpy(path, (offset && offset[0]) ? offset : P.m_Path); ofn.lpstrInitialDir = path; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | - (bMulti ? OFN_ALLOWMULTISELECT | OFN_EXPLORER : 0); - + ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | (bMulti ? OFN_ALLOWMULTISELECT | OFN_EXPLORER : 0); ofn.FlagsEx = OFN_EX_NOPLACESBAR; - /* - unsigned int dwVersion = GetVersion(); - unsigned int dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); - if ( dwWindowsMajorVersion == 6 ) - { - ofn.Flags |= OFN_ENABLEHOOK; - ofn.lpfnHook = OFNHookProcOldStyle; - } - */ - bool bRes = !!GetOpenFileName(&ofn); if (!bRes) { @@ -217,14 +205,12 @@ bool EFS_Utils::GetOpenNameInternal( bool EFS_Utils::GetSaveName(LPCSTR initial, string_path& buffer, LPCSTR offset, int start_flt_ext) { - // unsigned int dwVersion = GetVersion(); - // unsigned int dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); #if defined(XR_PLATFORM_WINDOWS) FS_Path& P = *FS.get_path(initial); string1024 flt; LPCSTR def_ext = P.m_DefExt; - if (false) //&& dwWindowsMajorVersion == 6 ) + if (false) { if (strstr(P.m_DefExt, "*.")) def_ext = strstr(P.m_DefExt, "*.") + 2; @@ -257,14 +243,6 @@ bool EFS_Utils::GetSaveName(LPCSTR initial, string_path& buffer, LPCSTR offset, ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR; ofn.FlagsEx = OFN_EX_NOPLACESBAR; - /* - if ( dwWindowsMajorVersion == 6 ) - { - ofn.Flags |= OFN_ENABLEHOOK; - ofn.lpfnHook = OFNHookProcOldStyle; - } - */ - bool bRes = !!GetSaveFileName(&ofn); if (!bRes) { @@ -288,8 +266,7 @@ LPCSTR EFS_Utils::AppendFolderToName(pstr tex_name, size_t const tex_name_size, return tex_name; } -LPCSTR EFS_Utils::AppendFolderToName( - LPCSTR src_name, pstr dest_name, size_t const dest_name_size, int depth, BOOL full_name) +LPCSTR EFS_Utils::AppendFolderToName(LPCSTR src_name, pstr dest_name, size_t const dest_name_size, int depth, BOOL full_name) { shared_str tmp = src_name; LPCSTR s = src_name; @@ -322,8 +299,7 @@ LPCSTR EFS_Utils::AppendFolderToName( return dest_name; } -LPCSTR EFS_Utils::GenerateName( - LPCSTR base_path, LPCSTR base_name, LPCSTR def_ext, pstr out_name, size_t const out_name_size) +LPCSTR EFS_Utils::GenerateName(LPCSTR base_path, LPCSTR base_name, LPCSTR def_ext, pstr out_name, size_t const out_name_size) { int cnt = 0; string_path fn; @@ -342,5 +318,3 @@ LPCSTR EFS_Utils::GenerateName( xr_strcpy(out_name, out_name_size, fn); return out_name; } - -//#endif diff --git a/src/xrCore/LocatorAPI.cpp b/src/xrCore/LocatorAPI.cpp index b14f56bb490..e029cf2c501 100644 --- a/src/xrCore/LocatorAPI.cpp +++ b/src/xrCore/LocatorAPI.cpp @@ -1112,8 +1112,7 @@ FileStatus CLocatorAPI::exist(string_path& fn, pcstr path, pcstr name, FSType fs return exist(fn, fsType); } -FileStatus CLocatorAPI::exist( - string_path& fn, pcstr path, pcstr name, pcstr ext, FSType fsType /*= FSType::Virtual*/) +FileStatus CLocatorAPI::exist(string_path& fn, pcstr path, pcstr name, pcstr ext, FSType fsType /*= FSType::Virtual*/) { string_path nm; strconcat(sizeof nm, nm, name, ext); diff --git a/src/xrCore/_matrix.h b/src/xrCore/_matrix.h index 940ae48f586..c4087f0025a 100644 --- a/src/xrCore/_matrix.h +++ b/src/xrCore/_matrix.h @@ -532,11 +532,12 @@ using Dmatrix = _matrix; template bool _valid(const _matrix& m) { - return _valid(m.i) && _valid(m._14_) && _valid(m.j) && _valid(m._24_) - && _valid(m.k) && _valid(m._34_) && _valid(m.c) && _valid(m._44_); + return _valid(m.i) && _valid(m._14_) && _valid(m.j) && _valid(m._24_) && _valid(m.k) && _valid(m._34_) && _valid(m.c) && _valid(m._44_); } extern XRCORE_API Fmatrix Fidentity; extern XRCORE_API Dmatrix Didentity; +constexpr float M_MIN_SCALE = 0.01f; + #endif diff --git a/src/xrEngine/xr_collide_form.cpp b/src/xrEngine/xr_collide_form.cpp index 97f901b5392..a7547eb197e 100644 --- a/src/xrEngine/xr_collide_form.cpp +++ b/src/xrEngine/xr_collide_form.cpp @@ -13,8 +13,7 @@ #ifdef DEBUG IC float DET(const Fmatrix& a) { - return ((a._11 * (a._22 * a._33 - a._23 * a._32) - a._12 * (a._21 * a._33 - a._23 * a._31) + - a._13 * (a._21 * a._32 - a._22 * a._31))); + return ((a._11 * (a._22 * a._33 - a._23 * a._32) - a._12 * (a._21 * a._33 - a._23 * a._31) + a._13 * (a._21 * a._32 - a._22 * a._31))); } #include "ObjectDump.h" #endif @@ -70,12 +69,14 @@ IC bool RAYvsOBB(const Fmatrix& IM, const Fvector& b_hsize, const Fvector& S, co } return false; } + IC bool RAYvsSPHERE(const Fsphere& s_sphere, const Fvector& S, const Fvector& D, float& R, bool bCull) { Fsphere::ERP_Result rp_res = s_sphere.intersect(S, D, R); VERIFY(R >= 0.f); return ((rp_res == Fsphere::rpOriginOutside) || (!bCull && (rp_res == Fsphere::rpOriginInside))); } + IC bool RAYvsCYLINDER(const Fcylinder& c_cylinder, const Fvector& S, const Fvector& D, float& R, bool bCull) { // Actual test @@ -142,9 +143,6 @@ void CCF_Skeleton::BuildState() const Fobb& B = shape.box; B.xform_get(ME); - // VERIFY2( DET(ME)>EPS, ( make_string("0 scale bone matrix, %d \n", I->elem_id ) + - // dbg_object_full_dump_string( owner ) ).c_str() ); - I->b_hsize.set(B.m_halfsize); // prepare matrix World to Element T.mul_43(Mbone, ME); // model space @@ -314,16 +312,14 @@ bool CCF_EventBox::Contact(IGameObject* O) } return true; } + bool CCF_EventBox::_RayQuery(const collide::ray_defs& Q, collide::rq_results& R) { return false; } -/* -void CCF_EventBox::_BoxQuery(const Fbox& B, const Fmatrix& M, u32 flags) -{ return; } -*/ //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- //---------------------------------------------------------------------------------- CCF_Shape::CCF_Shape(IGameObject* _owner) : ICollisionForm(_owner, cftShape) {} + bool CCF_Shape::_RayQuery(const collide::ray_defs& Q, collide::rq_results& R) { // Convert ray into local model space @@ -348,8 +344,7 @@ bool CCF_Shape::_RayQuery(const collide::ray_defs& Q, collide::rq_results& R) { // sphere Fsphere::ERP_Result rp_res = shape.data.sphere.intersect(dS, dD, range); - if ((rp_res == Fsphere::rpOriginOutside) || - (!(Q.flags & CDB::OPT_CULL) && (rp_res == Fsphere::rpOriginInside))) + if ((rp_res == Fsphere::rpOriginOutside) || (!(Q.flags & CDB::OPT_CULL) && (rp_res == Fsphere::rpOriginInside))) { bHIT = true; R.append_result(owner, range, el, Q.flags & CDB::OPT_ONLYNEAREST); @@ -385,10 +380,7 @@ bool CCF_Shape::_RayQuery(const collide::ray_defs& Q, collide::rq_results& R) } return bHIT; } -/* -void CCF_Shape::_BoxQuery(const Fbox& B, const Fmatrix& M, u32 flags) -{ return; } -*/ + void CCF_Shape::add_sphere(Fsphere& S) { shapes.push_back(shape_def()); diff --git a/src/xrGame/ActorAnimation.cpp b/src/xrGame/ActorAnimation.cpp index 8403dd2ca0e..27abae0e2af 100644 --- a/src/xrGame/ActorAnimation.cpp +++ b/src/xrGame/ActorAnimation.cpp @@ -316,9 +316,7 @@ CMotion* FindMotionKeys(MotionID motion_ID, IRenderVisual* V) #ifdef DEBUG BOOL g_ShowAnimationInfo = FALSE; -constexpr pcstr mov_state[] = { - "idle", "walk", "run", "sprint", -}; +constexpr pcstr mov_state[] = {"idle", "walk", "run", "sprint"}; #endif // DEBUG void CActor::g_SetAnimation(u32 mstate_rl) @@ -560,6 +558,13 @@ void CActor::g_SetAnimation(u32 mstate_rl) } } } + } + else if (!m_bAnimTorsoPlayed) + { + if (moving_idx == STorsoWpn::eSprint) + M_torso = ST->m_torso[0].moving[moving_idx]; + else + M_torso = ST->m_torso[4].moving[moving_idx]; //Alundaio: Fix torso anim no wpn } } @@ -575,6 +580,7 @@ void CActor::g_SetAnimation(u32 mstate_rl) else M_legs = ST->legs_idle; } + if (!M_head) M_head = ST->m_head_idle; diff --git a/src/xrGame/Actor_Movement.cpp b/src/xrGame/Actor_Movement.cpp index ac92d58f799..9a3c1292a67 100644 --- a/src/xrGame/Actor_Movement.cpp +++ b/src/xrGame/Actor_Movement.cpp @@ -88,18 +88,17 @@ void CActor::g_cl_ValidateMState(float dt, u32 mstate_wf) m_fJumpTime = s_fJumpTime; mstate_real &= ~(mcFall | mcJump); } + if ((mstate_wf & mcJump) == 0) m_bJumpKeyPressed = FALSE; // Зажало-ли меня/уперся - не двигаюсь - if (((character_physics_support()->movement()->GetVelocityActual() < 0.2f) && - (!(mstate_real & (mcFall | mcJump)))) || - character_physics_support()->movement()->bSleep) + if (((character_physics_support()->movement()->GetVelocityActual() < 0.2f) && (!(mstate_real & (mcFall | mcJump)))) || character_physics_support()->movement()->bSleep) { mstate_real &= ~mcAnyMove; } - if (character_physics_support()->movement()->Environment() == CPHMovementControl::peOnGround || - character_physics_support()->movement()->Environment() == CPHMovementControl::peAtWall) + + if (character_physics_support()->movement()->Environment() == CPHMovementControl::peOnGround || character_physics_support()->movement()->Environment() == CPHMovementControl::peAtWall) { // если на земле гарантированно снимать флажок Jump if (((s_fJumpTime - m_fJumpTime) > s_fJumpGroundTime) && (mstate_real & mcJump)) @@ -108,6 +107,7 @@ void CActor::g_cl_ValidateMState(float dt, u32 mstate_wf) m_fJumpTime = s_fJumpTime; } } + if (character_physics_support()->movement()->Environment() == CPHMovementControl::peAtWall) { if (!(mstate_real & mcClimb)) @@ -160,8 +160,7 @@ void CActor::g_cl_CheckControls(u32 mstate_wf, Fvector& vControlAccel, float& Ju mstate_old = mstate_real; vControlAccel.set(0, 0, 0); - if (!(mstate_real & mcFall) && - (character_physics_support()->movement()->Environment() == CPHMovementControl::peInAir)) + if (!(mstate_real & mcFall) && (character_physics_support()->movement()->Environment() == CPHMovementControl::peInAir)) { m_fFallTime -= dt; if (m_fFallTime <= 0.f) @@ -181,6 +180,7 @@ void CActor::g_cl_CheckControls(u32 mstate_wf, Fvector& vControlAccel, float& Ju mstate_wf &= ~mcJump; } } + // update player accel if (mstate_wf & mcFwd) vControlAccel.z += 1; @@ -438,19 +438,21 @@ void CActor::g_Orientate(u32 mstate_rl, float dt) if ((mstate_rl & mcLLookout) && (mstate_rl & mcRLookout)) tgt_roll = 0.0f; } + if (!fsimilar(tgt_roll, r_torso_tgt_roll, EPS)) { - angle_lerp(r_torso_tgt_roll, tgt_roll, PI_MUL_2, dt); + r_torso_tgt_roll = angle_inertion_var(r_torso_tgt_roll, tgt_roll, 0.f, CurrentHeight * PI_MUL_2, PI_DIV_2, dt); r_torso_tgt_roll = angle_normalize_signed(r_torso_tgt_roll); } } + bool CActor::g_LadderOrient() { Fvector leader_norm; character_physics_support()->movement()->GroundNormal(leader_norm); if (_abs(leader_norm.y) > M_SQRT1_2) return false; - // leader_norm.y=0.f; + float mag = leader_norm.magnitude(); if (mag < EPS_L) return false; @@ -462,27 +464,9 @@ bool CActor::g_LadderOrient() M.j.set(0.f, 1.f, 0.f); generate_orthonormal_basis1(M.k, M.j, M.i); M.i.invert(); - // M.j.invert(); - - // Fquaternion q1,q2,q3; - // q1.set(XFORM()); - // q2.set(M); - // q3.slerp(q1,q2,dt); - // Fvector angles1,angles2,angles3; - // XFORM().getHPB(angles1.x,angles1.y,angles1.z); - // M.getHPB(angles2.x,angles2.y,angles2.z); - ////angle_lerp(angles3.x,angles1.x,angles2.x,dt); - ////angle_lerp(angles3.y,angles1.y,angles2.y,dt); - ////angle_lerp(angles3.z,angles1.z,angles2.z,dt); - - // angles3.lerp(angles1,angles2,dt); - ////angle_lerp(angles3.y,angles1.y,angles2.y,dt); - ////angle_lerp(angles3.z,angles1.z,angles2.z,dt); - // angle_lerp(angles3.x,angles1.x,angles2.x,dt); - // XFORM().setHPB(angles3.x,angles3.y,angles3.z); + Fvector position; position.set(Position()); - // XFORM().rotation(q3); VERIFY2(_valid(M), "Invalide matrix in g_LadderOrient"); XFORM().set(M); VERIFY2(_valid(position), "Invalide position in g_LadderOrient"); @@ -509,8 +493,7 @@ void CActor::g_cl_Orientate(u32 mstate_rl, float dt) unaffected_r_torso.pitch = r_torso.pitch; unaffected_r_torso.roll = r_torso.roll; - CWeaponMagazined* pWM = smart_cast( - inventory().GetActiveSlot() != NO_ACTIVE_SLOT ? inventory().ItemFromSlot(inventory().GetActiveSlot()) : NULL); + CWeaponMagazined* pWM = smart_cast(inventory().GetActiveSlot() != NO_ACTIVE_SLOT ? inventory().ItemFromSlot(inventory().GetActiveSlot()) : NULL); if (pWM && pWM->GetCurrentFireMode() == 1 && eacFirstEye != cam_active) { Fvector dangle = weapon_recoil_last_delta(); @@ -531,7 +514,6 @@ void CActor::g_cl_Orientate(u32 mstate_rl, float dt) if (_abs(r_model_yaw - ty) > PI_DIV_4) { r_model_yaw_dest = ty; - // mstate_real |= mcTurn; } if (_abs(r_model_yaw - r_model_yaw_dest) < EPS_L) diff --git a/src/xrGame/ai_obstacle.cpp b/src/xrGame/ai_obstacle.cpp index c887b572f28..82285430bc7 100644 --- a/src/xrGame/ai_obstacle.cpp +++ b/src/xrGame/ai_obstacle.cpp @@ -98,7 +98,7 @@ void ai_obstacle::compute_matrix(Fmatrix& result, const Fvector& additional) u16 visible_bone_count = kinematics->LL_VisibleBoneCount(); if (!visible_bone_count) { - result.scale(0.f, 0.f, 0.f); + result.scale(M_MIN_SCALE, M_MIN_SCALE, M_MIN_SCALE); return; } diff --git a/src/xrGame/alife_object.cpp b/src/xrGame/alife_object.cpp index d16dd09c8f5..59783be139a 100644 --- a/src/xrGame/alife_object.cpp +++ b/src/xrGame/alife_object.cpp @@ -28,68 +28,75 @@ void CSE_ALifeObject::spawn_supplies(LPCSTR ini_string) CInifile ini(&reader, FS.get_path("$game_config$")->m_Path); #pragma warning(pop) - // Alundaio: This will spawn a single random section listed in [spawn_loadout] - // No need to spawn ammo, this will automatically spawn 1 box for weapon and if ammo_type is specified it will spawn that type - // count is used only for ammo boxes (ie wpn_pm = 3) will spawn 3 boxes, not 3 wpn_pm - // Usage: to create random weapon loadouts - if (ini.section_exist("spawn_loadout")) + u8 loadout_index = 1; + string32 loadout_section = "spawn_loadout"; + + // Alundaio: This will spawn a single random section listed in [spawn_loadout]. + // No need to spawn ammo, this will automatically spawn 1 box for weapon and if ammo_type is specified it will spawn that type. + // Count is used only for ammo boxes (ie wpn_pm = 3) will spawn 3 boxes, not 3 wpn_pm. + // Supports few loadout options, iterates over `spawn_loadout`, `spawn_loadout2` ... `spawn_loadoutN`. + while (ini.section_exist(loadout_section)) { - pcstr itmSection, V; - xr_vector OnlyOne; + LPCSTR level_name = *ai().game_graph().header().level(ai().game_graph().vertex(m_tGraphID)->level_id()).name(); + LPCSTR item_section, item_line; + xr_vector spawn_loadouts; - pcstr lname = *ai().game_graph().header().level(ai().game_graph().vertex(m_tGraphID)->level_id()).name(); - - for (u32 k = 0; ini.r_line("spawn_loadout", k, &itmSection, &V); k++) + for (u32 i = 0; ini.r_line(loadout_section, i, &item_section, &item_line); i++) { - // If level= then only spawn items if object on that level - if (strstr(V, "level=") != nullptr) + // If level= then only spawn items if object on that level + if (strstr(item_line, "level=") != nullptr) { - if (strstr(V, lname) != nullptr) - OnlyOne.push_back(k); + if (strstr(item_line, level_name) != nullptr) + { + spawn_loadouts.push_back(i); + } } else { - OnlyOne.push_back(k); + spawn_loadouts.push_back(i); } } - if (!OnlyOne.empty()) + if (spawn_loadouts.size()) { - s32 sel = Random.randI(0, OnlyOne.size()); - if (ini.r_line("spawn_loadout", OnlyOne.at(sel), &itmSection, &V)) + s32 selected_loadout_index = ::Random.randI(0, spawn_loadouts.size() - 1); + + if (ini.r_line(loadout_section, spawn_loadouts.at(selected_loadout_index), &item_section, &item_line)) { - VERIFY(xr_strlen(itmSection)); - if (pSettings->section_exist(itmSection)) + VERIFY(xr_strlen(item_section)); + + if (pSettings->section_exist(item_section)) { u32 spawn_count = 1; bool bScope = false; bool bSilencer = false; bool bLauncher = false; - float f_cond = 1.0f; - int i_ammo_type = 0, n = 0; + float fCondition = 1.0f; + int iAmmoType = 0, n = 0; - if (V && xr_strlen(V)) + if (item_line && xr_strlen(item_line)) { - n = _GetItemCount(V); + n = _GetItemCount(item_line); if (n > 0) { string64 tmp; - spawn_count = atoi(_GetItem(V, 0, tmp)); //count + spawn_count = atoi(_GetItem(item_line, 0, tmp)); } - if (!spawn_count) spawn_count = 1; - if (nullptr != strstr(V, "cond=")) - f_cond = static_cast(atof(strstr(V, "cond=") + 5)); - bScope = nullptr != strstr(V, "scope"); - bSilencer = nullptr != strstr(V, "silencer"); - bLauncher = nullptr != strstr(V, "launcher"); - if (nullptr != strstr(V, "ammo_type=")) - i_ammo_type = atoi(strstr(V, "ammo_type=") + 10); + if (!spawn_count) + spawn_count = 1; + if (nullptr != strstr(item_line, "cond=")) + fCondition = (float)atof(strstr(item_line, "cond=") + 5); + bScope = (nullptr != strstr(item_line, "scope")); + bSilencer = (nullptr != strstr(item_line, "silencer")); + bLauncher = (nullptr != strstr(item_line, "launcher")); + if (nullptr != strstr(item_line, "ammo_type=")) + iAmmoType = atoi(strstr(item_line, "ammo_type=") + 10); } - - CSE_Abstract* E = alife().spawn_item(itmSection, o_Position, m_tNodeID, m_tGraphID, ID); + CSE_Abstract* E = alife().spawn_item(item_section, o_Position, m_tNodeID, m_tGraphID, ID); CSE_ALifeItemWeapon* W = smart_cast(E); + if (W) { if (W->m_scope_status == ALife::eAddonAttachable) @@ -99,31 +106,41 @@ void CSE_ALifeObject::spawn_supplies(LPCSTR ini_string) if (W->m_grenade_launcher_status == ALife::eAddonAttachable) W->m_addon_flags.set(CSE_ALifeItemWeapon::eWeaponAddonGrenadeLauncher, bLauncher); - //spawn count box(es) of the correct ammo for weapon - if (pSettings->line_exist(itmSection, "ammo_class")) + // spawn count box(es) of the correct ammo for weapon + if (pSettings->line_exist(item_section, "ammo_class")) { - pcstr ammo_class = pSettings->r_string(itmSection, "ammo_class"); - pcstr ammoSec = ""; + LPCSTR ammo_class = pSettings->r_string(item_section, "ammo_class"); + LPCSTR ammo_section = ""; for (int i = 0, n = _GetItemCount(ammo_class); i < n; ++i) { string128 tmp; - ammoSec = _GetItem(ammo_class, i, tmp); - if (i == i_ammo_type) + ammo_section = _GetItem(ammo_class, i, tmp); + if (i == iAmmoType) break; } - if (xr_strlen(ammoSec) && pSettings->section_exist(ammoSec)) + if (xr_strlen(ammo_section) && pSettings->section_exist(ammo_section)) + { for (u32 i = 1; i <= spawn_count; ++i) - alife().spawn_item(ammoSec, o_Position, m_tNodeID, m_tGraphID, ID); + { + alife().spawn_item(ammo_section, o_Position, m_tNodeID, m_tGraphID, ID); + } + } } } + CSE_ALifeInventoryItem* IItem = smart_cast(E); if (IItem) - IItem->m_fCondition = f_cond; + { + IItem->m_fCondition = fCondition; + } } } } + + loadout_index += 1; + xr_sprintf(loadout_section, "spawn_loadout%d", loadout_index); } - //-Alundaio + // -Alundaio if (ini.section_exist("spawn")) { diff --git a/src/xrGame/visual_memory_manager.cpp b/src/xrGame/visual_memory_manager.cpp index 2319edc7652..624342e2990 100644 --- a/src/xrGame/visual_memory_manager.cpp +++ b/src/xrGame/visual_memory_manager.cpp @@ -295,6 +295,7 @@ float CVisualMemoryManager::object_luminocity(const CGameObject* game_object) co { if (!smart_cast(game_object)) return (1.f); + float luminocity = const_cast(game_object)->ROS()->get_luminocity(); float power = log(luminocity > .001f ? luminocity : .001f) * current_state().m_luminocity_factor; return (exp(power)); @@ -302,8 +303,7 @@ float CVisualMemoryManager::object_luminocity(const CGameObject* game_object) co float CVisualMemoryManager::get_object_velocity(const CGameObject* game_object, const CNotYetVisibleObject& not_yet_visible_object) const { - if ((game_object->ps_Size() < 2) || - (not_yet_visible_object.m_prev_time == game_object->ps_Element(game_object->ps_Size() - 2).dwTime)) + if ((game_object->ps_Size() < 2) || (not_yet_visible_object.m_prev_time == game_object->ps_Element(game_object->ps_Size() - 2).dwTime)) return (0.f); GameObjectSavedPosition pos0 = game_object->ps_Element(game_object->ps_Size() - 2); @@ -314,18 +314,28 @@ float CVisualMemoryManager::get_object_velocity(const CGameObject* game_object, float CVisualMemoryManager::get_visible_value(const CGameObject* game_object, float distance, float object_distance, float time_delta, float object_velocity, float luminocity) const { - float always_visible_distance = current_state().m_always_visible_distance; + float always_visible_distance = current_state().m_always_visible_distance; + if (object_distance <= always_visible_distance) + return current_state().m_visibility_threshold; + + if (distance <= always_visible_distance) + distance = always_visible_distance + EPS_L; - if (distance <= always_visible_distance + EPS_L) - return (current_state().m_visibility_threshold); + float fog_near = GamePersistent().Environment().CurrentEnv.fog_near; + float fog_far = GamePersistent().Environment().CurrentEnv.fog_far; + float fog_w = 1 / (fog_far - fog_near); + float fog_x = -fog_near * fog_w; + float fog = (object_distance * fog_w + fog_x) * current_state().m_fog_factor; + clamp(fog, 0.f, 1.f); + float fog_factor = 1.f - pow(fog, current_state().m_fog_pow); //Alundaio: hijack not_yet_visible_object to lua luabind::functor funct; if (GEnv.ScriptEngine->functor("visual_memory_manager.get_visible_value", funct)) - return (funct(m_object ? m_object->lua_game_object() : 0, game_object ? game_object->lua_game_object() : 0, time_delta, current_state().m_time_quant, luminocity, current_state().m_velocity_factor, object_velocity, distance, object_distance, always_visible_distance)); + return (funct(m_object ? m_object->lua_game_object() : 0, game_object ? game_object->lua_game_object() : 0, time_delta, current_state().m_time_quant, luminocity, current_state().m_velocity_factor, object_velocity, distance, object_distance, always_visible_distance, fog_factor)); //-Alundaio - return (time_delta / current_state().m_time_quant * luminocity * (1.f + current_state().m_velocity_factor * object_velocity) * (distance - object_distance) / (distance - always_visible_distance)); + return (time_delta / current_state().m_time_quant * luminocity * (1.f + current_state().m_velocity_factor * object_velocity) * (distance - object_distance) / (distance - always_visible_distance) * fog_factor); } CNotYetVisibleObject* CVisualMemoryManager::not_yet_visible_object(const CGameObject* game_object) diff --git a/src/xrGame/visual_memory_params.cpp b/src/xrGame/visual_memory_params.cpp index 4b49e6fdb76..969eadc82b1 100644 --- a/src/xrGame/visual_memory_params.cpp +++ b/src/xrGame/visual_memory_params.cpp @@ -27,4 +27,6 @@ void CVisionParameters::Load(pcstr section, bool not_a_stalker) m_decrease_value = pSettings->r_float(section, "decrease_value"); m_velocity_factor = pSettings->r_float(section, "velocity_factor"); m_luminocity_factor = pSettings->r_float(section, "luminocity_factor"); + m_fog_factor = READ_IF_EXISTS(pSettings, r_float, section, "fog_factor", 1.f); + m_fog_pow = READ_IF_EXISTS(pSettings, r_float, section, "fog_pow", 5.f); } diff --git a/src/xrGame/visual_memory_params.h b/src/xrGame/visual_memory_params.h index a99d9ae6389..25877615945 100644 --- a/src/xrGame/visual_memory_params.h +++ b/src/xrGame/visual_memory_params.h @@ -19,6 +19,8 @@ struct CVisionParameters float m_velocity_factor; float m_transparency_threshold; float m_luminocity_factor; + float m_fog_factor; + float m_fog_pow; u32 m_still_visible_time; void Load(pcstr section, bool not_a_stalker); diff --git a/src/xrMaterialSystem/GameMtlLib.cpp b/src/xrMaterialSystem/GameMtlLib.cpp index 2c66f9b1572..cb9a443f27b 100644 --- a/src/xrMaterialSystem/GameMtlLib.cpp +++ b/src/xrMaterialSystem/GameMtlLib.cpp @@ -119,6 +119,7 @@ void CGameMtlLibrary::Load() } OBJ->close(); } + const u32 mtlCount = materials.size(); material_pairs_rt.resize(mtlCount * mtlCount, 0); for (const auto& mtlPair : material_pairs) diff --git a/src/xrMaterialSystem/GameMtlLib_Engine.cpp b/src/xrMaterialSystem/GameMtlLib_Engine.cpp index 66b9bb7c230..0104641b834 100644 --- a/src/xrMaterialSystem/GameMtlLib_Engine.cpp +++ b/src/xrMaterialSystem/GameMtlLib_Engine.cpp @@ -10,6 +10,7 @@ void DestroySounds(xr_vector& lst) } void DestroyPSs(xr_vector& lst) {} + void CreateSounds(xr_vector& lst, pcstr buf) { string128 tmp;