Keep pan consistent when switching between integer multiple textures

* Basically for downsample chains and the like, the pixels should now
  exactly line up with each other rather than shifting back and forth.
This commit is contained in:
baldurk
2016-02-21 16:37:58 +01:00
parent 1a05f4fc4a
commit 1f1694af4f
2 changed files with 39 additions and 33 deletions
+9
View File
@@ -76,6 +76,15 @@ namespace renderdocui.Code
else return val;
}
public static float Area(this System.Drawing.PointF val)
{
return val.X * val.Y;
}
public static float Aspect(this System.Drawing.PointF val)
{
return val.X / val.Y;
}
public static uint AlignUp(this uint x, uint a)
{
return (x + (a - 1)) & (~(a - 1));
+30 -33
View File
@@ -1069,7 +1069,7 @@ namespace renderdocui.Windows
m_TextureSettings.Clear();
m_PrevArea = 0.0f;
m_PrevSize = PointF.Empty;
m_HighWaterStatusLength = 0;
saveTex.Enabled = false;
@@ -1444,7 +1444,7 @@ namespace renderdocui.Windows
private int prevFirstArraySlice = -1;
private int prevHighestMip = -1;
private float m_PrevArea = 0.0f;
private PointF m_PrevSize = PointF.Empty;
private void UI_OnTextureSelectionChanged()
{
@@ -1484,29 +1484,42 @@ namespace renderdocui.Windows
m_CurRealValue = null;
// try to maintain the pan in the new texture. If the new texture
// is an integer multiple of the old texture, this will keep the
// top left pixel the same. Due to the difference in scale, the rest
// of the image will be out though. This is useful for downsample chains and
// things where you're flipping back and forth between overlapping
// textures, but really needs a mode where the zoom level is changed
// to compensate as well.
float curArea = (float)CurrentTexture.width * (float)CurrentTexture.height;
// is approx an integer multiple of the old texture, just changing
// the scale will keep everything the same. This is useful for
// downsample chains and things where you're flipping back and forth
// between overlapping textures, but even in the non-integer case
// pan will be kept approximately the same.
PointF curSize = new PointF((float)CurrentTexture.width, (float)CurrentTexture.height);
float curArea = curSize.Area();
float prevArea = m_PrevSize.Area();
if(m_PrevArea > 0.0f)
if (prevArea > 0.0f)
{
float prevX = m_TexDisplay.offx;
float prevY = m_TexDisplay.offy;
float prevScale = m_TexDisplay.scale;
// this scale factor is arbitrary really, only intention is to have
// integer scales come out precisely, other 'similar' sizes will be
// similar ish
float scaleFactor = (float)(Math.Sqrt(curArea) / Math.Sqrt(m_PrevArea));
// allow slight difference in aspect ratio for rounding errors
// in downscales (e.g. 1680x1050 -> 840x525 -> 420x262 in the
// last downscale the ratios are 1.6 and 1.603053435).
if (Math.Abs(curSize.Aspect() - m_PrevSize.Aspect()) < 0.01f)
{
m_TexDisplay.scale *= m_PrevSize.X / curSize.X;
CurrentZoomValue = m_TexDisplay.scale;
}
else
{
// this scale factor is arbitrary really, only intention is to have
// integer scales come out precisely, other 'similar' sizes will be
// similar ish
float scaleFactor = (float)(Math.Sqrt(curArea) / Math.Sqrt(prevArea));
m_TexDisplay.offx = prevX * scaleFactor;
m_TexDisplay.offy = prevY * scaleFactor;
m_TexDisplay.offx = prevX * scaleFactor;
m_TexDisplay.offy = prevY * scaleFactor;
}
}
m_PrevArea = curArea;
m_PrevSize = curSize;
// refresh scroll position
ScrollPosition = ScrollPosition;
@@ -2452,22 +2465,6 @@ namespace renderdocui.Windows
m_TexDisplay.scale = Math.Max(0.1f, Math.Min(256.0f, s));
FetchTexture tex = CurrentTexture;
if (tex == null)
{
if(m_Core.LogLoaded)
foreach (var t in m_Core.CurTextures)
if (t.ID == m_TexDisplay.texid)
tex = t;
if(tex == null)
return;
}
//render.Width = Math.Min(500, (int)(tex.width * m_TexDisplay.scale));
//render.Height = Math.Min(500, (int)(tex.height * m_TexDisplay.scale));
m_Core.Renderer.BeginInvoke(RT_UpdateAndDisplay);
float scaleDelta = (m_TexDisplay.scale / prevScale);