145 lines
4.5 KiB
C#
145 lines
4.5 KiB
C#
using System;
|
|
using ANX.Framework.Graphics;
|
|
using ANX.Framework.NonXNA.RenderSystem;
|
|
using OpenTK.Graphics.OpenGL;
|
|
using ANX.RenderSystem.GL3.Helpers;
|
|
|
|
namespace ANX.RenderSystem.GL3
|
|
{
|
|
public class RenderTarget2DGL3 : Texture2DGL3, INativeRenderTarget2D
|
|
{
|
|
#region Private
|
|
private int framebufferHandle;
|
|
private int renderbufferHandle;
|
|
|
|
private bool generateMipmaps;
|
|
#endregion
|
|
|
|
// TODO: usage, preferredMultiSampleCount
|
|
#region Constructor
|
|
public RenderTarget2DGL3(int width, int height, bool mipMap,
|
|
SurfaceFormat preferredFormat, DepthFormat preferredDepthFormat,
|
|
int preferredMultiSampleCount, RenderTargetUsage usage)
|
|
: base()
|
|
{
|
|
generateMipmaps = mipMap;
|
|
PixelInternalFormat nativeFormat =
|
|
DatatypesMapping.SurfaceToPixelInternalFormat(preferredFormat);
|
|
|
|
#region Image creation
|
|
NativeHandle = GL.GenTexture();
|
|
GL.BindTexture(TextureTarget.Texture2D, NativeHandle);
|
|
GL.TexParameter(TextureTarget.Texture2D,
|
|
TextureParameterName.TextureMagFilter, (int)All.Linear);
|
|
GL.TexParameter(TextureTarget.Texture2D,
|
|
TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
|
|
GL.TexParameter(TextureTarget.Texture2D,
|
|
TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
|
|
if (generateMipmaps)
|
|
{
|
|
GL.TexParameter(TextureTarget.Texture2D,
|
|
TextureParameterName.GenerateMipmap, 1);
|
|
GL.TexParameter(TextureTarget.Texture2D,
|
|
TextureParameterName.TextureMinFilter, (int)All.LinearMipmapLinear);
|
|
}
|
|
else
|
|
{
|
|
GL.TexParameter(TextureTarget.Texture2D,
|
|
TextureParameterName.TextureMinFilter, (int)All.Linear);
|
|
}
|
|
|
|
GL.TexImage2D(TextureTarget.Texture2D, 0, nativeFormat,
|
|
width, height, 0, (PixelFormat)nativeFormat, PixelType.UnsignedByte,
|
|
IntPtr.Zero);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
#endregion
|
|
|
|
// create a renderbuffer object to store depth info
|
|
GL.GenRenderbuffers(1, out renderbufferHandle);
|
|
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, renderbufferHandle);
|
|
GL.RenderbufferStorage(RenderbufferTarget.Renderbuffer,
|
|
DepthFormatConversion(preferredDepthFormat), width, height);
|
|
GL.BindRenderbuffer(RenderbufferTarget.RenderbufferExt, 0);
|
|
|
|
// create a framebuffer object
|
|
GL.GenFramebuffers(1, out framebufferHandle);
|
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebufferHandle);
|
|
|
|
// attach the texture to FBO color attachment point
|
|
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
|
|
FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D,
|
|
NativeHandle, 0);
|
|
|
|
// attach the renderbuffer to depth attachment point
|
|
GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer,
|
|
FramebufferAttachment.DepthAttachment,
|
|
RenderbufferTarget.Renderbuffer, renderbufferHandle);
|
|
|
|
// check FBO status
|
|
FramebufferErrorCode status = GL.CheckFramebufferStatus(
|
|
FramebufferTarget.Framebuffer);
|
|
if (status != FramebufferErrorCode.FramebufferComplete)
|
|
{
|
|
throw new InvalidOperationException(
|
|
"Failed to create the render target! Error=" + status);
|
|
}
|
|
|
|
// switch back to window-system-provided framebuffer
|
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
|
}
|
|
#endregion
|
|
|
|
#region DepthFormatConversion
|
|
private RenderbufferStorage DepthFormatConversion(DepthFormat depthFormat)
|
|
{
|
|
switch(depthFormat)
|
|
{
|
|
default:
|
|
case DepthFormat.None:
|
|
// TODO
|
|
return RenderbufferStorage.DepthComponent16;
|
|
//return (RenderbufferStorage)All.DepthComponent;
|
|
|
|
case DepthFormat.Depth16:
|
|
return RenderbufferStorage.DepthComponent16;
|
|
|
|
case DepthFormat.Depth24:
|
|
return RenderbufferStorage.DepthComponent24;
|
|
|
|
case DepthFormat.Depth24Stencil8:
|
|
return RenderbufferStorage.DepthComponent32;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Bind
|
|
public void Bind()
|
|
{
|
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, framebufferHandle);
|
|
}
|
|
#endregion
|
|
|
|
#region Unbind
|
|
public void Unbind()
|
|
{
|
|
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
|
if (generateMipmaps)
|
|
{
|
|
GL.BindTexture(TextureTarget.Texture2D, NativeHandle);
|
|
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
|
|
GL.BindTexture(TextureTarget.Texture2D, 0);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Dispose
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
GL.DeleteFramebuffers(1, ref framebufferHandle);
|
|
GL.DeleteRenderbuffers(1, ref renderbufferHandle);
|
|
}
|
|
#endregion
|
|
}
|
|
}
|