Render voxels with an approximately-correct z-offset.
This commit is contained in:
@@ -22,9 +22,9 @@ namespace OpenRA.Graphics
|
|||||||
public readonly Sprite Sprite;
|
public readonly Sprite Sprite;
|
||||||
public readonly Sprite ShadowSprite;
|
public readonly Sprite ShadowSprite;
|
||||||
public readonly float ShadowDirection;
|
public readonly float ShadowDirection;
|
||||||
public readonly float2[] ProjectedShadowBounds;
|
public readonly float3[] ProjectedShadowBounds;
|
||||||
|
|
||||||
public VoxelRenderProxy(Sprite sprite, Sprite shadowSprite, float2[] projectedShadowBounds, float shadowDirection)
|
public VoxelRenderProxy(Sprite sprite, Sprite shadowSprite, float3[] projectedShadowBounds, float shadowDirection)
|
||||||
{
|
{
|
||||||
Sprite = sprite;
|
Sprite = sprite;
|
||||||
ShadowSprite = shadowSprite;
|
ShadowSprite = shadowSprite;
|
||||||
@@ -145,7 +145,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
var shadowScreenTransform = Util.MatrixMultiply(cameraTransform, invShadowTransform);
|
var shadowScreenTransform = Util.MatrixMultiply(cameraTransform, invShadowTransform);
|
||||||
var shadowGroundNormal = Util.MatrixVectorMultiply(shadowTransform, groundNormal);
|
var shadowGroundNormal = Util.MatrixVectorMultiply(shadowTransform, groundNormal);
|
||||||
var screenCorners = new float2[4];
|
var screenCorners = new float3[4];
|
||||||
for (var j = 0; j < 4; j++)
|
for (var j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
// Project to ground plane
|
// Project to ground plane
|
||||||
@@ -154,7 +154,7 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
// Rotate to camera-space
|
// Rotate to camera-space
|
||||||
corners[j] = Util.MatrixVectorMultiply(shadowScreenTransform, corners[j]);
|
corners[j] = Util.MatrixVectorMultiply(shadowScreenTransform, corners[j]);
|
||||||
screenCorners[j] = new float2(corners[j][0], corners[j][1]);
|
screenCorners[j] = new float3(corners[j][0], corners[j][1], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Shadows are rendered at twice the resolution to reduce artifacts
|
// Shadows are rendered at twice the resolution to reduce artifacts
|
||||||
|
|||||||
@@ -126,7 +126,10 @@ namespace OpenRA.Graphics
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (devTrait.Value != null)
|
if (devTrait.Value != null)
|
||||||
|
{
|
||||||
Game.Renderer.WorldSpriteRenderer.SetDepthPreviewEnabled(devTrait.Value.ShowDepthPreview);
|
Game.Renderer.WorldSpriteRenderer.SetDepthPreviewEnabled(devTrait.Value.ShowDepthPreview);
|
||||||
|
Game.Renderer.WorldRgbaSpriteRenderer.SetDepthPreviewEnabled(devTrait.Value.ShowDepthPreview);
|
||||||
|
}
|
||||||
|
|
||||||
RefreshPalette();
|
RefreshPalette();
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ using System.Collections.Generic;
|
|||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using OpenRA.Graphics;
|
using OpenRA.Graphics;
|
||||||
|
using OpenRA.Primitives;
|
||||||
|
|
||||||
namespace OpenRA.Mods.Common.Graphics
|
namespace OpenRA.Mods.Common.Graphics
|
||||||
{
|
{
|
||||||
@@ -107,7 +108,12 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
{
|
{
|
||||||
var groundPos = voxel.pos - new WVec(0, 0, wr.World.Map.DistanceAboveTerrain(voxel.pos).Length);
|
var groundPos = voxel.pos - new WVec(0, 0, wr.World.Map.DistanceAboveTerrain(voxel.pos).Length);
|
||||||
var groundZ = wr.World.Map.Grid.TileSize.Height * (groundPos.Z - voxel.pos.Z) / 1024f;
|
var groundZ = wr.World.Map.Grid.TileSize.Height * (groundPos.Z - voxel.pos.Z) / 1024f;
|
||||||
var pxOrigin = wr.ScreenPosition(voxel.pos);
|
var pxOrigin = wr.Screen3DPosition(voxel.pos);
|
||||||
|
|
||||||
|
// HACK: We don't have enough texture channels to pass the depth data to the shader
|
||||||
|
// so for now just offset everything forward so that the back corner is rendered at pos.
|
||||||
|
pxOrigin -= new float3(0, 0, Screen3DBounds(wr).Second.X);
|
||||||
|
|
||||||
var shadowOrigin = pxOrigin - groundZ * (new float2(renderProxy.ShadowDirection, 1));
|
var shadowOrigin = pxOrigin - groundZ * (new float2(renderProxy.ShadowDirection, 1));
|
||||||
|
|
||||||
var psb = renderProxy.ProjectedShadowBounds;
|
var psb = renderProxy.ProjectedShadowBounds;
|
||||||
@@ -135,12 +141,13 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
var c = Color.Purple;
|
var c = Color.Purple;
|
||||||
var psb = renderProxy.ProjectedShadowBounds;
|
var psb = renderProxy.ProjectedShadowBounds;
|
||||||
|
|
||||||
|
// TODO: add float3 support to WorldRgbaColorRenderer
|
||||||
Game.Renderer.WorldRgbaColorRenderer.DrawPolygon(new[]
|
Game.Renderer.WorldRgbaColorRenderer.DrawPolygon(new[]
|
||||||
{
|
{
|
||||||
shadowOrigin + psb[1],
|
shadowOrigin + psb[1].XY,
|
||||||
shadowOrigin + psb[3],
|
shadowOrigin + psb[3].XY,
|
||||||
shadowOrigin + psb[0],
|
shadowOrigin + psb[0].XY,
|
||||||
shadowOrigin + psb[2]
|
shadowOrigin + psb[2].XY
|
||||||
}, iz, c);
|
}, iz, c);
|
||||||
|
|
||||||
// Draw voxel bounding box
|
// Draw voxel bounding box
|
||||||
@@ -190,6 +197,11 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle ScreenBounds(WorldRenderer wr)
|
public Rectangle ScreenBounds(WorldRenderer wr)
|
||||||
|
{
|
||||||
|
return Screen3DBounds(wr).First;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<Rectangle, float2> Screen3DBounds(WorldRenderer wr)
|
||||||
{
|
{
|
||||||
var pxOrigin = wr.ScreenPosition(voxel.pos);
|
var pxOrigin = wr.ScreenPosition(voxel.pos);
|
||||||
var draw = voxel.voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
|
var draw = voxel.voxels.Where(v => v.DisableFunc == null || !v.DisableFunc());
|
||||||
@@ -198,8 +210,11 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
|
|
||||||
var minX = float.MaxValue;
|
var minX = float.MaxValue;
|
||||||
var minY = float.MaxValue;
|
var minY = float.MaxValue;
|
||||||
|
var minZ = float.MaxValue;
|
||||||
var maxX = float.MinValue;
|
var maxX = float.MinValue;
|
||||||
var maxY = float.MinValue;
|
var maxY = float.MinValue;
|
||||||
|
var maxZ = float.MinValue;
|
||||||
|
|
||||||
foreach (var v in draw)
|
foreach (var v in draw)
|
||||||
{
|
{
|
||||||
var bounds = v.Voxel.Bounds(v.FrameFunc());
|
var bounds = v.Voxel.Bounds(v.FrameFunc());
|
||||||
@@ -208,7 +223,7 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
|
|
||||||
float sx, sy, sz;
|
float sx, sy, sz;
|
||||||
wr.ScreenVectorComponents(v.OffsetFunc(), out sx, out sy, out sz);
|
wr.ScreenVectorComponents(v.OffsetFunc(), out sx, out sy, out sz);
|
||||||
var pxPos = pxOrigin + new float2(sx, sy);
|
var pxPos = pxOrigin + new float3(sx, sy, sz);
|
||||||
var screenTransform = OpenRA.Graphics.Util.MatrixMultiply(cameraTransform, worldTransform);
|
var screenTransform = OpenRA.Graphics.Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||||
|
|
||||||
for (var i = 0; i < 8; i++)
|
for (var i = 0; i < 8; i++)
|
||||||
@@ -217,12 +232,14 @@ namespace OpenRA.Mods.Common.Graphics
|
|||||||
var screen = OpenRA.Graphics.Util.MatrixVectorMultiply(screenTransform, vec);
|
var screen = OpenRA.Graphics.Util.MatrixVectorMultiply(screenTransform, vec);
|
||||||
minX = Math.Min(minX, pxPos.X + screen[0]);
|
minX = Math.Min(minX, pxPos.X + screen[0]);
|
||||||
minY = Math.Min(minY, pxPos.Y + screen[1]);
|
minY = Math.Min(minY, pxPos.Y + screen[1]);
|
||||||
|
minZ = Math.Min(minZ, pxPos.Z + screen[2]);
|
||||||
maxX = Math.Max(maxX, pxPos.X + screen[0]);
|
maxX = Math.Max(maxX, pxPos.X + screen[0]);
|
||||||
maxY = Math.Max(maxY, pxPos.Y + screen[1]);
|
maxY = Math.Max(maxY, pxPos.Y + screen[1]);
|
||||||
|
maxZ = Math.Max(minZ, pxPos.Z + screen[2]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Rectangle.FromLTRB((int)minX, (int)minY, (int)maxX, (int)maxY);
|
return Pair.New(Rectangle.FromLTRB((int)minX, (int)minY, (int)maxX, (int)maxY), new float2(minZ, maxZ));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,25 @@
|
|||||||
uniform sampler2D DiffuseTexture;
|
uniform sampler2D DiffuseTexture;
|
||||||
|
uniform bool EnableDepthPreview;
|
||||||
|
|
||||||
varying vec4 vTexCoord;
|
varying vec4 vTexCoord;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
gl_FragColor = texture2D(DiffuseTexture, vTexCoord.st);
|
vec4 c = texture2D(DiffuseTexture, vTexCoord.st);
|
||||||
|
// Discard any transparent fragments (both color and depth)
|
||||||
|
if (c.a == 0.0)
|
||||||
|
discard;
|
||||||
|
|
||||||
|
float depth = gl_FragCoord.z;
|
||||||
|
|
||||||
|
// Convert to window coords
|
||||||
|
gl_FragDepth = 0.5 * depth + 0.5;
|
||||||
|
|
||||||
|
if (EnableDepthPreview)
|
||||||
|
{
|
||||||
|
// Front of the depth buffer is at 0, but we want to render it as bright
|
||||||
|
gl_FragColor = vec4(vec3(1.0 - gl_FragDepth), 1.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gl_FragColor = c;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user