Fix artifacts on NPOT textures in OGL
Fix reuse check of textures Introduce Size field for textures (replacing W2, H2)
This commit is contained in:
1 parent
719c73e6d3
commit
54f97a4928
4 files changed
+56
-42
No files matched your search
@@ -46,11 +46,11 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
{
|
{
|
||||||
public readonly Texture D3DTexture;
|
public readonly Texture D3DTexture;
|
||||||
|
|
||||||
public CD3DTexture(Device device, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, texWidth, texHeight)
|
public CD3DTexture(Device device, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, new Size(texWidth, texHeight))
|
||||||
{
|
{
|
||||||
//Create a new texture in the managed pool, which does not need to be recreated on a lost device
|
//Create a new texture in the managed pool, which does not need to be recreated on a lost device
|
||||||
//because a copy of the texture is hold in the Ram
|
//because a copy of the texture is hold in the Ram
|
||||||
D3DTexture = device == null ? null : new Texture(device, W2, H2, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
|
D3DTexture = device == null ? null : new Texture(device, texWidth, texHeight, 0, Usage.AutoGenerateMipMap, Format.A8R8G8B8, Pool.Managed);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool IsLoaded
|
public override bool IsLoaded
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
// along with Vocaluxe. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Drawing.Imaging;
|
using System.Drawing.Imaging;
|
||||||
using OpenTK;
|
using OpenTK;
|
||||||
using OpenTK.Graphics;
|
using OpenTK.Graphics;
|
||||||
@@ -61,14 +62,14 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
//The texture "name" according to the specs
|
//The texture "name" according to the specs
|
||||||
public readonly int Name;
|
public readonly int Name;
|
||||||
|
|
||||||
public COGLTexture(int name, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, texWidth, texHeight)
|
public COGLTexture(int name, Size dataSize, int texWidth = 0, int texHeight = 0) : base(dataSize, new Size(texWidth, texHeight))
|
||||||
{
|
{
|
||||||
Name = name;
|
Name = name;
|
||||||
if (name == 0)
|
if (name == 0)
|
||||||
return;
|
return;
|
||||||
GL.BindTexture(TextureTarget.Texture2D, Name);
|
GL.BindTexture(TextureTarget.Texture2D, Name);
|
||||||
|
|
||||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, W2, H2, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, texWidth, texHeight, 0, PixelFormat.Bgra, PixelType.UnsignedByte, IntPtr.Zero);
|
||||||
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.ClampToEdge);
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.ClampToEdge);
|
||||||
@@ -94,6 +95,7 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
class COpenGL : CDrawBaseWindows<COGLTexture>, IDraw
|
class COpenGL : CDrawBaseWindows<COGLTexture>, IDraw
|
||||||
{
|
{
|
||||||
private readonly GLControl _Control;
|
private readonly GLControl _Control;
|
||||||
|
private int _FBO;
|
||||||
|
|
||||||
public COpenGL()
|
public COpenGL()
|
||||||
{
|
{
|
||||||
@@ -233,9 +235,17 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
GL.Enable(EnableCap.DepthTest);
|
GL.Enable(EnableCap.DepthTest);
|
||||||
GL.ClearColor(Color.Black);
|
GL.ClearColor(Color.Black);
|
||||||
|
|
||||||
|
GL.GenFramebuffers(1, out _FBO);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Unload()
|
||||||
|
{
|
||||||
|
base.Unload();
|
||||||
|
GL.DeleteFramebuffers(1, ref _FBO);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void _OnBeforeDraw()
|
protected override void _OnBeforeDraw()
|
||||||
{
|
{
|
||||||
//Nothing to do
|
//Nothing to do
|
||||||
@@ -400,8 +410,23 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void _ClearTexture(COGLTexture texture)
|
||||||
|
{
|
||||||
|
if (texture.DataSize.Equals(texture.Size))
|
||||||
|
return;
|
||||||
|
GL.BindFramebuffer(OpenTK.Graphics.OpenGL.FramebufferTarget.Framebuffer, _FBO);
|
||||||
|
GL.FramebufferTexture2D(OpenTK.Graphics.OpenGL.FramebufferTarget.Framebuffer, OpenTK.Graphics.OpenGL.FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D,
|
||||||
|
texture.Name, 0);
|
||||||
|
GL.ClearColor(Color.FromArgb(0));
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
|
GL.ClearColor(Color.Black);
|
||||||
|
GL.BindFramebuffer(OpenTK.Graphics.OpenGL.FramebufferTarget.Framebuffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void _WriteDataToTexture(COGLTexture texture, byte[] data)
|
protected override void _WriteDataToTexture(COGLTexture texture, byte[] data)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(texture.Name > 0);
|
||||||
|
_ClearTexture(texture);
|
||||||
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
|
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
|
||||||
|
|
||||||
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
|
||||||
@@ -412,6 +437,8 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
|
|
||||||
protected override void _WriteDataToTexture(COGLTexture texture, IntPtr data)
|
protected override void _WriteDataToTexture(COGLTexture texture, IntPtr data)
|
||||||
{
|
{
|
||||||
|
Debug.Assert(texture.Name > 0);
|
||||||
|
_ClearTexture(texture);
|
||||||
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
|
GL.BindTexture(TextureTarget.Texture2D, texture.Name);
|
||||||
|
|
||||||
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, texture.DataSize.Width, texture.DataSize.Height, PixelFormat.Bgra, PixelType.UnsignedByte, data);
|
||||||
|
|||||||
@@ -23,13 +23,9 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// texture width (on device), a power of 2 if necessary
|
/// texture Size (on device), a power of 2 if necessary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int W2 { get; protected set; }
|
public Size Size { get; private set; }
|
||||||
/// <summary>
|
|
||||||
/// texture height (on device), a power of 2 if necessary
|
|
||||||
/// </summary>
|
|
||||||
public int H2 { get; protected set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies which part of texture memory is actually used
|
/// Specifies which part of texture memory is actually used
|
||||||
@@ -49,38 +45,25 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
/// Creates a new texture
|
/// Creates a new texture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="dataSize">Size of the data used</param>
|
/// <param name="dataSize">Size of the data used</param>
|
||||||
/// <param name="texWidth">Width in video memory</param>
|
/// <param name="textureSize">Size in video memory</param>
|
||||||
/// <param name="texHeight">Height in video memory</param>
|
protected CTextureBase(Size dataSize, Size textureSize)
|
||||||
protected CTextureBase(Size dataSize, int texWidth = 0, int texHeight = 0)
|
|
||||||
{
|
{
|
||||||
_DataSize = dataSize;
|
_DataSize = dataSize;
|
||||||
W2 = (texWidth > 0) ? texWidth : dataSize.Width;
|
Size = textureSize;
|
||||||
H2 = (texHeight > 0) ? texHeight : dataSize.Height;
|
|
||||||
|
|
||||||
_CalcRatios();
|
_CalcRatios();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void _CalcRatios()
|
private void _CalcRatios()
|
||||||
{
|
{
|
||||||
if (_DataSize.Width == W2)
|
if (_DataSize.Width == Size.Width)
|
||||||
WidthRatio = 1f;
|
WidthRatio = 1f;
|
||||||
else
|
else
|
||||||
{
|
WidthRatio = (float)_DataSize.Width / Size.Width;
|
||||||
// OpenGL has a problem with partial (NPOT) textures, so we remove 1 pixel
|
if (_DataSize.Height == Size.Height)
|
||||||
int mod = 0;
|
|
||||||
if (_DataSize.Width > 1)
|
|
||||||
mod = -1;
|
|
||||||
WidthRatio = (float)(_DataSize.Width + mod) / W2;
|
|
||||||
}
|
|
||||||
if (_DataSize.Height == H2)
|
|
||||||
HeightRatio = 1f;
|
HeightRatio = 1f;
|
||||||
else
|
else
|
||||||
{
|
HeightRatio = (float)_DataSize.Height / Size.Height;
|
||||||
int mod = 0;
|
|
||||||
if (_DataSize.Height > 1)
|
|
||||||
mod = -1;
|
|
||||||
HeightRatio = (float)(_DataSize.Height + mod) / H2;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _IsDisposed;
|
private bool _IsDisposed;
|
||||||
|
|||||||
@@ -388,15 +388,15 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
return _GetTextureReference(new Size(origWidth, origHeight), texture);
|
return _GetTextureReference(new Size(origWidth, origHeight), texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool _IsTextureUsable(TTextureType texture, int dataWidth, int dataHeight)
|
private static bool _IsTextureUsable(TTextureType texture, Size dataSize)
|
||||||
{
|
{
|
||||||
if (texture == null)
|
if (texture == null)
|
||||||
return false;
|
return false;
|
||||||
if (texture.DataSize.Width != dataWidth || texture.DataSize.Height != dataHeight)
|
if (!texture.DataSize.Equals(dataSize))
|
||||||
{
|
{
|
||||||
if (texture.W2 > dataWidth || texture.H2 > dataHeight)
|
if (texture.Size.Width < dataSize.Width || texture.Size.Height < dataSize.Height)
|
||||||
return false; // Texture memory to small
|
return false; // Texture memory to small
|
||||||
if (texture.W2 * 0.9 < dataWidth || texture.H2 * 0.9 < dataHeight)
|
if (texture.Size.Width * 0.9 > dataSize.Width || texture.Size.Height * 0.9 > dataSize.Height)
|
||||||
return false; // Texture memory to big
|
return false; // Texture memory to big
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -491,7 +491,7 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
bmp.Dispose();
|
bmp.Dispose();
|
||||||
}
|
}
|
||||||
else if (q.Data is byte[])
|
else if (q.Data is byte[])
|
||||||
UpdateTexture(textureRef, q.DataSize.Width, q.DataSize.Height, (byte[])q.Data);
|
UpdateTexture(textureRef, q.DataSize, (byte[])q.Data);
|
||||||
else
|
else
|
||||||
throw new ArgumentException("q.Data is of invalid type");
|
throw new ArgumentException("q.Data is of invalid type");
|
||||||
// ReSharper restore CanBeReplacedWithTryCastAndCheckForNull
|
// ReSharper restore CanBeReplacedWithTryCastAndCheckForNull
|
||||||
@@ -776,30 +776,34 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
_EnqueueTextureAddOrUpdate(textureRef, bmp, EQueueAction.Update, true);
|
_EnqueueTextureAddOrUpdate(textureRef, bmp, EQueueAction.Update, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateTexture(CTextureRef textureRef, int w, int h, byte[] data)
|
||||||
|
{
|
||||||
|
UpdateTexture(textureRef, new Size(w, h), data);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Updates the data of a texture
|
/// Updates the data of a texture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="textureRef">The texture to update</param>
|
/// <param name="textureRef">The texture to update</param>
|
||||||
/// <param name="w"></param>
|
/// <param name="dataSize"></param>
|
||||||
/// <param name="h"></param>
|
|
||||||
/// <param name="data">A byte array containing the new texture's data</param>
|
/// <param name="data">A byte array containing the new texture's data</param>
|
||||||
/// <returns>True if succeeded</returns>
|
/// <returns>True if succeeded</returns>
|
||||||
public void UpdateTexture(CTextureRef textureRef, int w, int h, byte[] data)
|
public void UpdateTexture(CTextureRef textureRef, Size dataSize, byte[] data)
|
||||||
{
|
{
|
||||||
_EnsureMainThread();
|
_EnsureMainThread();
|
||||||
TTextureType texture;
|
TTextureType texture;
|
||||||
if (!_GetTexture(textureRef, out texture, false))
|
if (!_GetTexture(textureRef, out texture, false))
|
||||||
return;
|
return;
|
||||||
bool reuseTexture = _IsTextureUsable(texture, w, h);
|
bool reuseTexture = _IsTextureUsable(texture, dataSize);
|
||||||
if (reuseTexture && texture.RefCount == 1)
|
if (reuseTexture && texture.RefCount == 1)
|
||||||
{
|
{
|
||||||
texture.DataSize = new Size(w, h);
|
texture.DataSize = dataSize;
|
||||||
_WriteDataToTexture(texture, data);
|
_WriteDataToTexture(texture, data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_DisposeTexture(texture);
|
_DisposeTexture(texture);
|
||||||
texture = _CreateAndFillTexture(new Size(w, h), data);
|
texture = _CreateAndFillTexture(dataSize, data);
|
||||||
texture.RefCount = 1;
|
texture.RefCount = 1;
|
||||||
_Textures[textureRef.ID] = texture;
|
_Textures[textureRef.ID] = texture;
|
||||||
}
|
}
|
||||||
@@ -811,7 +815,7 @@ namespace Vocaluxe.Lib.Draw
|
|||||||
TTextureType texture;
|
TTextureType texture;
|
||||||
if (!_GetTexture(textureRef, out texture, false))
|
if (!_GetTexture(textureRef, out texture, false))
|
||||||
return;
|
return;
|
||||||
bool reuseTexture = _IsTextureUsable(texture, bmp.Width, bmp.Height);
|
bool reuseTexture = _IsTextureUsable(texture, bmp.Size);
|
||||||
if (reuseTexture && texture.RefCount == 1)
|
if (reuseTexture && texture.RefCount == 1)
|
||||||
_WriteBitmapToTexture(ref texture, bmp);
|
_WriteBitmapToTexture(ref texture, bmp);
|
||||||
else
|
else
|
||||||
|
|||||||
Reference in new issue
Block a user