diff --git a/Legacy/Window/Contexts/DrawContext.cs b/Legacy/Window/Contexts/DrawContext.cs new file mode 100644 index 0000000..cb449f5 --- /dev/null +++ b/Legacy/Window/Contexts/DrawContext.cs @@ -0,0 +1,103 @@ +#region usings + +using System.Collections.Generic; +using System.Dynamic; +using OpenTK; +using SM.Base.Drawing; +using SM.Base.Scene; +using SM.OGL.Mesh; + +#endregion + +namespace SM.Base.Contexts +{ + /// + /// Contains important information for drawing. + /// + public struct DrawContext + { + /// + /// This says if it was forced to use the viewport camera. + /// + public bool ForceViewport; + + /// + /// Contains the currently used render pipeline. + /// + public RenderPipeline ActivePipeline; + + public GenericScene ActiveScene; + public IGenericWindow Window; + + + public GenericCamera UsedCamera => + ForceViewport || ActiveScene._camera == null ? Window.ViewportCamera : ActiveScene._camera; + + + + /// + /// The mesh. + /// + public GenericMesh Mesh; + + /// + /// The material. + /// + public Material Material; + + /// + /// The drawing instances. + /// If there is only one, it's index 0 + /// + public IList Instances; + + + + /// + /// The current world scale. + /// + public Vector2 WorldScale; + + /// + /// The last collection the context was passed though. + /// + public object LastPassthough; + + + + /// + /// Returns the appropriate shader. + /// + /// Returns the material shader, if available, otherwise it will take the default shader from the render + /// pipeline. + /// + /// + public MaterialShader Shader => Material.CustomShader ?? ActivePipeline._defaultShader; + /// + /// Arguments for shaders + /// + public IDictionary ShaderArguments; + + + + /// + /// The current world matrix. + /// + public Matrix4 World; + + /// + /// The current view matrix. + /// + public Matrix4 View; + + /// + /// The current WorldView matrix. + /// + public Matrix4 WorldView; + + /// + /// The master model matrix. + /// + public Matrix4 ModelMaster; + } +} \ No newline at end of file diff --git a/Legacy/Window/Contexts/UpdateContext.cs b/Legacy/Window/Contexts/UpdateContext.cs new file mode 100644 index 0000000..63eb913 --- /dev/null +++ b/Legacy/Window/Contexts/UpdateContext.cs @@ -0,0 +1,32 @@ +#region usings + +using OpenTK.Input; +using SM.Base.Scene; + +#endregion + +namespace SM.Base.Contexts +{ + /// + /// The update context. + /// + public struct UpdateContext + { + /// + /// The delta time. + /// + public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime; + + /// + /// The current keyboard state. + /// + public KeyboardState KeyboardState; + + /// + /// The current mouse state. + /// + public MouseState MouseState; + + public GenericScene CurrentScene; + } +} \ No newline at end of file diff --git a/SMCode/SM2D/Window/GLWPFWindow2D.cs b/Legacy/Window/GLWPFWindow2D.cs similarity index 100% rename from SMCode/SM2D/Window/GLWPFWindow2D.cs rename to Legacy/Window/GLWPFWindow2D.cs diff --git a/SMCode/SM2D/Window/GLWindow2D.cs b/Legacy/Window/GLWindow2D.cs similarity index 100% rename from SMCode/SM2D/Window/GLWindow2D.cs rename to Legacy/Window/GLWindow2D.cs diff --git a/SMCode/SM.Base/Window/GenericWPFWindow.cs b/Legacy/Window/GenericWPFWindow.cs similarity index 100% rename from SMCode/SM.Base/Window/GenericWPFWindow.cs rename to Legacy/Window/GenericWPFWindow.cs diff --git a/SMCode/SM.Base/Window/GenericWindow.cs b/Legacy/Window/GenericWindow.cs similarity index 100% rename from SMCode/SM.Base/Window/GenericWindow.cs rename to Legacy/Window/GenericWindow.cs diff --git a/SMCode/SM.Base/Window/GenericWindowCode.cs b/Legacy/Window/GenericWindowCode.cs similarity index 100% rename from SMCode/SM.Base/Window/GenericWindowCode.cs rename to Legacy/Window/GenericWindowCode.cs diff --git a/SMCode/SM2D/Window/IGLWindow2D.cs b/Legacy/Window/IGLWindow2D.cs similarity index 100% rename from SMCode/SM2D/Window/IGLWindow2D.cs rename to Legacy/Window/IGLWindow2D.cs diff --git a/Legacy/Window/IGenericWindow.cs b/Legacy/Window/IGenericWindow.cs new file mode 100644 index 0000000..bc93341 --- /dev/null +++ b/Legacy/Window/IGenericWindow.cs @@ -0,0 +1,37 @@ +using System.Drawing; +using System.Windows; +using OpenTK; +using SM.Base.Scene; +using SM.OGL.Framebuffer; + +namespace SM.Base +{ + public interface IGenericWindow : IFramebufferWindow + { + bool Loading { get; } + float Aspect { get; set; } + + GenericCamera ViewportCamera { get; } + bool ForceViewportCamera { get; set; } + + int Width { get; } + int Height { get; } + + Rectangle ClientRectangle { get; } + Vector2 WorldScale { get; set; } + + void SetWorldScale(); + } + + public interface IGenericWindow : IGenericWindow + where TScene : GenericScene, new() + where TCamera : GenericCamera, new() + { + TScene CurrentScene { get; } + + RenderPipeline RenderPipeline { get; } + + void SetScene(TScene scene); + void SetRenderPipeline(RenderPipeline renderPipeline); + } +} \ No newline at end of file diff --git a/Legacy/Window/RenderPipeline.cs b/Legacy/Window/RenderPipeline.cs new file mode 100644 index 0000000..689511a --- /dev/null +++ b/Legacy/Window/RenderPipeline.cs @@ -0,0 +1,150 @@ +#region usings + +using System.Collections.Generic; +using System.Threading; +using SM.Base.Contexts; +using SM.Base.Drawing; +using SM.Base.Scene; +using SM.OGL.Framebuffer; + +#endregion + +namespace SM.Base +{ + /// + /// Definition of specific render options. + /// + public abstract class RenderPipeline + { + /// + /// If true, this pipeline was already once activated. + /// + public bool IsInitialized { get; private set; } = false; + + /// + /// The window the pipeline is connected to. + /// + protected IGenericWindow _window { get; private set; } + + /// + /// The framebuffers, that are used in this Pipeline. + /// + public virtual List Framebuffers { get; private set; } + + /// + /// The default shader for the pipeline. + /// + protected internal virtual MaterialShader _defaultShader { get; set; } + + public virtual Framebuffer MainFramebuffer { get; protected set; }= Framebuffer.Screen; + + /// + /// Occurs, when the window is loading. + /// + protected internal virtual void Load() + { + } + + /// + /// Occurs, when the window is resizing. + /// + protected internal virtual void Resize() + { + if (Framebuffers == null) return; + + foreach (var framebuffer in Framebuffers) + framebuffer.Dispose(); + + Thread.Sleep(50); + + foreach (Framebuffer framebuffer in Framebuffers) + { + framebuffer.Compile(); + } + } + + internal void Activate(IGenericWindow window) + { + _window = window; + + if (!IsInitialized) + { + if (_defaultShader == null) _defaultShader = SMRenderer.DefaultMaterialShader; + Framebuffers = new List(); + + Initialization(window); + + Framebuffers.Add(MainFramebuffer); + + IsInitialized = true; + } + + Activation(window); + } + + /// + /// Occurs, when the pipeline was connected to a window. + /// + protected internal virtual void Activation(IGenericWindow window) + { + } + + + /// + /// Occurs, when the pipeline was connected to a window the first time. + /// + /// + protected internal virtual void Initialization(IGenericWindow window) + { + + } + + /// + /// Occurs, when the window is unloading. + /// + protected internal virtual void Unload() + { + } + + /// + /// Creates a framebuffer, that has specific (often) required settings already applied. + /// + /// + public static Framebuffer CreateWindowFramebuffer() + { + Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow); + framebuffer.Append("color", 0); + return framebuffer; + } + } + + /// + /// Represents a render pipeline. + /// + /// The scene type + public abstract class RenderPipeline : RenderPipeline + where TScene : GenericScene + { + /// + /// The system to render stuff. + /// + internal void Render(ref DrawContext context) + { + context.ActivePipeline = this; + if (context.ActiveScene == null) return; + + RenderProcess(ref context, (TScene)context.ActiveScene); + } + + protected abstract void RenderProcess(ref DrawContext context, TScene scene); + + /// + /// Event, that triggers, when the scene in the current window changes. + /// + /// + protected internal virtual void SceneChanged(TScene scene) + { + + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Controls/Keyboard.cs b/SMCode/SM.Base/Controls/Keyboard.cs new file mode 100644 index 0000000..77ba027 --- /dev/null +++ b/SMCode/SM.Base/Controls/Keyboard.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Windows.Documents; +using System.Windows.Forms; +using OpenTK.Input; +using SharpDX.Win32; + +namespace SM.Base.Controls +{ + public class Keyboard + { + internal static KeyboardState? _keyboardState; + internal static List _lastPressedKeys = new List(); + + public static bool IsAnyKeyPressed => _keyboardState?.IsAnyKeyDown == true; + + + internal static void SetStage() + { + if (_keyboardState.HasValue) + { + _lastPressedKeys = new List(); + + foreach (object o in Enum.GetValues(typeof(Key))) + { + if (_keyboardState.Value[(Key)o]) _lastPressedKeys.Add((Key)o); + } + } + + _keyboardState = OpenTK.Input.Keyboard.GetState(); + } + + public static bool IsDown(Key key, bool once = false) => _keyboardState?[key] == true && !(once && _lastPressedKeys.Contains(key)); + public static bool WasDown(Key key) => _keyboardState?[key] == false && _lastPressedKeys.Contains(key); + public static bool IsUp(Key key, bool once = false) => _keyboardState?[key] == false && !(once && !_lastPressedKeys.Contains(key)); + + public static bool AreSpecificKeysPressed(int startIndex, int endIndex, bool once = false) + { + if (startIndex > endIndex) + throw new ArgumentException("The startIndex is greater than the endIndex.", nameof(startIndex)); + + int length = endIndex - startIndex; + for (int i = 0; i < length; i++) + { + int actualIndex = i + startIndex; + Key key = (Key) actualIndex; + if (IsDown(key, once)) return true; + } + + return false; + } + + public static bool AreSpecificKeysPressed(params Key[] keys) => AreSpecificKeysPressed(false, keys); + + public static bool AreSpecificKeysPressed(bool once, params Key[] keys) + { + foreach (Key key in keys) + { + if (IsDown(key, once)) return true; + } + + return false; + } + + public static bool AreSpecificKeysPressed(int startIndex, int endIndex, out Key[] pressedKeys, bool once = false) + { + if (startIndex > endIndex) + throw new ArgumentException("The startIndex is greater than the endIndex.", nameof(startIndex)); + + int length = endIndex - startIndex; + + bool success = false; + List keys = new List(); + for (int i = 0; i < length; i++) + { + int actualIndex = i + startIndex; + Key key = (Key)actualIndex; + if (IsDown(key, once)) + { + keys.Add(key); + success = true; + } + + } + + pressedKeys = keys.ToArray(); + return success; + } + + public static bool AreSpecificKeysPressed(out Key[] pressedKey, params Key[] keys) => AreSpecificKeysPressed(false, out pressedKey, keys); + + public static bool AreSpecificKeysPressed(bool once, out Key[] pressedKeys, params Key[] keys) + { + List pressedKey = new List(); + bool success = false; + + foreach (Key key in keys) + { + if (IsDown(key, once)) + { + pressedKey.Add(key); + success = true; + } + } + + pressedKeys = pressedKey.ToArray(); + return success; + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Controls/Mouse.cs b/SMCode/SM.Base/Controls/Mouse.cs index e06437d..a77dd4e 100644 --- a/SMCode/SM.Base/Controls/Mouse.cs +++ b/SMCode/SM.Base/Controls/Mouse.cs @@ -1,7 +1,11 @@ #region usings +using System; +using System.Collections.Generic; +using System.Windows.Documents; using OpenTK; using OpenTK.Input; +using SM.Base.Windows; #endregion @@ -11,41 +15,51 @@ namespace SM.Base.Controls /// Mouse controller /// /// The type of window this controller is connected to. - public class Mouse - where TWindow : IGenericWindow + public class Mouse { - /// - /// The window it is connected to. - /// - protected TWindow _window; - - /// - /// The constructor - /// - /// The window, its listen to. - protected internal Mouse(TWindow window) - { - _window = window; - } + internal static MouseState? _mouseState; + internal static List _lastButtonsPressed = new List(); /// /// The current position of the mouse in the screen. /// - public Vector2 InScreen { get; private set; } + public static Vector2 InScreen { get; private set; } /// /// The current position of the mouse in the screen from 0..1. /// - public Vector2 InScreenNormalized { get; private set; } + public static Vector2 InScreenNormalized { get; private set; } /// /// The event to update the values. /// /// The event args. - protected void MouseMoveEvent(MouseMoveEventArgs mmea) + internal static void MouseMoveEvent(MouseMoveEventArgs mmea, IGenericWindow window) { InScreen = new Vector2(mmea.X, mmea.Y); - InScreenNormalized = new Vector2(mmea.X / (float) _window.Width, mmea.Y / (float) _window.Height); + InScreenNormalized = new Vector2(mmea.X / (float)window.Width, mmea.Y / (float)window.Height); } + + internal static void SetState() + { + if (_mouseState.HasValue) + { + _lastButtonsPressed = new List(); + + foreach (object o in Enum.GetValues(typeof(MouseButton))) + { + if (_mouseState.Value[(MouseButton)o]) _lastButtonsPressed.Add((MouseButton)o); + } + } + + _mouseState = OpenTK.Input.Mouse.GetState(); + + } + + public static bool IsDown(MouseButton button, bool once = false) => _mouseState?[button] == true && !(once && _lastButtonsPressed.Contains(button)); + + public static bool IsUp(MouseButton button, bool once = false) => + _mouseState?[button] == false && !(once && !_lastButtonsPressed.Contains(button)); + } } \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/DrawingBasis.cs b/SMCode/SM.Base/Drawing/DrawingBasis.cs index 63bde5e..b235784 100644 --- a/SMCode/SM.Base/Drawing/DrawingBasis.cs +++ b/SMCode/SM.Base/Drawing/DrawingBasis.cs @@ -1,8 +1,9 @@ #region usings using System.Collections.Generic; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Scene; +using SM.Base.Windows; using SM.OGL.Mesh; #endregion @@ -12,17 +13,21 @@ namespace SM.Base.Drawing /// /// Contains general basis systems for drawing objects. /// - public abstract class DrawingBasis : IShowItem + public abstract class DrawingBasis : IShowItem, IModelItem { /// /// The material it should use. /// - protected Material _material = new Material(); + public Material Material = new Material(); + /// /// The mesh it should use. /// - protected GenericMesh _mesh = SMRenderer.DefaultMesh; + public GenericMesh Mesh { get; set; } = SMRenderer.DefaultMesh; + + public ShaderArguments ShaderArguments => Material.ShaderArguments; + public TextureTransformation TextureTransform = new TextureTransformation(); /// public object Parent { get; set; } @@ -36,15 +41,13 @@ namespace SM.Base.Drawing /// /// This value determents if the object should draw something. /// - public bool Active = true; + public bool Active { get; set; } = true; /// public void Draw(DrawContext context) { - if (!Active) return; - - context.Material = _material; - context.Mesh = _mesh; + context.Material = Material; + context.Mesh = Mesh; DrawContext(ref context); } @@ -65,6 +68,7 @@ namespace SM.Base.Drawing /// protected virtual void DrawContext(ref DrawContext context) { + context.TextureMatrix *= TextureTransform.GetMatrix(); } } @@ -72,19 +76,20 @@ namespace SM.Base.Drawing /// Contains general basis systems for drawing objects. /// /// The transformation type - public abstract class DrawingBasis : DrawingBasis + public abstract class DrawingBasis : DrawingBasis, IShowTransformItem where TTransformation : GenericTransformation, new() { /// /// The current transformation. /// - public TTransformation Transform = new TTransformation(); + public TTransformation Transform { get; set; } = new TTransformation(); /// protected override void DrawContext(ref DrawContext context) { base.DrawContext(ref context); - context.ModelMaster *= Transform.GetMatrix(); + Transform.LastMaster = context.ModelMatrix; + context.ModelMatrix = Transform.MergeMatrix(context.ModelMatrix); } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/GenericTransformation.cs b/SMCode/SM.Base/Drawing/GenericTransformation.cs index 0912b47..8cd032f 100644 --- a/SMCode/SM.Base/Drawing/GenericTransformation.cs +++ b/SMCode/SM.Base/Drawing/GenericTransformation.cs @@ -16,6 +16,8 @@ namespace SM.Base.Drawing /// public bool Ignore = false; + public Matrix4 LastMaster { get; internal set; } + /// /// Contains the current model matrix. /// @@ -43,6 +45,11 @@ namespace SM.Base.Drawing return _modelMatrix; } + public Matrix4 MergeMatrix(Matrix4 matrix) + { + return GetMatrix() * matrix; + } + /// /// Calculates the current matrix. /// diff --git a/SMCode/SM.Base/Drawing/Instance.cs b/SMCode/SM.Base/Drawing/Instance.cs index 2473fa8..7ef88c8 100644 --- a/SMCode/SM.Base/Drawing/Instance.cs +++ b/SMCode/SM.Base/Drawing/Instance.cs @@ -16,14 +16,6 @@ namespace SM.Base.Drawing /// public Matrix4 ModelMatrix = Matrix4.Identity; - /// - /// The texture offset. - /// - public Vector2 TexturePosition = Vector2.Zero; - - /// - /// The texture scale. - /// - public Vector2 TextureScale = Vector2.One; + public Matrix3 TextureMatrix = Matrix3.Identity; } } \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/Material.cs b/SMCode/SM.Base/Drawing/Material.cs index a1bf6d1..6a4b0a2 100644 --- a/SMCode/SM.Base/Drawing/Material.cs +++ b/SMCode/SM.Base/Drawing/Material.cs @@ -1,5 +1,6 @@ #region usings +using System.Collections.Generic; using OpenTK.Graphics; using SM.OGL.Texture; @@ -26,5 +27,9 @@ namespace SM.Base.Drawing /// The tint or color. /// public Color4 Tint = Color4.White; + + public ShaderArguments ShaderArguments { get; internal set; } = new ShaderArguments(); + + public bool Blending = false; } } \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/Particles/ParticleDrawingBasis.cs b/SMCode/SM.Base/Drawing/Particles/ParticleDrawingBasis.cs index e04789c..a89c8b3 100644 --- a/SMCode/SM.Base/Drawing/Particles/ParticleDrawingBasis.cs +++ b/SMCode/SM.Base/Drawing/Particles/ParticleDrawingBasis.cs @@ -1,10 +1,11 @@ using System; using System.Collections.Generic; using OpenTK; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Scene; using SM.Base.Time; using SM.Base.Types; +using SM.Base.Windows; using SM.OGL.Shaders; namespace SM.Base.Drawing.Particles diff --git a/SMCode/SM.Base/Drawing/ShaderArguments.cs b/SMCode/SM.Base/Drawing/ShaderArguments.cs new file mode 100644 index 0000000..07a5222 --- /dev/null +++ b/SMCode/SM.Base/Drawing/ShaderArguments.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; + +namespace SM.Base.Drawing +{ + public class ShaderArguments : Dictionary + { + public TType Get(string name, TType defaultValue = default) + { + return ContainsKey(name) ? (TType)this[name] : defaultValue; + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/Text/Font.cs b/SMCode/SM.Base/Drawing/Text/Font.cs index 183b612..737036b 100644 --- a/SMCode/SM.Base/Drawing/Text/Font.cs +++ b/SMCode/SM.Base/Drawing/Text/Font.cs @@ -32,6 +32,8 @@ namespace SM.Base.Drawing.Text /// public float FontSize = 12; + public float Spacing = 1; + /// /// The font style. /// Default: diff --git a/SMCode/SM.Base/Drawing/Text/TextDrawingBasis.cs b/SMCode/SM.Base/Drawing/Text/TextDrawingBasis.cs index 76fa790..1cd3c85 100644 --- a/SMCode/SM.Base/Drawing/Text/TextDrawingBasis.cs +++ b/SMCode/SM.Base/Drawing/Text/TextDrawingBasis.cs @@ -3,7 +3,8 @@ using System; using OpenTK; using OpenTK.Graphics; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; #endregion @@ -32,13 +33,19 @@ namespace SM.Base.Drawing.Text /// public float Spacing = 1; + public float ActualSpacing => Spacing * Font.Spacing; + + public float Width; + public float Height; + /// /// Creates a text object with a font. /// /// The font. protected TextDrawingBasis(Font font) { - _material.Texture = font; + Material.Texture = font; + Material.Blending = true; } /// @@ -46,10 +53,10 @@ namespace SM.Base.Drawing.Text /// public Font Font { - get => (Font) _material.Texture; + get => (Font) Material.Texture; set { - _material.Texture = value; + Material.Texture = value; GenerateMatrixes(); } } @@ -72,8 +79,8 @@ namespace SM.Base.Drawing.Text /// public Color4 Color { - get => _material.Tint; - set => _material.Tint = value; + get => Material.Tint; + set => Material.Tint = value; } @@ -92,15 +99,26 @@ namespace SM.Base.Drawing.Text { if (!Font.WasCompiled) Font.RegenerateTexture(); + _text = _text.Replace("\r\n", "\n").Replace("\t", " "); + _instances = new Instance[_text.Length]; float x = 0; + float y = 0; var _last = new CharParameter(); for (var i = 0; i < _text.Length; i++) { - if (_text[i] == 32) + if (_text[i] == ' ') { - x += _last.Width * Spacing; + x += Font.FontSize * ActualSpacing; + continue; + } + + if (_text[i] == '\n') + { + y += Font.Height; + Width = Math.Max(Width, x); + x = 0; continue; } @@ -115,17 +133,19 @@ namespace SM.Base.Drawing.Text } var matrix = Matrix4.CreateScale(parameter.Width, Font.Height, 1) * - Matrix4.CreateTranslation(x, 0, 0); + Matrix4.CreateTranslation(x, -y, 0); _instances[i] = new Instance { ModelMatrix = matrix, - TexturePosition = new Vector2(parameter.NormalizedX, 0), - TextureScale = new Vector2(parameter.NormalizedWidth, 1) + TextureMatrix = TextureTransformation.CalculateMatrix(new Vector2(parameter.NormalizedX, 0), new Vector2(parameter.NormalizedWidth, 1), 0), }; - x += parameter.Width * Spacing; + x += parameter.Width * ActualSpacing; _last = parameter; } + + Width = Math.Max(Width, x); + Height = y + Font.Height; } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Drawing/TextureTransformation.cs b/SMCode/SM.Base/Drawing/TextureTransformation.cs new file mode 100644 index 0000000..78ac108 --- /dev/null +++ b/SMCode/SM.Base/Drawing/TextureTransformation.cs @@ -0,0 +1,26 @@ +using System; +using OpenTK; +using SM.Base.Types; + +namespace SM.Base.Drawing +{ + public class TextureTransformation + { + public CVector2 Offset = new CVector2(0); + public CVector2 Scale = new CVector2(1); + public CVector1 Rotation = new CVector1(0); + + public Matrix3 GetMatrix() + { + return CalculateMatrix(Offset, Scale, Rotation); + } + + public static Matrix3 CalculateMatrix(Vector2 offset, Vector2 scale, float rotation) + { + float radians = MathHelper.DegreesToRadians(rotation); + Matrix3 result = Matrix3.CreateScale(scale.X, scale.Y, 1) * Matrix3.CreateRotationZ(radians); + result.Row2 = new Vector3(offset.X, offset.Y, 1); + return result; + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Log.cs b/SMCode/SM.Base/Log.cs index 49624f9..a043927 100644 --- a/SMCode/SM.Base/Log.cs +++ b/SMCode/SM.Base/Log.cs @@ -138,7 +138,7 @@ namespace SM.Base _logStream = new StreamWriter(path) {AutoFlush = true}; - Write(LogType.Info, $"Activated new log file. ['{path}']"); + Write(LogType.Info, $"Activate new log file. ['{path}']"); } internal static void Init() diff --git a/SMCode/SM.Base/Objects/InstancedMesh.cs b/SMCode/SM.Base/Objects/InstancedMesh.cs index 22ce589..eddbbab 100644 --- a/SMCode/SM.Base/Objects/InstancedMesh.cs +++ b/SMCode/SM.Base/Objects/InstancedMesh.cs @@ -4,7 +4,7 @@ using SM.OGL.Mesh; namespace SM.Base.Objects { - public class InstancedMesh : Mesh + public class InstancedMesh : Mesh, ILineMesh { public InstancedMesh(PrimitiveType type, string[] enabledAttibute) : base(type) { @@ -26,5 +26,7 @@ namespace SM.Base.Objects } } } + + public float LineWidth { get; set; } = 1; } } \ No newline at end of file diff --git a/SMCode/SM.Base/PostEffects/BloomEffect.cs b/SMCode/SM.Base/PostEffects/BloomEffect.cs index 9462f4e..d4af620 100644 --- a/SMCode/SM.Base/PostEffects/BloomEffect.cs +++ b/SMCode/SM.Base/PostEffects/BloomEffect.cs @@ -1,7 +1,10 @@ using System.ComponentModel; +using OpenTK; using OpenTK.Graphics.OpenGL4; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Drawing; using SM.Base.PostProcess; +using SM.Base.Windows; using SM.OGL.Framebuffer; using SM.OGL.Texture; using SM.Utility; @@ -10,37 +13,76 @@ namespace SM.Base.PostEffects { public class BloomEffect : PostProcessEffect { + private static BezierCurve _defaultCurve = new BezierCurve(Vector2.UnitY, new Vector2(0.32f, 1), new Vector2(0.432f, 0), new Vector2(1,0)); + + private const float _textureScale = .75f; + private Framebuffer _bloomBuffer1; private Framebuffer _bloomBuffer2; private ColorAttachment _xBuffer; private ColorAttachment _yBuffer; - private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM.Base.PostEffects.Shaders.bloom_blur.glsl")); - private PostProcessShader _mergeShader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM.Base.PostEffects.Shaders.bloom_merge.glsl")); + private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath+".bloom_blur.glsl")); + private PostProcessShader _mergeShader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath+".bloom_merge_vert.glsl"), AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath+".bloom_merge.glsl")); - private int _bloomLocation; private bool _hdr; + private Framebuffer _source; - public int Iterations = 5; - public float Threshold = 0.8f; - - public float[] Weights = { 0.227027f, 0.1945946f, 0.1216216f, 0.054054f, 0.016216f }; - - public BloomEffect(int bloomLocation, bool hdr = false) + private BezierCurve _weightCurve ; + private float[] _weights; + + public int Iterations = 1; + public float Threshold = .8f; + public float Power = 1; + + public bool Enable = true; + + public float MinAmount = 0; + public float MaxAmount = 1; + public TextureBase AmountMap; + public TextureTransformation AmountTransform = new TextureTransformation(); + + public BezierCurve WeightCurve { - _bloomLocation = bloomLocation; + get => _weightCurve; + set + { + _weightCurve = value; + UpdateWeights(); + } + } + + public int WeightCurvePickAmount = 4; + + + public BloomEffect(Framebuffer source = null, bool hdr = false) + { + _source = source; _hdr = hdr; + + WeightCurve = _defaultCurve; + } + + + private void UpdateWeights() + { + _weights = new float[WeightCurvePickAmount]; + + for (int i = 0; i < WeightCurvePickAmount; i++) + { + _weights[i] = _weightCurve.CalculatePoint((float)(i + 1) / (WeightCurvePickAmount + 1)).Y; + } } protected override void InitProcess() { - Pipeline.MainFramebuffer.ColorAttachments["color"].PixelInformation = PixelInformation.RGBA_HDR; + _source.ColorAttachments["color"].PixelInformation = PixelInformation.RGBA_HDR; - _bloomBuffer1 = new Framebuffer(SMRenderer.CurrentWindow); + _bloomBuffer1 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale); _bloomBuffer1.Append("xBuffer", _xBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR)); _bloomBuffer1.Compile(); - _bloomBuffer2 = new Framebuffer(SMRenderer.CurrentWindow); + _bloomBuffer2 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale); _bloomBuffer2.Append("yBuffer", _yBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR)); _bloomBuffer2.Compile(); @@ -50,35 +92,51 @@ namespace SM.Base.PostEffects public override void Draw(DrawContext context) { - Framebuffer target = Framebuffer.GetCurrentlyActive(); - - bool first = true, hoz = true; - int iter = Iterations * 2; - for (int i = 0; i < iter; i++) + if (Enable) { - (hoz ? _bloomBuffer1 : _bloomBuffer2).Activate(); - - _shader.Draw(first ? Pipeline.MainFramebuffer.ColorAttachments["color"] : (hoz ? _yBuffer : _xBuffer), collection => + GL.Viewport(0,0, (int)(Pipeline.ConnectedWindow.Width * _textureScale), (int)(Pipeline.ConnectedWindow.Height * _textureScale)); + + Framebuffer target = Framebuffer.GetCurrentlyActive(); + bool first = true, hoz = true; + int iter = Iterations * 2; + for (int i = 0; i < iter; i++) { - collection["First"].SetUniform1(first); - collection["Threshold"].SetUniform1(Threshold); + (hoz ? _bloomBuffer1 : _bloomBuffer2).Activate(); + + _shader.Draw(collection => + { + collection["renderedTexture"].SetTexture(first ? _source.ColorAttachments["color"] : (hoz ? _yBuffer : _xBuffer)); + collection["RenderScale"].SetUniform1(_textureScale); - collection["Horizontal"].SetUniform1(hoz); - - collection["Weights"].SetUniform1(Weights); - collection["WeightCount"].SetUniform1(Weights.Length); - }); - - hoz = !hoz; - if (first) first = false; + collection["First"].SetUniform1(first); + collection["Threshold"].SetUniform1(Threshold); + + collection["Horizontal"].SetUniform1(hoz); + + collection["Weights"].SetUniform1(_weights); + collection["WeightCount"].SetUniform1(WeightCurvePickAmount); + collection["Power"].SetUniform1(Power); + }); + + hoz = !hoz; + if (first) first = false; + } + + GL.Viewport(Pipeline.ConnectedWindow.ClientRectangle); + target.Activate(); } - target.Activate(); - _mergeShader.Draw(Pipeline.MainFramebuffer.ColorAttachments["color"], collection => + _mergeShader.Draw(collection => { + collection["Scene"].SetTexture(_source.ColorAttachments["color"]); collection["Bloom"].SetTexture(_yBuffer); - collection["Exposure"].SetUniform1(context.UsedCamera.Exposure); + collection["MinAmount"].SetUniform1(MinAmount); + collection["MaxAmount"].SetUniform1(MaxAmount); + collection["AmountMap"].SetTexture(AmountMap, collection["HasAmountMap"]); + collection["TextureTransform"].SetMatrix3(AmountTransform.GetMatrix()); + + collection["Exposure"].SetUniform1(context.UseCamera.Exposure); collection["HDR"].SetUniform1(_hdr); }); } diff --git a/SMCode/SM.Base/PostEffects/PostProcessFinals.cs b/SMCode/SM.Base/PostEffects/PostProcessFinals.cs new file mode 100644 index 0000000..30b6546 --- /dev/null +++ b/SMCode/SM.Base/PostEffects/PostProcessFinals.cs @@ -0,0 +1,46 @@ +using System.Windows.Controls; +using OpenTK.Graphics.OpenGL4; +using SM.Base.PostProcess; +using SM.Base.Windows; +using SM.OGL.Framebuffer; +using SM.Utility; + +namespace SM.Base.PostEffects +{ + public class PostProcessFinals + { + static PostProcessShader _hdrExposureShader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath+".finalize_hdr.glsl")); + static PostProcessShader _gammaShader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".finalize_gamma.glsl")); + + public static float Gamma = 2.2f; + + public static void ResolveMultisampledBuffers(Framebuffer multisampledBuffers, Framebuffer target) + { + multisampledBuffers.Activate(FramebufferTarget.ReadFramebuffer); + target.Activate(FramebufferTarget.DrawFramebuffer); + GL.BlitFramebuffer(0, 0, (int)multisampledBuffers.Size.X, (int)multisampledBuffers.Size.Y, 0, 0, (int)target.Size.X, (int)target.Size.Y, ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Nearest); + + target.Activate(); + } + + public static void FinalizeHDR(ColorAttachment attachment, float exposure) + { + + _hdrExposureShader.Draw(u => + { + u["Gamma"].SetUniform1(Gamma); + u["Exposure"].SetUniform1(exposure); + u["Scene"].SetTexture(attachment); + }); + } + + public static void FinalizeGamma(ColorAttachment attachment) + { + _gammaShader.Draw(u => + { + u["Gamma"].SetUniform1(Gamma); + u["Scene"].SetTexture(attachment); + }); + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl b/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl index 23b0a14..0393f55 100644 --- a/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl +++ b/SMCode/SM.Base/PostEffects/Shaders/bloom_blur.glsl @@ -1,6 +1,8 @@ #version 330 +#define PI 3.14159265359 uniform sampler2D renderedTexture; +uniform float RenderScale; uniform bool First; uniform float Threshold; @@ -9,27 +11,35 @@ uniform bool Horizontal; uniform float[32] Weights; uniform int WeightCount; +uniform float Power; layout(location = 0) out vec4 color; vec4 GetRenderColorOffset(vec2 offset); +float brightness(vec3 c) +{ + return max(max(c.r, c.g), c.b); +} + +float bright; + +float GetWeight(int dif) { + return Weights[dif]; +} + void main() { vec3 thres = vec3(First ? Threshold : 0); - vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0); - vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * Weights[0]; + vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0) * vec2(Horizontal ? 1 : 0, Horizontal ? 0 : 1); - if (Horizontal) { - for(int i = 1; i < WeightCount; i++) { - result += max(GetRenderColorOffset(vec2(tex_offset.x * i, 0)).rgb - thres, 0) * Weights[i]; - result += max(GetRenderColorOffset(vec2(-tex_offset.x * i, 0)).rgb - thres, 0) * Weights[i]; - } - } else { - for(int i = 1; i < WeightCount; i++) { - result += GetRenderColorOffset(vec2(0, tex_offset.x * i)).rgb * Weights[i]; - result += GetRenderColorOffset(vec2(0, -tex_offset.x * i)).rgb * Weights[i]; - } + vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * (First ? Power : 1); + result *= GetWeight(0); + + for(int i = 1; i < WeightCount; i++) { + result += max(GetRenderColorOffset(tex_offset * i).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i); + result += max(GetRenderColorOffset(-tex_offset * i).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i); } + color = vec4(result, 1); } \ No newline at end of file diff --git a/SMCode/SM.Base/PostEffects/Shaders/bloom_merge.glsl b/SMCode/SM.Base/PostEffects/Shaders/bloom_merge.glsl index 771015c..cef9313 100644 --- a/SMCode/SM.Base/PostEffects/Shaders/bloom_merge.glsl +++ b/SMCode/SM.Base/PostEffects/Shaders/bloom_merge.glsl @@ -1,10 +1,16 @@ #version 330 in vec2 vTexture; +in vec2 TransformedTexture; -uniform sampler2D renderedTexture; +uniform sampler2D Scene; uniform sampler2D Bloom; +uniform float MinAmount; +uniform float MaxAmount; +uniform sampler2D AmountMap; +uniform bool HasAmountMap; + uniform float Exposure; uniform bool HDR; @@ -12,10 +18,13 @@ layout(location = 0) out vec4 color; void main() { vec3 result = texture(Bloom, vTexture).rgb; + if (HasAmountMap) result *= clamp(length(texture(AmountMap, TransformedTexture).rgb) * (MaxAmount - MinAmount) + MinAmount, 0, 1); if (!HDR) { result = vec3(1.0) - exp(-result * Exposure); } - result += texture(renderedTexture, vTexture).rgb; + + + result = texture(Scene, vTexture).rgb + result; color = vec4(result, 1); } \ No newline at end of file diff --git a/SMCode/SM.Base/PostEffects/Shaders/bloom_merge_vert.glsl b/SMCode/SM.Base/PostEffects/Shaders/bloom_merge_vert.glsl new file mode 100644 index 0000000..127a8b5 --- /dev/null +++ b/SMCode/SM.Base/PostEffects/Shaders/bloom_merge_vert.glsl @@ -0,0 +1,11 @@ +#version 330 + +layout(location = 1) in vec2 aTex; + +uniform mat3 TextureTransform; + +out vec2 TransformedTexture; + +void vertex() { + TransformedTexture = vec2(TextureTransform * vec3(aTex, 1)); +} \ No newline at end of file diff --git a/SMCode/SM.Base/PostEffects/Shaders/finalize_gamma.glsl b/SMCode/SM.Base/PostEffects/Shaders/finalize_gamma.glsl new file mode 100644 index 0000000..74b3e6d --- /dev/null +++ b/SMCode/SM.Base/PostEffects/Shaders/finalize_gamma.glsl @@ -0,0 +1,12 @@ +#version 330 + +in vec2 vTexture; + +uniform sampler2D Scene; +uniform float Gamma; + +layout(location = 0) out vec4 color; + +void main() { + color = vec4(pow(texture(Scene, vTexture).rgb, vec3(1 / Gamma)), 1); +} \ No newline at end of file diff --git a/SMCode/SM.Base/PostEffects/Shaders/finalize_hdr.glsl b/SMCode/SM.Base/PostEffects/Shaders/finalize_hdr.glsl new file mode 100644 index 0000000..59406bc --- /dev/null +++ b/SMCode/SM.Base/PostEffects/Shaders/finalize_hdr.glsl @@ -0,0 +1,15 @@ +#version 330 + +in vec2 vTexture; + +uniform sampler2D Scene; +uniform float Exposure; +uniform float Gamma; + +layout(location = 0) out vec4 color; + +void main() { + vec3 result = vec3(1) - exp(-texture(Scene, vTexture).rgb * Exposure); + + color = vec4(pow(result, vec3(1 / Gamma)), 1); +} \ No newline at end of file diff --git a/SMCode/SM.Base/PostProcess/DefaultFiles/vertexFile.vert b/SMCode/SM.Base/PostProcess/DefaultFiles/vertexFile.vert index e4ab1dd..0631261 100644 --- a/SMCode/SM.Base/PostProcess/DefaultFiles/vertexFile.vert +++ b/SMCode/SM.Base/PostProcess/DefaultFiles/vertexFile.vert @@ -4,15 +4,11 @@ layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTex; uniform mat4 MVP; -uniform mat4 ModelMatrix; out vec2 vTexture; -out vec2 FragPos; void main() { vTexture = aTex; - - FragPos = vec2(ModelMatrix * vec4(aPos, 1)); gl_Position = MVP * vec4(aPos, 1); } \ No newline at end of file diff --git a/SMCode/SM.Base/PostProcess/DefaultFiles/vertexWithExt.vert b/SMCode/SM.Base/PostProcess/DefaultFiles/vertexWithExt.vert index 90ec253..508c2be 100644 --- a/SMCode/SM.Base/PostProcess/DefaultFiles/vertexWithExt.vert +++ b/SMCode/SM.Base/PostProcess/DefaultFiles/vertexWithExt.vert @@ -4,17 +4,13 @@ layout(location = 0) in vec3 aPos; layout(location = 1) in vec2 aTex; uniform mat4 MVP; -uniform mat4 ModelMatrix; out vec2 vTexture; -out vec2 FragPos; void vertex(); void main() { vTexture = aTex; - - FragPos = vec2(ModelMatrix * vec4(aPos, 1)); gl_Position = MVP * vec4(aPos, 1); diff --git a/SMCode/SM.Base/PostProcess/PostProcessEffect.cs b/SMCode/SM.Base/PostProcess/PostProcessEffect.cs index eb7e739..cd70945 100644 --- a/SMCode/SM.Base/PostProcess/PostProcessEffect.cs +++ b/SMCode/SM.Base/PostProcess/PostProcessEffect.cs @@ -3,9 +3,10 @@ using System.Collections.Generic; using System.Diagnostics; using OpenTK; using OpenTK.Graphics.OpenGL4; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Objects.Static; using SM.Base.Scene; +using SM.Base.Windows; using SM.OGL.Framebuffer; using SM.OGL.Shaders; @@ -16,8 +17,7 @@ namespace SM.Base.PostProcess /// public abstract class PostProcessEffect { - internal static Matrix4 Mvp; - internal static Matrix4 Model; + public static Matrix4 Mvp = Matrix4.Identity; protected RenderPipeline Pipeline; diff --git a/SMCode/SM.Base/PostProcess/PostProcessShader.cs b/SMCode/SM.Base/PostProcess/PostProcessShader.cs index 27b25c5..3ac88c5 100644 --- a/SMCode/SM.Base/PostProcess/PostProcessShader.cs +++ b/SMCode/SM.Base/PostProcess/PostProcessShader.cs @@ -42,45 +42,23 @@ namespace SM.Base.PostProcess fragment.GLSLExtensions.Add(_fragExtensions); } - /// - /// Draws the shader without special uniforms. - /// - /// - public void Draw(ColorAttachment color) - { - GL.UseProgram(this); - GL.BindVertexArray(Plate.Object); - - Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp); - Uniforms["ModelMatrix"].SetMatrix4(PostProcessEffect.Model); - Uniforms["renderedTexture"].SetTexture(color); - - GL.DrawArrays(PrimitiveType.Quads, 0, 4); - - CleanUp(); - GL.UseProgram(0); - } - /// /// Draws the shader with special uniforms. /// /// /// - public void Draw(ColorAttachment color, Action setUniformAction) + public void Draw(Action setUniformAction) { - GL.UseProgram(this); - GL.BindVertexArray(Plate.Object); + Activate(); + Plate.Object.Activate(); Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp); - Uniforms["ModelMatrix"].SetMatrix4(PostProcessEffect.Model); - Uniforms["renderedTexture"].SetTexture(color); setUniformAction(Uniforms); GL.DrawArrays(PrimitiveType.Quads, 0, 4); CleanUp(); - GL.UseProgram(0); } } } \ No newline at end of file diff --git a/SMCode/SM.Base/SM.Base.csproj b/SMCode/SM.Base/SM.Base.csproj index 09a0669..b1f312b 100644 --- a/SMCode/SM.Base/SM.Base.csproj +++ b/SMCode/SM.Base/SM.Base.csproj @@ -58,15 +58,25 @@ + - + + + + + + + + + + @@ -80,7 +90,7 @@ - + @@ -98,20 +108,17 @@ - - - - - + + - + @@ -121,9 +128,7 @@ SM.OGL - - - + @@ -134,6 +139,13 @@ + + + + + + + \ No newline at end of file diff --git a/SMCode/SM.Base/SM.Base.csproj.DotSettings b/SMCode/SM.Base/SM.Base.csproj.DotSettings new file mode 100644 index 0000000..df1a05c --- /dev/null +++ b/SMCode/SM.Base/SM.Base.csproj.DotSettings @@ -0,0 +1,5 @@ + + Latest + False + True + True \ No newline at end of file diff --git a/SMCode/SM.Base/SMRenderer.cs b/SMCode/SM.Base/SMRenderer.cs index c1696d5..b6f6df2 100644 --- a/SMCode/SM.Base/SMRenderer.cs +++ b/SMCode/SM.Base/SMRenderer.cs @@ -4,6 +4,7 @@ using SM.Base.Drawing; using SM.Base.Drawing.Text; using SM.Base.Objects.Static; using SM.Base.Scene; +using SM.Base.Windows; using SM.OGL.Mesh; using SM.OGL.Shaders; using SM.Utility; @@ -17,6 +18,8 @@ namespace SM.Base /// public class SMRenderer { + internal const string PostProcessPath = "SM.Base.PostEffects.Shaders"; + /// /// Defines, how many instances the 'SM_base_vertex_basic'-extension can handle. /// @@ -50,7 +53,7 @@ namespace SM.Base /// /// Current Frame /// - public static ulong CurrentFrame { get; internal set; } = 0; + public static ulong CurrentFrame { get; internal set; } = 1; /// /// Represents the current active window. diff --git a/SMCode/SM.Base/Scene/GenericCamera.cs b/SMCode/SM.Base/Scene/GenericCamera.cs index f4e7520..b207567 100644 --- a/SMCode/SM.Base/Scene/GenericCamera.cs +++ b/SMCode/SM.Base/Scene/GenericCamera.cs @@ -1,6 +1,7 @@ #region usings using OpenTK; +using SM.Base.Windows; #endregion @@ -11,48 +12,44 @@ namespace SM.Base.Scene /// public abstract class GenericCamera { - /// - /// The matrix for the orthographic world. - /// - public static Matrix4 OrthographicWorld { get; protected set; } - - /// - /// The matrix for the perspective world. - /// - public static Matrix4 PerspectiveWorld { get; protected set; } - /// /// This defines what is up. (Normalized) /// Default: /// - public static Vector3 UpVector { get; set; } = Vector3.UnitY; + public Vector3 UpVector { get; set; } = Vector3.UnitY; + + /// + /// Returns the world matrix that is connected to this camera. + /// + public Matrix4 World { get; protected set; } /// /// Contains the view matrix of this camera. /// Default: /// - public Matrix4 ViewMatrix { get; protected set; } = Matrix4.Identity; - - /// - /// Returns the world matrix that is connected to this camera. - /// - public Matrix4 World => Orthographic ? OrthographicWorld : PerspectiveWorld; + public Matrix4 View { get; protected set; } = Matrix4.Identity; /// /// Represents if the camera is orthographic. /// public abstract bool Orthographic { get; } + /// + /// Exposure defines the exposure to the Scene. + /// public float Exposure = 1; /// /// Calculates the view matrix. /// - /// The calculated view matrix. Same as - internal Matrix4 CalculateViewMatrix() + /// The calculated view matrix. Same as + internal void CalculateViewMatrix(IGenericWindow window) { - ViewMatrix = ViewCalculation(); - return ViewMatrix; + View = ViewCalculation(window); + if (WorldCalculation(window, out Matrix4 world)) + { + World = world; + } } /// @@ -60,16 +57,10 @@ namespace SM.Base.Scene /// /// /// The new view matrix. This is the returns for and the next value for - /// . + /// . /// - protected abstract Matrix4 ViewCalculation(); + protected abstract Matrix4 ViewCalculation(IGenericWindow window); - /// - /// This will calculate the world. - /// This is called on to calculate the world. - /// - /// The world scale - /// The aspect ratio from the window. - public abstract void RecalculateWorld(Vector2 world, float aspect); + protected abstract bool WorldCalculation(IGenericWindow window, out Matrix4 world); } } \ No newline at end of file diff --git a/SMCode/SM.Base/Scene/GenericItemCollection.cs b/SMCode/SM.Base/Scene/GenericItemCollection.cs index 3e70f59..54e1f29 100644 --- a/SMCode/SM.Base/Scene/GenericItemCollection.cs +++ b/SMCode/SM.Base/Scene/GenericItemCollection.cs @@ -2,8 +2,10 @@ using System.Collections.Generic; using System.Collections.ObjectModel; -using SM.Base.Contexts; +using OpenTK; +using SM.Base; using SM.Base.Drawing; +using SM.Base.Windows; #endregion @@ -12,9 +14,7 @@ namespace SM.Base.Scene /// /// Contains a list of show items. /// - /// The type of show items. - public abstract class GenericItemCollection : List, IShowItem, IShowCollection, IScriptable - where TItem : IShowItem + public abstract class GenericItemCollection : List, IShowItem, IShowCollection, IScriptable { private List _scriptableObjects = new List(); @@ -23,7 +23,7 @@ namespace SM.Base.Scene /// public ReadOnlyCollection ScriptableObjects => new ReadOnlyCollection(_scriptableObjects); /// - public List Objects => this; + public List Objects => this; /// public object Parent { get; set; } @@ -34,20 +34,32 @@ namespace SM.Base.Scene /// public ICollection Flags { get; set; } = new List() {"collection"}; + public bool Active { get; set; } = true; + public bool UpdateActive { get; set; } = true; + public bool RenderActive { get; set; } = true; + /// public virtual void Update(UpdateContext context) { + if (!Active || !UpdateActive) return; + for (var i = 0; i < _scriptableObjects.Count; i++) + { + if (!_scriptableObjects[i].Active) continue; _scriptableObjects[i].Update(context); + } } - /// + /// public virtual void Draw(DrawContext context) { - context.LastPassthough = this; + if (!Active || !RenderActive) return; for (var i = 0; i < Objects.Count; i++) + { + if (!this[i].Active) continue; this[i].Draw(context); + } } /// @@ -63,20 +75,22 @@ namespace SM.Base.Scene /// /// Adds a item to the draw and the script collection, when applicable. /// - public new void Add(TItem item) + public new void Add(params IShowItem[] items) { - AddObject(item); - - if (item is IScriptable scriptable) - AddScript(scriptable); + foreach (var item in items) + { + AddObject(item); + if (item is IScriptable scriptable) + AddScript(scriptable); + } } /// /// Adds the object to the collection. /// /// - public void AddObject(TItem item) + public void AddObject(IShowItem item) { base.Add(item); item.Parent = this; @@ -91,23 +105,22 @@ namespace SM.Base.Scene _scriptableObjects.Add(item); } - /// - /// Removes a item from the draw and script collection, when applicable. - /// - /// - public new void Remove(TItem item) + public new void Remove(params IShowItem[] items) { - RemoveObject(item); + foreach (var item in items) + { + RemoveObject(item); - if (item.GetType().IsAssignableFrom(typeof(IScriptable))) - RemoveScript((IScriptable)item); + if (item is IScriptable scriptable) + RemoveScript(scriptable); + } } /// /// Remove the object from the draw collection. /// /// - public void RemoveObject(TItem item) + public void RemoveObject(IShowItem item) { base.Remove(item); item.Parent = null; @@ -123,15 +136,27 @@ namespace SM.Base.Scene _scriptableObjects.Remove(item); } + public ICollection GetAllItems(bool includeCollections = false) + { + List items = new List(); + for (var i = 0; i < this.Count; i++) + { + if (!includeCollections && this[i] is IShowCollection) continue; + items.Add(this[i]); + } + + return items; + } + /// /// Returns a object with this name or the default, if not available. /// Not reclusive. /// /// /// - public TItem GetItemByName(string name) + public IShowItem GetItemByName(string name) { - TItem obj = default; + IShowItem obj = default; for (var i = 0; i < Count; i++) if (this[i].Name == name) { @@ -148,7 +173,7 @@ namespace SM.Base.Scene /// /// Type of return public TGetItem GetItemByName(string name) - where TGetItem : TItem + where TGetItem : IShowItem { return (TGetItem) GetItemByName(name); } @@ -157,9 +182,9 @@ namespace SM.Base.Scene /// Returns all object that have this flag. /// Only in this list. /// - public ICollection GetItemsWithFlag(string flag) + public ICollection GetItemsWithFlag(string flag) { - var list = new List(); + var list = new List(); for (var i = 0; i < Count; i++) { var obj = this[i]; @@ -176,19 +201,19 @@ namespace SM.Base.Scene /// /// The type of show items. /// The type of transformation. - public abstract class GenericItemCollection : GenericItemCollection - where TItem : IShowItem + public abstract class GenericItemCollection : GenericItemCollection, IShowTransformItem where TTransformation : GenericTransformation, new() { /// /// Transformation of the collection /// - public TTransformation Transform = new TTransformation(); + public TTransformation Transform { get; set; } = new TTransformation(); /// public override void Draw(DrawContext context) { - context.ModelMaster = Transform.GetMatrix() * context.ModelMaster; + Transform.LastMaster = context.ModelMatrix; + context.ModelMatrix = Transform.MergeMatrix(context.ModelMatrix); base.Draw(context); } diff --git a/SMCode/SM.Base/Scene/GenericScene.cs b/SMCode/SM.Base/Scene/GenericScene.cs index 5b17a44..edff7fa 100644 --- a/SMCode/SM.Base/Scene/GenericScene.cs +++ b/SMCode/SM.Base/Scene/GenericScene.cs @@ -3,8 +3,11 @@ using System; using System.Collections.Generic; using System.Dynamic; -using SM.Base.Contexts; +using System.Windows.Controls; +using SM.Base; using SM.Base.Drawing; +using SM.Base.Windows; +using SM.Utility; #endregion @@ -13,8 +16,11 @@ namespace SM.Base.Scene /// /// A generic scene, that imports functions for scene control. /// - public abstract class GenericScene + public abstract class GenericScene : IInitializable { + + private GenericItemCollection _hud; + private GenericItemCollection _objectCollection; private IBackgroundItem _background; private Dictionary _extensions = new Dictionary(); @@ -32,11 +38,31 @@ namespace SM.Base.Scene } /// - /// The active camera, that is used if the context doesn't force the viewport camera. - /// If none set, it automaticly uses the viewport camera. + /// Objects inside the scene. /// - internal GenericCamera _camera { get; set; } - + public GenericItemCollection Objects + { + get => _objectCollection; + set + { + value.Parent = this; + _objectCollection = value; + } + } + + /// + /// This defines the HUD objects. + /// + public GenericItemCollection HUD + { + get => _hud; + set + { + value.Parent = this; + _hud = value; + } + } + /// /// A collection for cameras to switch easier to different cameras. /// @@ -45,15 +71,38 @@ namespace SM.Base.Scene /// /// If true, the scene was already initialized. /// - public bool IsInitialized { get; private set; } + public bool IsInitialized { get; set; } + /// + /// If true, shows a axis helper at (0,0,0) + /// + public bool ShowAxisHelper { get; set; } = false; + + /// + /// The active camera, that is used if the context doesn't force the viewport camera. + /// If none set, it automaticly uses the viewport camera. + /// + public GenericCamera Camera { get; set; } + + /// + /// A camera to control the background. + /// + public GenericCamera BackgroundCamera { get; set; } + + /// + /// A camera to control the HUD. + /// + public GenericCamera HUDCamera { get; set; } + /// /// Updates this scene. /// /// public virtual void Update(UpdateContext context) { + _objectCollection?.Update(context); + _hud?.Update(context); } /// @@ -61,15 +110,61 @@ namespace SM.Base.Scene /// public virtual void Draw(DrawContext context) { + DrawBackground(context); + + DrawMainObjects(context); + + DrawHUD(context); + DrawDebug(context); } - + + /// + /// Draws only the background. + /// + /// + public void DrawBackground(DrawContext context) + { + var backgroundDrawContext = context; + backgroundDrawContext.SetCamera(BackgroundCamera); + _Background?.Draw(backgroundDrawContext); + } + + /// + /// Draws only the main objects + /// + /// + public void DrawMainObjects(DrawContext context) + { + if (!context.Window.ForceViewportCamera && Camera != null) context.SetCamera(Camera); + _objectCollection.Draw(context); + } + + /// + /// Draws only the HUD + /// + /// + public void DrawHUD(DrawContext context) + { + context.SetCamera(HUDCamera); + _hud?.Draw(context); + } + + /// + /// Draw the debug informations. + /// + /// + public virtual void DrawDebug(DrawContext context) + { + + } + /// /// Adds a extension to the scene. /// /// public virtual void SetExtension(object extension) { - _extensions[extension.GetType()] = extension; + _extensions[extension.GetType()] = extension; } /// @@ -89,32 +184,19 @@ namespace SM.Base.Scene return (T)ext; } - - /// - /// Called, when the user activates the scene. - /// - internal void Activate() - { - if (!IsInitialized) - { - OnInitialization(); - IsInitialized = true; - } - OnActivating(); + + public virtual void Activate() + { + } - /// - /// Called, when the user activates the scene for the first time. - /// - protected virtual void OnInitialization() - { } + public virtual void Initialization() + { - /// - /// Called, when the user activates the scene. - /// - protected virtual void OnActivating() - { } + } + + public virtual void Deactivate() {} } /// @@ -123,117 +205,43 @@ namespace SM.Base.Scene /// The type of cameras. /// The type of show items. /// The type for collections - public abstract class GenericScene : GenericScene + public abstract class GenericScene : GenericScene where TCamera : GenericCamera, new() - where TCollection : GenericItemCollection, new() - where TItem : IShowItem + where TCollection : GenericItemCollection, new() { - private TCollection _hud = new TCollection(); - private TCollection _objectCollection = new TCollection(); - - /// - /// If true, shows a axis helper at (0,0,0) - /// - public bool ShowAxisHelper { get; set; } = false; - - /// - /// The active camera, that is used if the context doesn't force the viewport camera. - /// If none set, it automaticly uses the viewport camera. - /// - public TCamera Camera => (TCamera) _camera; - - /// - /// A camera to control the background. - /// - public TCamera BackgroundCamera { get; set; } = new TCamera(); - - /// - /// A camera to control the HUD. - /// - public TCamera HUDCamera { get; set; } = new TCamera(); - - /// - /// Objects inside the scene. - /// - public TCollection Objects + public new TCollection Objects { - get => _objectCollection; - set + get => (TCollection) base.Objects; + set => base.Objects = value; + } + + public new TCollection HUD + { + get { - value.Parent = this; - _objectCollection = value; + base.HUD ??= new TCollection(); + return (TCollection) base.HUD; } + set => base.HUD = value; } - /// - /// This defines the HUD objects. - /// - public TCollection HUD + public new TCamera Camera { - get => _hud; - set - { - value.Parent = this; - _hud = value; - } + get => (TCamera) base.Camera; + set => base.Camera = value; } - /// - public override void Update(UpdateContext context) + public new TCamera HUDCamera { - _objectCollection.Update(context); - _hud.Update(context); + get => (TCamera) base.HUDCamera; + set => base.HUDCamera = value; } - /// - public override void Draw(DrawContext context) + public new TCamera BackgroundCamera { - DrawBackground(context); - - DrawMainObjects(context); - - DrawHUD(context); - DrawDebug(context); + get => (TCamera) base.BackgroundCamera; + set => base.BackgroundCamera = value; } - /// - /// Draws only the background. - /// - /// - public void DrawBackground(DrawContext context) - { - var backgroundDrawContext = context; - backgroundDrawContext.View = BackgroundCamera.CalculateViewMatrix(); - _Background?.Draw(backgroundDrawContext); - } - - /// - /// Draws only the main objects - /// - /// - public void DrawMainObjects(DrawContext context) - { - if (!context.ForceViewport && Camera != null) context.View = Camera.CalculateViewMatrix(); - _objectCollection.Draw(context); - } - - /// - /// Draws only the HUD - /// - /// - public void DrawHUD(DrawContext context) - { - context.View = HUDCamera.CalculateViewMatrix(); - _hud.Draw(context); - } - - /// - /// Draw the debug informations. - /// - /// - public virtual void DrawDebug(DrawContext context) - { - - } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Scene/IScriptable.cs b/SMCode/SM.Base/Scene/IScriptable.cs index 2772e3f..5c6087a 100644 --- a/SMCode/SM.Base/Scene/IScriptable.cs +++ b/SMCode/SM.Base/Scene/IScriptable.cs @@ -1,4 +1,5 @@ -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; namespace SM.Base.Scene { @@ -7,6 +8,8 @@ namespace SM.Base.Scene /// public interface IScriptable { + bool Active { get; set; } + /// /// Updates the object. /// diff --git a/SMCode/SM.Base/Scene/IShowCollection.cs b/SMCode/SM.Base/Scene/IShowCollection.cs index 19066b7..aac9a3f 100644 --- a/SMCode/SM.Base/Scene/IShowCollection.cs +++ b/SMCode/SM.Base/Scene/IShowCollection.cs @@ -1,7 +1,8 @@ #region usings using System.Collections.Generic; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; #endregion @@ -11,12 +12,12 @@ namespace SM.Base.Scene /// Adds functions, that is required for a collection. /// /// The type of show item. - public interface IShowCollection where TItem : IShowItem + public interface IShowCollection { /// /// The object collection. /// - List Objects { get; } + List Objects { get; } /// /// This draws the objects in the list. diff --git a/SMCode/SM.Base/Scene/IShowItem.cs b/SMCode/SM.Base/Scene/IShowItem.cs index b698073..6d3bd00 100644 --- a/SMCode/SM.Base/Scene/IShowItem.cs +++ b/SMCode/SM.Base/Scene/IShowItem.cs @@ -1,7 +1,10 @@ #region usings using System.Collections.Generic; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Drawing; +using SM.Base.Windows; +using SM.OGL.Mesh; #endregion @@ -26,6 +29,8 @@ namespace SM.Base.Scene /// Contains specific flags for the object. /// ICollection Flags { get; set; } + + bool Active { get; set; } /// /// Tells the object to draw its object. @@ -43,4 +48,19 @@ namespace SM.Base.Scene /// void OnRemoved(object sender); } + + public interface ITransformItem + where TTransform : GenericTransformation + { + TTransform Transform { get; set; } + } + + public interface IShowTransformItem : IShowItem, ITransformItem + where TTransform : GenericTransformation + {} + + public interface IModelItem + { + GenericMesh Mesh { get; set; } + } } \ No newline at end of file diff --git a/SMCode/SM.Base/ShaderExtension/ExtensionManager.cs b/SMCode/SM.Base/Shaders/Extensions/ExtensionManager.cs similarity index 93% rename from SMCode/SM.Base/ShaderExtension/ExtensionManager.cs rename to SMCode/SM.Base/Shaders/Extensions/ExtensionManager.cs index 2999fca..c538b49 100644 --- a/SMCode/SM.Base/ShaderExtension/ExtensionManager.cs +++ b/SMCode/SM.Base/Shaders/Extensions/ExtensionManager.cs @@ -10,7 +10,7 @@ namespace SM.Base.ShaderExtension { internal static void InitExtensions() { - ShaderExtensions.AddAssemblyExtensions("SM_base", "SM.Base.ShaderExtension"); + ShaderExtensions.AddAssemblyExtensions("SM_base", "SM.Base.Shaders.Extensions"); ShaderExtensions.Extensions["SM_base_vertex_basic"].StringOverrides["instanceMax"] = SMRenderer.MaxInstances.ToString(); diff --git a/SMCode/SM.Base/Shaders/Extensions/fragment/noise.glsl b/SMCode/SM.Base/Shaders/Extensions/fragment/noise.glsl new file mode 100644 index 0000000..563d88e --- /dev/null +++ b/SMCode/SM.Base/Shaders/Extensions/fragment/noise.glsl @@ -0,0 +1,71 @@ +#version 330 + +// Permute +vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } +vec4 permute(vec4 x){return mod(((x*34.0)+1.0)*x, 289.0);} + +// Classic Perlin 2D Noise +// by Stefan Gustavson +vec2 fade(vec2 t) {return t*t*t*(t*(t*6.0-15.0)+10.0);} + +float ClassicPerlinNoise(vec2 P){ + vec4 Pi = floor(P.xyxy) + vec4(0.0, 0.0, 1.0, 1.0); + vec4 Pf = fract(P.xyxy) - vec4(0.0, 0.0, 1.0, 1.0); + Pi = mod(Pi, 289.0); // To avoid truncation effects in permutation + vec4 ix = Pi.xzxz; + vec4 iy = Pi.yyww; + vec4 fx = Pf.xzxz; + vec4 fy = Pf.yyww; + vec4 i = permute(permute(ix) + iy); + vec4 gx = 2.0 * fract(i * 0.0243902439) - 1.0; // 1/41 = 0.024... + vec4 gy = abs(gx) - 0.5; + vec4 tx = floor(gx + 0.5); + gx = gx - tx; + vec2 g00 = vec2(gx.x,gy.x); + vec2 g10 = vec2(gx.y,gy.y); + vec2 g01 = vec2(gx.z,gy.z); + vec2 g11 = vec2(gx.w,gy.w); + vec4 norm = 1.79284291400159 - 0.85373472095314 * + vec4(dot(g00, g00), dot(g01, g01), dot(g10, g10), dot(g11, g11)); + g00 *= norm.x; + g01 *= norm.y; + g10 *= norm.z; + g11 *= norm.w; + float n00 = dot(g00, vec2(fx.x, fy.x)); + float n10 = dot(g10, vec2(fx.y, fy.y)); + float n01 = dot(g01, vec2(fx.z, fy.z)); + float n11 = dot(g11, vec2(fx.w, fy.w)); + vec2 fade_xy = fade(Pf.xy); + vec2 n_x = mix(vec2(n00, n01), vec2(n10, n11), fade_xy.x); + float n_xy = mix(n_x.x, n_x.y, fade_xy.y); + return 2.3 * n_xy; +} + +// Simplex 2D noise + +float SimplexNoise(vec2 v){ + const vec4 C = vec4(0.211324865405187, 0.366025403784439, + -0.577350269189626, 0.024390243902439); + vec2 i = floor(v + dot(v, C.yy) ); + vec2 x0 = v - i + dot(i, C.xx); + vec2 i1; + i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + vec4 x12 = x0.xyxy + C.xxzz; + x12.xy -= i1; + i = mod(i, 289.0); + vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + + i.x + vec3(0.0, i1.x, 1.0 )); + vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), + dot(x12.zw,x12.zw)), 0.0); + m = m*m ; + m = m*m ; + vec3 x = 2.0 * fract(p * C.www) - 1.0; + vec3 h = abs(x) - 0.5; + vec3 ox = floor(x + 0.5); + vec3 a0 = x - ox; + m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); + vec3 g; + g.x = a0.x * x0.x + h.x * x0.y; + g.yz = a0.yz * x12.xz + h.yz * x12.yw; + return 130.0 * dot(m, g); +} \ No newline at end of file diff --git a/SMCode/SM.Base/Shaders/Extensions/fragment/textureGamma.glsl b/SMCode/SM.Base/Shaders/Extensions/fragment/textureGamma.glsl new file mode 100644 index 0000000..9027b61 --- /dev/null +++ b/SMCode/SM.Base/Shaders/Extensions/fragment/textureGamma.glsl @@ -0,0 +1,8 @@ +#version 330 + +uniform float Gamma; + +vec4 texture2DGamma(sampler2D s, vec2 P) { + vec4 tex = texture2D(s, P); + return vec4(pow(tex.rgb, vec3(Gamma)), tex.a); +} \ No newline at end of file diff --git a/SMCode/SM.Base/ShaderExtension/vertex/basic.vert b/SMCode/SM.Base/Shaders/Extensions/vertex/basic.vert similarity index 100% rename from SMCode/SM.Base/ShaderExtension/vertex/basic.vert rename to SMCode/SM.Base/Shaders/Extensions/vertex/basic.vert diff --git a/SMCode/SM.Base/Drawing/MaterialShader.cs b/SMCode/SM.Base/Shaders/MaterialShader.cs similarity index 68% rename from SMCode/SM.Base/Drawing/MaterialShader.cs rename to SMCode/SM.Base/Shaders/MaterialShader.cs index bb14df0..ba4b142 100644 --- a/SMCode/SM.Base/Drawing/MaterialShader.cs +++ b/SMCode/SM.Base/Shaders/MaterialShader.cs @@ -1,7 +1,9 @@ #region usings using OpenTK.Graphics.OpenGL4; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; +using SM.OGL.Mesh; using SM.OGL.Shaders; #endregion @@ -33,17 +35,22 @@ namespace SM.Base.Drawing /// The context public virtual void Draw(DrawContext context) { - GL.UseProgram(this); + context.Shader.Activate(); - GL.BindVertexArray(context.Mesh); + context.Mesh.Activate(); + + if (context.Mesh is ILineMesh lineMesh) + GL.LineWidth(context.Material.ShaderArguments.Get("LineWidth", lineMesh.LineWidth)); + + if (context.Material.Blending) + { + GL.Enable(EnableCap.Blend); + GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); + } else GL.Disable(EnableCap.Blend); DrawProcess(context); CleanUp(); - - GL.UseProgram(0); - - context.ShaderArguments.Clear(); } /// diff --git a/SMCode/SM.Base/Shaders/SimpleShader.cs b/SMCode/SM.Base/Shaders/SimpleShader.cs new file mode 100644 index 0000000..27dbf9d --- /dev/null +++ b/SMCode/SM.Base/Shaders/SimpleShader.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Dynamic; +using SM.Base.Windows; +using SM.OGL.Shaders; +using SM.Utility; + +namespace SM.Base.Drawing +{ + public class SimpleShader : MaterialShader + { + public static Dictionary>> VertexFiles = + new Dictionary>>(); + + static ShaderFile _extensionDefineFile = new ShaderFile("#define SM_SIMPLE_EXTENSION"); + + static SimpleShader() + { + VertexFiles.Add("basic", new Tuple>( + new ShaderFile(AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl")) + { + StringOverrides = {["extension"] = "0"} + }, + BasicSetUniforms + )); + VertexFiles.Add("E_basic", new Tuple>( + new ShaderFile(AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl")) + { + StringOverrides = {["extension"] = "1"} + }, + BasicSetUniforms + )); + + VertexFiles.Add("instanced", new Tuple>( + new ShaderFile( + AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.instanced_vertex.glsl")) + { + StringOverrides = { ["instanceMax"] = SMRenderer.MaxInstances.ToString(), ["extension"] = "0" } + }, + InstancedSetUniforms + )); + VertexFiles.Add("E_instanced", new Tuple>( + new ShaderFile( + AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.instanced_vertex.glsl")) + { + StringOverrides = { ["instanceMax"] = SMRenderer.MaxInstances.ToString(), ["extension"] = "0" } + }, + InstancedSetUniforms + )); + } + + static void BasicSetUniforms(UniformCollection uniforms, DrawContext context) + { + // Vertex Uniforms + uniforms["MVP"].SetMatrix4(context.Instances[0].ModelMatrix * context.ModelMatrix * context.View * context.World); + uniforms["MasterTextureMatrix"].SetMatrix3(context.Instances[0].TextureMatrix * context.TextureMatrix); + uniforms["HasVColor"] + .SetUniform1(context.Mesh.Attributes.Has("color")); + + DrawObject(context.Mesh); + } + + static void InstancedSetUniforms(UniformCollection uniforms, DrawContext context) + { + uniforms["MVP"].SetMatrix4(context.ModelMatrix * context.View * context.World); + uniforms["MasterTextureMatrix"].SetMatrix3(context.TextureMatrix); + uniforms["HasVColor"] + .SetUniform1(context.Mesh.Attributes.Has("color")); + + UniformArray instances = uniforms.GetArray("Instances"); + + int shaderInstanceI = 0; + for (int i = 0; i < context.Instances.Count; i++) + { + if (shaderInstanceI > instances.Length - 1) + { + DrawObject(context.Mesh, instances.Length); + shaderInstanceI = 0; + } + + var shaderInstance = instances[shaderInstanceI]; + var instance = context.Instances[i]; + if (instance == null) continue; + shaderInstance["ModelMatrix"].SetMatrix4(instance.ModelMatrix); + shaderInstance["TextureMatrix"].SetMatrix3(instance.TextureMatrix); + + shaderInstanceI++; + } + DrawObject(context.Mesh, shaderInstanceI); + } + + private string _vertexPreset; + + public Action SetUniform; + + public SimpleShader(string vertexPreset, string fragment, Action setUniform) : base(new ShaderFileCollection(VertexFiles[vertexPreset].Item1, new ShaderFile(fragment))) + { + _vertexPreset = vertexPreset; + SetUniform = setUniform; + } + + public SimpleShader(string vertexPreset, string vertexExtension, string fragment, + Action setUniform) : base(new ShaderFileCollection( + new[] {VertexFiles["E_"+vertexPreset].Item1, new ShaderFile(vertexExtension)}, + new[] {new ShaderFile(fragment),})) + { + _vertexPreset = vertexPreset; + SetUniform = setUniform; + } + + protected override void DrawProcess(DrawContext context) + { + SetUniform?.Invoke(Uniforms, context); + + VertexFiles[_vertexPreset].Item2(Uniforms, context); + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Shaders/SimpleShaderPresets/basic_vertex.glsl b/SMCode/SM.Base/Shaders/SimpleShaderPresets/basic_vertex.glsl new file mode 100644 index 0000000..503fb5a --- /dev/null +++ b/SMCode/SM.Base/Shaders/SimpleShaderPresets/basic_vertex.glsl @@ -0,0 +1,32 @@ +#version 330 +#define SM_SIMPLE_EXTENSION //!extension + +layout(location = 0) in vec3 a_Position; +layout(location = 1) in vec2 a_Texture; +layout(location = 3) in vec4 a_Color; + +uniform bool HasVColor; +uniform mat4 MVP; +uniform mat3 MasterTextureMatrix; + +out vec3 v_VertexPosition; +out vec2 v_TexCoords; +out vec4 v_Color; + +#if (SM_SIMPLE_EXTENSION == 1) +void v_Extension(); +#endif + +void main() { + v_Color = vec4(1); + if (HasVColor) v_Color = a_Color; + + v_TexCoords = vec2(MasterTextureMatrix * vec3(a_Texture, 1)); + + v_VertexPosition = a_Position; + gl_Position = MVP * vec4(a_Position, 1); + + #if (SM_SIMPLE_EXTENSION == 1) + v_Extension(); + #endif +} \ No newline at end of file diff --git a/SMCode/SM.Base/Shaders/SimpleShaderPresets/instanced_vertex.glsl b/SMCode/SM.Base/Shaders/SimpleShaderPresets/instanced_vertex.glsl new file mode 100644 index 0000000..3565cf6 --- /dev/null +++ b/SMCode/SM.Base/Shaders/SimpleShaderPresets/instanced_vertex.glsl @@ -0,0 +1,39 @@ +#version 330 +#define maxInstances //!instanceMax +#define SM_SIMPLE_EXTENSION //!extension + +struct Instance { + mat4 ModelMatrix; + mat3 TextureMatrix; +}; + +layout(location = 0) in vec3 a_Position; +layout(location = 1) in vec2 a_Texture; +layout(location = 3) in vec4 a_Color; + +uniform mat4 MVP; +uniform mat3 MasterTextureMatrix; +uniform Instance[maxInstances] Instances; +uniform bool HasVColor; + +out vec3 v_VertexPosition; +out vec2 v_TexCoords; +out vec4 v_Color; + +#if (SM_SIMPLE_EXTENSION == 1) +void v_Extension(); +#endif + +void main() { + v_Color = vec4(1); + if (HasVColor) v_Color = a_Color; + + v_TexCoords = vec2(MasterTextureMatrix * Instances[gl_InstanceID].TextureMatrix * vec3(a_Texture, 1)); + + v_VertexPosition = a_Position; + gl_Position = MVP * Instances[gl_InstanceID].ModelMatrix * vec4(a_Position, 1); + + #if (SM_SIMPLE_EXTENSION == 1) + v_Extension(); + #endif +} \ No newline at end of file diff --git a/SMCode/SM.Base/Time/Interval.cs b/SMCode/SM.Base/Time/Interval.cs index 663aa90..ea24f1f 100644 --- a/SMCode/SM.Base/Time/Interval.cs +++ b/SMCode/SM.Base/Time/Interval.cs @@ -1,7 +1,8 @@ #region usings using System; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; #endregion diff --git a/SMCode/SM.Base/Time/Stopwatch.cs b/SMCode/SM.Base/Time/Stopwatch.cs index 667a100..1eb8525 100644 --- a/SMCode/SM.Base/Time/Stopwatch.cs +++ b/SMCode/SM.Base/Time/Stopwatch.cs @@ -2,7 +2,8 @@ using System; using System.Collections.Generic; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; #endregion diff --git a/SMCode/SM.Base/Time/Timer.cs b/SMCode/SM.Base/Time/Timer.cs index 7eec1ca..9d73bbc 100644 --- a/SMCode/SM.Base/Time/Timer.cs +++ b/SMCode/SM.Base/Time/Timer.cs @@ -2,7 +2,8 @@ using System; using System.Diagnostics.Eventing.Reader; -using SM.Base.Contexts; +using SM.Base; +using SM.Base.Windows; #endregion diff --git a/SMCode/SM.Base/Types/CVector1.cs b/SMCode/SM.Base/Types/CVector1.cs index 62687d4..0e8b19e 100644 --- a/SMCode/SM.Base/Types/CVector1.cs +++ b/SMCode/SM.Base/Types/CVector1.cs @@ -7,11 +7,15 @@ namespace SM.Base.Types /// A One-dimensional Vector (also known as ), in a class. /// public class CVector1 - { + { /// /// X - Component /// - public float X { get; set; } + public float X + { + get; + set; + } /// /// The length/magnitute of the vector. @@ -26,6 +30,8 @@ namespace SM.Base.Types /// public float LengthSquared => GetLength(true); + public event Action Changed; + /// /// Creates a class vector /// @@ -63,14 +69,16 @@ namespace SM.Base.Types /// Sets the X-Component. /// /// X-Component - public virtual void Set(float uniform) + public virtual void Set(float uniform, bool triggerChanged = true) { X = uniform; + if (triggerChanged) TriggerChanged(); } - public virtual void Add(float uniform) + public virtual void Add(float uniform, bool triggerChanged = true) { X += uniform; + if (triggerChanged) TriggerChanged(); } /// @@ -82,15 +90,20 @@ namespace SM.Base.Types /// /// /// - public static implicit operator CVector1(float f) => new CVector1(f); + //public static implicit operator CVector1(float f) => new CVector1(f); - private protected virtual float GetLengthProcess() + protected virtual float GetLengthProcess() { return X * X; } - private protected virtual void NormalizationProcess(float length) + protected virtual void NormalizationProcess(float length) { X *= length; } + + protected void TriggerChanged() + { + Changed?.Invoke(); + } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Types/CVector2.cs b/SMCode/SM.Base/Types/CVector2.cs index 00ec717..a670c88 100644 --- a/SMCode/SM.Base/Types/CVector2.cs +++ b/SMCode/SM.Base/Types/CVector2.cs @@ -29,12 +29,12 @@ namespace SM.Base.Types Y = y; } - private protected override float GetLengthProcess() + protected override float GetLengthProcess() { return base.GetLengthProcess() + Y * Y; } - private protected override void NormalizationProcess(float length) + protected override void NormalizationProcess(float length) { base.NormalizationProcess(length); Y *= length; @@ -44,19 +44,19 @@ namespace SM.Base.Types /// Sets each component to the same value /// /// - public override void Set(float uniform) + public override void Set(float uniform, bool triggerChanged = true) { - base.Set(uniform); Y = uniform; + base.Set(uniform, triggerChanged); } /// /// Sets each component to the counter-part. /// /// - public void Set(Vector2 vector) + public void Set(Vector2 vector, bool triggerChanged = true) { - Set(vector.X, vector.Y); + Set(vector.X, vector.Y, triggerChanged); } /// @@ -64,27 +64,27 @@ namespace SM.Base.Types /// /// /// - public void Set(float x, float y) + public void Set(float x, float y, bool triggerChanged = true) { - base.Set(x); Y = y; + base.Set(x, triggerChanged); } - public override void Add(float uniform) + public override void Add(float uniform, bool triggerChanged = true) { - base.Add(uniform); Y += uniform; + base.Add(uniform, triggerChanged); } - public void Add(Vector2 vector) + public void Add(Vector2 vector, bool triggerChanged = true) { - Add(vector.X, vector.Y); + Add(vector.X, vector.Y, triggerChanged); } - public void Add(float x, float y) + public void Add(float x, float y, bool triggerChanged = true) { - base.Add(x); Y += y; + base.Add(x, triggerChanged); } /// diff --git a/SMCode/SM.Base/Types/CVector3.cs b/SMCode/SM.Base/Types/CVector3.cs index f139743..6510bcd 100644 --- a/SMCode/SM.Base/Types/CVector3.cs +++ b/SMCode/SM.Base/Types/CVector3.cs @@ -28,56 +28,56 @@ namespace SM.Base.Types Z = z; } - private protected override float GetLengthProcess() + protected override float GetLengthProcess() { return base.GetLengthProcess() + Z * Z; } - private protected override void NormalizationProcess(float length) + protected override void NormalizationProcess(float length) { base.NormalizationProcess(length); Z *= length; } /// - public override void Set(float uniform) + public override void Set(float uniform, bool triggerChanged = true) { - base.Set(uniform); Z = uniform; + base.Set(uniform, triggerChanged); } /// /// Sets the a own value to each component. /// - public void Set(float x, float y, float z) + public void Set(float x, float y, float z, bool triggerChanged = true) { - base.Set(x,y); Z = z; + base.Set(x,y, triggerChanged); } /// /// Sets each component to the counter-part. /// /// - public void Set(Vector3 vector) + public void Set(Vector3 vector, bool triggerChanged = true) { - Set(vector.X, vector.Y, vector.Z); + Set(vector.X, vector.Y, vector.Z, triggerChanged); } - public override void Add(float uniform) + public override void Add(float uniform, bool triggerChanged = true) { - base.Add(uniform); Z += uniform; + base.Add(uniform, triggerChanged); } - public void Add(Vector3 vector) + public void Add(Vector3 vector, bool triggerChanged = true) { - Add(vector.X, vector.Y, vector.Z); + Add(vector.X, vector.Y, vector.Z, triggerChanged); } - public void Add(float x, float y, float z) + public void Add(float x, float y, float z, bool triggerChanged = true) { - base.Add(x,y); Z += z; + base.Add(x,y, triggerChanged); } /// diff --git a/SMCode/SM.Base/Utility/IInitializable.cs b/SMCode/SM.Base/Utility/IInitializable.cs new file mode 100644 index 0000000..325222a --- /dev/null +++ b/SMCode/SM.Base/Utility/IInitializable.cs @@ -0,0 +1,10 @@ +namespace SM.Utility +{ + public interface IInitializable + { + bool IsInitialized { get; set; } + + void Activate(); + void Initialization(); + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Utility/Util.cs b/SMCode/SM.Base/Utility/Util.cs new file mode 100644 index 0000000..eb1d275 --- /dev/null +++ b/SMCode/SM.Base/Utility/Util.cs @@ -0,0 +1,15 @@ +namespace SM.Utility +{ + public class Util + { + public static void Activate(IInitializable obj) + { + if (!obj.IsInitialized) + { + obj.Initialization(); + obj.IsInitialized = true; + } + obj.Activate(); + } + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Window/Contexts/DrawContext.cs b/SMCode/SM.Base/Window/Contexts/DrawContext.cs index cb449f5..eaf6930 100644 --- a/SMCode/SM.Base/Window/Contexts/DrawContext.cs +++ b/SMCode/SM.Base/Window/Contexts/DrawContext.cs @@ -1,103 +1,33 @@ -#region usings - -using System.Collections.Generic; -using System.Dynamic; +using System.Collections.Generic; using OpenTK; using SM.Base.Drawing; using SM.Base.Scene; using SM.OGL.Mesh; -#endregion - -namespace SM.Base.Contexts +namespace SM.Base.Windows { - /// - /// Contains important information for drawing. - /// public struct DrawContext { - /// - /// This says if it was forced to use the viewport camera. - /// - public bool ForceViewport; + public IGenericWindow Window { get; internal set; } + public GenericScene Scene { get; internal set; } + public RenderPipeline RenderPipeline { get; internal set; } - /// - /// Contains the currently used render pipeline. - /// - public RenderPipeline ActivePipeline; + public GenericCamera UseCamera { get; internal set; } + public Matrix4 World => UseCamera.World; + public Matrix4 View => UseCamera.View; - public GenericScene ActiveScene; - public IGenericWindow Window; + public GenericMesh Mesh { get; set; } + public Material Material { get; set; } + public MaterialShader Shader => Material.CustomShader ?? RenderPipeline.DefaultShader; - - public GenericCamera UsedCamera => - ForceViewport || ActiveScene._camera == null ? Window.ViewportCamera : ActiveScene._camera; - - - - /// - /// The mesh. - /// - public GenericMesh Mesh; - - /// - /// The material. - /// - public Material Material; - - /// - /// The drawing instances. - /// If there is only one, it's index 0 - /// + public Matrix4 ModelMatrix; + public Matrix3 TextureMatrix; public IList Instances; - - - /// - /// The current world scale. - /// - public Vector2 WorldScale; - - /// - /// The last collection the context was passed though. - /// - public object LastPassthough; - - - - /// - /// Returns the appropriate shader. - /// - /// Returns the material shader, if available, otherwise it will take the default shader from the render - /// pipeline. - /// - /// - public MaterialShader Shader => Material.CustomShader ?? ActivePipeline._defaultShader; - /// - /// Arguments for shaders - /// - public IDictionary ShaderArguments; - - - - /// - /// The current world matrix. - /// - public Matrix4 World; - - /// - /// The current view matrix. - /// - public Matrix4 View; - - /// - /// The current WorldView matrix. - /// - public Matrix4 WorldView; - - /// - /// The master model matrix. - /// - public Matrix4 ModelMaster; + public void SetCamera(GenericCamera camera) + { + UseCamera = camera; + camera.CalculateViewMatrix(Window); + } } } \ No newline at end of file diff --git a/SMCode/SM.Base/Window/Contexts/UpdateContext.cs b/SMCode/SM.Base/Window/Contexts/UpdateContext.cs index 63eb913..be0e7a6 100644 --- a/SMCode/SM.Base/Window/Contexts/UpdateContext.cs +++ b/SMCode/SM.Base/Window/Contexts/UpdateContext.cs @@ -1,32 +1,14 @@ -#region usings - -using OpenTK.Input; +using OpenTK.Input; using SM.Base.Scene; -#endregion - -namespace SM.Base.Contexts +namespace SM.Base.Windows { - /// - /// The update context. - /// public struct UpdateContext { - /// - /// The delta time. - /// + public IGenericWindow Window; + public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime; - /// - /// The current keyboard state. - /// - public KeyboardState KeyboardState; - - /// - /// The current mouse state. - /// - public MouseState MouseState; - - public GenericScene CurrentScene; + public GenericScene Scene; } } \ No newline at end of file diff --git a/SMCode/SM.Base/Window/GLWindow.cs b/SMCode/SM.Base/Window/GLWindow.cs new file mode 100644 index 0000000..b60a14c --- /dev/null +++ b/SMCode/SM.Base/Window/GLWindow.cs @@ -0,0 +1,130 @@ +using System; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Input; +using SM.Base.Controls; +using SM.Base.Scene; +using SM.OGL; +using Mouse = SM.Base.Controls.Mouse; + +namespace SM.Base.Windows +{ + public class GLWindow : GameWindow, IGenericWindow + { + public bool Loading { get; private set; } = true; + public float AspectRatio { get; set; } + public float AspectRatioReverse { get; set; } + + public GenericCamera ViewportCamera { get; set; } + public bool ForceViewportCamera { get; set; } + + public bool DrawWhileUnfocused { get; set; } = true; + public bool UpdateWhileUnfocused { get; set; } = false; + + public Vector2 WindowSize { get; set; } + + public ISetup AppliedSetup { get; private set; } + public event Action Resize; + public event Action Load; + public event Action Loaded; + + public GenericScene CurrentScene { get; private set; } + public RenderPipeline CurrentRenderPipeline { get; private set; } + + public GLWindow() : this(1280, 720, "Generic OpenGL Title", GameWindowFlags.Default) {} + + public GLWindow(int width, int height, string title, GameWindowFlags flags, VSyncMode vSync = VSyncMode.On) : + base(width, height, default, title, flags, DisplayDevice.Default, GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion, GraphicsContextFlags.Default) + { + VSync = vSync; + } + + protected override void OnLoad(EventArgs e) + { + WindowCode.Load(this); + SMRenderer.CurrentWindow = this; + + base.OnLoad(e); + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + WindowCode.Resize(this); + + if (Loading) + { + Loading = false; + Loaded?.Invoke(this); + AppliedSetup?.Loaded(this); + } + } + + protected override void OnUpdateFrame(FrameEventArgs e) + { + if (!Focused && !UpdateWhileUnfocused) return; + + base.OnUpdateFrame(e); + + WindowCode.Update(this, (float)e.Time); + } + + + protected override void OnRenderFrame(FrameEventArgs e) + { + base.OnRenderFrame(e); + + WindowCode.Render(this, (float)e.Time); + + SwapBuffers(); + + GLDebugging.CheckGLErrors(); + } + + protected override void OnMouseMove(MouseMoveEventArgs e) + { + base.OnMouseMove(e); + Mouse.MouseMoveEvent(e, this); + } + + public void Update(UpdateContext context) + { + + } + + public void ApplySetup(ISetup setup) + { + AppliedSetup = setup; + setup.Applied(this); + } + + public void SetScene(GenericScene scene) + { + if (Loading) + { + Loaded += window => SetScene(scene); + return; + } + + WindowCode.PrepareScene(this, scene); + CurrentScene = scene; + } + + public void SetRenderPipeline(RenderPipeline renderPipeline) + { + if (Loading) + { + Loaded += window => SetRenderPipeline(renderPipeline); + return; + } + + WindowCode.PreparePipeline(this, renderPipeline); + CurrentRenderPipeline = renderPipeline; + } + + public void TriggerLoad() => Load?.Invoke(this); + + public void TriggerResize() => Resize?.Invoke(this); + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Window/IGenericWindow.cs b/SMCode/SM.Base/Window/IGenericWindow.cs index bc93341..4d6d804 100644 --- a/SMCode/SM.Base/Window/IGenericWindow.cs +++ b/SMCode/SM.Base/Window/IGenericWindow.cs @@ -1,37 +1,48 @@ -using System.Drawing; -using System.Windows; +using System; +using System.Drawing; using OpenTK; +using SM.Base.Controls; using SM.Base.Scene; using SM.OGL.Framebuffer; -namespace SM.Base +namespace SM.Base.Windows { public interface IGenericWindow : IFramebufferWindow { bool Loading { get; } - float Aspect { get; set; } + float AspectRatio { get; set; } + float AspectRatioReverse { get; set; } - GenericCamera ViewportCamera { get; } + GenericCamera ViewportCamera { get; set; } bool ForceViewportCamera { get; set; } + bool DrawWhileUnfocused { get; set; } + bool UpdateWhileUnfocused { get; set; } + int Width { get; } int Height { get; } + Vector2 WindowSize { get; set; } Rectangle ClientRectangle { get; } - Vector2 WorldScale { get; set; } - void SetWorldScale(); - } + ISetup AppliedSetup { get; } - public interface IGenericWindow : IGenericWindow - where TScene : GenericScene, new() - where TCamera : GenericCamera, new() - { - TScene CurrentScene { get; } + event Action Resize; + event Action Load; - RenderPipeline RenderPipeline { get; } + GenericScene CurrentScene { get; } + RenderPipeline CurrentRenderPipeline { get; } - void SetScene(TScene scene); - void SetRenderPipeline(RenderPipeline renderPipeline); + void Update(UpdateContext context); + + void ApplySetup(ISetup setup); + + void SetScene(GenericScene scene); + void SetRenderPipeline(RenderPipeline renderPipeline); + + void TriggerLoad(); + void TriggerResize(); + + void Close(); } } \ No newline at end of file diff --git a/SMCode/SM.Base/Window/ISetup.cs b/SMCode/SM.Base/Window/ISetup.cs new file mode 100644 index 0000000..9b10c0c --- /dev/null +++ b/SMCode/SM.Base/Window/ISetup.cs @@ -0,0 +1,10 @@ +namespace SM.Base.Windows +{ + public interface ISetup + { + void Applied(IGenericWindow window); + void Load(IGenericWindow window); + void Loaded(IGenericWindow window); + void Resize(IGenericWindow window); + } +} \ No newline at end of file diff --git a/SMCode/SM.Base/Window/RenderPipeline.cs b/SMCode/SM.Base/Window/RenderPipeline.cs index 689511a..2777f10 100644 --- a/SMCode/SM.Base/Window/RenderPipeline.cs +++ b/SMCode/SM.Base/Window/RenderPipeline.cs @@ -1,150 +1,57 @@ -#region usings - -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading; -using SM.Base.Contexts; using SM.Base.Drawing; -using SM.Base.Scene; using SM.OGL.Framebuffer; +using SM.OGL.Texture; +using SM.Utility; -#endregion - -namespace SM.Base +namespace SM.Base.Windows { - /// - /// Definition of specific render options. - /// - public abstract class RenderPipeline + public abstract class RenderPipeline : IInitializable { - /// - /// If true, this pipeline was already once activated. - /// - public bool IsInitialized { get; private set; } = false; + public IGenericWindow ConnectedWindow { get; internal set; } - /// - /// The window the pipeline is connected to. - /// - protected IGenericWindow _window { get; private set; } + public Framebuffer MainFramebuffer { get; protected set; } - /// - /// The framebuffers, that are used in this Pipeline. - /// - public virtual List Framebuffers { get; private set; } + public List Framebuffers { get; } = new List(); - /// - /// The default shader for the pipeline. - /// - protected internal virtual MaterialShader _defaultShader { get; set; } + public virtual MaterialShader DefaultShader { get; protected set; } + public virtual Material DefaultMaterial { get; protected set; } - public virtual Framebuffer MainFramebuffer { get; protected set; }= Framebuffer.Screen; + public bool IsInitialized { get; set; } - /// - /// Occurs, when the window is loading. - /// - protected internal virtual void Load() - { - } + internal void Render(ref DrawContext context) => RenderProcess(ref context); - /// - /// Occurs, when the window is resizing. - /// - protected internal virtual void Resize() + protected abstract void RenderProcess(ref DrawContext context); + + public virtual void Resize() { if (Framebuffers == null) return; - - foreach (var framebuffer in Framebuffers) + foreach(var framebuffer in Framebuffers) framebuffer.Dispose(); Thread.Sleep(50); - foreach (Framebuffer framebuffer in Framebuffers) - { + foreach(var framebuffer in Framebuffers) framebuffer.Compile(); - } } - internal void Activate(IGenericWindow window) + public virtual void Activate() { - _window = window; - - if (!IsInitialized) - { - if (_defaultShader == null) _defaultShader = SMRenderer.DefaultMaterialShader; - Framebuffers = new List(); - - Initialization(window); - - Framebuffers.Add(MainFramebuffer); - - IsInitialized = true; - } - - Activation(window); + } - /// - /// Occurs, when the pipeline was connected to a window. - /// - protected internal virtual void Activation(IGenericWindow window) + public virtual void Initialization() { + if (MainFramebuffer != null) Framebuffers.Add(MainFramebuffer); + DefaultShader ??= SMRenderer.DefaultMaterialShader; } - - /// - /// Occurs, when the pipeline was connected to a window the first time. - /// - /// - protected internal virtual void Initialization(IGenericWindow window) + public Framebuffer CreateWindowFramebuffer(int multisamples) { - - } - - /// - /// Occurs, when the window is unloading. - /// - protected internal virtual void Unload() - { - } - - /// - /// Creates a framebuffer, that has specific (often) required settings already applied. - /// - /// - public static Framebuffer CreateWindowFramebuffer() - { - Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow); - framebuffer.Append("color", 0); + Framebuffer framebuffer = new Framebuffer(window: ConnectedWindow); + framebuffer.Append("color", new ColorAttachment(0, PixelInformation.RGBA_LDR, multisamples)); return framebuffer; } } - - /// - /// Represents a render pipeline. - /// - /// The scene type - public abstract class RenderPipeline : RenderPipeline - where TScene : GenericScene - { - /// - /// The system to render stuff. - /// - internal void Render(ref DrawContext context) - { - context.ActivePipeline = this; - if (context.ActiveScene == null) return; - - RenderProcess(ref context, (TScene)context.ActiveScene); - } - - protected abstract void RenderProcess(ref DrawContext context, TScene scene); - - /// - /// Event, that triggers, when the scene in the current window changes. - /// - /// - protected internal virtual void SceneChanged(TScene scene) - { - - } - } } \ No newline at end of file diff --git a/SMCode/SM.Base/Window/WindowCode.cs b/SMCode/SM.Base/Window/WindowCode.cs new file mode 100644 index 0000000..ea2c565 --- /dev/null +++ b/SMCode/SM.Base/Window/WindowCode.cs @@ -0,0 +1,133 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using OpenTK; +using OpenTK.Graphics.OpenGL4; +using OpenTK.Input; +using SM.Base.Drawing; +using SM.Base.Objects.Static; +using SM.Base.PostProcess; +using SM.Base.Scene; +using SM.Base.ShaderExtension; +using SM.Base.Time; +using SM.OGL; +using SM.Utility; +using Keyboard = SM.Base.Controls.Keyboard; + +namespace SM.Base.Windows +{ + internal class WindowCode + { + internal static void Load(IGenericWindow window) + { + GLSystem.INIT_SYSTEM(); + GLSettings.ShaderPreProcessing = true; + + var args = Environment.GetCommandLineArgs(); + if (args.Contains("--advDebugging")) + { + SMRenderer.AdvancedDebugging = true; + GLSettings.InfoEveryUniform = true; + } + + Log.Init(); + + Log.Write("#", ConsoleColor.Cyan, "----------------------", + "--- OpenGL Loading ---", + "----------------------------------", + $"--- {"DeviceVersion",14}: {GLSystem.DeviceVersion,-10} ---", + $"--- {"ForcedVersion",14}: {GLSettings.ForcedVersion,-10} ---", + $"--- {"ShadingVersion",14}: {GLSystem.ShadingVersion,-10} ---", + $"--- {"Debugging",14}: {GLSystem.Debugging,-10} ---", + $"--- {"AdvDebugging",14}: {SMRenderer.AdvancedDebugging,-10} ---", + "----------------------------------"); + + if (SMRenderer.AdvancedDebugging) Log.Write("Extension", ConsoleColor.DarkCyan, GLSystem.Extensions); + + ExtensionManager.InitExtensions(); + + window.TriggerLoad(); + window.AppliedSetup?.Load(window); + } + + internal static void Resize(IGenericWindow window) + { + window.WindowSize = new Vector2(window.Width, window.Height); + window.AspectRatio = (float) window.Width / window.Height; + window.AspectRatioReverse = (float) window.Height / window.Width; + GL.Viewport(window.ClientRectangle); + + window.CurrentRenderPipeline?.Resize(); + + PostProcessEffect.Mvp = Matrix4.CreateScale(window.Width, -window.Height, 1) * + Matrix4.LookAt(Vector3.UnitZ, Vector3.Zero, Vector3.UnitY) * + Matrix4.CreateOrthographic(window.Width, window.Height, .1f, 100f); + + window.AppliedSetup?.Resize(window); + } + + internal static void Update(IGenericWindow window, float deltatime) + { + Deltatime.UpdateDelta = deltatime; + SM.Base.Controls.Mouse.SetState(); + Controls.Keyboard.SetStage(); + var context = new UpdateContext() + { + Window = window, + + Scene = window.CurrentScene + }; + + if (Keyboard.IsDown(Key.AltLeft) && Keyboard.IsDown(Key.F4)) + { + window.Close(); + } + + Stopwatch.PerformTicks(context); + window.CurrentScene?.Update(context); + window.Update(context); + } + + internal static void Render(IGenericWindow window, float deltatime) + { + if (window.CurrentScene == null) return; + + SMRenderer.CurrentFrame++; + + Deltatime.RenderDelta = deltatime; + var drawContext = new DrawContext() + { + Window = window, + Scene = window.CurrentScene, + RenderPipeline = window.CurrentRenderPipeline, + + Mesh = Plate.Object, + Material = window.CurrentRenderPipeline.DefaultMaterial, + + ModelMatrix = Matrix4.Identity, + TextureMatrix = Matrix3.Identity, + Instances = new Instance[1] + { + new Instance() {ModelMatrix = Matrix4.Identity, TextureMatrix = Matrix3.Identity} + } + }; + drawContext.SetCamera(window.ViewportCamera); + + window.CurrentRenderPipeline?.Render(ref drawContext); + } + + internal static void PrepareScene(IGenericWindow window, GenericScene scene) + { + window.CurrentScene?.Deactivate(); + + Util.Activate(scene); + } + + internal static void PreparePipeline(IGenericWindow window, RenderPipeline pipeline) + { + pipeline.ConnectedWindow = window; + Util.Activate(pipeline); + } + } +} \ No newline at end of file diff --git a/SMCode/SM.OGL/Framebuffer/ColorAttachment.cs b/SMCode/SM.OGL/Framebuffer/ColorAttachment.cs index 75d98ad..3ef152b 100644 --- a/SMCode/SM.OGL/Framebuffer/ColorAttachment.cs +++ b/SMCode/SM.OGL/Framebuffer/ColorAttachment.cs @@ -14,20 +14,8 @@ namespace SM.OGL.Framebuffer /// public class ColorAttachment : TextureBase { - /// - /// Creates a attachment with a specific id. - /// - /// - public ColorAttachment(int attachmentId) : this(attachmentId, PixelInformation.RGBA_LDR) - { } - - public ColorAttachment(int attachmentID, PixelInformation pixelInformation) - { - - AttachmentID = attachmentID; - PixelInformation = pixelInformation; - } - + private int _multisamples; + /// /// The ID the attachment was given. /// @@ -50,6 +38,22 @@ namespace SM.OGL.Framebuffer /// public DrawBuffersEnum DrawBuffersEnum => DrawBuffersEnum.ColorAttachment0 + AttachmentID; + public bool IsMultisampled => _multisamples > 0; + + /// + /// Creates a attachment with a specific id. + /// + /// + public ColorAttachment(int attachmentId) : this(attachmentId, PixelInformation.RGBA_LDR) + { } + + public ColorAttachment(int attachmentID, PixelInformation pixelInformation, int multisamples = 0) + { + AttachmentID = attachmentID; + PixelInformation = pixelInformation; + _multisamples = multisamples; + Target = IsMultisampled ? TextureTarget.Texture2DMultisample : TextureTarget.Texture2D; + } /// /// Generates the attachment. /// @@ -57,20 +61,36 @@ namespace SM.OGL.Framebuffer public void Generate(Framebuffer f) { _id = GL.GenTexture(); + + if (IsMultisampled) GenerateMultisampledTexture(f); + else GenerateTexture(f); + } + + private void GenerateTexture(Framebuffer f) + { GL.BindTexture(TextureTarget.Texture2D, _id); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInformation.InternalFormat, - (int) f.Size.X, (int) f.Size.Y, + (int)f.Size.X, (int)f.Size.Y, 0, PixelInformation.Format, PixelInformation.DataType, IntPtr.Zero); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, - (int) TextureMinFilter.Linear); + (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, - (int) TextureMinFilter.Linear); + (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, - (int) TextureParameterName.ClampToEdge); + (int)TextureParameterName.ClampToEdge); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, - (int) TextureParameterName.ClampToEdge); + (int)TextureParameterName.ClampToEdge); + + GL.BindTexture(TextureTarget.Texture2D, 0); + } + + private void GenerateMultisampledTexture(Framebuffer f) + { + GL.BindTexture(TextureTarget.Texture2DMultisample, _id); + GL.TexImage2DMultisample(TextureTargetMultisample.Texture2DMultisample, _multisamples, PixelInformation.InternalFormat, (int)f.Size.X, (int)f.Size.Y, true); + GL.BindTexture(TextureTarget.Texture2DMultisample, 0); } } } \ No newline at end of file diff --git a/SMCode/SM.OGL/Framebuffer/Framebuffer.cs b/SMCode/SM.OGL/Framebuffer/Framebuffer.cs index e2f387d..1fdd3bf 100644 --- a/SMCode/SM.OGL/Framebuffer/Framebuffer.cs +++ b/SMCode/SM.OGL/Framebuffer/Framebuffer.cs @@ -14,6 +14,8 @@ namespace SM.OGL.Framebuffer /// public class Framebuffer : GLObject { + protected override bool AutoCompile { get; } = true; + /// /// Represents the screen buffer. /// @@ -92,7 +94,7 @@ namespace SM.OGL.Framebuffer GL.DrawBuffers(enums.Length, enums); foreach (var pair in ColorAttachments) - GL.FramebufferTexture(FramebufferTarget.Framebuffer, pair.Value.FramebufferAttachment, pair.Value.ID, + GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, pair.Value.FramebufferAttachment, pair.Value.Target, pair.Value.ID, 0); var err = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer); @@ -123,7 +125,6 @@ namespace SM.OGL.Framebuffer ColorAttachments.Add(key, value); } - /// /// Activates the framebuffer without clearing the buffer. /// diff --git a/SMCode/SM.OGL/Mesh/BoundingBox.cs b/SMCode/SM.OGL/Mesh/BoundingBox.cs index b7ea997..d5b97f4 100644 --- a/SMCode/SM.OGL/Mesh/BoundingBox.cs +++ b/SMCode/SM.OGL/Mesh/BoundingBox.cs @@ -2,6 +2,7 @@ using System; using OpenTK; +using OpenTK.Graphics.OpenGL; #endregion @@ -47,9 +48,35 @@ namespace SM.OGL.Mesh /// If true, it takes the Y-value of maximum, otherwise the minimum. /// If true, it takes the Z-value of maximum, otherwise the minimum. /// - public Vector3 this[bool x, bool y, bool z] => - new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.Z); + public Vector3 this[bool x, bool y, bool z] => Get(x,y,z); + public Vector3 Get(bool x, bool y, bool z) + { + return new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.Z); + } + + public Vector3 Get(bool xyz) => Get(xyz, xyz, xyz); + + public Vector3 Get(Matrix4 transformation, bool x, bool y, bool z) + { + Vector3 get = Get(x, y, z); + return (new Vector4(get, 1) * transformation).Xyz; + } + + public Vector3 Get(Matrix4 transformation, bool xyz) => Get(transformation, xyz, xyz, xyz); + + public void Update(GenericMesh mesh) + { + int pos = 0; + foreach (float f in mesh.Vertex) + { + Min[pos] = Math.Min(Min[pos], f); + Max[pos] = Math.Max(Max[pos], f); + + pos++; + pos %= mesh.Vertex.PointerSize; + } + } /// /// Updates the bounding box. /// diff --git a/SMCode/SM.OGL/Mesh/GenericMesh.cs b/SMCode/SM.OGL/Mesh/GenericMesh.cs index 45cabac..99948c8 100644 --- a/SMCode/SM.OGL/Mesh/GenericMesh.cs +++ b/SMCode/SM.OGL/Mesh/GenericMesh.cs @@ -13,6 +13,9 @@ namespace SM.OGL.Mesh /// public abstract class GenericMesh : GLObject { + private bool _boundingBoxUpdated = false; + + public static int LastID { get; internal set; } = -1; /// /// Generates the AttribDataIndex @@ -69,14 +72,28 @@ namespace SM.OGL.Mesh /// public virtual int[] Indices { get; set; } + public void UpdateBoundingBox() + { + BoundingBox.Update(this); + _boundingBoxUpdated = true; + } + + public void Activate() + { + GL.BindVertexArray(ID); + } + /// public override void Compile() { _id = GL.GenVertexArray(); GL.BindVertexArray(_id); - + if (Attributes == null || Attributes.Count == 0) throw new Exception("[Critical] The model requires attributes."); + if (!_boundingBoxUpdated) + UpdateBoundingBox(); + foreach (var kvp in Attributes) kvp.ConnectedVBO?.BindBuffer(kvp.Index); diff --git a/SMCode/SM.OGL/Mesh/ILineMesh.cs b/SMCode/SM.OGL/Mesh/ILineMesh.cs new file mode 100644 index 0000000..67d219d --- /dev/null +++ b/SMCode/SM.OGL/Mesh/ILineMesh.cs @@ -0,0 +1,7 @@ +namespace SM.OGL.Mesh +{ + public interface ILineMesh + { + float LineWidth { get; set; } + } +} \ No newline at end of file diff --git a/SMCode/SM.OGL/Mesh/MeshAttributeList.cs b/SMCode/SM.OGL/Mesh/MeshAttributeList.cs index 5c1c94c..0b492e6 100644 --- a/SMCode/SM.OGL/Mesh/MeshAttributeList.cs +++ b/SMCode/SM.OGL/Mesh/MeshAttributeList.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; +using OpenTK.Graphics.OpenGL; namespace SM.OGL.Mesh { @@ -50,5 +51,11 @@ namespace SM.OGL.Mesh //if (vbo == null) return; Add(new MeshAttribute(id, name, vbo)); } + + public bool Has(string name) + { + VBO attribute = this[name]; + return attribute != null && attribute.Active; + } } } \ No newline at end of file diff --git a/SMCode/SM.OGL/Mesh/VBO.cs b/SMCode/SM.OGL/Mesh/VBO.cs index 0664f63..3348271 100644 --- a/SMCode/SM.OGL/Mesh/VBO.cs +++ b/SMCode/SM.OGL/Mesh/VBO.cs @@ -40,6 +40,8 @@ namespace SM.OGL.Mesh /// public int PointerStride; + public bool Active = true; + /// /// Specifies the data type of each component in the array. /// @@ -133,6 +135,14 @@ namespace SM.OGL.Mesh Add(vector.X, vector.Y, z, w); } + public void Add(params Vector2[] vectors) + { + foreach (Vector2 vector in vectors) + { + Add(vector); + } + } + /// /// Adds a Vector3. /// @@ -149,6 +159,13 @@ namespace SM.OGL.Mesh Add(vector.X, vector.Y, vector.Z, w); } + public void Add(params Vector3[] vectors) + { + foreach (Vector3 vector in vectors) + { + Add(vector); + } + } /// /// Adds a vector4. /// @@ -172,6 +189,8 @@ namespace SM.OGL.Mesh /// The id for the attribute. internal void BindBuffer(int attribID) { + if (!Active) return; + var data = ToArray(); var buffer = GL.GenBuffer(); diff --git a/SMCode/SM.OGL/SM.OGL.csproj b/SMCode/SM.OGL/SM.OGL.csproj index e731e18..a802a51 100644 --- a/SMCode/SM.OGL/SM.OGL.csproj +++ b/SMCode/SM.OGL/SM.OGL.csproj @@ -51,6 +51,7 @@ + diff --git a/SMCode/SM.OGL/Shaders/GenericShader.cs b/SMCode/SM.OGL/Shaders/GenericShader.cs index 6fb2ca9..e911463 100644 --- a/SMCode/SM.OGL/Shaders/GenericShader.cs +++ b/SMCode/SM.OGL/Shaders/GenericShader.cs @@ -106,6 +106,11 @@ namespace SM.OGL.Shaders GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%"); } + public void Activate() + { + GL.UseProgram(ID); + } + /// public override void Compile() { @@ -122,7 +127,7 @@ namespace SM.OGL.Shaders /// /// The mesh. /// The amounts for instancing. - protected void DrawObject(GenericMesh mesh, int amount = 1) + public static void DrawObject(GenericMesh mesh, int amount = 1) { if (mesh.Indices != null) GL.DrawElementsInstanced(mesh.PrimitiveType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); @@ -138,7 +143,6 @@ namespace SM.OGL.Shaders Uniforms.NextTexture = 0; GL.BindTexture(TextureTarget.Texture2D, 0); - GL.BindVertexArray(0); } } } \ No newline at end of file diff --git a/SMCode/SM.OGL/Shaders/ShaderFileCollection.cs b/SMCode/SM.OGL/Shaders/ShaderFileCollection.cs index 2f18f97..cfec97b 100644 --- a/SMCode/SM.OGL/Shaders/ShaderFileCollection.cs +++ b/SMCode/SM.OGL/Shaders/ShaderFileCollection.cs @@ -14,17 +14,17 @@ namespace SM.OGL.Shaders /// /// Contains the vertex file. /// - public ShaderFile Vertex; + public ShaderFile[] Vertex; /// /// Contains the geometry file. /// - public ShaderFile Geometry; + public ShaderFile[] Geometry; /// /// Contains the fragment file. /// - public ShaderFile Fragment; + public ShaderFile[] Fragment; /// /// Creating the collection with vertex and fragment files. @@ -44,6 +44,14 @@ namespace SM.OGL.Shaders /// /// public ShaderFileCollection(ShaderFile vertex, ShaderFile fragment, ShaderFile geometry = default) + { + Vertex = new []{vertex}; + if (geometry != null) Geometry = new[] {geometry}; + else Geometry = default; + Fragment = new []{fragment}; + } + + public ShaderFileCollection(ShaderFile[] vertex, ShaderFile[] fragment, ShaderFile[] geometry = default) { Vertex = vertex; Geometry = geometry; @@ -56,9 +64,15 @@ namespace SM.OGL.Shaders /// internal void Append(GenericShader shader) { - Vertex.Compile(shader, ShaderType.VertexShader); - Geometry?.Compile(shader, ShaderType.GeometryShader); - Fragment.Compile(shader, ShaderType.FragmentShader); + foreach (ShaderFile file in Vertex) + file.Compile(shader, ShaderType.VertexShader); + + if (Geometry != null) + foreach (ShaderFile file in Geometry) + file.Compile(shader, ShaderType.GeometryShader); + + foreach (ShaderFile file in Fragment) + file.Compile(shader, ShaderType.FragmentShader); } /// @@ -67,9 +81,15 @@ namespace SM.OGL.Shaders /// internal void Detach(GenericShader shader) { - GL.DetachShader(shader, Vertex); - if (Geometry != null) GL.DetachShader(shader, Geometry); - GL.DetachShader(shader, Fragment); + foreach (ShaderFile file in Vertex) + GL.DetachShader(shader, file); + + if (Geometry != null) + foreach (ShaderFile file in Geometry) + GL.DetachShader(shader, file); + + foreach (ShaderFile file in Fragment) + GL.DetachShader(shader, file); GLDebugging.CheckGLErrors($"Error at detaching '{shader.GetType()}'"); } diff --git a/SMCode/SM.OGL/Shaders/Uniform.cs b/SMCode/SM.OGL/Shaders/Uniform.cs index 46f8dc4..6b498ac 100644 --- a/SMCode/SM.OGL/Shaders/Uniform.cs +++ b/SMCode/SM.OGL/Shaders/Uniform.cs @@ -354,7 +354,7 @@ namespace SM.OGL.Shaders #region Matrix2 - public void SetMatrix2(ref Matrix2 matrix, bool transpose = false) + public void SetMatrix2(Matrix2 matrix, bool transpose = false) { GL.UniformMatrix2(Location, transpose, ref matrix); } @@ -383,7 +383,7 @@ namespace SM.OGL.Shaders #region Matrix3 - public void SetMatrix3(ref Matrix3 matrix, bool transpose = false) + public void SetMatrix3(Matrix3 matrix, bool transpose = false) { GL.UniformMatrix3(Location, transpose, ref matrix); } @@ -485,7 +485,7 @@ namespace SM.OGL.Shaders { Parent.NextTexture = texturePos + 1; GL.ActiveTexture(TextureUnit.Texture0 + texturePos); - GL.BindTexture(TextureTarget.Texture2D, texture); + GL.BindTexture(texture.Target, texture); SetUniform1(texturePos); } diff --git a/SMCode/SM.OGL/Shaders/UniformArray.cs b/SMCode/SM.OGL/Shaders/UniformArray.cs index 2a86480..19c882b 100644 --- a/SMCode/SM.OGL/Shaders/UniformArray.cs +++ b/SMCode/SM.OGL/Shaders/UniformArray.cs @@ -12,6 +12,7 @@ namespace SM.OGL.Shaders public string Name { get; internal set; } public UniformCollection Parent { get; internal set; } public GenericShader ParentShader { get; internal set; } + public int Length => storedUniforms.Count; public Dictionary this[int index] => Get(index); diff --git a/SMCode/SM.OGL/Shaders/UniformCollection.cs b/SMCode/SM.OGL/Shaders/UniformCollection.cs index f0a8785..a0e231e 100644 --- a/SMCode/SM.OGL/Shaders/UniformCollection.cs +++ b/SMCode/SM.OGL/Shaders/UniformCollection.cs @@ -24,7 +24,7 @@ namespace SM.OGL.Shaders } catch (KeyNotFoundException) { - GLCustomActions.AtWarning?.Invoke("Uniform '" + KeyString + key + "' was not found. Tried to recreate it."); + GLCustomActions.AtWarning?.Invoke("Uniform '" + KeyString + key + "' at '" + ParentShader.GetType().Name + "' was not found. Tried to recreate it."); var u = new Uniform(GL.GetUniformLocation(ParentShader, KeyString + key), this); Add(key, u); return u; diff --git a/SMCode/SM.OGL/Texture/TextureBase.cs b/SMCode/SM.OGL/Texture/TextureBase.cs index 0eb354d..2f0a107 100644 --- a/SMCode/SM.OGL/Texture/TextureBase.cs +++ b/SMCode/SM.OGL/Texture/TextureBase.cs @@ -13,12 +13,15 @@ namespace SM.OGL.Texture { /// protected override bool AutoCompile { get; } = true; + /// public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Texture; public PixelInformation PixelInformation; + public TextureTarget Target { get; set; } = TextureTarget.Texture2D; + /// /// The texture filter. /// Default: diff --git a/SMCode/SM2D/Controls/Mouse2D.cs b/SMCode/SM2D/Controls/Mouse2D.cs index 3fae862..5c95095 100644 --- a/SMCode/SM2D/Controls/Mouse2D.cs +++ b/SMCode/SM2D/Controls/Mouse2D.cs @@ -1,41 +1,63 @@ -#region usings - +using System.Collections.Generic; using OpenTK; -using OpenTK.Input; using SM.Base.Controls; +using SM.Base.Drawing; +using SM.Base.Scene; using SM2D.Scene; using SM2D.Types; -#endregion - namespace SM2D.Controls { - public class Mouse2D : Mouse + public class Mouse2D { - protected internal Mouse2D(IGLWindow2D window) : base(window) + public static Vector2 InWorld(Vector2 worldScale) { - } - - internal new void MouseMoveEvent(MouseMoveEventArgs mmea) - { - base.MouseMoveEvent(mmea); - } - - public Vector2 InWorld() - { - var res = _window.WorldScale; + var res = worldScale; res.Y *= -1; - return InScreenNormalized * res - res / 2; + return Mouse.InScreenNormalized * res - res / 2; } - public Vector2 InWorld(Camera cam) + public static Vector2 InWorld(Camera cam) { - return InWorld() + cam.Position; + return InWorld(cam.WorldScale) + cam.Position; } - public Vector2 InWorld(Vector2 position) + public static Vector2 InWorld(Vector2 worldScale, Vector2 position) { - return InWorld() + position; + return InWorld(worldScale) + position; + } + + public static bool MouseOver(Vector2 mousePos, params TObject[] checkingObjects) + where TObject : IModelItem, ITransformItem + => MouseOver(mousePos, out _, checkingObjects); + + public static bool MouseOver(Vector2 mousePos, ICollection checkingObjects) + where TObject : IModelItem, ITransformItem + => MouseOver(mousePos, out _, checkingObjects); + + public static bool MouseOver(Vector2 mousePos, out TObject clicked, params TObject[] checkingObjects) + where TObject : IModelItem, ITransformItem + => MouseOver(mousePos, out clicked, (ICollection)checkingObjects); + + public static bool MouseOver(Vector2 mousePos, out TObject clickedObj, ICollection checkingObjects) + where TObject : IModelItem, ITransformItem + { + clickedObj = default; + + foreach (TObject obj in checkingObjects) + { + Vector3 min = obj.Mesh.BoundingBox.Get(obj.Transform.MergeMatrix(obj.Transform.LastMaster), false); + Vector3 max = obj.Mesh.BoundingBox.Get(obj.Transform.MergeMatrix(obj.Transform.LastMaster), true); + + if (mousePos.X > min.X && mousePos.X < max.X && + mousePos.Y > min.Y && mousePos.Y < max.Y) + { + clickedObj = obj; + return true; + } + } + + return false; } } } \ No newline at end of file diff --git a/SMCode/SM2D/Drawing/DrawBackground.cs b/SMCode/SM2D/Drawing/DrawBackground.cs index 13162b0..2b62d60 100644 --- a/SMCode/SM2D/Drawing/DrawBackground.cs +++ b/SMCode/SM2D/Drawing/DrawBackground.cs @@ -4,20 +4,38 @@ using System.Collections.Generic; using System.Drawing; using OpenTK; using OpenTK.Graphics; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Drawing; using SM.Base.Objects.Static; using SM.Base.Scene; using SM.Base.Textures; +using SM.Base.Windows; using SM.OGL.Texture; +using SM2D.Scene; #endregion namespace SM2D.Drawing { - public class DrawBackground : IBackgroundItem + public class DrawBackground : DrawingBasis, IBackgroundItem { - private Material _material = new Material(); + public Color4 Color + { + get => Material.Tint; + set => Material.Tint = value; + } + + public TextureBase Texture + { + get => Material.Texture; + set + { + if (Material.Tint == Color4.Black) Material.Tint = Color4.White; + Material.Texture = value; + } + } + + public DrawBackground() : this(Color4.Black) {} public DrawBackground(Color4 color) { @@ -35,41 +53,12 @@ namespace SM2D.Drawing Texture = (Texture) texture; } - public Color4 Color + + protected override void DrawContext(ref DrawContext context) { - get => _material.Tint; - set => _material.Tint = value; - } - - public TextureBase Texture - { - get => _material.Texture; - set => _material.Texture = value; - } - - public object Parent { get; set; } - public string Name { get; set; } = "Background"; - public ICollection Flags { get; set; } = new string[0]; - - public void Update(UpdateContext context) - { - } - - public void Draw(DrawContext context) - { - context.Material = _material; - context.Mesh = Plate.Object; - - context.ModelMaster = Matrix4.CreateScale(context.WorldScale.X, context.WorldScale.Y, 1); + base.DrawContext(ref context); + context.ModelMatrix = Matrix4.CreateScale((context.UseCamera as Camera).WorldScale.X, (context.UseCamera as Camera).WorldScale.Y, 1); context.Shader.Draw(context); } - - public void OnAdded(object sender) - { - } - - public void OnRemoved(object sender) - { - } } } \ No newline at end of file diff --git a/SMCode/SM2D/Drawing/DrawObject2D.cs b/SMCode/SM2D/Drawing/DrawObject2D.cs index f04b141..b5e3121 100644 --- a/SMCode/SM2D/Drawing/DrawObject2D.cs +++ b/SMCode/SM2D/Drawing/DrawObject2D.cs @@ -2,30 +2,30 @@ using System.Drawing; using OpenTK; using OpenTK.Graphics; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Drawing; using SM.Base.Objects; using SM.Base.Textures; +using SM.Base.Windows; +using SM.OGL.Mesh; using SM2D.Object; using SM2D.Scene; using SM2D.Types; namespace SM2D.Drawing { - public class DrawObject2D : DrawingBasis, I2DShowItem + public class DrawObject2D : DrawingBasis { - public int ZIndex { get; set; } - public Texture Texture { - get => (Texture) _material.Texture; - set => _material.Texture = value; + get => (Texture) Material.Texture; + set => Material.Texture = value; } public Color4 Color { - get => _material.Tint; - set => _material.Tint = value; + get => Material.Tint; + set => Material.Tint = value; } protected override void DrawContext(ref DrawContext context) @@ -33,37 +33,32 @@ namespace SM2D.Drawing base.DrawContext(ref context); context.Shader.Draw(context); } + + public void SetShader(MaterialShader shader) => Material.CustomShader = shader; - public Material GetMaterialReference() => _material; - public void SetMaterialReference(Material material) => _material = material; - - public void SetShader(MaterialShader shader) => _material.CustomShader = shader; - - public Polygon ApplyPolygon(ICollection vertices) + public Polygon ApplyPolygon(ICollection vertices, bool centerUVs = false) { Polygon polygon = new Polygon(vertices); - _mesh = polygon; + Mesh = polygon; return polygon; } - public Polygon ApplyPolygon(ICollection vertices) + public Polygon ApplyPolygon(ICollection vertices, bool centerUVs = false) { Polygon polygon = new Polygon(vertices); - _mesh = polygon; + Mesh = polygon; return polygon; } public void ApplyPolygon(Polygon polygon) { - _mesh = polygon; + Mesh = polygon; } - public void ApplyMesh(Mesh mesh) => _mesh = mesh; - - public Polygon ApplyCircle(int segments = 32) + public Polygon ApplyCircle(int segments = 32, bool centerUVs = false) { Polygon pol = Polygon.GenerateCircle(segments); - _mesh = pol; + Mesh = pol; return pol; } - + } } \ No newline at end of file diff --git a/SMCode/SM2D/Drawing/DrawParticles.cs b/SMCode/SM2D/Drawing/DrawParticles.cs index 0eadc4e..2c2b135 100644 --- a/SMCode/SM2D/Drawing/DrawParticles.cs +++ b/SMCode/SM2D/Drawing/DrawParticles.cs @@ -7,9 +7,8 @@ using SM2D.Types; namespace SM2D.Drawing { - public class DrawParticles : ParticleDrawingBasis, I2DShowItem + public class DrawParticles : ParticleDrawingBasis { - public int ZIndex { get; set; } public override Func MovementCalculation { get; set; } = ParticleMovement.Default2D; public DrawParticles(TimeSpan duration) : base(duration) diff --git a/SMCode/SM2D/Drawing/DrawText.cs b/SMCode/SM2D/Drawing/DrawText.cs index e801c61..79675dd 100644 --- a/SMCode/SM2D/Drawing/DrawText.cs +++ b/SMCode/SM2D/Drawing/DrawText.cs @@ -1,8 +1,9 @@ #region usings -using SM.Base.Contexts; +using SM.Base; using SM.Base.Drawing.Text; using SM.Base.Types; +using SM.Base.Windows; using SM2D.Scene; using SM2D.Types; @@ -10,7 +11,7 @@ using SM2D.Types; namespace SM2D.Drawing { - public class DrawText : TextDrawingBasis, I2DShowItem + public class DrawText : TextDrawingBasis { public DrawText(Font font, string text) : base(font) { @@ -18,8 +19,6 @@ namespace SM2D.Drawing Transform.Size = new CVector2(1); } - public int ZIndex { get; set; } - protected override void DrawContext(ref DrawContext context) { base.DrawContext(ref context); diff --git a/SMCode/SM2D/Object/PolyLine.cs b/SMCode/SM2D/Object/PolyLine.cs new file mode 100644 index 0000000..bf9c5d2 --- /dev/null +++ b/SMCode/SM2D/Object/PolyLine.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using OpenTK; +using OpenTK.Graphics; +using OpenTK.Graphics.OpenGL4; +using SM.Base.Objects; +using SM.OGL.Mesh; + +namespace SM2D.Object +{ + public enum PolyLineType + { + NotConnected = 1, + Connected = 3, + ConnectedLoop = 2 + } + + public class PolyLine : Polygon, ILineMesh + { + public float LineWidth { get; set; } = 1; + + public PolyLine(ICollection vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices) + { + UVs.Active = false; + + PrimitiveType = (PrimitiveType)lineType; + } + + public PolyLine(ICollection vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices) + { + UVs.Active = false; + PrimitiveType = (PrimitiveType)lineType; + } + + } +} \ No newline at end of file diff --git a/SMCode/SM2D/Object/Polygon.cs b/SMCode/SM2D/Object/Polygon.cs index 01d73ce..437edd9 100644 --- a/SMCode/SM2D/Object/Polygon.cs +++ b/SMCode/SM2D/Object/Polygon.cs @@ -16,13 +16,16 @@ namespace SM2D.Object { public Polygon(ICollection vertices) : base(PrimitiveType.TriangleFan) { + Color.Active = false; + foreach (var vertex in vertices) { - Color.Add(Color4.White); - AddVertex(vertex); + Vertex.Add(vertex, 0); } - foreach (var vertex in vertices) AddUV(vertex); + UpdateBoundingBox(); + + if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex); } public Polygon(ICollection vertices) : base(PrimitiveType.TriangleFan) @@ -30,10 +33,12 @@ namespace SM2D.Object foreach (var polygonVertex in vertices) { Color.Add(polygonVertex.Color); - AddVertex(polygonVertex.Vertex); + Vertex.Add(polygonVertex.Vertex, 0); } - foreach (var vertex in vertices) AddUV(vertex.Vertex); + UpdateBoundingBox(); + + if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex.Vertex); } public override VBO Vertex { get; protected set; } = new VBO(); @@ -42,12 +47,6 @@ namespace SM2D.Object public override PrimitiveType PrimitiveType { get; protected set; } = PrimitiveType.TriangleFan; - private void AddVertex(Vector2 vertex) - { - BoundingBox.Update(vertex); - Vertex.Add(vertex, 0); - } - private void AddUV(Vector2 vertex) { var uv = Vector2.Divide(vertex - BoundingBox.Min.Xy, BoundingBox.Max.Xy - BoundingBox.Min.Xy); diff --git a/SMCode/SM2D/Pipelines/Adv2DPipeline.cs b/SMCode/SM2D/Pipelines/Adv2DPipeline.cs deleted file mode 100644 index 306d42d..0000000 --- a/SMCode/SM2D/Pipelines/Adv2DPipeline.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace SM2D.Pipelines -{ - public class Adv2DPipeline - { - } -} \ No newline at end of file diff --git a/SMCode/SM2D/Pipelines/Basic2DPipeline.cs b/SMCode/SM2D/Pipelines/Basic2DPipeline.cs index c20fb2d..a6ad7a2 100644 --- a/SMCode/SM2D/Pipelines/Basic2DPipeline.cs +++ b/SMCode/SM2D/Pipelines/Basic2DPipeline.cs @@ -1,26 +1,23 @@ using System; using OpenTK.Graphics.OpenGL4; using SM.Base; -using SM.Base.Contexts; using SM.Base.Drawing; +using SM.Base.Windows; using SM.OGL.Framebuffer; using SM2D.Shader; namespace SM2D.Pipelines { - public class Basic2DPipeline : RenderPipeline + public class Basic2DPipeline : RenderPipeline { public static Basic2DPipeline Pipeline = new Basic2DPipeline(); + public override MaterialShader DefaultShader { get; protected set; } = ShaderCollection.Instanced; - private Basic2DPipeline() - { - _defaultShader = Basic2DShader.Shader; - } - protected override void RenderProcess(ref DrawContext context, Scene.Scene scene) + protected override void RenderProcess(ref DrawContext context) { - scene?.Draw(context); + context.Scene?.Draw(context); } } } \ No newline at end of file diff --git a/SMCode/SM2D/Pipelines/Default2DPipeline.cs b/SMCode/SM2D/Pipelines/Default2DPipeline.cs deleted file mode 100644 index ae21000..0000000 --- a/SMCode/SM2D/Pipelines/Default2DPipeline.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region usings - -using System.Collections.Generic; -using OpenTK.Graphics.OpenGL4; -using SM.Base; -using SM.Base.Contexts; -using SM.Base.Scene; -using SM.OGL.Framebuffer; -using SM2D.Shader; - -#endregion - -namespace SM2D.Pipelines -{ - public class Default2DPipeline : RenderPipeline - { - public static Default2DPipeline Pipeline = new Default2DPipeline(); - - - private Default2DPipeline() - { - - } - - protected override void Initialization(IGenericWindow window) - { - MainFramebuffer = CreateWindowFramebuffer(); - } - - protected override void RenderProcess(ref DrawContext context, Scene.Scene scene) - { - if (scene != null) - { - scene.DrawBackground(context); - - scene.DrawMainObjects(context); - - scene.DrawHUD(context); - scene.DrawDebug(context); - } - } - - protected override void SceneChanged(Scene.Scene scene) - { - base.SceneChanged(scene); - } - } -} \ No newline at end of file diff --git a/SMCode/SM2D/SM2D.csproj b/SMCode/SM2D/SM2D.csproj index 0e33453..1e8c488 100644 --- a/SMCode/SM2D/SM2D.csproj +++ b/SMCode/SM2D/SM2D.csproj @@ -45,22 +45,19 @@ - - - + - - - + - + + @@ -72,9 +69,6 @@ SM.OGL - - - 3.3.1 diff --git a/SMCode/SM2D/SM2D.csproj.DotSettings b/SMCode/SM2D/SM2D.csproj.DotSettings index c1524cb..a6e7cec 100644 --- a/SMCode/SM2D/SM2D.csproj.DotSettings +++ b/SMCode/SM2D/SM2D.csproj.DotSettings @@ -1,3 +1,4 @@  True + False True \ No newline at end of file diff --git a/SMCode/SM2D/Scene/Camera.cs b/SMCode/SM2D/Scene/Camera.cs index 3900717..a643dee 100644 --- a/SMCode/SM2D/Scene/Camera.cs +++ b/SMCode/SM2D/Scene/Camera.cs @@ -1,8 +1,11 @@ #region usings +using System; using OpenTK; +using SM.Base; using SM.Base.Scene; using SM.Base.Types; +using SM.Base.Windows; #endregion @@ -10,18 +13,73 @@ namespace SM2D.Scene { public class Camera : GenericCamera { + internal static int ResizeCounter = 0; + + private int _resizeCounter = 0; + private bool _updateWorldScale = false; + private Vector2? _requestedWorldScale = null; + + public Vector2? RequestedWorldScale + { + get => _requestedWorldScale; + set + { + _requestedWorldScale = value; + _updateWorldScale = true; + } + } + + public Vector2 WorldScale { get; private set; } = Vector2.Zero; + + public event Action WorldScaleChanged; + public CVector2 Position = new CVector2(0); public override bool Orthographic { get; } = true; - protected override Matrix4 ViewCalculation() + protected override Matrix4 ViewCalculation(IGenericWindow window) { - return Matrix4.LookAt(Position.X, Position.Y, 2, Position.X, Position.Y, 0, 0, 1, 0); + return Matrix4.LookAt(Position.X, Position.Y, 1, Position.X, Position.Y, 0, 0, 1, 0); } - public override void RecalculateWorld(Vector2 world, float aspect) + protected override bool WorldCalculation(IGenericWindow window, out Matrix4 world) { - OrthographicWorld = - Matrix4.CreateOrthographic(world.X, world.Y, 0.1f, 100f); + world = Matrix4.Identity; + if (ResizeCounter != _resizeCounter || _updateWorldScale) + { + _updateWorldScale = false; + _resizeCounter = ResizeCounter; + CalculateWorldScale(window); + + world = Matrix4.CreateOrthographic(WorldScale.X, WorldScale.Y, .0001f, 1.5f); + return true; + } + + return false; + } + + public void CalculateWorldScale(IGenericWindow window) + { + if (RequestedWorldScale.HasValue) + { + float aspect = window.Width > window.Height ? window.AspectRatio : window.AspectRatioReverse; + Vector2 requested = RequestedWorldScale.Value; + + if (requested.X > 0 && requested.Y > 0) + { + float requestRatio = requested.X / requested.Y; + + if (requestRatio > aspect) WorldScale = new Vector2(requested.X, requested.X / aspect); + else WorldScale = new Vector2(aspect * requested.Y, requested.Y); + } + else if (requested.X > 0) WorldScale = new Vector2(requested.X, requested.X / aspect); + else if (requested.Y > 0) WorldScale = new Vector2(aspect * requested.Y, requested.Y); + } + else + { + WorldScale = window.WindowSize; + } + + WorldScaleChanged?.Invoke(this); } } } \ No newline at end of file diff --git a/SMCode/SM2D/Scene/ItemCollection.cs b/SMCode/SM2D/Scene/ItemCollection.cs index 5335ef6..a6796af 100644 --- a/SMCode/SM2D/Scene/ItemCollection.cs +++ b/SMCode/SM2D/Scene/ItemCollection.cs @@ -1,15 +1,16 @@ #region usings -using SM.Base.Contexts; +using SM.Base; using SM.Base.Scene; using SM.Base.Types; +using SM.Base.Windows; using SM2D.Types; #endregion namespace SM2D.Scene { - public class ItemCollection : GenericItemCollection, I2DShowItem + public class ItemCollection : GenericItemCollection { public ItemCollection() { @@ -18,11 +19,7 @@ namespace SM2D.Scene public override void Draw(DrawContext context) { - Sort((x, y) => x.ZIndex - y.ZIndex); - base.Draw(context); } - - public int ZIndex { get; set; } } } \ No newline at end of file diff --git a/SMCode/SM2D/Scene/Scene.cs b/SMCode/SM2D/Scene/Scene.cs index 64b6953..0625838 100644 --- a/SMCode/SM2D/Scene/Scene.cs +++ b/SMCode/SM2D/Scene/Scene.cs @@ -2,16 +2,17 @@ using OpenTK; using OpenTK.Graphics; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Objects.Static; using SM.Base.Scene; +using SM.Base.Windows; using SM2D.Drawing; #endregion namespace SM2D.Scene { - public class Scene : GenericScene + public class Scene : GenericScene { private static DrawObject2D _axisHelper; @@ -19,16 +20,24 @@ namespace SM2D.Scene static Scene() { _axisHelper = new DrawObject2D(); - _axisHelper.ApplyMesh(AxisHelper.Object); + _axisHelper.Mesh = AxisHelper.Object; } public Scene() { _Background = new DrawBackground(Color4.Black); + Objects = new ItemCollection(); + + BackgroundCamera = new Camera(); + HUDCamera = new Camera(); } - public DrawBackground Background => (DrawBackground) _Background; + public DrawBackground Background + { + get => (DrawBackground) _Background; + set => _Background = value; + } public override void DrawDebug(DrawContext context) { diff --git a/SMCode/SM2D/Shader/Basic2DShader.cs b/SMCode/SM2D/Shader/Basic2DShader.cs deleted file mode 100644 index 7e9b128..0000000 --- a/SMCode/SM2D/Shader/Basic2DShader.cs +++ /dev/null @@ -1,40 +0,0 @@ -using SM.Base.Contexts; -using SM.Base.Drawing; -using SM.OGL.Shaders; -using SM.Utility; - -namespace SM2D.Shader -{ - public class Basic2DShader : MaterialShader - { - - public static Basic2DShader Shader = new Basic2DShader(); - private Basic2DShader() : base(AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl")) - { - } - - protected override void DrawProcess(DrawContext context) - { - // Vertex Uniforms - Uniforms["MVP"].SetMatrix4(context.ModelMaster * context.View * context.World); - Uniforms["HasVColor"] - .SetUniform1(context.Mesh.Attributes["color"] != null); - - UniformArray instances = Uniforms.GetArray("Instances"); - for (int i = 0; i < context.Instances.Count; i++) - { - var shaderInstance = instances[i]; - var instance = context.Instances[i]; - shaderInstance["ModelMatrix"].SetMatrix4(instance.ModelMatrix); - shaderInstance["TextureOffset"].SetUniform2(instance.TexturePosition); - shaderInstance["TextureScale"].SetUniform2(instance.TextureScale); - } - - // Fragment Uniforms - Uniforms["Tint"].SetUniform4(context.Material.Tint); - Uniforms["Texture"].SetTexture(context.Material.Texture, Uniforms["UseTexture"]); - - DrawObject(context.Mesh, context.Instances.Count); - } - } -} \ No newline at end of file diff --git a/SMCode/SM2D/Shader/Default2DShader.cs b/SMCode/SM2D/Shader/Default2DShader.cs deleted file mode 100644 index 7038ca6..0000000 --- a/SMCode/SM2D/Shader/Default2DShader.cs +++ /dev/null @@ -1,48 +0,0 @@ -#region usings - -using OpenTK.Graphics.OpenGL4; -using SM.Base.Contexts; -using SM.Base.Drawing; -using SM.Base.Scene; -using SM.OGL.Shaders; -using SM.Utility; - -#endregion - -namespace SM2D.Shader -{ - public class Default2DShader : MaterialShader - { - public static Default2DShader MaterialShader = new Default2DShader(); - - - private Default2DShader() : base(AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.default.glsl")) - { - } - - protected override void DrawProcess(DrawContext context) - { - // Vertex Uniforms - Uniforms["MVP"].SetMatrix4(context.ModelMaster * context.View * context.World); - Uniforms["HasVColor"] - .SetUniform1(context.Mesh.Attributes["color"] != null); - Uniforms["occlude"].SetUniform1(context.ShaderArguments.ContainsKey("occluder")); - - UniformArray instances = Uniforms.GetArray("Instances"); - for (int i = 0; i < context.Instances.Count; i++) - { - var shaderInstance = instances[i]; - var instance = context.Instances[i]; - shaderInstance["ModelMatrix"].SetMatrix4(instance.ModelMatrix); - shaderInstance["TextureOffset"].SetUniform2(instance.TexturePosition); - shaderInstance["TextureScale"].SetUniform2(instance.TextureScale); - } - - // Fragment Uniforms - Uniforms["Tint"].SetUniform4(context.Material.Tint); - Uniforms["Texture"].SetTexture(context.Material.Texture, Uniforms["UseTexture"]); - - DrawObject(context.Mesh, context.Instances.Count); - } - } -} \ No newline at end of file diff --git a/SMCode/SM2D/Shader/ShaderCollection.cs b/SMCode/SM2D/Shader/ShaderCollection.cs new file mode 100644 index 0000000..92da6fe --- /dev/null +++ b/SMCode/SM2D/Shader/ShaderCollection.cs @@ -0,0 +1,19 @@ +using SM.Base.Drawing; +using SM.Base.Windows; +using SM.OGL.Shaders; +using SM.Utility; + +namespace SM2D.Shader +{ + public class ShaderCollection + { + public static SimpleShader Basic = new SimpleShader("basic", AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl"), SetUniforms); + public static SimpleShader Instanced = new SimpleShader("instanced", AssemblyUtility.ReadAssemblyFile("SM2D.Shader.ShaderFiles.basic.glsl"), SetUniforms); + + static void SetUniforms(UniformCollection uniforms, DrawContext context) + { + uniforms["Tint"].SetUniform4(context.Material.Tint); + uniforms["Texture"].SetTexture(context.Material.Texture, uniforms["UseTexture"]); + } + } +} \ No newline at end of file diff --git a/SMCode/SM2D/Shader/ShaderFiles/basic.glsl b/SMCode/SM2D/Shader/ShaderFiles/basic.glsl index 10978de..fdd77bc 100644 --- a/SMCode/SM2D/Shader/ShaderFiles/basic.glsl +++ b/SMCode/SM2D/Shader/ShaderFiles/basic.glsl @@ -1,20 +1,6 @@ #version 330 -//# region vertex - -//# import SM_base_vertex_basic -void ApplyTexModifier(); -void CheckVertexColor(); -void ApplyModelTransformation(); - -void vmain() { - ApplyTexModifier(); - CheckVertexColor(); - ApplyModelTransformation(); -} - -//# region fragment -in vec2 vTexture; -in vec4 vColor; +in vec2 v_TexCoords; +in vec4 v_Color; uniform vec4 Tint; uniform bool UseTexture; @@ -22,7 +8,9 @@ uniform sampler2D Texture; layout(location = 0) out vec4 color; -void fmain() { - color = vColor * Tint; - if (UseTexture) color *= texture(Texture, vTexture); +void main() { + color = vec4(v_TexCoords, 0, 1); + return; + color = v_Color * Tint; + if (UseTexture) color = texture(Texture, v_TexCoords); } \ No newline at end of file diff --git a/SMCode/SM2D/Shader/ShaderFiles/default.glsl b/SMCode/SM2D/Shader/ShaderFiles/default.glsl deleted file mode 100644 index b02f716..0000000 --- a/SMCode/SM2D/Shader/ShaderFiles/default.glsl +++ /dev/null @@ -1,32 +0,0 @@ -#version 330 - -//# region vertex - -//# import SM_base_vertex_basic -void ApplyTexModifier(); -void CheckVertexColor(); -void ApplyModelTransformation(); - -void vmain() { - ApplyTexModifier(); - CheckVertexColor(); - ApplyModelTransformation(); -} - -//# region fragment -in vec2 vTexture; -in vec4 vColor; - -uniform bool occlude; - -uniform vec4 Tint; -uniform bool UseTexture; -uniform sampler2D Texture; - -layout(location = 0) out vec4 color; -layout(location = 1) out vec4 bloom; - -void fmain() { - color = vColor * Tint; - if (UseTexture) color *= texture(Texture, vTexture); -} \ No newline at end of file diff --git a/SMCode/SM2D/Types/Transformation.cs b/SMCode/SM2D/Types/Transformation.cs index d75f00a..2f32a73 100644 --- a/SMCode/SM2D/Types/Transformation.cs +++ b/SMCode/SM2D/Types/Transformation.cs @@ -1,6 +1,7 @@ #region usings using System; +using System.Drawing.Drawing2D; using OpenTK; using SM.Base.Drawing; using SM.Base.Scene; @@ -14,22 +15,32 @@ namespace SM2D.Types { public class Transformation : GenericTransformation { + public static int ZIndexPercision = 300; + public CVector2 Position { get; set; } = new CVector2(0); public CVector2 Size { get; set; } = new CVector2(50); - public float Rotation { get; set; } + public CVector1 Rotation { get; set; } = new CVector1(0); + + public bool HorizontalFlip { get; set; } = false; + + public bool VerticalFlip { get; set; } = false; + + public int ZIndex { get; set; } protected override Matrix4 RequestMatrix() { return Matrix4.CreateScale(Size.X, Size.Y, 1) * + Matrix4.CreateRotationX(MathHelper.DegreesToRadians(HorizontalFlip ? 180 : 0)) * + Matrix4.CreateRotationY(MathHelper.DegreesToRadians(VerticalFlip ? 180 : 0)) * Matrix4.CreateRotationZ(MathHelper.DegreesToRadians(Rotation)) * - Matrix4.CreateTranslation(Position.X, Position.Y, 0); + Matrix4.CreateTranslation(Position.X, Position.Y, -(1 / (float)ZIndexPercision * ZIndex)); } public void TurnTo(Vector2 v) { - Rotation = RotationUtility.TurnTowards(Position, v); + Rotation.Set(RotationUtility.TurnTowards(Position, v)); } public Vector2 LookAtVector() diff --git a/SMCode/SM2D/Window/I2DSetup.cs b/SMCode/SM2D/Window/I2DSetup.cs new file mode 100644 index 0000000..13cbd18 --- /dev/null +++ b/SMCode/SM2D/Window/I2DSetup.cs @@ -0,0 +1,10 @@ +using OpenTK; +using SM.Base.Windows; + +namespace SM2D +{ + public interface I2DSetup : ISetup + { + Vector2? WorldScale { get; set; } + } +} \ No newline at end of file diff --git a/SMCode/SM2D/Window/Window2DSetup.cs b/SMCode/SM2D/Window/Window2DSetup.cs new file mode 100644 index 0000000..b44ff93 --- /dev/null +++ b/SMCode/SM2D/Window/Window2DSetup.cs @@ -0,0 +1,38 @@ +using System.Drawing.Drawing2D; +using OpenTK; +using OpenTK.Graphics.OpenGL4; +using SM.Base; +using SM.Base.PostProcess; +using SM.Base.Windows; +using SM2D.Scene; +using SM2D.Shader; + +namespace SM2D +{ + public struct Window2DSetup : I2DSetup + { + public Vector2? WorldScale { get; set; } + + public void Applied(IGenericWindow window) + { + window.ViewportCamera = new Camera(); + + SMRenderer.DefaultMaterialShader = ShaderCollection.Instanced; + } + + public void Load(IGenericWindow window) + { + (window.ViewportCamera as Camera).RequestedWorldScale = WorldScale; + GL.Enable(EnableCap.DepthTest); + } + + public void Loaded(IGenericWindow window) + { + } + + public void Resize(IGenericWindow window) + { + Camera.ResizeCounter++; + } + } +} \ No newline at end of file diff --git a/SM_TEST/Program.cs b/SM_TEST/Program.cs index df42ad5..e006a4b 100644 --- a/SM_TEST/Program.cs +++ b/SM_TEST/Program.cs @@ -1,7 +1,9 @@ using System; using OpenTK; +using OpenTK.Graphics; using OpenTK.Input; using SM.Base; +using SM.Base.Windows; using SM.Game.Controls; using SM2D; using SM2D.Drawing; @@ -15,7 +17,7 @@ namespace SM_TEST { static Scene scene; private static Font font; - private static GLWindow2D window; + private static GLWindow window; static void Main(string[] args) { font = new Font(@"C:\Windows\Fonts\Arial.ttf") @@ -25,8 +27,8 @@ namespace SM_TEST Log.SetLogFile(compressionFolder:"logs"); - window = new GLWindow2D {Scaling = new Vector2(0, 1000), VSync = VSyncMode.Off}; - //window.GrabCursor(); + window = new GLWindow {VSync = VSyncMode.Off}; + window.ApplySetup(new Window2DSetup() {WorldScale = new Vector2(0,1000)}); window.SetRenderPipeline(new TestRenderPipeline()); window.SetScene(scene = new Scene()); window.Load += WindowOnLoad; @@ -45,15 +47,16 @@ namespace SM_TEST GameControllerState s2 = new GameController(1).GetState(); } - private static void WindowOnLoad(object sender, EventArgs e) + private static void WindowOnLoad(IGenericWindow window) { scene.ShowAxisHelper = true; - - //scene.Background.Color = Color4.White; + DrawObject2D box = new DrawObject2D(); + scene.Objects.Add(box); + DrawText text = new DrawText(font, "Text"); - text.Transform.Position.Set(0, 0); + text.Transform.Position.Set(50, 0); text.Transform.Size.Set(2); scene.Objects.Add(text); diff --git a/SM_TEST/TestRenderPipeline.cs b/SM_TEST/TestRenderPipeline.cs index 25336f5..009ea9b 100644 --- a/SM_TEST/TestRenderPipeline.cs +++ b/SM_TEST/TestRenderPipeline.cs @@ -1,39 +1,40 @@ using System.Collections.Generic; using OpenTK.Graphics.OpenGL4; using SM.Base; -using SM.Base.Contexts; +using SM.Base; using SM.Base.Drawing; using SM.Base.PostEffects; +using SM.Base.Windows; using SM.OGL.Framebuffer; using SM2D.Scene; namespace SM_TEST { - public class TestRenderPipeline : RenderPipeline + public class TestRenderPipeline : RenderPipeline { private BloomEffect _bloom; - - protected override void Initialization(GenericWindow window) + + public override void Initialization() { - base.Initialization(window); _bloom = new BloomEffect(1); MainFramebuffer = CreateWindowFramebuffer(); _bloom.Initilize(this); + base.Initialization(); } - protected override void RenderProcess(ref DrawContext context, Scene scene) + protected override void RenderProcess(ref DrawContext context) { MainFramebuffer.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); - scene.DrawBackground(context); - scene.DrawMainObjects(context); + context.Scene.DrawBackground(context); + context.Scene.DrawMainObjects(context); Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); _bloom.Draw(context); - scene.DrawHUD(context); - scene.DrawDebug(context); + context.Scene.DrawHUD(context); + context.Scene.DrawDebug(context); } } } \ No newline at end of file diff --git a/SM_WPF_TEST/MainWindow.xaml.cs b/SM_WPF_TEST/MainWindow.xaml.cs index 8aa8e58..ffd04ef 100644 --- a/SM_WPF_TEST/MainWindow.xaml.cs +++ b/SM_WPF_TEST/MainWindow.xaml.cs @@ -28,7 +28,7 @@ namespace SM_WPF_TEST public MainWindow() { InitializeComponent(); - + /* GLWPFWindow2D gl; Scene scene; gl = new GLWPFWindow2D(); @@ -44,7 +44,7 @@ namespace SM_WPF_TEST cube.Color = Color4.Blue; scene.Objects.Add(cube); - new Window1().Show(); + new Window1().Show();*/ } } } diff --git a/SM_WPF_TEST/Window1.xaml.cs b/SM_WPF_TEST/Window1.xaml.cs index 74f388c..162cfc9 100644 --- a/SM_WPF_TEST/Window1.xaml.cs +++ b/SM_WPF_TEST/Window1.xaml.cs @@ -28,7 +28,7 @@ namespace SM_WPF_TEST { InitializeComponent(); - GLWPFWindow2D gl; + /*GLWPFWindow2D gl; Scene scene; Content = gl = new GLWPFWindow2D(); gl.Start(); @@ -41,7 +41,7 @@ namespace SM_WPF_TEST Color = Color4.Red }; obj.ApplyCircle(); - scene.Objects.Add(obj); + scene.Objects.Add(obj);*/ } } }