-
Notifications
You must be signed in to change notification settings - Fork 292
Ss RTX #3343
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Ss RTX #3343
Changes from 6 commits
5d1298c
bec5187
20e1e9a
642a26d
9defef7
351d8f6
ddaa3b0
ce390b9
9a81d15
e201ad6
405543b
3c5e578
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| using System.Numerics; | ||
| using Content.Shared.ADT.Mirror; | ||
| using Content.Shared.Humanoid; | ||
| using Robust.Client.GameObjects; | ||
| using Robust.Client.Graphics; | ||
| using Robust.Shared.Enums; | ||
| using Robust.Shared.Graphics; | ||
| using Robust.Shared.Map; | ||
| using Robust.Shared.Physics; | ||
| using Robust.Shared.Prototypes; | ||
| using DrawDepth = Content.Shared.DrawDepth.DrawDepth; | ||
| using static Robust.Client.GameObjects.SpriteComponent; | ||
| using Content.Shared.Stealth.Components; | ||
|
|
||
| namespace Content.Client.ADT.Mirror; | ||
|
|
||
| public sealed partial class MirrorOverlay : Overlay | ||
| { | ||
| private static readonly ProtoId<ShaderPrototype> StencilClearShader = "StencilClear"; | ||
| private static readonly ProtoId<ShaderPrototype> StencilMaskShader = "StencilMask"; | ||
| private static readonly ProtoId<ShaderPrototype> StencilEqualDrawShader = "StencilEqualDraw"; | ||
|
|
||
| [Dependency] private IEntityManager _entityManager = default!; | ||
| [Dependency] private IPrototypeManager _prototypeManager = default!; | ||
| [Dependency] private IEyeManager _eyeMan = default!; | ||
| private SpriteSystem _sprite = default!; | ||
| private TransformSystem _transform = default!; | ||
| private ContainerSystem _container = default!; | ||
|
|
||
| public override OverlaySpace Space => OverlaySpace.WorldSpaceEntities; | ||
|
|
||
| public MirrorOverlay() | ||
| { | ||
| IoCManager.InjectDependencies(this); | ||
|
|
||
| ZIndex = (int)DrawDepth.BelowMobs; | ||
| } | ||
|
|
||
| protected override bool BeforeDraw(in OverlayDrawArgs args) | ||
| { | ||
| _sprite ??= _entityManager.System<SpriteSystem>(); | ||
| _transform ??= _entityManager.System<TransformSystem>(); | ||
| _container ??= _entityManager.System<ContainerSystem>(); | ||
|
|
||
| return base.BeforeDraw(args); | ||
| } | ||
|
|
||
| protected override void Draw(in OverlayDrawArgs args) | ||
| { | ||
| var eye = args.Viewport.Eye; | ||
| if (eye == null) | ||
| return; | ||
|
|
||
| var mapId = args.MapId; | ||
| var worldAabb = args.WorldAABB; | ||
|
|
||
| var mirrors = _entityManager.AllEntityQueryEnumerator<MirrorComponent, SpriteComponent, TransformComponent>(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Этот цикл по сути ничего не делает, кроме лишней нагрузки. |
||
| var mirrorData = new List<(MirrorComponent Component, Vector2 Position, Angle Rotation)>(); | ||
| while (mirrors.MoveNext(out var uid, out var component, out var sprite, out var transform)) | ||
| { | ||
| if (transform.MapID == mapId) | ||
| { | ||
| var position = _sprite.GetSpriteWorldPosition((uid, sprite, transform)); | ||
| var rotation = _transform.GetWorldRotation(transform) + sprite.Rotation; | ||
| mirrorData.Add((component, position, rotation)); | ||
| } | ||
| } | ||
|
|
||
| if (mirrorData.Count == 0) | ||
| return; | ||
|
|
||
| var worldHandle = args.WorldHandle; | ||
|
|
||
| worldHandle.SetTransform(Matrix3x2.Identity); | ||
| worldHandle.UseShader(_prototypeManager.Index(StencilClearShader).Instance()); | ||
| worldHandle.DrawRect(worldAabb, Color.White); | ||
|
|
||
| // Сама отрисовка начинается тут | ||
| // Каждое зеркало делает свою маску и рисует сущности, которые может | ||
| var mirrorEntities = _entityManager.AllEntityQueryEnumerator<MirrorComponent, SpriteComponent, TransformComponent>(); | ||
| while (mirrorEntities.MoveNext(out var uid, out var mirror, out var sprite, out var transform)) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нет отсечения зеркал по видимости. Перебираются все зеркала на карте, включая те, что за экраном, и на каждое идёт два полноэкранных драв рект с шейдерами + полный проход рендер ентитис по всем отражаемым сущностям |
||
| { | ||
| if (transform.MapID != mapId) | ||
| continue; | ||
|
|
||
| worldHandle.UseShader(_prototypeManager.Index(StencilMaskShader).Instance()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. _prototypeManager.Index на каждой итерации цикла Сделай три шейдер инстанса один раз в BeforeDraw и держи в полях(вроде должно работать) |
||
|
|
||
| _sprite.RenderSprite((uid, sprite), worldHandle, eye.Rotation, _transform.GetWorldRotation(transform), | ||
| _transform.GetWorldPosition(transform)); | ||
|
|
||
| worldHandle.UseShader(_prototypeManager.Index(StencilEqualDrawShader).Instance()); | ||
| RenderEntities(worldAabb, eye, worldHandle, mapId, | ||
| (mirror, _sprite.GetSpriteWorldPosition((uid, sprite, transform)), | ||
| _transform.GetWorldRotation(transform) + sprite.Rotation)); | ||
|
|
||
| worldHandle.UseShader(_prototypeManager.Index(StencilClearShader).Instance()); | ||
| worldHandle.SetTransform(Matrix3x2.Identity); | ||
| worldHandle.DrawRect(worldAabb, Color.White); | ||
| } | ||
|
|
||
| worldHandle.UseShader(null); | ||
| } | ||
|
|
||
| private void RenderEntities(Box2 worldAabb, IEye eye, DrawingHandleWorld worldHandle, MapId mapId, | ||
| (MirrorComponent Component, Vector2 Position, Angle Rotation) mirrorData) | ||
| { | ||
| var entities = _entityManager.AllEntityQueryEnumerator<MirrorReflectionComponent, SpriteComponent, TransformComponent>(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. перебираются все сущности с миррор рефлекшин для КАЖДОГО зеркала, которое ща есть в пвс у игрока. |
||
| while (entities.MoveNext(out var uid, out var reflection, out var sprite, out var transform)) | ||
| { | ||
| if (_entityManager.HasComponent<MirrorComponent>(uid) || transform.MapID != mapId) | ||
| continue; | ||
|
|
||
| if (!reflection.ReflectIfInvisible && _entityManager.HasComponent<StealthComponent>(uid)) | ||
|
coderabbitai[bot] marked this conversation as resolved.
Outdated
|
||
| continue; | ||
|
|
||
| var (mirror, mirrorPosition, mirrorRotation) = mirrorData; | ||
| var sourcePosition = _transform.GetWorldPosition(transform); | ||
| if (!worldAabb.Contains(sourcePosition) || _container.IsEntityInContainer(uid)) | ||
| continue; | ||
|
|
||
| var normalAngle = mirrorRotation + Angle.FromDegrees(mirror.DirRotation); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Все эти данные т.е. позиция, градус и тд зависят от зеркала, которое обычно статичное и никак не изменяется, но при этом на каждой итерации все равно пересчитывается заново |
||
| var normal = normalAngle.ToVec().Normalized(); | ||
| var entitySide = Vector2.Dot(sourcePosition - mirrorPosition, normal); | ||
| var viewerSide = Vector2.Dot(eye.Position.Position - mirrorPosition, normal); | ||
| if (entitySide * viewerSide <= 0f) | ||
| continue; | ||
|
|
||
| if (mirror.FadeFactor > 0 && | ||
| Vector2.Distance(sourcePosition, mirrorPosition) >= mirror.GatherOffset + 1f / mirror.FadeFactor) | ||
| { | ||
| continue; | ||
| } | ||
|
|
||
| var color = sprite.Color; | ||
| var newColor = GetTransparentColor(uid, color, mirrorPosition, mirror.ToleratedDistance, mirror.FadeFactor); | ||
| _sprite.SetColor(uid, newColor); | ||
|
|
||
| var offsetSourcePosition = sourcePosition + normal * mirror.GatherOffset; | ||
| var reflectedPosition = offsetSourcePosition - 2f * Vector2.Dot(offsetSourcePosition - mirrorPosition, normal) * normal; | ||
| var reflectedFacing = normalAngle * 2f - _transform.GetWorldRotation(transform); | ||
|
|
||
| // Этот ебучий слой ломал вообще всё | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Комментарий - есть |
||
| // Не убирайте этот фикс | ||
| var hiddenStencilLayers = new List<(ISpriteLayer Layer, bool Visible)>(); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new List<...> на каждую сущность на каждое зеркало каждый кадр, хотя слоя максимум два |
||
| if (_sprite.LayerMapTryGet((uid, sprite), HumanoidVisualLayers.StencilMask, out var stencilMaskLayer, false)) | ||
| { | ||
| var stencilMask = sprite[stencilMaskLayer]; | ||
| hiddenStencilLayers.Add((stencilMask, stencilMask.Visible)); | ||
| stencilMask.Visible = false; | ||
|
|
||
| if (stencilMaskLayer > 0) | ||
| { | ||
| var stencilClear = sprite[stencilMaskLayer - 1]; | ||
| hiddenStencilLayers.Add((stencilClear, stencilClear.Visible)); | ||
| stencilClear.Visible = false; | ||
| } | ||
| } | ||
|
|
||
| _sprite.RenderSprite((uid, sprite), worldHandle, eye.Rotation, reflectedFacing, | ||
| reflectedPosition - normal * mirror.ReflectionOffset); | ||
|
|
||
| foreach (var (layer, visible) in hiddenStencilLayers) | ||
| layer.Visible = visible; | ||
|
|
||
| worldHandle.UseShader(_prototypeManager.Index(StencilEqualDrawShader).Instance()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Избыточная повторная индексация прототипа |
||
| _sprite.SetColor(uid, color); | ||
| } | ||
| } | ||
|
|
||
| private Color GetTransparentColor(EntityUid uid, Color originalColor, Vector2 mirrorPos, float toleratedDistance, float fadeFactorMod) | ||
| { | ||
| var dist = (_transform.GetWorldPosition(uid) - mirrorPos).Length(); | ||
|
|
||
| var fadeFactor = MathF.Max(dist - toleratedDistance, 0f); | ||
| return originalColor.WithAlpha(Math.Clamp(originalColor.A - fadeFactor * fadeFactorMod, 0f, 0.9f)); | ||
| } | ||
|
|
||
| protected override void DisposeBehavior() | ||
| { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Это не надо. |
||
| base.DisposeBehavior(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| using Robust.Client.Graphics; | ||
|
|
||
| namespace Content.Client.ADT.Mirror; | ||
|
|
||
| public sealed partial class MirrorSystem : EntitySystem | ||
| { | ||
| [Dependency] private IOverlayManager _overlay = default!; | ||
|
|
||
| public override void Initialize() | ||
| { | ||
| base.Initialize(); | ||
|
|
||
| _overlay.AddOverlay(new MirrorOverlay()); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Оверлей не снимается при шутдауне. |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| using Robust.Shared.GameStates; | ||
|
|
||
| namespace Content.Shared.ADT.Mirror; | ||
|
|
||
| [RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Нетворкед + авто генерейт компонент стейт лишние. |
||
| public sealed partial class MirrorComponent : Component | ||
| { | ||
| [DataField, AutoNetworkedField] | ||
| public float DirRotation = 90f; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Перевести из float в Angle |
||
|
|
||
| [DataField, AutoNetworkedField] | ||
| public float GatherOffset = 1f; | ||
|
|
||
| [DataField, AutoNetworkedField] | ||
| public float ReflectionOffset = 0.2f; | ||
|
|
||
| [DataField, AutoNetworkedField] | ||
| public float FadeFactor = 1f; | ||
|
|
||
| [DataField, AutoNetworkedField] | ||
| public float ToleratedDistance = 1f; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| using Robust.Shared.GameStates; | ||
|
|
||
| namespace Content.Shared.ADT.Mirror; | ||
|
|
||
| [RegisterComponent, NetworkedComponent, AutoGenerateComponentState] | ||
| public sealed partial class MirrorReflectionComponent : Component | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Файл называется Reflection, а компонент MirrorReflection. Приведи к единому. |
||
| { | ||
| [DataField, AutoNetworkedField] | ||
| public bool ReflectIfInvisible = false; | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_eyeMan не используется