Implement optimized pixel-art antialiasing mode for non-integer world zoom.
This commit is contained in:
@@ -172,5 +172,10 @@ namespace OpenRA.Graphics
|
|||||||
{
|
{
|
||||||
shader.SetBool("EnableDepthPreview", enabled);
|
shader.SetBool("EnableDepthPreview", enabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetAntialiasingPixelsPerTexel(float pxPerTx)
|
||||||
|
{
|
||||||
|
shader.SetVec("AntialiasPixelsPerTexel", pxPerTx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,6 +181,9 @@ namespace OpenRA
|
|||||||
|
|
||||||
// Render the world into a framebuffer at 1:1 scaling to allow the depth buffer to match the artwork at all zoom levels
|
// Render the world into a framebuffer at 1:1 scaling to allow the depth buffer to match the artwork at all zoom levels
|
||||||
worldBuffer = Context.CreateFrameBuffer(worldBufferSize);
|
worldBuffer = Context.CreateFrameBuffer(worldBufferSize);
|
||||||
|
|
||||||
|
// Pixel art scaling mode is a customized bilinear sampling
|
||||||
|
worldBuffer.Texture.ScaleFilter = TextureScaleFilter.Linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (worldSprite == null || worldViewport.Size != worldSprite.Bounds.Size)
|
if (worldSprite == null || worldViewport.Size != worldSprite.Bounds.Size)
|
||||||
@@ -217,8 +220,11 @@ namespace OpenRA
|
|||||||
|
|
||||||
var scale = Window.WindowScale;
|
var scale = Window.WindowScale;
|
||||||
var bufferSize = new Size((int)(screenSprite.Bounds.Width / scale), (int)(-screenSprite.Bounds.Height / scale));
|
var bufferSize = new Size((int)(screenSprite.Bounds.Width / scale), (int)(-screenSprite.Bounds.Height / scale));
|
||||||
|
|
||||||
|
SpriteRenderer.SetAntialiasingPixelsPerTexel(Window.SurfaceSize.Height * 1f / worldSprite.Bounds.Height);
|
||||||
RgbaSpriteRenderer.DrawSprite(worldSprite, float3.Zero, new float2(bufferSize));
|
RgbaSpriteRenderer.DrawSprite(worldSprite, float3.Zero, new float2(bufferSize));
|
||||||
Flush();
|
Flush();
|
||||||
|
SpriteRenderer.SetAntialiasingPixelsPerTexel(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ uniform sampler2D Palette;
|
|||||||
|
|
||||||
uniform bool EnableDepthPreview;
|
uniform bool EnableDepthPreview;
|
||||||
uniform float DepthTextureScale;
|
uniform float DepthTextureScale;
|
||||||
|
uniform float AntialiasPixelsPerTexel;
|
||||||
|
|
||||||
in vec4 vTexCoord;
|
in vec4 vTexCoord;
|
||||||
in vec2 vTexMetadata;
|
in vec2 vTexMetadata;
|
||||||
@@ -44,6 +45,24 @@ float jet_b(float x)
|
|||||||
return x < 0.3 ? 4.0 * x + 0.5 : -4.0 * x + 2.5;
|
return x < 0.3 ? 4.0 * x + 0.5 : -4.0 * x + 2.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ivec2 Size(float samplerIndex)
|
||||||
|
{
|
||||||
|
if (samplerIndex < 0.5)
|
||||||
|
return textureSize(Texture0, 0);
|
||||||
|
else if (samplerIndex < 1.5)
|
||||||
|
return textureSize(Texture1, 0);
|
||||||
|
else if (samplerIndex < 2.5)
|
||||||
|
return textureSize(Texture2, 0);
|
||||||
|
else if (samplerIndex < 3.5)
|
||||||
|
return textureSize(Texture3, 0);
|
||||||
|
else if (samplerIndex < 4.5)
|
||||||
|
return textureSize(Texture4, 0);
|
||||||
|
else if (samplerIndex < 5.5)
|
||||||
|
return textureSize(Texture5, 0);
|
||||||
|
|
||||||
|
return textureSize(Texture6, 0);
|
||||||
|
}
|
||||||
|
|
||||||
vec4 Sample(float samplerIndex, vec2 pos)
|
vec4 Sample(float samplerIndex, vec2 pos)
|
||||||
{
|
{
|
||||||
if (samplerIndex < 0.5)
|
if (samplerIndex < 0.5)
|
||||||
@@ -64,7 +83,23 @@ vec4 Sample(float samplerIndex, vec2 pos)
|
|||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
vec4 x = Sample(vTexSampler.s, vTexCoord.st);
|
vec2 coords = vTexCoord.st;
|
||||||
|
|
||||||
|
if (AntialiasPixelsPerTexel > 0)
|
||||||
|
{
|
||||||
|
vec2 textureSize = Size(vTexSampler.s);
|
||||||
|
vec2 offset = fract(coords.st * textureSize);
|
||||||
|
|
||||||
|
// Offset the sampling point to simulate bilinear intepolation in window coordinates instead of texture coordinates
|
||||||
|
// https://csantosbh.wordpress.com/2014/01/25/manual-texture-filtering-for-pixelated-games-in-webgl/
|
||||||
|
// https://csantosbh.wordpress.com/2014/02/05/automatically-detecting-the-texture-filter-threshold-for-pixelated-magnifications/
|
||||||
|
// ik is defined as 1/k from the articles, set to 1/0.7 because it looks good
|
||||||
|
float ik = 1.43;
|
||||||
|
vec2 interp = clamp(offset * ik * AntialiasPixelsPerTexel, 0.0, .5) + clamp((offset - 1.0) * ik * AntialiasPixelsPerTexel + .5, 0.0, .5);
|
||||||
|
coords = (floor(coords.st * textureSize) + interp) / textureSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 x = Sample(vTexSampler.s, coords);
|
||||||
vec2 p = vec2(dot(x, vChannelMask), vTexMetadata.s);
|
vec2 p = vec2(dot(x, vChannelMask), vTexMetadata.s);
|
||||||
vec4 c = vPalettedFraction * texture(Palette, p) + vRGBAFraction * x + vColorFraction * vTexCoord;
|
vec4 c = vPalettedFraction * texture(Palette, p) + vRGBAFraction * x + vColorFraction * vTexCoord;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user