diff --git a/FModel/FModel.csproj b/FModel/FModel.csproj index 1d5c1898..94f23186 100644 --- a/FModel/FModel.csproj +++ b/FModel/FModel.csproj @@ -141,6 +141,7 @@ + diff --git a/FModel/ViewModels/CUE4ParseViewModel.cs b/FModel/ViewModels/CUE4ParseViewModel.cs index b766165d..9bb0edd6 100644 --- a/FModel/ViewModels/CUE4ParseViewModel.cs +++ b/FModel/ViewModels/CUE4ParseViewModel.cs @@ -757,7 +757,10 @@ public class CUE4ParseViewModel : ViewModel export.Owner.Name.EndsWith($"/RenderSwitch_Materials/{export.Name}", StringComparison.OrdinalIgnoreCase) || export.Owner.Name.EndsWith($"/MI_BPTile/{export.Name}", StringComparison.OrdinalIgnoreCase))): { - SnooperViewer.Run(cancellationToken, export); + Application.Current.Dispatcher.Invoke(delegate + { + SnooperViewer.Run(cancellationToken, export); + }); return true; } case UMaterialInstance m when ModelIsOverwritingMaterial: diff --git a/FModel/Views/Snooper/FWindow.cs b/FModel/Views/Snooper/FWindow.cs index 259f9137..f233e14e 100644 --- a/FModel/Views/Snooper/FWindow.cs +++ b/FModel/Views/Snooper/FWindow.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Numerics; using System.Threading; using CUE4Parse.UE4.Assets.Exports; using CUE4Parse.UE4.Assets.Exports.Material; @@ -13,7 +14,6 @@ using CUE4Parse.UE4.Objects.Engine; using CUE4Parse.UE4.Objects.UObject; using CUE4Parse_Conversion.Meshes; using OpenTK.Graphics.OpenGL4; -using OpenTK.Mathematics; using OpenTK.Windowing.Common; using OpenTK.Windowing.Desktop; using OpenTK.Windowing.GraphicsLibraryFramework; @@ -22,13 +22,11 @@ namespace FModel.Views.Snooper; public class FWindow : GameWindow { - private SnimGui _imGui; private Camera _camera; - private IMouse _mouse; private Image _icon; private Options _options; - private readonly FramebufferObject _framebuffer; + // private readonly FramebufferObject _framebuffer; private readonly Skybox _skybox; private readonly Grid _grid; @@ -43,7 +41,7 @@ public class FWindow : GameWindow public FWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings) { _options = new Options(); - _framebuffer = new FramebufferObject(Size); + // _framebuffer = new FramebufferObject(Size); _skybox = new Skybox(); _grid = new Grid(); _models = new Dictionary(); @@ -161,7 +159,7 @@ public class FWindow : GameWindow throw new ArgumentOutOfRangeException(nameof(export)); } - DoLoop(); + Run(); } public void SwapMaterial(UMaterialInstance mi) @@ -171,13 +169,12 @@ public class FWindow : GameWindow section.SwapMaterial(mi); _options.SwapMaterial(false); - DoLoop(); + Run(); } private void DoLoop() { if (_options.Append) _options.Append = false; - _window.Run(); // if (_window.IsInitialized) // { // if (!_window.GLContext.IsCurrent) @@ -223,24 +220,15 @@ public class FWindow : GameWindow protected override void OnLoad() { base.OnLoad(); + CenterWindow(); - _window.SetWindowIcon(ref _icon); - _window.Center(); + GL.Enable(EnableCap.Blend); + GL.Enable(EnableCap.DepthTest); + GL.Enable(EnableCap.Multisample); + GL.StencilOp(StencilOp.Keep, StencilOp.Replace, StencilOp.Replace); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - var input = _window.CreateInput(); - _keyboard = input.Keyboards[0]; - _mouse = input.Mice[0]; - - _gl = GL.GetApi(_window); - _gl.Enable(EnableCap.Blend); - _gl.Enable(EnableCap.DepthTest); - _gl.Enable(EnableCap.Multisample); - _gl.StencilOp(StencilOp.Keep, StencilOp.Replace, StencilOp.Replace); - _gl.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); - - _imGui = new SnimGui(_gl, _window, input); - - _framebuffer.Setup(); + // _framebuffer.Setup(); _skybox.Setup(); _grid.Setup(); @@ -258,12 +246,10 @@ public class FWindow : GameWindow { base.OnRenderFrame(args); - _imGui.Update((float) args.Time); - ClearWhatHasBeenDrawn(); // in main window - _framebuffer.Bind(); // switch to dedicated window - ClearWhatHasBeenDrawn(); // in dedicated window + // _framebuffer.Bind(); // switch to dedicated window + // ClearWhatHasBeenDrawn(); // in dedicated window _skybox.Bind(_camera); _grid.Bind(_camera); @@ -300,20 +286,16 @@ public class FWindow : GameWindow model.Outline(_outline); } - _imGui.Construct(ref _options, _size, _framebuffer, _camera, _mouse, _models); - - _framebuffer.BindMsaa(); - _framebuffer.Bind(0); // switch back to main window - _framebuffer.BindStuff(); - - _imGui.Render(); // render ImGui in main window + // _framebuffer.BindMsaa(); + // _framebuffer.Bind(0); // switch back to main window + // _framebuffer.BindStuff(); SwapBuffers(); } private void ClearWhatHasBeenDrawn() { - GL.ClearColor(1.0f, 0.102f, 0.129f, 1.0f); + GL.ClearColor(1.0f, 0f, 0f, 1.0f); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); } @@ -321,28 +303,32 @@ public class FWindow : GameWindow protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); - if (!IsFocused || ImGui.GetIO().WantTextInput) + if (!IsFocused) return; - var multiplier = KeyboardState.IsKeyPressed(Keys.LeftShift) ? 2f : 1f; + var multiplier = KeyboardState.IsKeyDown(Keys.LeftShift) ? 2f : 1f; var moveSpeed = _camera.Speed * multiplier * (float) e.Time; - if (KeyboardState.IsKeyPressed(Keys.W)) + if (KeyboardState.IsKeyDown(Keys.W)) _camera.Position += moveSpeed * _camera.Direction; - if (KeyboardState.IsKeyPressed(Keys.S)) + if (KeyboardState.IsKeyDown(Keys.S)) _camera.Position -= moveSpeed * _camera.Direction; - if (KeyboardState.IsKeyPressed(Keys.A)) + if (KeyboardState.IsKeyDown(Keys.A)) _camera.Position -= Vector3.Normalize(Vector3.Cross(_camera.Direction, _camera.Up)) * moveSpeed; - if (KeyboardState.IsKeyPressed(Keys.D)) + if (KeyboardState.IsKeyDown(Keys.D)) _camera.Position += Vector3.Normalize(Vector3.Cross(_camera.Direction, _camera.Up)) * moveSpeed; - if (KeyboardState.IsKeyPressed(Keys.E)) + if (KeyboardState.IsKeyDown(Keys.E)) _camera.Position += moveSpeed * _camera.Up; - if (KeyboardState.IsKeyPressed(Keys.Q)) + if (KeyboardState.IsKeyDown(Keys.Q)) _camera.Position -= moveSpeed * _camera.Up; - if (KeyboardState.IsKeyPressed(Keys.X)) + if (KeyboardState.IsKeyDown(Keys.X)) _camera.ModifyZoom(-.5f); - if (KeyboardState.IsKeyPressed(Keys.C)) + if (KeyboardState.IsKeyDown(Keys.C)) _camera.ModifyZoom(+.5f); + const float lookSensitivity = 0.1f; + var delta = MouseState.Delta * lookSensitivity; + _camera.ModifyDirection(delta.X, delta.Y); + if (KeyboardState.IsKeyPressed(Keys.H)) IsVisible = false; if (KeyboardState.IsKeyPressed(Keys.Escape)) @@ -351,7 +337,7 @@ public class FWindow : GameWindow private void OnClose() { - _framebuffer.Dispose(); + // _framebuffer.Dispose(); _grid.Dispose(); _skybox.Dispose(); _shader.Dispose(); @@ -366,9 +352,6 @@ public class FWindow : GameWindow _options.Reset(); _previousSpeed = 0f; } - _imGui.Dispose(); - _window.Dispose(); - _gl.Dispose(); } protected override void OnResize(ResizeEventArgs e) @@ -376,6 +359,6 @@ public class FWindow : GameWindow base.OnResize(e); GL.Viewport(0, 0, Size.X, Size.Y); - _camera.AspectRatio = Size.X / (float)Size.Y; + // _camera.AspectRatio = Size.X / (float)Size.Y; } } diff --git a/FModel/Views/Snooper/SnimGui.cs b/FModel/Views/Snooper/SnimGui.cs deleted file mode 100644 index 17457ff2..00000000 --- a/FModel/Views/Snooper/SnimGui.cs +++ /dev/null @@ -1,559 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Numerics; -using System.Windows; -using CUE4Parse.UE4.Objects.Core.Misc; -using FModel.Creator; -using ImGuiNET; -using Silk.NET.Input; -using Silk.NET.Maths; -using Silk.NET.OpenGL; -using Silk.NET.OpenGL.Extensions.ImGui; -using Silk.NET.Windowing; - -namespace FModel.Views.Snooper; - -public class SnimGui : IDisposable -{ - private readonly ImGuiController _controller; - private readonly GraphicsAPI _api; - private readonly string _renderer; - - private readonly Vector4 _xAxis = new (1.0f, 0.102f, 0.129f, 1.0f); - private readonly Vector4 _yAxis = new (0.102f, 0.102f, 1.0f, 1.0f); - private readonly Vector4 _zAxis = new (0.102f, 0.102f, 0.129f, 1.0f); - - private readonly Vector2 _outlinerSize; - private readonly Vector2 _outlinerPosition; - private readonly Vector2 _propertiesSize; - private readonly Vector2 _propertiesPosition; - private readonly Vector2 _viewportSize; - private readonly Vector2 _viewportPosition; - private readonly Vector2 _textureSize; - private readonly Vector2 _texturePosition; - private bool _viewportFocus; - - private const ImGuiWindowFlags _noResize = ImGuiWindowFlags.NoResize | ImGuiWindowFlags.NoMove; // delete once we have a proper docking branch - private const ImGuiCond _firstUse = ImGuiCond.Appearing; // switch to FirstUseEver once the docking branch will not be useful anymore... - private const uint _dockspaceId = 1337; - - public SnimGui(GL gl, IWindow window, IInputContext input) - { - var fontConfig = new ImGuiFontConfig("C:\\Windows\\Fonts\\segoeui.ttf", 16); - _controller = new ImGuiController(gl, window, input, fontConfig); - _api = window.API; - _renderer = gl.GetStringS(StringName.Renderer); - - var style = ImGui.GetStyle(); - var viewport = ImGui.GetMainViewport(); - var titleBarHeight = ImGui.GetFontSize() + style.FramePadding.Y * 2; - - _outlinerSize = new Vector2(400, 300); - _outlinerPosition = new Vector2(viewport.WorkSize.X - _outlinerSize.X, titleBarHeight); - _propertiesSize = _outlinerSize with { Y = viewport.WorkSize.Y - _outlinerSize.Y - titleBarHeight }; - _propertiesPosition = new Vector2(viewport.WorkSize.X - _propertiesSize.X, _outlinerPosition.Y + _outlinerSize.Y); - _viewportSize = _outlinerPosition with { Y = viewport.WorkSize.Y - titleBarHeight - 150 }; - _viewportPosition = new Vector2(0, titleBarHeight); - _textureSize = _viewportSize with { Y = viewport.WorkSize.Y - _viewportSize.Y - titleBarHeight }; - _texturePosition = new Vector2(0, _viewportPosition.Y + _viewportSize.Y); - - Theme(style); - } - - public void Construct(ref Options options, Vector2D size, FramebufferObject framebuffer, Camera camera, IMouse mouse, IDictionary models) - { - DrawDockSpace(size); - DrawNavbar(); - - DrawOuliner(ref options, camera, models); - DrawProperties(ref options, camera, models); - DrawTextures(ref options, models); - Draw3DViewport(framebuffer, camera, mouse); - } - - /// - /// absolutely useless at the moment since ImGui.NET lacks DockerBuilder bindinds - /// - private void DrawDockSpace(Vector2D size) - { - const ImGuiWindowFlags flags = - ImGuiWindowFlags.MenuBar | ImGuiWindowFlags.NoDocking | - ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoResize | - ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoMove | - ImGuiWindowFlags.NoBringToFrontOnFocus | ImGuiWindowFlags.NoNavFocus; - - ImGui.SetNextWindowPos(new Vector2(0, 0)); - ImGui.SetNextWindowSize(new Vector2(size.X, size.Y)); - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); - ImGui.Begin("Snooper", flags); - ImGui.PopStyleVar(); - ImGui.DockSpace(_dockspaceId); - } - - private void DrawNavbar() - { - if (!ImGui.BeginMainMenuBar()) return; - - if (ImGui.BeginMenu("Window")) - { - ImGui.MenuItem("Append", "H"); - ImGui.MenuItem("Close", "ESC"); - ImGui.EndMenu(); - } - if (ImGui.BeginMenu("Edit")) - { - if (ImGui.MenuItem("Undo", "CTRL+Z")) {} - if (ImGui.MenuItem("Redo", "CTRL+Y", false, false)) {} // Disabled item - ImGui.Separator(); - if (ImGui.MenuItem("Cut", "CTRL+X")) {} - if (ImGui.MenuItem("Copy", "CTRL+C")) {} - if (ImGui.MenuItem("Paste", "CTRL+V")) {} - ImGui.EndMenu(); - } - - const string text = "Press ESC to Exit..."; - ImGui.SetCursorPosX(ImGui.GetWindowViewport().WorkSize.X - ImGui.CalcTextSize(text).X - 5); - ImGui.TextColored(new Vector4(0.36f, 0.42f, 0.47f, 1.00f), text); // ImGuiCol.TextDisabled - - ImGui.EndMainMenuBar(); - } - - private void DrawOuliner(ref Options options, Camera camera, IDictionary models) - { - ImGui.SetNextWindowSize(_outlinerSize, _firstUse); - ImGui.SetNextWindowPos(_outlinerPosition, _firstUse); - ImGui.Begin("Scene Hierarchy", _noResize | ImGuiWindowFlags.NoCollapse); - - ImGui.Text("hello world!"); - ImGui.Spacing(); - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.CollapsingHeader("Collection")) - { - if (ImGui.BeginListBox("", new Vector2(ImGui.GetContentRegionAvail().X, _outlinerSize.Y / 2))) - { - var i = 0; - foreach (var (guid, model) in models) - { - ImGui.PushID(i); - model.IsSelected = options.SelectedModel == guid; - if (ImGui.Selectable(model.Name, model.IsSelected)) - { - options.SelectModel(guid); - } - if (ImGui.BeginPopupContextItem()) - { - options.SelectModel(guid); - if (ImGui.Selectable("Deselect")) - options.SelectModel(Guid.Empty); - if (ImGui.Selectable("Delete")) - models.Remove(guid); - if (ImGui.Selectable("Copy Name to Clipboard")) - Application.Current.Dispatcher.Invoke(delegate - { - Clipboard.SetText(model.Name); - }); - ImGui.EndPopup(); - } - ImGui.PopID(); - i++; - } - ImGui.EndListBox(); - } - } - - if (ImGui.CollapsingHeader("Camera")) - { - PushStyleCompact(); - string[] modes = { "free cam", "orbital cam" }; - int selectedMode = 0; - ImGui.Combo("Projection", ref selectedMode, modes, modes.Length); - ImGui.DragFloat3("Position", ref camera.Position); - ImGui.DragFloat3("Direction", ref camera.Direction); - ImGui.DragFloat("Speed", ref camera.Speed, 0.01f); - ImGui.DragFloat("Zoom", ref camera.Zoom); - PopStyleCompact(); - } - - ImGui.End(); - } - - private void DrawProperties(ref Options options, Camera camera, IDictionary models) - { - ImGui.SetNextWindowSize(_propertiesSize, _firstUse); - ImGui.SetNextWindowPos(_propertiesPosition, _firstUse); - ImGui.Begin("Properties", _noResize | ImGuiWindowFlags.NoCollapse); - if (!models.TryGetValue(options.SelectedModel, out var model)) - return; - - ImGui.Text($"Entity: ({model.Type}) {model.Name}"); - ImGui.Text($"Guid: {options.SelectedModel.ToString(EGuidFormats.UniqueObjectGuid)}"); - PushStyleCompact(); - ImGui.Columns(4, "Actions", false); - if (ImGui.Button("Go To")) camera.Position = model.Transforms[options.SelectedModelInstance].Position; - ImGui.NextColumn(); ImGui.Checkbox("Show", ref model.Show); - ImGui.NextColumn(); ImGui.BeginDisabled(!model.HasVertexColors); ImGui.Checkbox("Colors", ref model.DisplayVertexColors); ImGui.EndDisabled(); - ImGui.NextColumn(); ImGui.BeginDisabled(!model.HasBones); ImGui.Checkbox("Bones", ref model.DisplayBones); ImGui.EndDisabled(); - ImGui.Columns(1); - PopStyleCompact(); - - ImGui.Separator(); - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.BeginTabBar("properties_tab_bar", ImGuiTabBarFlags.None)) - { - if (ImGui.BeginTabItem("Transform")) - { - const int width = 100; - var speed = camera.Speed / 100; - - PushStyleCompact(); - ImGui.PushID(0); ImGui.BeginDisabled(model.TransformsCount < 2); - ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); - ImGui.SliderInt("", ref options.SelectedModelInstance, 0, model.TransformsCount - 1, "Instance %i", ImGuiSliderFlags.AlwaysClamp); - ImGui.EndDisabled(); ImGui.PopID(); - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.TreeNode("Location")) - { - ImGui.PushID(1); - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("X", ref model.Transforms[options.SelectedModelInstance].Position.X, speed, 0f, 0f, "%.2f m"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Y", ref model.Transforms[options.SelectedModelInstance].Position.Y, speed, 0f, 0f, "%.2f m"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Z", ref model.Transforms[options.SelectedModelInstance].Position.Z, speed, 0f, 0f, "%.2f m"); - - ImGui.PopID(); - ImGui.TreePop(); - } - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.TreeNode("Rotation")) - { - ImGui.PushID(2); - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("X", ref model.Transforms[options.SelectedModelInstance].Rotation.Pitch, .5f, 0f, 0f, "%.1f°"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Y", ref model.Transforms[options.SelectedModelInstance].Rotation.Roll, .5f, 0f, 0f, "%.1f°"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Z", ref model.Transforms[options.SelectedModelInstance].Rotation.Yaw, .5f, 0f, 0f, "%.1f°"); - - ImGui.PopID(); - ImGui.TreePop(); - } - - ImGui.SetNextItemOpen(true, ImGuiCond.Appearing); - if (ImGui.TreeNode("Scale")) - { - ImGui.PushID(3); - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("X", ref model.Transforms[options.SelectedModelInstance].Scale.X, speed, 0f, 0f, "%.3f"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Y", ref model.Transforms[options.SelectedModelInstance].Scale.Y, speed, 0f, 0f, "%.3f"); - - ImGui.SetNextItemWidth(width); - ImGui.DragFloat("Z", ref model.Transforms[options.SelectedModelInstance].Scale.Z, speed, 0f, 0f, "%.3f"); - - ImGui.PopID(); - ImGui.TreePop(); - } - - model.UpdateMatrix(options.SelectedModelInstance); - PopStyleCompact(); - ImGui.EndTabItem(); - } - - if (ImGui.BeginTabItem("Materials")) - { - PushStyleCompact(); - ImGui.BeginTable("Sections", 2, ImGuiTableFlags.Borders | ImGuiTableFlags.Resizable); - ImGui.TableSetupColumn("Index", ImGuiTableColumnFlags.NoHeaderWidth | ImGuiTableColumnFlags.WidthFixed); - ImGui.TableSetupColumn("Name"); - ImGui.TableHeadersRow(); - for (var i = 0; i < model.Sections.Length; i++) - { - var section = model.Sections[i]; - - ImGui.PushID(i); - ImGui.TableNextRow(); - ImGui.TableNextColumn(); - if (!section.Show) - ImGui.TableSetBgColor(ImGuiTableBgTarget.RowBg0, ImGui.GetColorU32(new Vector4(1, 0, 0, .5f))); - ImGui.Text(section.Index.ToString("D")); - ImGui.TableNextColumn(); - if (ImGui.Selectable(section.Name, options.SelectedSection == i, ImGuiSelectableFlags.SpanAllColumns)) - options.SelectSection(i); - if (ImGui.BeginPopupContextItem()) - { - options.SelectSection(i); - if (ImGui.Selectable("Swap")) - options.SwapMaterial(true); - if (ImGui.Selectable("Copy Name to Clipboard")) - Application.Current.Dispatcher.Invoke(delegate - { - Clipboard.SetText(section.Name); - }); - ImGui.EndPopup(); - } - ImGui.PopID(); - } - ImGui.EndTable(); - PopStyleCompact(); - ImGui.EndTabItem(); - } - - if (model.HasMorphTargets && ImGui.BeginTabItem("Morph Targets")) - { - PushStyleCompact(); - if (ImGui.BeginListBox("", new Vector2(ImGui.GetContentRegionAvail().X, _propertiesSize.Y / 2))) - { - for (int i = 0; i < model.Morphs.Length; i++) - { - ImGui.PushID(i); - if (ImGui.Selectable(model.Morphs[i].Name, options.SelectedMorph == i)) - options.SelectMorph(i, model); - ImGui.PopID(); - } - ImGui.EndListBox(); - ImGui.Separator(); - ImGui.DragFloat("Value", ref model.MorphTime, 0.01f, 0.0f, 1.0f, "%.2f", ImGuiSliderFlags.AlwaysClamp); - } - PopStyleCompact(); - ImGui.EndTabItem(); - } - } - - ImGui.End(); - } - - private void DrawTextures(ref Options options, IDictionary models) - { - ImGui.SetNextWindowSize(_textureSize, _firstUse); - ImGui.SetNextWindowPos(_texturePosition, _firstUse); - ImGui.Begin("Textures", _noResize | ImGuiWindowFlags.NoCollapse); - if (!models.TryGetValue(options.SelectedModel, out var model) || - !options.TryGetSection(model, out var section)) - return; - - PushStyleCompact(); ImGui.BeginGroup(); - ImGui.Checkbox("Show", ref section.Show); - ImGui.Checkbox("Wireframe", ref section.Wireframe); - ImGui.SetNextItemWidth(50); ImGui.DragFloat("Metallic", ref section.Parameters.MetallicValue, 0.01f, 0.0f, 1.0f, "%.2f"); - ImGui.SetNextItemWidth(50); ImGui.DragFloat("Roughness", ref section.Parameters.RoughnessValue, 0.01f, 0.0f, 1.0f, "%.2f"); - ImGui.EndGroup(); PopStyleCompact(); ImGui.SameLine(); ImGui.BeginGroup(); - if (section.HasDiffuseColor) - { - ImGui.SetNextItemWidth(300); - ImGui.ColorEdit4(section.TexturesLabels[0], ref section.DiffuseColor, ImGuiColorEditFlags.AlphaPreview | ImGuiColorEditFlags.AlphaBar); - if (section.Textures[1] is { } normalMap) DrawTexture(normalMap, "Normal"); - } - else - { - for (var i = 0;i < section.Textures.Length; i++) - { - if (section.Textures[i] is not {} texture) - continue; - - DrawTexture(texture, section.TexturesLabels[i]); - - if (i == 3) // emissive, show color - { - ImGui.SameLine(); - ImGui.SetNextItemWidth(300); - ImGui.ColorEdit4($"{section.TexturesLabels[i]} Color", ref section.EmissionColor, ImGuiColorEditFlags.NoAlpha); - } - } - } - ImGui.EndGroup(); - - ImGui.End(); - } - - private void DrawTexture(Texture texture, string label) - { - ImGui.SameLine(); - ImGui.BeginGroup(); - ImGui.Image(texture.GetPointer(), new Vector2(88), Vector2.Zero, Vector2.One, Vector4.One, new Vector4(1, 1, 1, .5f)); - if (ImGui.IsItemHovered()) - { - ImGui.BeginTooltip(); - ImGui.Text($"Type: ({texture.Format}) {texture.Type}:{texture.Name}"); - ImGui.Text($"Texture: {texture.Path}"); - ImGui.Text($"Imported: {texture.ImportedWidth}x{texture.ImportedHeight}"); - ImGui.Text($"Mip Used: {texture.Width}x{texture.Height}"); - ImGui.Spacing(); - ImGui.TextDisabled(texture.Label); - ImGui.EndTooltip(); - } - - if (ImGui.IsItemClicked()) - { - Application.Current.Dispatcher.Invoke(delegate - { - Clipboard.SetText(Utils.FixPath(texture.Path)); - texture.Label = "(?) Path Copied to Clipboard"; - }); - } - - var width = ImGui.GetCursorPos().X; - ImGui.SetCursorPosX(width + ImGui.CalcTextSize(label).X * 0.5f); - ImGui.Text(label); - ImGui.EndGroup(); - } - - private void Draw3DViewport(FramebufferObject framebuffer, Camera camera, IMouse mouse) - { - const float lookSensitivity = 0.1f; - const ImGuiWindowFlags flags = - ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse | - ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.AlwaysUseWindowPadding; - - ImGui.SetNextWindowSize(_viewportSize, _firstUse); - ImGui.SetNextWindowPos(_viewportPosition, _firstUse); - ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, Vector2.Zero); - ImGui.Begin($"Viewport ({_api.API} {_api.Version.MajorVersion}.{_api.Version.MinorVersion}) ({_renderer})", _noResize | flags); - ImGui.PopStyleVar(); - - var largest = ImGui.GetContentRegionAvail(); - largest.X -= ImGui.GetScrollX(); - largest.Y -= ImGui.GetScrollY(); - - var width = largest.X; - var height = width / camera.AspectRatio; - if (height > largest.Y) - { - height = largest.Y; - width = height * camera.AspectRatio; - } - - var pos = new Vector2(largest.X / 2f - width / 2f + ImGui.GetCursorPosX(), largest.Y / 2f - height / 2f + ImGui.GetCursorPosY()); - var size = new Vector2(width, height); - ImGui.SetCursorPos(pos); - ImGui.ImageButton(framebuffer.GetPointer(), size, new Vector2(0, 1), new Vector2(1, 0), 0); - - // it took me 5 hours to make it work, don't change any of the following code - // basically the Raw cursor doesn't actually freeze the mouse position - // so for ImGui, the IsItemHovered will be false if mouse leave, even in Raw mode - var io = ImGui.GetIO(); - if (ImGui.IsItemHovered()) - { - // if right button down while mouse is hover viewport - if (ImGui.IsMouseDown(ImGuiMouseButton.Right) && !_viewportFocus) - _viewportFocus = true; - } - - // this can't be inside IsItemHovered! read it as - // if right mouse button was pressed while hovering the viewport - // move camera until right mouse button is released - // no matter where mouse position end up - if (ImGui.IsMouseDragging(ImGuiMouseButton.Right, lookSensitivity) && _viewportFocus) - { - var delta = io.MouseDelta * lookSensitivity; - camera.ModifyDirection(delta.X, delta.Y); - mouse.Cursor.CursorMode = CursorMode.Raw; - } - - // if left button up and mouse was in viewport - if (ImGui.IsMouseReleased(ImGuiMouseButton.Right) && _viewportFocus) - { - _viewportFocus = false; - mouse.Cursor.CursorMode = CursorMode.Normal; - } - - const float padding = 5f; - float framerate = ImGui.GetIO().Framerate; - var text = $"FPS: {framerate:0} ({1000.0f / framerate:0.##} ms)"; - ImGui.SetCursorPos(new Vector2(pos.X + padding, pos.Y + size.Y - ImGui.CalcTextSize(text).Y - padding)); - ImGui.Text(text); - - ImGui.End(); - } - - private void PushStyleCompact() - { - var style = ImGui.GetStyle(); - ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, style.FramePadding with { Y = style.FramePadding.Y * 0.6f }); - ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, style.ItemSpacing with { Y = style.ItemSpacing.Y * 0.6f }); - } - - private void PopStyleCompact() => ImGui.PopStyleVar(2); - - private void Theme(ImGuiStylePtr style) - { - var io = ImGui.GetIO(); - io.ConfigFlags |= ImGuiConfigFlags.DockingEnable; - io.ConfigFlags |= ImGuiConfigFlags.ViewportsEnable; - io.ConfigWindowsMoveFromTitleBarOnly = true; - io.ConfigDockingWithShift = true; - - style.WindowMenuButtonPosition = ImGuiDir.Right; - style.ScrollbarSize = 10f; - style.FrameRounding = 3.0f; - - style.Colors[(int) ImGuiCol.Text] = new Vector4(1.00f, 1.00f, 1.00f, 1.00f); - style.Colors[(int) ImGuiCol.TextDisabled] = new Vector4(0.50f, 0.50f, 0.50f, 1.00f); - style.Colors[(int) ImGuiCol.WindowBg] = new Vector4(0.11f, 0.11f, 0.12f, 1.00f); - style.Colors[(int) ImGuiCol.ChildBg] = new Vector4(0.15f, 0.15f, 0.19f, 1.00f); - style.Colors[(int) ImGuiCol.PopupBg] = new Vector4(0.08f, 0.08f, 0.08f, 0.94f); - style.Colors[(int) ImGuiCol.Border] = new Vector4(0.25f, 0.26f, 0.33f, 1.00f); - style.Colors[(int) ImGuiCol.BorderShadow] = new Vector4(0.00f, 0.00f, 0.00f, 0.00f); - style.Colors[(int) ImGuiCol.FrameBg] = new Vector4(0.05f, 0.05f, 0.05f, 0.54f); - style.Colors[(int) ImGuiCol.FrameBgHovered] = new Vector4(0.69f, 0.69f, 1.00f, 0.20f); - style.Colors[(int) ImGuiCol.FrameBgActive] = new Vector4(0.69f, 0.69f, 1.00f, 0.39f); - style.Colors[(int) ImGuiCol.TitleBg] = new Vector4(0.09f, 0.09f, 0.09f, 1.00f); - style.Colors[(int) ImGuiCol.TitleBgActive] = new Vector4(0.09f, 0.09f, 0.09f, 1.00f); - style.Colors[(int) ImGuiCol.TitleBgCollapsed] = new Vector4(0.05f, 0.05f, 0.05f, 0.51f); - style.Colors[(int) ImGuiCol.MenuBarBg] = new Vector4(0.14f, 0.14f, 0.14f, 1.00f); - style.Colors[(int) ImGuiCol.ScrollbarBg] = new Vector4(0.02f, 0.02f, 0.02f, 0.53f); - style.Colors[(int) ImGuiCol.ScrollbarGrab] = new Vector4(0.31f, 0.31f, 0.31f, 1.00f); - style.Colors[(int) ImGuiCol.ScrollbarGrabHovered] = new Vector4(0.41f, 0.41f, 0.41f, 1.00f); - style.Colors[(int) ImGuiCol.ScrollbarGrabActive] = new Vector4(0.51f, 0.51f, 0.51f, 1.00f); - style.Colors[(int) ImGuiCol.CheckMark] = new Vector4(0.13f, 0.42f, 0.83f, 1.00f); - style.Colors[(int) ImGuiCol.SliderGrab] = new Vector4(0.13f, 0.42f, 0.83f, 0.78f); - style.Colors[(int) ImGuiCol.SliderGrabActive] = new Vector4(0.13f, 0.42f, 0.83f, 1.00f); - style.Colors[(int) ImGuiCol.Button] = new Vector4(0.05f, 0.05f, 0.05f, 0.54f); - style.Colors[(int) ImGuiCol.ButtonHovered] = new Vector4(0.69f, 0.69f, 1.00f, 0.20f); - style.Colors[(int) ImGuiCol.ButtonActive] = new Vector4(0.69f, 0.69f, 1.00f, 0.39f); - style.Colors[(int) ImGuiCol.Header] = new Vector4(0.16f, 0.16f, 0.21f, 1.00f); - style.Colors[(int) ImGuiCol.HeaderHovered] = new Vector4(0.69f, 0.69f, 1.00f, 0.20f); - style.Colors[(int) ImGuiCol.HeaderActive] = new Vector4(0.69f, 0.69f, 1.00f, 0.39f); - style.Colors[(int) ImGuiCol.Separator] = new Vector4(0.43f, 0.43f, 0.50f, 0.50f); - style.Colors[(int) ImGuiCol.SeparatorHovered] = new Vector4(0.10f, 0.40f, 0.75f, 0.78f); - style.Colors[(int) ImGuiCol.SeparatorActive] = new Vector4(0.10f, 0.40f, 0.75f, 1.00f); - style.Colors[(int) ImGuiCol.ResizeGrip] = new Vector4(0.13f, 0.42f, 0.83f, 0.39f); - style.Colors[(int) ImGuiCol.ResizeGripHovered] = new Vector4(0.12f, 0.41f, 0.81f, 0.78f); - style.Colors[(int) ImGuiCol.ResizeGripActive] = new Vector4(0.12f, 0.41f, 0.81f, 1.00f); - style.Colors[(int) ImGuiCol.Tab] = new Vector4(0.15f, 0.15f, 0.19f, 1.00f); - style.Colors[(int) ImGuiCol.TabHovered] = new Vector4(0.35f, 0.35f, 0.41f, 0.80f); - style.Colors[(int) ImGuiCol.TabActive] = new Vector4(0.23f, 0.24f, 0.29f, 1.00f); - style.Colors[(int) ImGuiCol.TabUnfocused] = new Vector4(0.15f, 0.15f, 0.15f, 1.00f); - style.Colors[(int) ImGuiCol.TabUnfocusedActive] = new Vector4(0.14f, 0.26f, 0.42f, 1.00f); - style.Colors[(int) ImGuiCol.DockingPreview] = new Vector4(0.26f, 0.59f, 0.98f, 0.70f); - style.Colors[(int) ImGuiCol.DockingEmptyBg] = new Vector4(0.20f, 0.20f, 0.20f, 1.00f); - style.Colors[(int) ImGuiCol.PlotLines] = new Vector4(0.61f, 0.61f, 0.61f, 1.00f); - style.Colors[(int) ImGuiCol.PlotLinesHovered] = new Vector4(1.00f, 0.43f, 0.35f, 1.00f); - style.Colors[(int) ImGuiCol.PlotHistogram] = new Vector4(0.90f, 0.70f, 0.00f, 1.00f); - style.Colors[(int) ImGuiCol.PlotHistogramHovered] = new Vector4(1.00f, 0.60f, 0.00f, 1.00f); - style.Colors[(int) ImGuiCol.TableHeaderBg] = new Vector4(0.09f, 0.09f, 0.09f, 1.00f); - style.Colors[(int) ImGuiCol.TableBorderStrong] = new Vector4(0.69f, 0.69f, 1.00f, 0.20f); - style.Colors[(int) ImGuiCol.TableBorderLight] = new Vector4(0.69f, 0.69f, 1.00f, 0.20f); - style.Colors[(int) ImGuiCol.TableRowBg] = new Vector4(0.00f, 0.00f, 0.00f, 0.00f); - style.Colors[(int) ImGuiCol.TableRowBgAlt] = new Vector4(1.00f, 1.00f, 1.00f, 0.06f); - style.Colors[(int) ImGuiCol.TextSelectedBg] = new Vector4(0.26f, 0.59f, 0.98f, 0.35f); - style.Colors[(int) ImGuiCol.DragDropTarget] = new Vector4(1.00f, 1.00f, 0.00f, 0.90f); - style.Colors[(int) ImGuiCol.NavHighlight] = new Vector4(0.26f, 0.59f, 0.98f, 1.00f); - style.Colors[(int) ImGuiCol.NavWindowingHighlight] = new Vector4(1.00f, 1.00f, 1.00f, 0.70f); - style.Colors[(int) ImGuiCol.NavWindowingDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.20f); - style.Colors[(int) ImGuiCol.ModalWindowDimBg] = new Vector4(0.80f, 0.80f, 0.80f, 0.35f); - } - - public void Update(float deltaTime) => _controller.Update(deltaTime); - public void Render() => _controller.Render(); - public void Dispose() => _controller.Dispose(); -} diff --git a/FModel/Views/Snooper/Snooper.cs b/FModel/Views/Snooper/Snooper.cs index 44976058..11bfb3d2 100644 --- a/FModel/Views/Snooper/Snooper.cs +++ b/FModel/Views/Snooper/Snooper.cs @@ -31,7 +31,7 @@ public class Snooper public void Run(CancellationToken cancellationToken, UObject export) { - _window.Run(); + _window.Run(cancellationToken, export); } public void SwapMaterial(UMaterialInstance mi) diff --git a/FModel/Views/Snooper/Texture.cs b/FModel/Views/Snooper/Texture.cs index e87899e5..8776eff8 100644 --- a/FModel/Views/Snooper/Texture.cs +++ b/FModel/Views/Snooper/Texture.cs @@ -2,6 +2,8 @@ using System.Windows; using CUE4Parse.UE4.Assets.Exports.Texture; using OpenTK.Graphics.OpenGL4; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; using SkiaSharp; namespace FModel.Views.Snooper; @@ -30,16 +32,16 @@ public class Texture : IDisposable public Texture(uint width, uint height) : this(TextureType.MsaaFramebuffer) { - Width = width; - Height = height; + Width = (int) width; + Height = (int) height; Bind(TextureUnit.Texture0); GL.TexImage2DMultisample(TextureTargetMultisample.Texture2DMultisample, Constants.SAMPLES_COUNT, PixelInternalFormat.Rgb, Width, Height, true); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureMinFilter, (int) GLEnum.Nearest); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureMagFilter, (int) GLEnum.Nearest); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureWrapS, (int) GLEnum.ClampToEdge); - GL.TexParameter(TextureTarget.Texture2DMultisample, TextureParameterName.TextureWrapT, (int) GLEnum.ClampToEdge); + 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.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2DMultisample, _handle, 0); } @@ -50,12 +52,12 @@ public class Texture : IDisposable Height = height; Bind(TextureUnit.Texture0); - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, null); + GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgb, PixelType.UnsignedByte, IntPtr.Zero); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) GLEnum.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) GLEnum.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) GLEnum.ClampToEdge); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) GLEnum.ClampToEdge); + 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.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, _handle, 0); } @@ -68,20 +70,17 @@ public class Texture : IDisposable Format = texture2D.Format; ImportedWidth = texture2D.ImportedSize.X; ImportedHeight = texture2D.ImportedSize.Y; - Width = width; - Height = height; + Width = (int) width; + Height = (int) height; Bind(TextureUnit.Texture0); - fixed (void* d = &data[0]) - { - GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgb, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, d); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) GLEnum.LinearMipmapLinear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) GLEnum.Linear); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBaseLevel, 0); - GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 8); + 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.GenerateMipmap(GenerateMipmapTarget.Texture2D); - } + GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); } public unsafe Texture(string[] textures) : this(TextureType.Cubemap) @@ -92,42 +91,41 @@ public class Texture : IDisposable { var info = Application.GetResourceStream(new Uri($"/FModel;component/Resources/{textures[t]}.png", UriKind.Relative)); using var img = Image.Load(info.Stream); - Width = (uint) img.Width; // we don't care anyway - Height = (uint) img.Height; // we don't care anyway - GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX + t, 0, PixelInternalFormat.Rgba8, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, null); + Width = img.Width; // we don't care anyway + Height = img.Height; // we don't care anyway + GL.TexImage2D(TextureTarget.TextureCubeMapPositiveX + t, 0, PixelInternalFormat.Rgba8, Width, Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero); img.ProcessPixelRows(accessor => { for (int y = 0; y < accessor.Height; y++) { - fixed (void* data = accessor.GetRowSpan(y)) - { - GL.TexSubImage2D(TextureTarget.TextureCubeMapPositiveX + t, 0, 0, y, (uint) accessor.Width, 1, PixelFormat.Rgba, PixelType.UnsignedByte, data); - } + GL.TexSubImage2D(TextureTarget.TextureCubeMapPositiveX + t, 0, 0, y, accessor.Width, 1, PixelFormat.Rgba, PixelType.UnsignedByte, accessor.GetRowSpan(y).ToArray()); } }); } - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMinFilter, (int) GLEnum.Linear); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureMagFilter, (int) GLEnum.Linear); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapR, (int) GLEnum.ClampToEdge); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapS, (int) GLEnum.ClampToEdge); - GL.TexParameter(TextureTarget.TextureCubeMap, TextureParameterName.TextureWrapT, (int) GLEnum.ClampToEdge); + 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); } public unsafe Texture(uint width, uint height, IntPtr data) : this(TextureType.Normal) { - Width = width; - Height = height; + Width = (int) width; + Height = (int) height; Bind(TextureTarget.Texture2D); GL.TexStorage2D(TextureTarget2d.Texture2D, 1, SizedInternalFormat.Rgba8, Width, Height); - GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, PixelFormat.Bgra, PixelType.UnsignedByte, (void*) data); + GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, PixelFormat.Bgra, PixelType.UnsignedByte, data); - GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); - GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); + var repeat = (int) TextureWrapMode.Repeat; + GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, ref repeat); + GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, ref repeat); - GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, 1 - 1); + var zero = 1 - 1; + GL.TexParameterI(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, ref zero); } public void Bind(TextureUnit textureSlot)