Working on Texture2DGL3.

This commit is contained in:
SND\AstrorEnales_cp 2011-11-14 21:01:54 +00:00
parent e02485ab9e
commit b3e50da398
3 changed files with 195 additions and 95 deletions

View File

@ -119,16 +119,11 @@ namespace ANX.Framework.Windows.GL3
/// <param name="width">The width of the texture.</param>
/// <param name="height">The height of the texture.</param>
/// <param name="mipCount">The number of mipmaps in the texture.</param>
/// <param name="mipMaps">The mipmaps as a single byte array.</param>
/// <returns></returns>
public INativeTexture2D CreateTexture(GraphicsDevice graphics,
SurfaceFormat surfaceFormat, int width, int height, int mipCount) //,
//byte[] mipMaps)
SurfaceFormat surfaceFormat, int width, int height, int mipCount)
{
throw new NotImplementedException();
//return new Texture2DGL3(graphics, surfaceFormat, width,
// height, mipCount, mipMaps);
return new Texture2DGL3(surfaceFormat, width, height, mipCount);
}
#endregion

View File

@ -1,6 +1,7 @@
using System;
using ANX.Framework.Graphics;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
#region License
@ -159,6 +160,80 @@ namespace ANX.Framework.Windows.GL3
}
#endregion
#region SurfaceToPixelInternalFormat (TODO)
/// <summary>
/// Translate the XNA surface format to an OpenGL PixelInternalFormat.
/// </summary>
/// <param name="format">XNA surface format.</param>
/// <returns>Translated format for OpenGL.</returns>
public static PixelInternalFormat SurfaceToPixelInternalFormat(
SurfaceFormat format)
{
switch (format)
{
// TODO
case SurfaceFormat.HdrBlendable:
case SurfaceFormat.Bgr565:
throw new NotImplementedException("Surface Format '" + format +
"' isn't implemented yet!");
// TODO: CHECK!
case SurfaceFormat.NormalizedByte2:
return PixelInternalFormat.Rg8;
default:
case SurfaceFormat.Color:
case SurfaceFormat.NormalizedByte4:
return PixelInternalFormat.Rgba;
case SurfaceFormat.Dxt1:
return PixelInternalFormat.CompressedRgbaS3tcDxt1Ext;
case SurfaceFormat.Dxt3:
return PixelInternalFormat.CompressedRgbaS3tcDxt3Ext;
case SurfaceFormat.Dxt5:
return PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
case SurfaceFormat.HalfVector2:
return PixelInternalFormat.Rg16;
case SurfaceFormat.HalfVector4:
return PixelInternalFormat.Rgba16f;
case SurfaceFormat.Bgra4444:
return PixelInternalFormat.Rgba4;
case SurfaceFormat.Bgra5551:
return PixelInternalFormat.Rgb5A1;
case SurfaceFormat.Alpha8:
return PixelInternalFormat.Alpha8;
case SurfaceFormat.Rg32:
return PixelInternalFormat.Rg32f;
case SurfaceFormat.Rgba1010102:
return PixelInternalFormat.Rgb10A2;
case SurfaceFormat.Rgba64:
return PixelInternalFormat.Rgba16f;
case SurfaceFormat.HalfSingle:
return PixelInternalFormat.R16f;
case SurfaceFormat.Single:
return PixelInternalFormat.R32f;
case SurfaceFormat.Vector2:
return PixelInternalFormat.Rg32f;
case SurfaceFormat.Vector4:
return PixelInternalFormat.Rgba32f;
}
}
#endregion
#region Tests
private class Tests
{

View File

@ -1,7 +1,8 @@
using System;
using ANX.Framework.Graphics;
using OpenTK.Graphics.OpenGL;
using System.Runtime.InteropServices;
using ANX.Framework.Graphics;
using ANX.Framework.NonXNA.RenderSystem;
using OpenTK.Graphics.OpenGL;
#region License
@ -53,10 +54,37 @@ using System.Runtime.InteropServices;
namespace ANX.Framework.Windows.GL3
{
/// <summary>
/// BIG TODO
/// Native OpenGL Texture implementation.
/// </summary>
public class Texture2DGL3 : Texture2D
public class Texture2DGL3 : INativeTexture2D
{
#region Private
/// <summary>
/// The native OpenGL pixel format of the texture.
/// </summary>
private PixelInternalFormat nativeFormat;
/// <summary>
/// The number of mipmaps used by this texture [1-n].
/// </summary>
private int numberOfMipMaps;
/// <summary>
/// Width of the texture.
/// </summary>
private int width;
/// <summary>
/// Height of the texture.
/// </summary>
private int height;
/// <summary>
/// Flag if the texture is a compressed format or not.
/// </summary>
private bool isCompressed;
#endregion
#region Public
/// <summary>
/// The OpenGL texture handle.
@ -69,18 +97,26 @@ namespace ANX.Framework.Windows.GL3
#endregion
#region Constructor
internal Texture2DGL3(GraphicsDevice graphics,
SurfaceFormat surfaceFormat, int width, int height, int mipCount,
byte[] mipMaps)
: base(graphics, width, height, mipCount > 0, surfaceFormat)
/// <summary>
/// Create a new native OpenGL texture.
/// </summary>
/// <param name="surfaceFormat">Surface format of the texture.</param>
/// <param name="setWidth">Width of the first mip level.</param>
/// <param name="setHeight">Height of the first mip level.</param>
/// <param name="mipCount">Number of mip levels [1-n].</param>
internal Texture2DGL3(SurfaceFormat surfaceFormat, int setWidth,
int setHeight, int mipCount)
{
int dataLengthPerTexture = 0;
width = setWidth;
height = setHeight;
numberOfMipMaps = mipCount;
isCompressed = nativeFormat.ToString().StartsWith("Compressed");
NativeHandle = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, NativeHandle);
int wrapMode = (int)All.ClampToEdge;
int filter = (int)(mipCount > 0 ? All.LinearMipmapLinear : All.Linear);
int filter = (int)(mipCount > 1 ? All.LinearMipmapLinear : All.Linear);
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureWrapS, wrapMode);
@ -91,97 +127,81 @@ namespace ANX.Framework.Windows.GL3
GL.TexParameter(TextureTarget.Texture2D,
TextureParameterName.TextureMinFilter, filter);
PixelInternalFormat formatUsed = PixelInternalFormat.Rgba;
nativeFormat =
DatatypesMapping.SurfaceToPixelInternalFormat(surfaceFormat);
}
#endregion
// TODO: offsetInBytes
// TODO: startIndex
// TODO: elementCount
// TODO: get size of first mipmap!
#region SetData
public void SetData<T>(GraphicsDevice graphicsDevice, T[] data)
where T : struct
{
SetData<T>(graphicsDevice, data, 0, data.Length);
}
public void SetData<T>(GraphicsDevice graphicsDevice, T[] data,
int startIndex, int elementCount) where T : struct
{
SetData<T>(graphicsDevice, 0, data, 0, data.Length);
}
public void SetData<T>(GraphicsDevice graphicsDevice, int offsetInBytes,
T[] data, int startIndex, int elementCount) where T : struct
{
if (numberOfMipMaps > 1)
{
throw new NotImplementedException(
"Loading mipmaps is not correctly implemented yet!");
}
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
// TODO: get size of first mipmap!
int mipmapByteSize = data.Length;
GCHandle handle = GCHandle.Alloc(mipMaps, GCHandleType.Pinned);
try
{
IntPtr dataPointer = handle.AddrOfPinnedObject();
if (surfaceFormat == SurfaceFormat.Dxt1 ||
surfaceFormat == SurfaceFormat.Dxt3 ||
surfaceFormat == SurfaceFormat.Dxt5)
if (isCompressed)
{
// TODO: read dataLengthPerTexture from dds file.
#region Dds
formatUsed =
surfaceFormat == SurfaceFormat.Dxt1 ?
PixelInternalFormat.CompressedRgbS3tcDxt1Ext :
surfaceFormat == SurfaceFormat.Dxt3 ?
PixelInternalFormat.CompressedRgbaS3tcDxt3Ext :
PixelInternalFormat.CompressedRgbaS3tcDxt5Ext;
GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, formatUsed,
width, height, 0, dataLengthPerTexture, dataPointer);
int mipmapByteSize = dataLengthPerTexture;
int mipmapWidth = width;
int mipmapHeight = height;
for (int i = 1; i < mipCount; i++)
{
// Move our data pointer along.
dataPointer += mipmapByteSize;
mipmapByteSize /= 4;
mipmapWidth /= 2;
mipmapHeight /= 2;
if (mipmapByteSize < 32)
{
mipmapByteSize = 32;
}
if (mipmapWidth < 1)
{
mipmapWidth = 1;
}
if (mipmapHeight < 1)
{
mipmapHeight = 1;
}
GL.CompressedTexImage2D(TextureTarget.Texture2D, i, formatUsed,
mipmapWidth, mipmapHeight, 0, mipmapByteSize, dataPointer);
}
#endregion
GL.CompressedTexImage2D(TextureTarget.Texture2D, 0, nativeFormat,
width, height, 0, mipmapByteSize, dataPointer);
}
else
{
#region Other
PixelType pixelType = PixelType.UnsignedByte;
GL.TexImage2D(TextureTarget.Texture2D, 0, nativeFormat,
width, height, 0, (PixelFormat)nativeFormat,
PixelType.UnsignedByte, dataPointer);
}
GL.TexImage2D(TextureTarget.Texture2D, 0,
// Use the same for internal format (Rgba or Rgb)
formatUsed, width, height, 0,
// And the same for the pixel format of the incoming data
(PixelFormat)formatUsed, pixelType, dataPointer);
int mipmapWidth = width;
int mipmapHeight = height;
for (int index = 1; index < numberOfMipMaps; index++)
{
dataPointer += mipmapByteSize;
mipmapByteSize /= 4;
mipmapWidth /= 2;
mipmapHeight /= 2;
mipmapWidth = Math.Max(mipmapWidth, 1);
mipmapHeight = Math.Max(mipmapHeight, 1);
int mipmapByteSize = dataLengthPerTexture;
int mipmapWidth = width;
int mipmapHeight = height;
if (mipmapByteSize > 0 &&
mipCount > 0)
if (isCompressed)
{
for (int i = 1; i < mipCount; i++)
{
// Move our data pointer along.
dataPointer += mipmapByteSize;
mipmapByteSize /= 4;
mipmapWidth /= 2;
mipmapHeight /= 2;
if (mipmapWidth < 1)
{
mipmapWidth = 1;
}
if (mipmapHeight < 1)
{
mipmapHeight = 1;
}
GL.TexImage2D(TextureTarget.Texture2D, i,
// Use the same for internal format (Rgba or Rgb)
formatUsed, mipmapWidth, mipmapHeight, 0,
// And the same for the pixel format of the incoming data
(PixelFormat)formatUsed, pixelType, dataPointer);
}
GL.CompressedTexImage2D(TextureTarget.Texture2D, index,
nativeFormat, width, height, 0, mipmapByteSize,
dataPointer);
}
else
{
GL.TexImage2D(TextureTarget.Texture2D, index, nativeFormat,
mipmapWidth, mipmapHeight, 0, (PixelFormat)nativeFormat,
PixelType.UnsignedByte, dataPointer);
}
#endregion
}
}
finally
@ -190,5 +210,15 @@ namespace ANX.Framework.Windows.GL3
}
}
#endregion
#region Dispose
/// <summary>
/// Dispose the native OpenGL texture handle.
/// </summary>
public void Dispose()
{
GL.DeleteTexture(NativeHandle);
}
#endregion
}
}