mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Enable depth buffer and 3D wall rendering
This commit is contained in:
@@ -28,4 +28,7 @@ void main()
|
||||
[SHADER_CODE]
|
||||
|
||||
FragColor = COLOR * modulate;
|
||||
|
||||
if (FragColor.a < 0.5)
|
||||
discard;
|
||||
}
|
||||
|
||||
@@ -994,33 +994,25 @@ namespace Robust.Client.GameObjects
|
||||
}
|
||||
|
||||
/// Render the sprite in 3D. This is almost entirely copy-pasted from the 2D version.
|
||||
internal void Render3D(Graphics.Clyde.Clyde.Render3D render, in Matrix4 worldTransform, Angle worldRotation,
|
||||
internal void Render3D(Graphics.Clyde.Clyde.Render3D render, Vector2 worldPosition, Angle worldRotation,
|
||||
Sprite3DRenderMode renderMode, Direction? overrideDirection = null
|
||||
) {
|
||||
|
||||
var angle = Rotation;
|
||||
Angle angle;
|
||||
if (Directional)
|
||||
{
|
||||
angle -= worldRotation;
|
||||
angle = Rotation;
|
||||
}
|
||||
else
|
||||
{
|
||||
angle -= new Angle(MathHelper.PiOver2);
|
||||
angle = Rotation + worldRotation;
|
||||
}
|
||||
|
||||
var mOffset = Matrix4.CreateTranslation(new Vector3(Offset));
|
||||
var mRotation = Matrix4.CreateRotationZ((float)angle.Theta); //Matrix4.CreateFromAxisAngle(new Vector3(0,0,1),(float)angle.Theta);
|
||||
|
||||
render.AdjustSpriteTransform(renderMode, ref mOffset);
|
||||
//System.Console.WriteLine("???" + Offset);
|
||||
|
||||
//var transform = mRotation * mOffset;
|
||||
var transform = mOffset * mRotation;
|
||||
|
||||
|
||||
transform = transform * worldTransform;
|
||||
var mRotation = Matrix4.CreateRotationZ((float)angle);
|
||||
var mWorldOffset = Matrix4.CreateTranslation(worldPosition.X, worldPosition.Y, 0);
|
||||
|
||||
// Draw layers
|
||||
int layer_n = 0;
|
||||
foreach (var layer in Layers)
|
||||
{
|
||||
if (!layer.Visible)
|
||||
@@ -1066,7 +1058,30 @@ namespace Robust.Client.GameObjects
|
||||
|
||||
texture ??= resourceCache.GetFallback<TextureResource>();
|
||||
|
||||
render.DrawRect3D(transform, texture, color * layer.Color);
|
||||
float offsetZ = renderMode == Sprite3DRenderMode.SimpleSprite ? layer_n * 0.001f : 0.001f;
|
||||
var mOffset = Matrix4.CreateTranslation(new Vector3(Offset.X, Offset.Y, offsetZ));
|
||||
|
||||
bool isWall = renderMode == Sprite3DRenderMode.Wall;
|
||||
int rectCount = isWall ? 5 : 1;
|
||||
|
||||
for (int i = 0; i < rectCount; i++)
|
||||
{
|
||||
var m3D = render.GetSpriteTransform(renderMode, i);
|
||||
|
||||
var transform = mOffset * mRotation * m3D * mWorldOffset;
|
||||
|
||||
var rectColor = color * layer.Color;
|
||||
var rectTexture = texture;
|
||||
|
||||
if (isWall && i == rectCount - 1)
|
||||
{
|
||||
rectColor = Color.Black;
|
||||
}
|
||||
|
||||
render.DrawRect3D(transform, rectTexture, rectColor);
|
||||
}
|
||||
|
||||
layer_n++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
Floor, // Draw Flat on the ground, no extra transformations
|
||||
Table, // Higher than floor
|
||||
SimpleSprite, // Always rotate to face the camera
|
||||
Wall // Render 4 sides + top cap
|
||||
}
|
||||
|
||||
public Render3D(Clyde clyde)
|
||||
@@ -145,20 +146,32 @@ namespace Robust.Client.Graphics.Clyde
|
||||
return (projMatrixWorld, viewMatrixWorld);
|
||||
}
|
||||
|
||||
public void AdjustSpriteTransform(Sprite3DRenderMode renderMode, ref Matrix4 matrix)
|
||||
public Matrix4 GetSpriteTransform(Sprite3DRenderMode renderMode, int n = 0)
|
||||
{
|
||||
switch (renderMode)
|
||||
{
|
||||
case Sprite3DRenderMode.Floor:
|
||||
matrix *= Matrix4.CreateTranslation(0, 0, -.5f);
|
||||
break;
|
||||
return Matrix4.CreateTranslation(0, 0, -.5f);
|
||||
case Sprite3DRenderMode.Table:
|
||||
matrix *= Matrix4.CreateTranslation(0, 0, -.25f);
|
||||
break;
|
||||
return Matrix4.CreateTranslation(0, 0, -.25f);
|
||||
case Sprite3DRenderMode.Wall:
|
||||
switch (n)
|
||||
{
|
||||
case 0:
|
||||
return Matrix4.CreateRotationY(MathHelper.PiOver2) * Matrix4.CreateTranslation(.5f, 0, 0);
|
||||
case 1:
|
||||
return Matrix4.CreateRotationY(MathHelper.PiOver2) * Matrix4.CreateTranslation(-.5f, 0, 0);
|
||||
case 2:
|
||||
return Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(0, .5f, 0);
|
||||
case 3:
|
||||
return Matrix4.CreateRotationX(MathHelper.PiOver2) * Matrix4.CreateTranslation(0, -.5f, 0);
|
||||
default:
|
||||
return Matrix4.CreateTranslation(0, 0, .5f);
|
||||
}
|
||||
case Sprite3DRenderMode.SimpleSprite:
|
||||
matrix *= FaceCameraRotation;
|
||||
break;
|
||||
return FaceCameraRotation;
|
||||
}
|
||||
return Matrix4.Identity;
|
||||
}
|
||||
|
||||
public static Sprite3DRenderMode InferRenderMode(IEntity ent)
|
||||
@@ -168,11 +181,15 @@ namespace Robust.Client.Graphics.Clyde
|
||||
case "worktop":
|
||||
return Sprite3DRenderMode.Table;
|
||||
case "Solid wall":
|
||||
return Sprite3DRenderMode.Table; // todo walls
|
||||
return Sprite3DRenderMode.Wall;
|
||||
case "Catwalk":
|
||||
case "Wire":
|
||||
return Sprite3DRenderMode.Floor;
|
||||
}
|
||||
if (ent.Name.Contains("Airlock"))
|
||||
{
|
||||
return Sprite3DRenderMode.Wall;
|
||||
}
|
||||
|
||||
return Sprite3DRenderMode.SimpleSprite;
|
||||
}
|
||||
|
||||
@@ -66,8 +66,11 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
private readonly RefList<RenderCommand> _queuedRenderCommands = new RefList<RenderCommand>();
|
||||
|
||||
private readonly RefList<(SpriteComponent sprite, Matrix3 worldMatrix, Angle worldRotation, Render3D.Sprite3DRenderMode renderMode)> _drawingSpriteList =
|
||||
new RefList<(SpriteComponent, Matrix3, Angle, Render3D.Sprite3DRenderMode)>();
|
||||
private readonly RefList<(SpriteComponent sprite, Matrix3 worldMatrix, Angle worldRotation)> _drawingSpriteList =
|
||||
new RefList<(SpriteComponent, Matrix3, Angle)>();
|
||||
|
||||
private readonly RefList<(SpriteComponent sprite, Vector2 worldPosition, Angle worldRotation, Render3D.Sprite3DRenderMode renderMode)> _drawingSpriteList3D =
|
||||
new RefList<(SpriteComponent, Vector2, Angle, Render3D.Sprite3DRenderMode)>();
|
||||
|
||||
public void Render()
|
||||
{
|
||||
@@ -131,6 +134,14 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_drawLights(worldBounds);
|
||||
}
|
||||
|
||||
if (eye.Is3D)
|
||||
{
|
||||
// Start 3D rendering. Enable depth buffer.
|
||||
GL.Enable(EnableCap.DepthTest);
|
||||
GL.DepthMask(true);
|
||||
GL.DepthFunc(DepthFunction.Less);
|
||||
}
|
||||
|
||||
using (DebugGroup("Grids"))
|
||||
{
|
||||
_drawGrids(worldBounds);
|
||||
@@ -141,6 +152,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
DrawEntities(worldBounds);
|
||||
}
|
||||
|
||||
// Any 3D rendering should be done.
|
||||
GL.Disable(EnableCap.DepthTest);
|
||||
|
||||
RenderOverlays(OverlaySpace.WorldSpace);
|
||||
|
||||
_lightingReady = false;
|
||||
@@ -166,8 +180,6 @@ namespace Robust.Client.Graphics.Clyde
|
||||
return;
|
||||
}
|
||||
|
||||
bool is3d = _eyeManager.CurrentEye.Is3D;
|
||||
|
||||
// So we could calculate the correct size of the entities based on the contents of their sprite...
|
||||
// Or we can just assume that no entity is larger than 10x10 and get a stupid easy check.
|
||||
// TODO: Make this check more accurate.
|
||||
@@ -176,39 +188,36 @@ namespace Robust.Client.Graphics.Clyde
|
||||
var mapEntity = _mapManager.GetMapEntity(_eyeManager.CurrentMap);
|
||||
|
||||
var identity = Matrix3.Identity;
|
||||
ProcessSpriteEntities(mapEntity, ref identity, Angle.Zero, widerBounds, _drawingSpriteList, is3d);
|
||||
|
||||
// We use a separate list for indexing so that the sort is faster.
|
||||
var indexList = ArrayPool<int>.Shared.Rent(_drawingSpriteList.Count);
|
||||
|
||||
for (var i = 0; i < _drawingSpriteList.Count; i++)
|
||||
{
|
||||
indexList[i] = i;
|
||||
}
|
||||
|
||||
Array.Sort(indexList, 0, _drawingSpriteList.Count, new SpriteDrawingOrderComparer(_drawingSpriteList));
|
||||
bool is3d = _eyeManager.CurrentEye.Is3D;
|
||||
|
||||
if (is3d)
|
||||
{
|
||||
ProcessSpriteEntities3D(mapEntity, ref identity, Angle.Zero, widerBounds, _drawingSpriteList3D);
|
||||
|
||||
var clyde3d = GetRender3D();
|
||||
|
||||
for (var i = 0; i < _drawingSpriteList3D.Count; i++)
|
||||
{
|
||||
ref var entry = ref _drawingSpriteList3D[i];
|
||||
|
||||
entry.sprite.Render3D(clyde3d, entry.worldPosition, entry.worldRotation, entry.renderMode);
|
||||
}
|
||||
_drawingSpriteList3D.Clear();
|
||||
} else
|
||||
{
|
||||
ProcessSpriteEntities(mapEntity, ref identity, Angle.Zero, widerBounds, _drawingSpriteList);
|
||||
|
||||
// We use a separate list for indexing so that the sort is faster.
|
||||
var indexList = ArrayPool<int>.Shared.Rent(_drawingSpriteList.Count);
|
||||
|
||||
for (var i = 0; i < _drawingSpriteList.Count; i++)
|
||||
{
|
||||
ref var entry = ref _drawingSpriteList[indexList[i]];
|
||||
|
||||
var mat3 = entry.worldMatrix;
|
||||
|
||||
var mat4 = new Matrix4(
|
||||
mat3.R0C0, mat3.R1C0, 0, mat3.R2C0,
|
||||
mat3.R0C1, mat3.R1C1, 0, mat3.R2C1,
|
||||
0, 0, 1, 0,
|
||||
mat3.R0C2, mat3.R1C2, 0, mat3.R2C2
|
||||
);
|
||||
|
||||
entry.sprite.Render3D(clyde3d, mat4, entry.worldRotation, entry.renderMode);
|
||||
indexList[i] = i;
|
||||
}
|
||||
} else
|
||||
{
|
||||
|
||||
Array.Sort(indexList, 0, _drawingSpriteList.Count, new SpriteDrawingOrderComparer(_drawingSpriteList));
|
||||
|
||||
for (var i = 0; i < _drawingSpriteList.Count; i++)
|
||||
{
|
||||
ref var entry = ref _drawingSpriteList[indexList[i]];
|
||||
@@ -250,15 +259,15 @@ namespace Robust.Client.Graphics.Clyde
|
||||
_renderHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
_drawingSpriteList.Clear();
|
||||
}
|
||||
|
||||
_drawingSpriteList.Clear();
|
||||
|
||||
FlushRenderQueue();
|
||||
}
|
||||
|
||||
private void ProcessSpriteEntities(IEntity entity, ref Matrix3 parentTransform, Angle parentRotation,
|
||||
Box2 worldBounds, RefList<(SpriteComponent, Matrix3, Angle, Render3D.Sprite3DRenderMode)> list, bool include3DRenderMode)
|
||||
Box2 worldBounds, RefList<(SpriteComponent, Matrix3, Angle)> list)
|
||||
{
|
||||
entity.TryGetComponent(out ContainerManagerComponent containerManager);
|
||||
|
||||
@@ -293,16 +302,61 @@ namespace Robust.Client.Graphics.Clyde
|
||||
entry.Item1 = sprite;
|
||||
entry.Item3 = childWorldRotation;
|
||||
|
||||
if (include3DRenderMode)
|
||||
/*if (include3DRenderMode)
|
||||
{
|
||||
entry.Item4 = Render3D.InferRenderMode(childEntity);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
if (childTransform.ChildCount > 0)
|
||||
{
|
||||
ProcessSpriteEntities(childEntity, ref matrix, rotation, worldBounds, list, include3DRenderMode);
|
||||
ProcessSpriteEntities(childEntity, ref matrix, rotation, worldBounds, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ProcessSpriteEntities3D(IEntity entity, ref Matrix3 parentTransform, Angle parentRotation,
|
||||
Box2 worldBounds, RefList<(SpriteComponent, Vector2, Angle, Render3D.Sprite3DRenderMode)> list)
|
||||
{
|
||||
entity.TryGetComponent(out ContainerManagerComponent containerManager);
|
||||
|
||||
var localMatrix = entity.Transform.GetLocalMatrix();
|
||||
Matrix3.Multiply(ref parentTransform, ref localMatrix, out var matrix);
|
||||
var rotation = parentRotation + entity.Transform.LocalRotation;
|
||||
|
||||
foreach (var child in entity.Transform.ChildEntityUids)
|
||||
{
|
||||
var childEntity = _entityManager.GetEntity(child);
|
||||
|
||||
if (containerManager != null && containerManager.TryGetContainer(childEntity, out var container) &&
|
||||
!container.ShowContents)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var childTransform = childEntity.Transform;
|
||||
|
||||
var worldPosition = Matrix3.Transform(matrix, childTransform.LocalPosition);
|
||||
|
||||
if (worldBounds.Contains(worldPosition))
|
||||
{
|
||||
if (childEntity.TryGetComponent(out SpriteComponent sprite) && sprite.Visible)
|
||||
{
|
||||
ref var entry = ref list.AllocAdd();
|
||||
|
||||
var childWorldRotation = rotation + childTransform.LocalRotation;
|
||||
|
||||
entry.Item1 = sprite;
|
||||
entry.Item2 = worldPosition;
|
||||
entry.Item3 = childWorldRotation;
|
||||
entry.Item4 = Render3D.InferRenderMode(childEntity);
|
||||
}
|
||||
}
|
||||
|
||||
if (childTransform.ChildCount > 0)
|
||||
{
|
||||
ProcessSpriteEntities3D(childEntity, ref matrix, rotation, worldBounds, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -712,7 +766,8 @@ namespace Robust.Client.Graphics.Clyde
|
||||
{
|
||||
GL.ClearColor(color.ConvertOpenTK());
|
||||
GL.ClearStencil(0);
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.StencilBufferBit);
|
||||
GL.ClearDepth(1);
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.StencilBufferBit | ClearBufferMask.DepthBufferBit);
|
||||
}
|
||||
|
||||
private (ShaderProgram, LoadedShader) ActivateShaderInstance(ClydeHandle handle)
|
||||
@@ -1189,9 +1244,9 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
private sealed class SpriteDrawingOrderComparer : IComparer<int>
|
||||
{
|
||||
private readonly RefList<(SpriteComponent, Matrix3, Angle, Render3D.Sprite3DRenderMode)> _drawList;
|
||||
private readonly RefList<(SpriteComponent, Matrix3, Angle)> _drawList;
|
||||
|
||||
public SpriteDrawingOrderComparer(RefList<(SpriteComponent, Matrix3, Angle, Render3D.Sprite3DRenderMode)> drawList)
|
||||
public SpriteDrawingOrderComparer(RefList<(SpriteComponent, Matrix3, Angle)> drawList)
|
||||
{
|
||||
_drawList = drawList;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user