diff --git a/EpicManifestParser b/EpicManifestParser index 0c633f3d..00bc31fa 160000 --- a/EpicManifestParser +++ b/EpicManifestParser @@ -1 +1 @@ -Subproject commit 0c633f3d3ad6f1eed9df9cee60917e1e169a0101 +Subproject commit 00bc31fa4cc570efd3f9d54694feb16a8d21251c diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index a6351c28..ee406e32 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -103,6 +103,8 @@ + + @@ -122,6 +124,8 @@ + + diff --git a/FModel/Framework/ImGuiController.cs b/FModel/Framework/ImGuiController.cs index 808ad9ba..4c842309 100644 --- a/FModel/Framework/ImGuiController.cs +++ b/FModel/Framework/ImGuiController.cs @@ -32,7 +32,7 @@ public class ImGuiController : IDisposable private int _windowWidth; private int _windowHeight; - private System.Numerics.Vector2 _scaleFactor = System.Numerics.Vector2.One; + private readonly System.Numerics.Vector2 _scaleFactor = System.Numerics.Vector2.One; private static bool KHRDebugAvailable = false; diff --git a/FModel/Resources/picking.frag b/FModel/Resources/picking.frag new file mode 100644 index 00000000..11208c3c --- /dev/null +++ b/FModel/Resources/picking.frag @@ -0,0 +1,13 @@ +#version 330 + +uniform uint uA; +uniform uint uB; +uniform uint uC; +uniform uint uD; + +out uvec4 FragColor; + +void main() +{ + FragColor = uvec4(uA, uB, uC, uD); +} diff --git a/FModel/Resources/picking.vert b/FModel/Resources/picking.vert new file mode 100644 index 00000000..53ee7fff --- /dev/null +++ b/FModel/Resources/picking.vert @@ -0,0 +1,15 @@ +#version 330 core + +layout (location = 1) in vec3 vPos; +layout (location = 8) in mat4 vInstanceMatrix; +layout (location = 12) in vec3 vMorphTarget; + +uniform mat4 uView; +uniform mat4 uProjection; +uniform float uMorphTime; + +void main() +{ + vec3 pos = mix(vPos, vMorphTarget, uMorphTime); + gl_Position = uProjection * uView * vInstanceMatrix * vec4(pos, 1.0); +} diff --git a/FModel/Views/Snooper/FramebufferObject.cs b/FModel/Views/Snooper/FramebufferObject.cs index 0fba96d4..5d06f5b2 100644 --- a/FModel/Views/Snooper/FramebufferObject.cs +++ b/FModel/Views/Snooper/FramebufferObject.cs @@ -9,8 +9,8 @@ public class FramebufferObject : IDisposable private int _framebufferHandle; private int _postProcessingHandle; - private readonly int _width; - private readonly int _height; + private int _width; + private int _height; private readonly RenderbufferObject _renderbuffer; private BufferObject _ebo; @@ -43,7 +43,7 @@ public class FramebufferObject : IDisposable public void Setup() { _framebufferHandle = GL.GenFramebuffer(); - Bind(_framebufferHandle); + Bind(); _framebufferTexture = new Texture((uint) _width, (uint) _height); @@ -102,6 +102,17 @@ public class FramebufferObject : IDisposable public IntPtr GetPointer() => _postProcessingTexture.GetPointer(); + public void WindowResized(int width, int height) + { + _width = width; + _height = height; + + _renderbuffer.WindowResized(width, height); + + _framebufferTexture.WindowResized(width, height); + _postProcessingTexture.WindowResized(width, height); + } + public void Dispose() { _vao.Dispose(); diff --git a/FModel/Views/Snooper/Model.cs b/FModel/Views/Snooper/Model.cs index 747d1d85..4a56fd61 100644 --- a/FModel/Views/Snooper/Model.cs +++ b/FModel/Views/Snooper/Model.cs @@ -266,6 +266,17 @@ public class Model : IDisposable } } + public void SimpleRender(Shader shader) + { + _vao.Bind(); + shader.SetUniform("uMorphTime", MorphTime); + for (int section = 0; section < Sections.Length; section++) + { + Sections[section].Render(TransformsCount); + } + _vao.Unbind(); + } + public void Outline(Shader shader) { GL.StencilMask(0x00); diff --git a/FModel/Views/Snooper/PickingTexture.cs b/FModel/Views/Snooper/PickingTexture.cs new file mode 100644 index 00000000..5c2b1d3d --- /dev/null +++ b/FModel/Views/Snooper/PickingTexture.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using CUE4Parse.UE4.Objects.Core.Misc; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Mathematics; +using Vector2 = System.Numerics.Vector2; + +namespace FModel.Views.Snooper; + +public class PickingTexture : IDisposable +{ + private int _width; + private int _height; + + private int _framebufferHandle; + + private Shader _shader; + private int _pickingTexture; + private int _depthTexture; + + public PickingTexture(int width, int height) + { + _width = width; + _height = height; + } + + public void Setup() + { + _framebufferHandle = GL.GenFramebuffer(); + Bind(); + + _shader = new Shader("picking"); + + _pickingTexture = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, _pickingTexture); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32ui, _width, _height, 0, PixelFormat.RgbaInteger, PixelType.UnsignedInt, IntPtr.Zero); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Nearest); + GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Nearest); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, _pickingTexture, 0); + + _depthTexture = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, _depthTexture); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, _width, _height, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2D, _depthTexture, 0); + + var status = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer); + if (status != FramebufferErrorCode.FramebufferComplete) + { + throw new Exception($"Framebuffer failed to bind with error: {GL.GetProgramInfoLog(_framebufferHandle)}"); + } + + GL.BindTexture(TextureTarget.Texture2D, 0); + Bind(0); + } + + public void Render(Matrix4 viewMatrix, Matrix4 projMatrix, IDictionary models) + { + Bind(); + GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); + + _shader.Use(); + _shader.SetUniform("uView", viewMatrix); + _shader.SetUniform("uProjection", projMatrix); + + foreach ((FGuid guid, Model model) in models) + { + _shader.SetUniform("uA", guid.A); + _shader.SetUniform("uB", guid.B); + _shader.SetUniform("uC", guid.C); + _shader.SetUniform("uD", guid.D); + + if (!model.Show) continue; + model.SimpleRender(_shader); + } + + Bind(0); + } + + public void Bind() => Bind(_framebufferHandle); + public void Bind(int handle) + { + GL.BindFramebuffer(FramebufferTarget.Framebuffer, handle); + } + + public FGuid ReadPixel(Vector2 mousePos, Vector2 windowPos, Vector2 windowSize) + { + Bind(); + FGuid pixel = default; + + var scaleX = windowSize.X / _width; + var scaleY = windowSize.Y / _height; + var x = Convert.ToInt32((mousePos.X - windowPos.X) / scaleX); + var y = -Convert.ToInt32((mousePos.Y - windowPos.Y) / scaleY); + + GL.ReadBuffer(ReadBufferMode.ColorAttachment0); + GL.ReadPixels(x, y, 1, 1, PixelFormat.RgbaInteger, PixelType.UnsignedInt, ref pixel); + GL.ReadBuffer(ReadBufferMode.None); + + Bind(0); + return pixel; + } + + public void WindowResized(int width, int height) + { + _width = width; + _height = height; + + GL.BindTexture(TextureTarget.Texture2D, _pickingTexture); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba32ui, _width, _height, 0, PixelFormat.RgbaInteger, PixelType.UnsignedInt, IntPtr.Zero); + + GL.BindTexture(TextureTarget.Texture2D, _depthTexture); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.DepthComponent, _width, _height, 0, PixelFormat.DepthComponent, PixelType.Float, IntPtr.Zero); + } + + public void Dispose() + { + _shader?.Dispose(); + GL.DeleteTexture(_pickingTexture); + GL.DeleteTexture(_depthTexture); + GL.DeleteFramebuffer(_framebufferHandle); + } +} diff --git a/FModel/Views/Snooper/RenderbufferObject.cs b/FModel/Views/Snooper/RenderbufferObject.cs index 30fac53b..6ff1ceb4 100644 --- a/FModel/Views/Snooper/RenderbufferObject.cs +++ b/FModel/Views/Snooper/RenderbufferObject.cs @@ -7,8 +7,8 @@ public class RenderbufferObject : IDisposable { private int _handle; - private readonly int _width; - private readonly int _height; + private int _width; + private int _height; public RenderbufferObject(int width, int height) { @@ -25,6 +25,15 @@ public class RenderbufferObject : IDisposable GL.FramebufferRenderbuffer(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, RenderbufferTarget.Renderbuffer, _handle); } + public void WindowResized(int width, int height) + { + _width = width; + _height = height; + + GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, _handle); + GL.RenderbufferStorageMultisample(RenderbufferTarget.Renderbuffer, Constants.SAMPLES_COUNT, RenderbufferStorage.Depth24Stencil8, _width, _height); + } + public void Dispose() { GL.DeleteRenderbuffer(_handle); diff --git a/FModel/Views/Snooper/Renderer.cs b/FModel/Views/Snooper/Renderer.cs index 5919ecf8..65fa4fcc 100644 --- a/FModel/Views/Snooper/Renderer.cs +++ b/FModel/Views/Snooper/Renderer.cs @@ -22,11 +22,13 @@ public class Renderer : IDisposable private Vector3 _diffuseLight; private Vector3 _specularLight; + public PickingTexture Picking { get; } public Cache Cache { get; } public Options Settings { get; } - public Renderer() + public Renderer(int width, int height) { + Picking = new PickingTexture(width, height); Cache = new Cache(); Settings = new Options(); } @@ -60,6 +62,7 @@ public class Renderer : IDisposable _diffuseLight = new Vector3(0.75f); _specularLight = new Vector3(0.5f); + Picking.Setup(); Cache.Setup(); } @@ -85,6 +88,8 @@ public class Renderer : IDisposable Cache.Render(_shader); GL.Enable(EnableCap.StencilTest); Cache.Outline(_outline); + + Picking.Render(viewMatrix, projMatrix, Cache.Models); } private Camera SetupCamera(FBox box) @@ -222,6 +227,7 @@ public class Renderer : IDisposable { _shader.Dispose(); _outline.Dispose(); + Picking.Dispose(); Cache.Dispose(); } } diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs index 876ec978..1b6cab06 100644 --- a/FModel/Views/Snooper/SnimGui.cs +++ b/FModel/Views/Snooper/SnimGui.cs @@ -1,5 +1,4 @@ using System; -using System.Windows; using CUE4Parse.UE4.Objects.Core.Misc; using FModel.Framework; using ImGuiNET; @@ -449,15 +448,20 @@ public class SnimGui _viewportFocus = true; s.CursorState = CursorState.Grabbed; } + if (ImGui.IsMouseClicked(ImGuiMouseButton.Right)) + { + var guid = s.Renderer.Picking.ReadPixel(ImGui.GetMousePos(), ImGui.GetCursorScreenPos(), size); + s.Renderer.Settings.SelectModel(guid); + } } // this can't be inside IsItemHovered! read it as // if left mouse button was pressed while hovering the viewport // move camera until left mouse button is released // no matter where mouse position end up - var io = ImGui.GetIO(); if (ImGui.IsMouseDragging(ImGuiMouseButton.Left, lookSensitivity) && _viewportFocus) { + var io = ImGui.GetIO(); var delta = io.MouseDelta * lookSensitivity; s.Camera.ModifyDirection(delta.X, delta.Y); } diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs index ac8a616c..ec3a5dc2 100644 --- a/FModel/Views/Snooper/Snooper.cs +++ b/FModel/Views/Snooper/Snooper.cs @@ -13,7 +13,7 @@ namespace FModel.Views.Snooper; public class Snooper : GameWindow { public Camera Camera; - public FramebufferObject Framebuffer; + public readonly FramebufferObject Framebuffer; public readonly Renderer Renderer; private readonly Skybox _skybox; @@ -26,8 +26,8 @@ public class Snooper : GameWindow public Snooper(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) { - Framebuffer = new FramebufferObject(Size); - Renderer = new Renderer(); + Framebuffer = new FramebufferObject(ClientSize); + Renderer = new Renderer(ClientSize.X, ClientSize.Y); _skybox = new Skybox(); _grid = new Grid(); @@ -87,9 +87,10 @@ public class Snooper : GameWindow GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); Framebuffer.Setup(); + Renderer.Setup(); + _skybox.Setup(); _grid.Setup(); - Renderer.Setup(); _init = true; } @@ -177,9 +178,10 @@ public class Snooper : GameWindow GL.Viewport(0, 0, e.Width, e.Height); - Framebuffer = new FramebufferObject(e.Size); - Framebuffer.Setup(); Camera.AspectRatio = e.Width / (float) e.Height; + Framebuffer.WindowResized(e.Width, e.Height); + Renderer.Picking.WindowResized(e.Width, e.Height); + _gui.Controller.WindowResized(e.Width, e.Height); } @@ -187,9 +189,11 @@ public class Snooper : GameWindow { base.Dispose(disposing); + Framebuffer?.Dispose(); + Renderer?.Dispose(); + _skybox?.Dispose(); _grid?.Dispose(); - Renderer?.Dispose(); _gui?.Controller.Dispose(); } } diff --git a/FModel/Views/Snooper/Texture.cs b/FModel/Views/Snooper/Texture.cs index 1df8f377..44545e27 100644 --- a/FModel/Views/Snooper/Texture.cs +++ b/FModel/Views/Snooper/Texture.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Windows; using CUE4Parse.UE4.Assets.Exports.Texture; using OpenTK.Graphics.OpenGL4; @@ -12,6 +12,7 @@ public class Texture : IDisposable { private readonly int _handle; private readonly TextureType _type; + private readonly TextureTarget _target; public readonly string Type; public readonly string Name; @@ -19,14 +20,20 @@ public class Texture : IDisposable public readonly EPixelFormat Format; public readonly uint ImportedWidth; public readonly uint ImportedHeight; - public readonly int Width; - public readonly int Height; + public int Width; + public int Height; public string Label; public Texture(TextureType type) { _handle = GL.GenTexture(); _type = type; + _target = _type switch + { + TextureType.Cubemap => TextureTarget.TextureCubeMap, + TextureType.MsaaFramebuffer => TextureTarget.Texture2DMultisample, + _ => TextureTarget.Texture2D + }; Label = "(?) Click to Copy Path"; } @@ -38,12 +45,12 @@ public class Texture : IDisposable GL.TexImage2DMultisample(TextureTargetMultisample.Texture2DMultisample, Constants.SAMPLES_COUNT, PixelInternalFormat.Rgb, Width, Height, true); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Nearest); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Nearest); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToEdge); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Nearest); + GL.TexParameter(_target, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Nearest); + GL.TexParameter(_target, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToEdge); - GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2DMultisample, _handle, 0); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, _target, _handle, 0); } public Texture(int width, int height) : this(TextureType.Framebuffer) @@ -52,14 +59,14 @@ public class Texture : IDisposable Height = height; Bind(TextureUnit.Texture0); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, IntPtr.Zero); + GL.TexImage2D(_target, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, IntPtr.Zero); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToEdge); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Linear); + GL.TexParameter(_target, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear); + GL.TexParameter(_target, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToEdge); - GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, _handle, 0); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, _target, _handle, 0); } public Texture(byte[] data, int width, int height, UTexture2D texture2D) : this(TextureType.Normal) @@ -74,11 +81,11 @@ public class Texture : IDisposable Height = height; Bind(TextureUnit.Texture0); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBaseLevel, 0); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 8); + GL.TexImage2D(_target, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, data); + GL.TexParameter(_target, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear); + GL.TexParameter(_target, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear); + GL.TexParameter(_target, TextureParameterName.TextureBaseLevel, 0); + GL.TexParameter(_target, TextureParameterName.TextureMaxLevel, 8); GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } @@ -104,39 +111,34 @@ public class Texture : IDisposable }); } - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int) TextureWrapMode.ClampToEdge); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToEdge); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.Linear); + GL.TexParameter(_target, TextureParameterName.TextureMagFilter, (int) TextureMinFilter.Linear); + GL.TexParameter(_target, TextureParameterName.TextureWrapR, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToEdge); + GL.TexParameter(_target, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToEdge); } public Texture(uint width, uint height, IntPtr data) : this(TextureType.Normal) { Width = (int) width; Height = (int) height; - Bind(TextureTarget.Texture2D); + Bind(_target); GL.TexStorage2D(TextureTarget2d.Texture2D, 1, SizedInternalFormat.Rgba8, Width, Height); - GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, PixelFormat.Bgra, PixelType.UnsignedByte, data); + GL.TexSubImage2D(_target, 0, 0, 0, Width, Height, PixelFormat.Bgra, PixelType.UnsignedByte, data); var repeat = (int) TextureWrapMode.Repeat; - GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, ref repeat); - GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, ref repeat); + GL.TexParameterI(_target, TextureParameterName.TextureWrapS, ref repeat); + GL.TexParameterI(_target, TextureParameterName.TextureWrapT, ref repeat); var zero = 1 - 1; - GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, ref zero); + GL.TexParameterI(_target, TextureParameterName.TextureMaxLevel, ref zero); } public void Bind(TextureUnit textureSlot) { GL.ActiveTexture(textureSlot); - Bind(_type switch - { - TextureType.Cubemap => TextureTarget.TextureCubeMap, - TextureType.MsaaFramebuffer => TextureTarget.Texture2DMultisample, - _ => TextureTarget.Texture2D - }); + Bind(_target); } public void Bind(TextureTarget target) @@ -144,8 +146,34 @@ public class Texture : IDisposable GL.BindTexture(target, _handle); } + public void Bind() + { + GL.BindTexture(_target, _handle); + } + public IntPtr GetPointer() => (IntPtr) _handle; + public void WindowResized(int width, int height) + { + Width = width; + Height = height; + + Bind(); + switch (_type) + { + case TextureType.MsaaFramebuffer: + GL.TexImage2DMultisample(TextureTargetMultisample.Texture2DMultisample, Constants.SAMPLES_COUNT, PixelInternalFormat.Rgb, Width, Height, true); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, _target, _handle, 0); + break; + case TextureType.Framebuffer: + GL.TexImage2D(_target, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, IntPtr.Zero); + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, _target, _handle, 0); + break; + default: + throw new NotSupportedException(); + } + } + public void Dispose() { GL.DeleteTexture(_handle);