From dabea59b7d83aec97aea6020bf56919f918b3f3d Mon Sep 17 00:00:00 2001 From: Paul Chote Date: Thu, 1 Oct 2015 18:55:54 +0100 Subject: [PATCH] Pass depth scale factors to vertex shaders. --- OpenRA.Game/Game.cs | 3 +++ OpenRA.Game/Graphics/SpriteRenderer.cs | 14 ++++++++++---- OpenRA.Game/Map/MapGrid.cs | 2 ++ OpenRA.Game/Renderer.cs | 25 +++++++++++++++++++++---- glsl/rgba.vert | 7 +++---- glsl/shp.frag | 22 +++++++++++++++++++--- glsl/shp.vert | 7 +++---- 7 files changed, 61 insertions(+), 19 deletions(-) diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 64031fe1e3..054a142a7b 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -359,6 +359,9 @@ namespace OpenRA ModData.InitializeLoaders(ModData.DefaultFileSystem); Renderer.InitializeFonts(ModData); + var grid = ModData.Manifest.Contains() ? ModData.Manifest.Get() : null; + Renderer.InitializeDepthBuffer(grid); + if (Cursor != null) Cursor.Dispose(); diff --git a/OpenRA.Game/Graphics/SpriteRenderer.cs b/OpenRA.Game/Graphics/SpriteRenderer.cs index 41c2f2a707..70580db08b 100644 --- a/OpenRA.Game/Graphics/SpriteRenderer.cs +++ b/OpenRA.Game/Graphics/SpriteRenderer.cs @@ -114,11 +114,17 @@ namespace OpenRA.Graphics shader.SetTexture("Palette", palette); } - public void SetViewportParams(Size screen, float zoom, int2 scroll) + public void SetViewportParams(Size screen, float depthScale, float depthOffset, float zoom, int2 scroll) { - shader.SetVec("Scroll", scroll.X, scroll.Y); - shader.SetVec("r1", zoom * 2f / screen.Width, -zoom * 2f / screen.Height); - shader.SetVec("r2", -1, 1); + shader.SetVec("Scroll", scroll.X, scroll.Y, scroll.Y); + shader.SetVec("r1", + zoom * 2f / screen.Width, + -zoom * 2f / screen.Height, + -depthScale * zoom / screen.Height); + shader.SetVec("r2", -1, 1, 1 - depthOffset); + + // Texture index is sampled as a float, so convert to pixels then scale + shader.SetVec("DepthTextureScale", 128 * depthScale * zoom / screen.Height); } public void SetDepthPreviewEnabled(bool enabled) diff --git a/OpenRA.Game/Map/MapGrid.cs b/OpenRA.Game/Map/MapGrid.cs index 05cdf4f63f..651288d3a7 100644 --- a/OpenRA.Game/Map/MapGrid.cs +++ b/OpenRA.Game/Map/MapGrid.cs @@ -28,6 +28,8 @@ namespace OpenRA public readonly int MaximumTileSearchRange = 50; + public readonly bool EnableDepthBuffer = false; + public readonly WVec[] SubCellOffsets = { new WVec(0, 0, 0), // full cell - index 0 diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index 4690dae2e4..266fa714d7 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -40,6 +40,9 @@ namespace OpenRA SheetBuilder fontSheetBuilder; + float depthScale; + float depthOffset; + Size? lastResolution; int2? lastScroll; float? lastZoom; @@ -102,6 +105,20 @@ namespace OpenRA } } + public void InitializeDepthBuffer(MapGrid mapGrid) + { + // The depth buffer needs to be initialized with enough range to cover: + // - the height of the screen + // - the z-offset of tiles from MaxTerrainHeight below the bottom of the screen (pushed into view) + // - additional z-offset from actors on top of MaxTerrainHeight terrain + // - a small margin so that tiles rendered partially above the top edge of the screen aren't pushed behind the clip plane + // We need an offset of mapGrid.MaximumTerrainHeight * mapGrid.TileSize.Height / 2 to cover the terrain height + // and choose to use mapGrid.MaximumTerrainHeight * mapGrid.TileSize.Height / 4 for each of the actor and top-edge cases + this.depthScale = mapGrid == null || !mapGrid.EnableDepthBuffer ? 0 : + (float)Resolution.Height / (Resolution.Height + mapGrid.TileSize.Height * mapGrid.MaximumTerrainHeight); + this.depthOffset = this.depthScale / 2; + } + public void BeginFrame(int2 scroll, float zoom) { Device.Clear(); @@ -115,8 +132,8 @@ namespace OpenRA if (resolutionChanged) { lastResolution = Resolution; - RgbaSpriteRenderer.SetViewportParams(Resolution, 1f, int2.Zero); - SpriteRenderer.SetViewportParams(Resolution, 1f, int2.Zero); + RgbaSpriteRenderer.SetViewportParams(Resolution, 0f, 0f, 1f, int2.Zero); + SpriteRenderer.SetViewportParams(Resolution, 0f, 0f, 1f, int2.Zero); RgbaColorRenderer.SetViewportParams(Resolution, 1f, int2.Zero); } @@ -125,8 +142,8 @@ namespace OpenRA { lastScroll = scroll; lastZoom = zoom; - WorldRgbaSpriteRenderer.SetViewportParams(Resolution, zoom, scroll); - WorldSpriteRenderer.SetViewportParams(Resolution, zoom, scroll); + WorldRgbaSpriteRenderer.SetViewportParams(Resolution, depthScale, depthOffset, zoom, scroll); + WorldSpriteRenderer.SetViewportParams(Resolution, depthScale, depthOffset, zoom, scroll); WorldVoxelRenderer.SetViewportParams(Resolution, zoom, scroll); WorldRgbaColorRenderer.SetViewportParams(Resolution, zoom, scroll); } diff --git a/glsl/rgba.vert b/glsl/rgba.vert index f5d8177526..7b7e5b7958 100644 --- a/glsl/rgba.vert +++ b/glsl/rgba.vert @@ -1,5 +1,5 @@ -uniform vec2 Scroll; -uniform vec2 r1, r2; +uniform vec3 Scroll; +uniform vec3 r1, r2; attribute vec4 aVertexPosition; attribute vec4 aVertexTexCoord; @@ -7,7 +7,6 @@ varying vec4 vTexCoord; void main() { - vec2 p = (aVertexPosition.xy - Scroll.xy)*r1 + r2; - gl_Position = vec4(p.x,p.y,0,1); + gl_Position = vec4((aVertexPosition.xyz - Scroll.xyz) * r1 + r2, 1); vTexCoord = aVertexTexCoord; } diff --git a/glsl/shp.frag b/glsl/shp.frag index c7e1c1189f..df27bb2284 100644 --- a/glsl/shp.frag +++ b/glsl/shp.frag @@ -1,6 +1,7 @@ uniform sampler2D DiffuseTexture, Palette; uniform bool EnableDepthPreview; +uniform float DepthTextureScale; varying vec4 vTexCoord; varying vec4 vChannelMask; @@ -17,9 +18,24 @@ void main() discard; if (EnableDepthPreview && length(vDepthMask) > 0.0) - { - float depth = dot(x, vDepthMask); - gl_FragColor = vec4(depth, depth, depth, 1); + { + if (abs(DepthTextureScale) > 0.0) + { + // Preview vertex aware depth + float depth = gl_FragCoord.z + DepthTextureScale * dot(x, vDepthMask); + + // Convert to window coords + depth = 0.5 * depth + 0.5; + + // Front of the depth buffer is at 0, but we want to render it as bright + gl_FragColor = vec4(vec3(1.0 - depth), 1.0); + } + else + { + // Preview boring sprite-only depth + float depth = dot(x, vDepthMask); + gl_FragColor = vec4(depth, depth, depth, 1.0); + } } else gl_FragColor = c; diff --git a/glsl/shp.vert b/glsl/shp.vert index c59498a96b..8e46666dfa 100644 --- a/glsl/shp.vert +++ b/glsl/shp.vert @@ -1,5 +1,5 @@ -uniform vec2 Scroll; -uniform vec2 r1,r2; // matrix elements +uniform vec3 Scroll; +uniform vec3 r1, r2; attribute vec4 aVertexPosition; attribute vec4 aVertexTexCoord; @@ -36,8 +36,7 @@ vec4 DecodeDepthChannelMask(float x) void main() { - vec2 p = (aVertexPosition.xy - Scroll.xy) * r1 + r2; - gl_Position = vec4(p.x,p.y,0,1); + gl_Position = vec4((aVertexPosition.xyz - Scroll.xyz) * r1 + r2, 1); vTexCoord = aVertexTexCoord; vChannelMask = DecodeChannelMask(aVertexTexCoord.w); vDepthMask = DecodeDepthChannelMask(aVertexTexCoord.w);