Loads and loads of small improvements I added while developing on my game

This commit is contained in:
Michel Fedde 2021-03-02 19:54:19 +01:00
parent 41421b1df9
commit a7c71e7ea1
107 changed files with 2278 additions and 1023 deletions

View file

@ -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
{
/// <summary>
/// Contains important information for drawing.
/// </summary>
public struct DrawContext
{
/// <summary>
/// This says if it was forced to use the viewport camera.
/// </summary>
public bool ForceViewport;
/// <summary>
/// Contains the currently used render pipeline.
/// </summary>
public RenderPipeline ActivePipeline;
public GenericScene ActiveScene;
public IGenericWindow Window;
public GenericCamera UsedCamera =>
ForceViewport || ActiveScene._camera == null ? Window.ViewportCamera : ActiveScene._camera;
/// <summary>
/// The mesh.
/// </summary>
public GenericMesh Mesh;
/// <summary>
/// The material.
/// </summary>
public Material Material;
/// <summary>
/// The drawing instances.
/// <para>If there is only one, it's index 0</para>
/// </summary>
public IList<Instance> Instances;
/// <summary>
/// The current world scale.
/// </summary>
public Vector2 WorldScale;
/// <summary>
/// The last collection the context was passed though.
/// </summary>
public object LastPassthough;
/// <summary>
/// Returns the appropriate shader.
/// <para>
/// Returns the material shader, if available, otherwise it will take the default shader from the render
/// pipeline.
/// </para>
/// </summary>
public MaterialShader Shader => Material.CustomShader ?? ActivePipeline._defaultShader;
/// <summary>
/// Arguments for shaders
/// </summary>
public IDictionary<string, object> ShaderArguments;
/// <summary>
/// The current world matrix.
/// </summary>
public Matrix4 World;
/// <summary>
/// The current view matrix.
/// </summary>
public Matrix4 View;
/// <summary>
/// The current WorldView matrix.
/// </summary>
public Matrix4 WorldView;
/// <summary>
/// The master model matrix.
/// </summary>
public Matrix4 ModelMaster;
}
}

View file

@ -0,0 +1,32 @@
#region usings
using OpenTK.Input;
using SM.Base.Scene;
#endregion
namespace SM.Base.Contexts
{
/// <summary>
/// The update context.
/// </summary>
public struct UpdateContext
{
/// <summary>
/// The delta time.
/// </summary>
public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime;
/// <summary>
/// The current keyboard state.
/// </summary>
public KeyboardState KeyboardState;
/// <summary>
/// The current mouse state.
/// </summary>
public MouseState MouseState;
public GenericScene CurrentScene;
}
}

View file

@ -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<TScene, TCamera> : IGenericWindow
where TScene : GenericScene, new()
where TCamera : GenericCamera, new()
{
TScene CurrentScene { get; }
RenderPipeline<TScene> RenderPipeline { get; }
void SetScene(TScene scene);
void SetRenderPipeline(RenderPipeline<TScene> renderPipeline);
}
}

View file

@ -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
{
/// <summary>
/// Definition of specific render options.
/// </summary>
public abstract class RenderPipeline
{
/// <summary>
/// If true, this pipeline was already once activated.
/// </summary>
public bool IsInitialized { get; private set; } = false;
/// <summary>
/// The window the pipeline is connected to.
/// </summary>
protected IGenericWindow _window { get; private set; }
/// <summary>
/// The framebuffers, that are used in this Pipeline.
/// </summary>
public virtual List<Framebuffer> Framebuffers { get; private set; }
/// <summary>
/// The default shader for the pipeline.
/// </summary>
protected internal virtual MaterialShader _defaultShader { get; set; }
public virtual Framebuffer MainFramebuffer { get; protected set; }= Framebuffer.Screen;
/// <summary>
/// Occurs, when the window is loading.
/// </summary>
protected internal virtual void Load()
{
}
/// <summary>
/// Occurs, when the window is resizing.
/// </summary>
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<Framebuffer>();
Initialization(window);
Framebuffers.Add(MainFramebuffer);
IsInitialized = true;
}
Activation(window);
}
/// <summary>
/// Occurs, when the pipeline was connected to a window.
/// </summary>
protected internal virtual void Activation(IGenericWindow window)
{
}
/// <summary>
/// Occurs, when the pipeline was connected to a window the first time.
/// </summary>
/// <param name="window"></param>
protected internal virtual void Initialization(IGenericWindow window)
{
}
/// <summary>
/// Occurs, when the window is unloading.
/// </summary>
protected internal virtual void Unload()
{
}
/// <summary>
/// Creates a framebuffer, that has specific (often) required settings already applied.
/// </summary>
/// <returns></returns>
public static Framebuffer CreateWindowFramebuffer()
{
Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow);
framebuffer.Append("color", 0);
return framebuffer;
}
}
/// <summary>
/// Represents a render pipeline.
/// </summary>
/// <typeparam name="TScene">The scene type</typeparam>
public abstract class RenderPipeline<TScene> : RenderPipeline
where TScene : GenericScene
{
/// <summary>
/// The system to render stuff.
/// </summary>
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);
/// <summary>
/// Event, that triggers, when the scene in the current window changes.
/// </summary>
/// <param name="scene"></param>
protected internal virtual void SceneChanged(TScene scene)
{
}
}
}

View file

@ -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<Key> _lastPressedKeys = new List<Key>();
public static bool IsAnyKeyPressed => _keyboardState?.IsAnyKeyDown == true;
internal static void SetStage()
{
if (_keyboardState.HasValue)
{
_lastPressedKeys = new List<Key>();
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<Key> keys = new List<Key>();
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<Key> pressedKey = new List<Key>();
bool success = false;
foreach (Key key in keys)
{
if (IsDown(key, once))
{
pressedKey.Add(key);
success = true;
}
}
pressedKeys = pressedKey.ToArray();
return success;
}
}
}

View file

@ -1,7 +1,11 @@
#region usings #region usings
using System;
using System.Collections.Generic;
using System.Windows.Documents;
using OpenTK; using OpenTK;
using OpenTK.Input; using OpenTK.Input;
using SM.Base.Windows;
#endregion #endregion
@ -11,41 +15,51 @@ namespace SM.Base.Controls
/// Mouse controller /// Mouse controller
/// </summary> /// </summary>
/// <typeparam name="TWindow">The type of window this controller is connected to.</typeparam> /// <typeparam name="TWindow">The type of window this controller is connected to.</typeparam>
public class Mouse<TWindow> public class Mouse
where TWindow : IGenericWindow
{ {
/// <summary> internal static MouseState? _mouseState;
/// The window it is connected to. internal static List<MouseButton> _lastButtonsPressed = new List<MouseButton>();
/// </summary>
protected TWindow _window;
/// <summary>
/// The constructor
/// </summary>
/// <param name="window">The window, its listen to.</param>
protected internal Mouse(TWindow window)
{
_window = window;
}
/// <summary> /// <summary>
/// The current position of the mouse in the screen. /// The current position of the mouse in the screen.
/// </summary> /// </summary>
public Vector2 InScreen { get; private set; } public static Vector2 InScreen { get; private set; }
/// <summary> /// <summary>
/// The current position of the mouse in the screen from 0..1. /// The current position of the mouse in the screen from 0..1.
/// </summary> /// </summary>
public Vector2 InScreenNormalized { get; private set; } public static Vector2 InScreenNormalized { get; private set; }
/// <summary> /// <summary>
/// The event to update the values. /// The event to update the values.
/// </summary> /// </summary>
/// <param name="mmea">The event args.</param> /// <param name="mmea">The event args.</param>
protected void MouseMoveEvent(MouseMoveEventArgs mmea) internal static void MouseMoveEvent(MouseMoveEventArgs mmea, IGenericWindow window)
{ {
InScreen = new Vector2(mmea.X, mmea.Y); 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<MouseButton>();
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));
} }
} }

View file

@ -1,8 +1,9 @@
#region usings #region usings
using System.Collections.Generic; using System.Collections.Generic;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Windows;
using SM.OGL.Mesh; using SM.OGL.Mesh;
#endregion #endregion
@ -12,17 +13,21 @@ namespace SM.Base.Drawing
/// <summary> /// <summary>
/// Contains general basis systems for drawing objects. /// Contains general basis systems for drawing objects.
/// </summary> /// </summary>
public abstract class DrawingBasis : IShowItem public abstract class DrawingBasis : IShowItem, IModelItem
{ {
/// <summary> /// <summary>
/// The material it should use. /// The material it should use.
/// </summary> /// </summary>
protected Material _material = new Material(); public Material Material = new Material();
/// <summary> /// <summary>
/// The mesh it should use. /// The mesh it should use.
/// </summary> /// </summary>
protected GenericMesh _mesh = SMRenderer.DefaultMesh; public GenericMesh Mesh { get; set; } = SMRenderer.DefaultMesh;
public ShaderArguments ShaderArguments => Material.ShaderArguments;
public TextureTransformation TextureTransform = new TextureTransformation();
/// <inheritdoc /> /// <inheritdoc />
public object Parent { get; set; } public object Parent { get; set; }
@ -36,15 +41,13 @@ namespace SM.Base.Drawing
/// <summary> /// <summary>
/// This value determents if the object should draw something. /// This value determents if the object should draw something.
/// </summary> /// </summary>
public bool Active = true; public bool Active { get; set; } = true;
/// <inheritdoc /> /// <inheritdoc />
public void Draw(DrawContext context) public void Draw(DrawContext context)
{ {
if (!Active) return; context.Material = Material;
context.Mesh = Mesh;
context.Material = _material;
context.Mesh = _mesh;
DrawContext(ref context); DrawContext(ref context);
} }
@ -65,6 +68,7 @@ namespace SM.Base.Drawing
/// <param name="context"></param> /// <param name="context"></param>
protected virtual void DrawContext(ref DrawContext context) 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. /// Contains general basis systems for drawing objects.
/// </summary> /// </summary>
/// <typeparam name="TTransformation">The transformation type</typeparam> /// <typeparam name="TTransformation">The transformation type</typeparam>
public abstract class DrawingBasis<TTransformation> : DrawingBasis public abstract class DrawingBasis<TTransformation> : DrawingBasis, IShowTransformItem<TTransformation>
where TTransformation : GenericTransformation, new() where TTransformation : GenericTransformation, new()
{ {
/// <summary> /// <summary>
/// The current transformation. /// The current transformation.
/// </summary> /// </summary>
public TTransformation Transform = new TTransformation(); public TTransformation Transform { get; set; } = new TTransformation();
/// <inheritdoc /> /// <inheritdoc />
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context); base.DrawContext(ref context);
context.ModelMaster *= Transform.GetMatrix(); Transform.LastMaster = context.ModelMatrix;
context.ModelMatrix = Transform.MergeMatrix(context.ModelMatrix);
} }
} }
} }

View file

@ -16,6 +16,8 @@ namespace SM.Base.Drawing
/// </summary> /// </summary>
public bool Ignore = false; public bool Ignore = false;
public Matrix4 LastMaster { get; internal set; }
/// <summary> /// <summary>
/// Contains the current model matrix. /// Contains the current model matrix.
/// </summary> /// </summary>
@ -43,6 +45,11 @@ namespace SM.Base.Drawing
return _modelMatrix; return _modelMatrix;
} }
public Matrix4 MergeMatrix(Matrix4 matrix)
{
return GetMatrix() * matrix;
}
/// <summary> /// <summary>
/// Calculates the current matrix. /// Calculates the current matrix.
/// </summary> /// </summary>

View file

@ -16,14 +16,6 @@ namespace SM.Base.Drawing
/// </summary> /// </summary>
public Matrix4 ModelMatrix = Matrix4.Identity; public Matrix4 ModelMatrix = Matrix4.Identity;
/// <summary> public Matrix3 TextureMatrix = Matrix3.Identity;
/// The texture offset.
/// </summary>
public Vector2 TexturePosition = Vector2.Zero;
/// <summary>
/// The texture scale.
/// </summary>
public Vector2 TextureScale = Vector2.One;
} }
} }

View file

@ -1,5 +1,6 @@
#region usings #region usings
using System.Collections.Generic;
using OpenTK.Graphics; using OpenTK.Graphics;
using SM.OGL.Texture; using SM.OGL.Texture;
@ -26,5 +27,9 @@ namespace SM.Base.Drawing
/// The tint or color. /// The tint or color.
/// </summary> /// </summary>
public Color4 Tint = Color4.White; public Color4 Tint = Color4.White;
public ShaderArguments ShaderArguments { get; internal set; } = new ShaderArguments();
public bool Blending = false;
} }
} }

View file

@ -1,10 +1,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using OpenTK; using OpenTK;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Time; using SM.Base.Time;
using SM.Base.Types; using SM.Base.Types;
using SM.Base.Windows;
using SM.OGL.Shaders; using SM.OGL.Shaders;
namespace SM.Base.Drawing.Particles namespace SM.Base.Drawing.Particles

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
namespace SM.Base.Drawing
{
public class ShaderArguments : Dictionary<string, object>
{
public TType Get<TType>(string name, TType defaultValue = default)
{
return ContainsKey(name) ? (TType)this[name] : defaultValue;
}
}
}

View file

@ -32,6 +32,8 @@ namespace SM.Base.Drawing.Text
/// </summary> /// </summary>
public float FontSize = 12; public float FontSize = 12;
public float Spacing = 1;
/// <summary> /// <summary>
/// The font style. /// The font style.
/// <para>Default: <see cref="System.Drawing.FontStyle.Regular" /></para> /// <para>Default: <see cref="System.Drawing.FontStyle.Regular" /></para>

View file

@ -3,7 +3,8 @@
using System; using System;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
#endregion #endregion
@ -32,13 +33,19 @@ namespace SM.Base.Drawing.Text
/// </summary> /// </summary>
public float Spacing = 1; public float Spacing = 1;
public float ActualSpacing => Spacing * Font.Spacing;
public float Width;
public float Height;
/// <summary> /// <summary>
/// Creates a text object with a font. /// Creates a text object with a font.
/// </summary> /// </summary>
/// <param name="font">The font.</param> /// <param name="font">The font.</param>
protected TextDrawingBasis(Font font) protected TextDrawingBasis(Font font)
{ {
_material.Texture = font; Material.Texture = font;
Material.Blending = true;
} }
/// <summary> /// <summary>
@ -46,10 +53,10 @@ namespace SM.Base.Drawing.Text
/// </summary> /// </summary>
public Font Font public Font Font
{ {
get => (Font) _material.Texture; get => (Font) Material.Texture;
set set
{ {
_material.Texture = value; Material.Texture = value;
GenerateMatrixes(); GenerateMatrixes();
} }
} }
@ -72,8 +79,8 @@ namespace SM.Base.Drawing.Text
/// </summary> /// </summary>
public Color4 Color public Color4 Color
{ {
get => _material.Tint; get => Material.Tint;
set => _material.Tint = value; set => Material.Tint = value;
} }
@ -92,15 +99,26 @@ namespace SM.Base.Drawing.Text
{ {
if (!Font.WasCompiled) Font.RegenerateTexture(); if (!Font.WasCompiled) Font.RegenerateTexture();
_text = _text.Replace("\r\n", "\n").Replace("\t", " ");
_instances = new Instance[_text.Length]; _instances = new Instance[_text.Length];
float x = 0; float x = 0;
float y = 0;
var _last = new CharParameter(); var _last = new CharParameter();
for (var i = 0; i < _text.Length; i++) 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; continue;
} }
@ -115,17 +133,19 @@ namespace SM.Base.Drawing.Text
} }
var matrix = Matrix4.CreateScale(parameter.Width, Font.Height, 1) * var matrix = Matrix4.CreateScale(parameter.Width, Font.Height, 1) *
Matrix4.CreateTranslation(x, 0, 0); Matrix4.CreateTranslation(x, -y, 0);
_instances[i] = new Instance _instances[i] = new Instance
{ {
ModelMatrix = matrix, ModelMatrix = matrix,
TexturePosition = new Vector2(parameter.NormalizedX, 0), TextureMatrix = TextureTransformation.CalculateMatrix(new Vector2(parameter.NormalizedX, 0), new Vector2(parameter.NormalizedWidth, 1), 0),
TextureScale = new Vector2(parameter.NormalizedWidth, 1)
}; };
x += parameter.Width * Spacing; x += parameter.Width * ActualSpacing;
_last = parameter; _last = parameter;
} }
Width = Math.Max(Width, x);
Height = y + Font.Height;
} }
} }
} }

View file

@ -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;
}
}
}

View file

@ -138,7 +138,7 @@ namespace SM.Base
_logStream = new StreamWriter(path) {AutoFlush = true}; _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() internal static void Init()

View file

@ -4,7 +4,7 @@ using SM.OGL.Mesh;
namespace SM.Base.Objects namespace SM.Base.Objects
{ {
public class InstancedMesh : Mesh public class InstancedMesh : Mesh, ILineMesh
{ {
public InstancedMesh(PrimitiveType type, string[] enabledAttibute) : base(type) public InstancedMesh(PrimitiveType type, string[] enabledAttibute) : base(type)
{ {
@ -26,5 +26,7 @@ namespace SM.Base.Objects
} }
} }
} }
public float LineWidth { get; set; } = 1;
} }
} }

View file

@ -1,7 +1,10 @@
using System.ComponentModel; using System.ComponentModel;
using OpenTK;
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Drawing;
using SM.Base.PostProcess; using SM.Base.PostProcess;
using SM.Base.Windows;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
using SM.OGL.Texture; using SM.OGL.Texture;
using SM.Utility; using SM.Utility;
@ -10,37 +13,76 @@ namespace SM.Base.PostEffects
{ {
public class BloomEffect : PostProcessEffect 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 _bloomBuffer1;
private Framebuffer _bloomBuffer2; private Framebuffer _bloomBuffer2;
private ColorAttachment _xBuffer; private ColorAttachment _xBuffer;
private ColorAttachment _yBuffer; private ColorAttachment _yBuffer;
private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM.Base.PostEffects.Shaders.bloom_blur.glsl")); private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath+".bloom_blur.glsl"));
private PostProcessShader _mergeShader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM.Base.PostEffects.Shaders.bloom_merge.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 bool _hdr;
private Framebuffer _source;
public int Iterations = 5; private BezierCurve _weightCurve ;
public float Threshold = 0.8f; private float[] _weights;
public float[] Weights = { 0.227027f, 0.1945946f, 0.1216216f, 0.054054f, 0.016216f }; public int Iterations = 1;
public float Threshold = .8f;
public BloomEffect(int bloomLocation, bool hdr = false) 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; _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() 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.Append("xBuffer", _xBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
_bloomBuffer1.Compile(); _bloomBuffer1.Compile();
_bloomBuffer2 = new Framebuffer(SMRenderer.CurrentWindow); _bloomBuffer2 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale);
_bloomBuffer2.Append("yBuffer", _yBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR)); _bloomBuffer2.Append("yBuffer", _yBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
_bloomBuffer2.Compile(); _bloomBuffer2.Compile();
@ -50,35 +92,51 @@ namespace SM.Base.PostEffects
public override void Draw(DrawContext context) public override void Draw(DrawContext context)
{ {
Framebuffer target = Framebuffer.GetCurrentlyActive(); if (Enable)
bool first = true, hoz = true;
int iter = Iterations * 2;
for (int i = 0; i < iter; i++)
{ {
(hoz ? _bloomBuffer1 : _bloomBuffer2).Activate(); GL.Viewport(0,0, (int)(Pipeline.ConnectedWindow.Width * _textureScale), (int)(Pipeline.ConnectedWindow.Height * _textureScale));
_shader.Draw(first ? Pipeline.MainFramebuffer.ColorAttachments["color"] : (hoz ? _yBuffer : _xBuffer), collection => Framebuffer target = Framebuffer.GetCurrentlyActive();
bool first = true, hoz = true;
int iter = Iterations * 2;
for (int i = 0; i < iter; i++)
{ {
collection["First"].SetUniform1(first); (hoz ? _bloomBuffer1 : _bloomBuffer2).Activate();
collection["Threshold"].SetUniform1(Threshold);
_shader.Draw(collection =>
{
collection["renderedTexture"].SetTexture(first ? _source.ColorAttachments["color"] : (hoz ? _yBuffer : _xBuffer));
collection["RenderScale"].SetUniform1(_textureScale);
collection["Horizontal"].SetUniform1(hoz); collection["First"].SetUniform1(first);
collection["Threshold"].SetUniform1(Threshold);
collection["Weights"].SetUniform1(Weights);
collection["WeightCount"].SetUniform1(Weights.Length); collection["Horizontal"].SetUniform1(hoz);
});
collection["Weights"].SetUniform1(_weights);
hoz = !hoz; collection["WeightCount"].SetUniform1(WeightCurvePickAmount);
if (first) first = false; collection["Power"].SetUniform1(Power);
});
hoz = !hoz;
if (first) first = false;
}
GL.Viewport(Pipeline.ConnectedWindow.ClientRectangle);
target.Activate();
} }
target.Activate(); _mergeShader.Draw(collection =>
_mergeShader.Draw(Pipeline.MainFramebuffer.ColorAttachments["color"], collection =>
{ {
collection["Scene"].SetTexture(_source.ColorAttachments["color"]);
collection["Bloom"].SetTexture(_yBuffer); 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); collection["HDR"].SetUniform1(_hdr);
}); });
} }

View file

@ -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);
});
}
}
}

View file

@ -1,6 +1,8 @@
#version 330 #version 330
#define PI 3.14159265359
uniform sampler2D renderedTexture; uniform sampler2D renderedTexture;
uniform float RenderScale;
uniform bool First; uniform bool First;
uniform float Threshold; uniform float Threshold;
@ -9,27 +11,35 @@ uniform bool Horizontal;
uniform float[32] Weights; uniform float[32] Weights;
uniform int WeightCount; uniform int WeightCount;
uniform float Power;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
vec4 GetRenderColorOffset(vec2 offset); 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() { void main() {
vec3 thres = vec3(First ? Threshold : 0); vec3 thres = vec3(First ? Threshold : 0);
vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0); vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0) * vec2(Horizontal ? 1 : 0, Horizontal ? 0 : 1);
vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * Weights[0];
if (Horizontal) { vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * (First ? Power : 1);
for(int i = 1; i < WeightCount; i++) { result *= GetWeight(0);
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]; for(int i = 1; i < WeightCount; i++) {
} result += max(GetRenderColorOffset(tex_offset * i).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i);
} else { result += max(GetRenderColorOffset(-tex_offset * i).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i);
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];
}
} }
color = vec4(result, 1); color = vec4(result, 1);
} }

View file

@ -1,10 +1,16 @@
#version 330 #version 330
in vec2 vTexture; in vec2 vTexture;
in vec2 TransformedTexture;
uniform sampler2D renderedTexture; uniform sampler2D Scene;
uniform sampler2D Bloom; uniform sampler2D Bloom;
uniform float MinAmount;
uniform float MaxAmount;
uniform sampler2D AmountMap;
uniform bool HasAmountMap;
uniform float Exposure; uniform float Exposure;
uniform bool HDR; uniform bool HDR;
@ -12,10 +18,13 @@ layout(location = 0) out vec4 color;
void main() { void main() {
vec3 result = texture(Bloom, vTexture).rgb; vec3 result = texture(Bloom, vTexture).rgb;
if (HasAmountMap) result *= clamp(length(texture(AmountMap, TransformedTexture).rgb) * (MaxAmount - MinAmount) + MinAmount, 0, 1);
if (!HDR) { if (!HDR) {
result = vec3(1.0) - exp(-result * Exposure); result = vec3(1.0) - exp(-result * Exposure);
} }
result += texture(renderedTexture, vTexture).rgb;
result = texture(Scene, vTexture).rgb + result;
color = vec4(result, 1); color = vec4(result, 1);
} }

View file

@ -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));
}

View file

@ -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);
}

View file

@ -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);
}

View file

@ -4,15 +4,11 @@ layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTex; layout(location = 1) in vec2 aTex;
uniform mat4 MVP; uniform mat4 MVP;
uniform mat4 ModelMatrix;
out vec2 vTexture; out vec2 vTexture;
out vec2 FragPos;
void main() { void main() {
vTexture = aTex; vTexture = aTex;
FragPos = vec2(ModelMatrix * vec4(aPos, 1));
gl_Position = MVP * vec4(aPos, 1); gl_Position = MVP * vec4(aPos, 1);
} }

View file

@ -4,17 +4,13 @@ layout(location = 0) in vec3 aPos;
layout(location = 1) in vec2 aTex; layout(location = 1) in vec2 aTex;
uniform mat4 MVP; uniform mat4 MVP;
uniform mat4 ModelMatrix;
out vec2 vTexture; out vec2 vTexture;
out vec2 FragPos;
void vertex(); void vertex();
void main() { void main() {
vTexture = aTex; vTexture = aTex;
FragPos = vec2(ModelMatrix * vec4(aPos, 1));
gl_Position = MVP * vec4(aPos, 1); gl_Position = MVP * vec4(aPos, 1);

View file

@ -3,9 +3,10 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using OpenTK; using OpenTK;
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Objects.Static; using SM.Base.Objects.Static;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Windows;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
using SM.OGL.Shaders; using SM.OGL.Shaders;
@ -16,8 +17,7 @@ namespace SM.Base.PostProcess
/// </summary> /// </summary>
public abstract class PostProcessEffect public abstract class PostProcessEffect
{ {
internal static Matrix4 Mvp; public static Matrix4 Mvp = Matrix4.Identity;
internal static Matrix4 Model;
protected RenderPipeline Pipeline; protected RenderPipeline Pipeline;

View file

@ -42,45 +42,23 @@ namespace SM.Base.PostProcess
fragment.GLSLExtensions.Add(_fragExtensions); fragment.GLSLExtensions.Add(_fragExtensions);
} }
/// <summary>
/// Draws the shader without special uniforms.
/// </summary>
/// <param name="color"></param>
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);
}
/// <summary> /// <summary>
/// Draws the shader with special uniforms. /// Draws the shader with special uniforms.
/// </summary> /// </summary>
/// <param name="color"></param> /// <param name="color"></param>
/// <param name="setUniformAction"></param> /// <param name="setUniformAction"></param>
public void Draw(ColorAttachment color, Action<UniformCollection> setUniformAction) public void Draw(Action<UniformCollection> setUniformAction)
{ {
GL.UseProgram(this); Activate();
GL.BindVertexArray(Plate.Object); Plate.Object.Activate();
Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp); Uniforms["MVP"].SetMatrix4(PostProcessEffect.Mvp);
Uniforms["ModelMatrix"].SetMatrix4(PostProcessEffect.Model);
Uniforms["renderedTexture"].SetTexture(color);
setUniformAction(Uniforms); setUniformAction(Uniforms);
GL.DrawArrays(PrimitiveType.Quads, 0, 4); GL.DrawArrays(PrimitiveType.Quads, 0, 4);
CleanUp(); CleanUp();
GL.UseProgram(0);
} }
} }
} }

View file

@ -58,15 +58,25 @@
<Reference Include="WindowsBase" /> <Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Controls\Keyboard.cs" />
<Compile Include="Controls\Mouse.cs" /> <Compile Include="Controls\Mouse.cs" />
<Compile Include="Drawing\DrawingBasis.cs" /> <Compile Include="Drawing\DrawingBasis.cs" />
<Compile Include="Drawing\GenericTransformation.cs" /> <Compile Include="Drawing\GenericTransformation.cs" />
<Compile Include="Drawing\Instance.cs" /> <Compile Include="Drawing\Instance.cs" />
<Compile Include="Drawing\MaterialShader.cs" /> <Compile Include="Drawing\ShaderArguments.cs" />
<Compile Include="Drawing\TextureTransformation.cs" />
<Compile Include="PostEffects\PostProcessFinals.cs" />
<Compile Include="Shaders\MaterialShader.cs" />
<Compile Include="Drawing\Particles\ParticleContext.cs" /> <Compile Include="Drawing\Particles\ParticleContext.cs" />
<Compile Include="Drawing\Particles\ParticleMovement.cs" /> <Compile Include="Drawing\Particles\ParticleMovement.cs" />
<Compile Include="Drawing\Particles\ParticleStruct.cs" /> <Compile Include="Drawing\Particles\ParticleStruct.cs" />
<Compile Include="Drawing\Particles\ParticleDrawingBasis.cs" /> <Compile Include="Drawing\Particles\ParticleDrawingBasis.cs" />
<Compile Include="Shaders\SimpleShader.cs" />
<Compile Include="Utility\IInitializable.cs" />
<Compile Include="Utility\Util.cs" />
<Compile Include="Window\Contexts\DrawContext.cs" />
<Compile Include="Window\Contexts\UpdateContext.cs" />
<Compile Include="Window\GLWindow.cs" />
<Compile Include="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="Objects\InstancedMesh.cs" /> <Compile Include="Objects\InstancedMesh.cs" />
<Compile Include="Objects\Mesh.cs" /> <Compile Include="Objects\Mesh.cs" />
@ -80,7 +90,7 @@
<Compile Include="Drawing\Material.cs" /> <Compile Include="Drawing\Material.cs" />
<Compile Include="Scene\IBackgroundItem.cs" /> <Compile Include="Scene\IBackgroundItem.cs" />
<Compile Include="Scene\GenericItemCollection.cs" /> <Compile Include="Scene\GenericItemCollection.cs" />
<Compile Include="ShaderExtension\ExtensionManager.cs" /> <Compile Include="Shaders\Extensions\ExtensionManager.cs" />
<Compile Include="SMRenderer.cs" /> <Compile Include="SMRenderer.cs" />
<Compile Include="Textures\Texture.cs" /> <Compile Include="Textures\Texture.cs" />
<Compile Include="Drawing\Text\CharParameter.cs" /> <Compile Include="Drawing\Text\CharParameter.cs" />
@ -98,20 +108,17 @@
<Compile Include="Utility\Randomize.cs" /> <Compile Include="Utility\Randomize.cs" />
<Compile Include="Utility\RotationUtility.cs" /> <Compile Include="Utility\RotationUtility.cs" />
<Compile Include="Utility\ShaderUtility.cs" /> <Compile Include="Utility\ShaderUtility.cs" />
<Compile Include="Window\Contexts\DrawContext.cs" />
<Compile Include="Window\Contexts\UpdateContext.cs" />
<Compile Include="Window\GenericWindow.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Scene\GenericCamera.cs" /> <Compile Include="Scene\GenericCamera.cs" />
<Compile Include="Scene\GenericScene.cs" /> <Compile Include="Scene\GenericScene.cs" />
<Compile Include="Objects\Static\Plate.cs" /> <Compile Include="Objects\Static\Plate.cs" />
<Compile Include="Window\GenericWindowCode.cs" />
<Compile Include="Window\GenericWPFWindow.cs" />
<Compile Include="Window\IGenericWindow.cs" /> <Compile Include="Window\IGenericWindow.cs" />
<Compile Include="Window\ISetup.cs" />
<Compile Include="Window\RenderPipeline.cs" /> <Compile Include="Window\RenderPipeline.cs" />
<Compile Include="Window\WindowCode.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="ShaderExtension\vertex\basic.vert" /> <EmbeddedResource Include="Shaders\Extensions\vertex\basic.vert" />
<EmbeddedResource Include="PostProcess\DefaultFiles\vertexFile.vert" /> <EmbeddedResource Include="PostProcess\DefaultFiles\vertexFile.vert" />
<EmbeddedResource Include="PostProcess\DefaultFiles\extensions.frag" /> <EmbeddedResource Include="PostProcess\DefaultFiles\extensions.frag" />
</ItemGroup> </ItemGroup>
@ -121,9 +128,7 @@
<Name>SM.OGL</Name> <Name>SM.OGL</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup />
<Folder Include="ShaderExtension\fragment\" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="PostProcess\DefaultFiles\vertexWithExt.vert" /> <EmbeddedResource Include="PostProcess\DefaultFiles\vertexWithExt.vert" />
</ItemGroup> </ItemGroup>
@ -134,6 +139,13 @@
<ItemGroup> <ItemGroup>
<None Include="OpenTK.dll.config" /> <None Include="OpenTK.dll.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<EmbeddedResource Include="Shaders\SimpleShaderPresets\basic_vertex.glsl" />
<EmbeddedResource Include="Shaders\SimpleShaderPresets\instanced_vertex.glsl" />
<EmbeddedResource Include="PostEffects\Shaders\bloom_merge_vert.glsl" />
<EmbeddedResource Include="PostEffects\Shaders\finalize_hdr.glsl" />
<EmbeddedResource Include="PostEffects\Shaders\finalize_gamma.glsl" />
<EmbeddedResource Include="Shaders\Extensions\fragment\textureGamma.glsl" />
<EmbeddedResource Include="Shaders\Extensions\fragment\noise.glsl" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -0,0 +1,5 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/CSharpLanguageProject/LanguageLevel/@EntryValue">Latest</s:String>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=windows/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=windows_005Ccontexts/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=window_005Ccontexts/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -4,6 +4,7 @@ using SM.Base.Drawing;
using SM.Base.Drawing.Text; using SM.Base.Drawing.Text;
using SM.Base.Objects.Static; using SM.Base.Objects.Static;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Windows;
using SM.OGL.Mesh; using SM.OGL.Mesh;
using SM.OGL.Shaders; using SM.OGL.Shaders;
using SM.Utility; using SM.Utility;
@ -17,6 +18,8 @@ namespace SM.Base
/// </summary> /// </summary>
public class SMRenderer public class SMRenderer
{ {
internal const string PostProcessPath = "SM.Base.PostEffects.Shaders";
/// <summary> /// <summary>
/// Defines, how many instances the 'SM_base_vertex_basic'-extension can handle. /// Defines, how many instances the 'SM_base_vertex_basic'-extension can handle.
/// </summary> /// </summary>
@ -50,7 +53,7 @@ namespace SM.Base
/// <summary> /// <summary>
/// Current Frame /// Current Frame
/// </summary> /// </summary>
public static ulong CurrentFrame { get; internal set; } = 0; public static ulong CurrentFrame { get; internal set; } = 1;
/// <summary> /// <summary>
/// Represents the current active window. /// Represents the current active window.

View file

@ -1,6 +1,7 @@
#region usings #region usings
using OpenTK; using OpenTK;
using SM.Base.Windows;
#endregion #endregion
@ -11,48 +12,44 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public abstract class GenericCamera public abstract class GenericCamera
{ {
/// <summary>
/// The matrix for the orthographic world.
/// </summary>
public static Matrix4 OrthographicWorld { get; protected set; }
/// <summary>
/// The matrix for the perspective world.
/// </summary>
public static Matrix4 PerspectiveWorld { get; protected set; }
/// <summary> /// <summary>
/// This defines what is up. (Normalized) /// This defines what is up. (Normalized)
/// <para>Default: <see cref="Vector3.UnitY" /></para> /// <para>Default: <see cref="Vector3.UnitY" /></para>
/// </summary> /// </summary>
public static Vector3 UpVector { get; set; } = Vector3.UnitY; public Vector3 UpVector { get; set; } = Vector3.UnitY;
/// <summary>
/// Returns the world matrix that is connected to this camera.
/// </summary>
public Matrix4 World { get; protected set; }
/// <summary> /// <summary>
/// Contains the view matrix of this camera. /// Contains the view matrix of this camera.
/// <para>Default: <see cref="Matrix4.Identity" /></para> /// <para>Default: <see cref="Matrix4.Identity" /></para>
/// </summary> /// </summary>
public Matrix4 ViewMatrix { get; protected set; } = Matrix4.Identity; public Matrix4 View { get; protected set; } = Matrix4.Identity;
/// <summary>
/// Returns the world matrix that is connected to this camera.
/// </summary>
public Matrix4 World => Orthographic ? OrthographicWorld : PerspectiveWorld;
/// <summary> /// <summary>
/// Represents if the camera is orthographic. /// Represents if the camera is orthographic.
/// </summary> /// </summary>
public abstract bool Orthographic { get; } public abstract bool Orthographic { get; }
/// <summary>
/// Exposure defines the exposure to the Scene.
/// </summary>
public float Exposure = 1; public float Exposure = 1;
/// <summary> /// <summary>
/// Calculates the view matrix. /// Calculates the view matrix.
/// </summary> /// </summary>
/// <returns>The calculated view matrix. Same as <see cref="ViewMatrix" /></returns> /// <returns>The calculated view matrix. Same as <see cref="View" /></returns>
internal Matrix4 CalculateViewMatrix() internal void CalculateViewMatrix(IGenericWindow window)
{ {
ViewMatrix = ViewCalculation(); View = ViewCalculation(window);
return ViewMatrix; if (WorldCalculation(window, out Matrix4 world))
{
World = world;
}
} }
/// <summary> /// <summary>
@ -60,16 +57,10 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
/// <returns> /// <returns>
/// The new view matrix. This is the returns for <see cref="CalculateViewMatrix" /> and the next value for /// The new view matrix. This is the returns for <see cref="CalculateViewMatrix" /> and the next value for
/// <see cref="ViewMatrix" />. /// <see cref="View" />.
/// </returns> /// </returns>
protected abstract Matrix4 ViewCalculation(); protected abstract Matrix4 ViewCalculation(IGenericWindow window);
/// <summary> protected abstract bool WorldCalculation(IGenericWindow window, out Matrix4 world);
/// This will calculate the world.
/// <para>This is called on <see cref="GenericWindow{TScene,TCamera}.ViewportCamera" /> to calculate the world.</para>
/// </summary>
/// <param name="world">The world scale</param>
/// <param name="aspect">The aspect ratio from the window.</param>
public abstract void RecalculateWorld(Vector2 world, float aspect);
} }
} }

View file

@ -2,8 +2,10 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using SM.Base.Contexts; using OpenTK;
using SM.Base;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Windows;
#endregion #endregion
@ -12,9 +14,7 @@ namespace SM.Base.Scene
/// <summary> /// <summary>
/// Contains a list of show items. /// Contains a list of show items.
/// </summary> /// </summary>
/// <typeparam name="TItem">The type of show items.</typeparam> public abstract class GenericItemCollection : List<IShowItem>, IShowItem, IShowCollection, IScriptable
public abstract class GenericItemCollection<TItem> : List<TItem>, IShowItem, IShowCollection<TItem>, IScriptable
where TItem : IShowItem
{ {
private List<IScriptable> _scriptableObjects = new List<IScriptable>(); private List<IScriptable> _scriptableObjects = new List<IScriptable>();
@ -23,7 +23,7 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public ReadOnlyCollection<IScriptable> ScriptableObjects => new ReadOnlyCollection<IScriptable>(_scriptableObjects); public ReadOnlyCollection<IScriptable> ScriptableObjects => new ReadOnlyCollection<IScriptable>(_scriptableObjects);
/// <inheritdoc /> /// <inheritdoc />
public List<TItem> Objects => this; public List<IShowItem> Objects => this;
/// <inheritdoc /> /// <inheritdoc />
public object Parent { get; set; } public object Parent { get; set; }
@ -34,20 +34,32 @@ namespace SM.Base.Scene
/// <inheritdoc /> /// <inheritdoc />
public ICollection<string> Flags { get; set; } = new List<string>() {"collection"}; public ICollection<string> Flags { get; set; } = new List<string>() {"collection"};
public bool Active { get; set; } = true;
public bool UpdateActive { get; set; } = true;
public bool RenderActive { get; set; } = true;
/// <inheritdoc /> /// <inheritdoc />
public virtual void Update(UpdateContext context) public virtual void Update(UpdateContext context)
{ {
if (!Active || !UpdateActive) return;
for (var i = 0; i < _scriptableObjects.Count; i++) for (var i = 0; i < _scriptableObjects.Count; i++)
{
if (!_scriptableObjects[i].Active) continue;
_scriptableObjects[i].Update(context); _scriptableObjects[i].Update(context);
}
} }
/// <inheritdoc cref="IShowCollection{TItem}.Draw" /> /// <inheritdoc cref="IShowCollection.Draw" />
public virtual void Draw(DrawContext context) public virtual void Draw(DrawContext context)
{ {
context.LastPassthough = this; if (!Active || !RenderActive) return;
for (var i = 0; i < Objects.Count; i++) for (var i = 0; i < Objects.Count; i++)
{
if (!this[i].Active) continue;
this[i].Draw(context); this[i].Draw(context);
}
} }
/// <inheritdoc /> /// <inheritdoc />
@ -63,20 +75,22 @@ namespace SM.Base.Scene
/// <summary> /// <summary>
/// Adds a item to the draw and the script collection, when applicable. /// Adds a item to the draw and the script collection, when applicable.
/// </summary> /// </summary>
public new void Add(TItem item) public new void Add(params IShowItem[] items)
{ {
AddObject(item); foreach (var item in items)
{
if (item is IScriptable scriptable) AddObject(item);
AddScript(scriptable);
if (item is IScriptable scriptable)
AddScript(scriptable);
}
} }
/// <summary> /// <summary>
/// Adds the object to the collection. /// Adds the object to the collection.
/// </summary> /// </summary>
/// <param name="item"></param> /// <param name="item"></param>
public void AddObject(TItem item) public void AddObject(IShowItem item)
{ {
base.Add(item); base.Add(item);
item.Parent = this; item.Parent = this;
@ -91,23 +105,22 @@ namespace SM.Base.Scene
_scriptableObjects.Add(item); _scriptableObjects.Add(item);
} }
/// <summary> public new void Remove(params IShowItem[] items)
/// Removes a item from the draw and script collection, when applicable.
/// </summary>
/// <param name="item"></param>
public new void Remove(TItem item)
{ {
RemoveObject(item); foreach (var item in items)
{
RemoveObject(item);
if (item.GetType().IsAssignableFrom(typeof(IScriptable))) if (item is IScriptable scriptable)
RemoveScript((IScriptable)item); RemoveScript(scriptable);
}
} }
/// <summary> /// <summary>
/// Remove the object from the draw collection. /// Remove the object from the draw collection.
/// </summary> /// </summary>
/// <param name="item"></param> /// <param name="item"></param>
public void RemoveObject(TItem item) public void RemoveObject(IShowItem item)
{ {
base.Remove(item); base.Remove(item);
item.Parent = null; item.Parent = null;
@ -123,15 +136,27 @@ namespace SM.Base.Scene
_scriptableObjects.Remove(item); _scriptableObjects.Remove(item);
} }
public ICollection<IShowItem> GetAllItems(bool includeCollections = false)
{
List<IShowItem> items = new List<IShowItem>();
for (var i = 0; i < this.Count; i++)
{
if (!includeCollections && this[i] is IShowCollection) continue;
items.Add(this[i]);
}
return items;
}
/// <summary> /// <summary>
/// Returns a object with this name or the default, if not available. /// Returns a object with this name or the default, if not available.
/// <para>Not reclusive.</para> /// <para>Not reclusive.</para>
/// </summary> /// </summary>
/// <param name="name"></param> /// <param name="name"></param>
/// <returns></returns> /// <returns></returns>
public TItem GetItemByName(string name) public IShowItem GetItemByName(string name)
{ {
TItem obj = default; IShowItem obj = default;
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
if (this[i].Name == name) if (this[i].Name == name)
{ {
@ -148,7 +173,7 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
/// <typeparam name="TGetItem">Type of return</typeparam> /// <typeparam name="TGetItem">Type of return</typeparam>
public TGetItem GetItemByName<TGetItem>(string name) public TGetItem GetItemByName<TGetItem>(string name)
where TGetItem : TItem where TGetItem : IShowItem
{ {
return (TGetItem) GetItemByName(name); return (TGetItem) GetItemByName(name);
} }
@ -157,9 +182,9 @@ namespace SM.Base.Scene
/// Returns all object that have this flag. /// Returns all object that have this flag.
/// <para>Only in this list.</para> /// <para>Only in this list.</para>
/// </summary> /// </summary>
public ICollection<TItem> GetItemsWithFlag(string flag) public ICollection<IShowItem> GetItemsWithFlag(string flag)
{ {
var list = new List<TItem>(); var list = new List<IShowItem>();
for (var i = 0; i < Count; i++) for (var i = 0; i < Count; i++)
{ {
var obj = this[i]; var obj = this[i];
@ -176,19 +201,19 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
/// <typeparam name="TItem">The type of show items.</typeparam> /// <typeparam name="TItem">The type of show items.</typeparam>
/// <typeparam name="TTransformation">The type of transformation.</typeparam> /// <typeparam name="TTransformation">The type of transformation.</typeparam>
public abstract class GenericItemCollection<TItem, TTransformation> : GenericItemCollection<TItem> public abstract class GenericItemCollection<TTransformation> : GenericItemCollection, IShowTransformItem<TTransformation>
where TItem : IShowItem
where TTransformation : GenericTransformation, new() where TTransformation : GenericTransformation, new()
{ {
/// <summary> /// <summary>
/// Transformation of the collection /// Transformation of the collection
/// </summary> /// </summary>
public TTransformation Transform = new TTransformation(); public TTransformation Transform { get; set; } = new TTransformation();
/// <inheritdoc /> /// <inheritdoc />
public override void Draw(DrawContext context) 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); base.Draw(context);
} }

View file

@ -3,8 +3,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Dynamic; using System.Dynamic;
using SM.Base.Contexts; using System.Windows.Controls;
using SM.Base;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Windows;
using SM.Utility;
#endregion #endregion
@ -13,8 +16,11 @@ namespace SM.Base.Scene
/// <summary> /// <summary>
/// A generic scene, that imports functions for scene control. /// A generic scene, that imports functions for scene control.
/// </summary> /// </summary>
public abstract class GenericScene public abstract class GenericScene : IInitializable
{ {
private GenericItemCollection _hud;
private GenericItemCollection _objectCollection;
private IBackgroundItem _background; private IBackgroundItem _background;
private Dictionary<Type, object> _extensions = new Dictionary<Type, object>(); private Dictionary<Type, object> _extensions = new Dictionary<Type, object>();
@ -32,11 +38,31 @@ namespace SM.Base.Scene
} }
/// <summary> /// <summary>
/// The active camera, that is used if the context doesn't force the viewport camera. /// Objects inside the scene.
/// <para>If none set, it automaticly uses the viewport camera.</para>
/// </summary> /// </summary>
internal GenericCamera _camera { get; set; } public GenericItemCollection Objects
{
get => _objectCollection;
set
{
value.Parent = this;
_objectCollection = value;
}
}
/// <summary>
/// This defines the HUD objects.
/// </summary>
public GenericItemCollection HUD
{
get => _hud;
set
{
value.Parent = this;
_hud = value;
}
}
/// <summary> /// <summary>
/// A collection for cameras to switch easier to different cameras. /// A collection for cameras to switch easier to different cameras.
/// </summary> /// </summary>
@ -45,15 +71,38 @@ namespace SM.Base.Scene
/// <summary> /// <summary>
/// If true, the scene was already initialized. /// If true, the scene was already initialized.
/// </summary> /// </summary>
public bool IsInitialized { get; private set; } public bool IsInitialized { get; set; }
/// <summary>
/// If true, shows a axis helper at (0,0,0)
/// </summary>
public bool ShowAxisHelper { get; set; } = false;
/// <summary>
/// The active camera, that is used if the context doesn't force the viewport camera.
/// <para>If none set, it automaticly uses the viewport camera.</para>
/// </summary>
public GenericCamera Camera { get; set; }
/// <summary>
/// A camera to control the background.
/// </summary>
public GenericCamera BackgroundCamera { get; set; }
/// <summary>
/// A camera to control the HUD.
/// </summary>
public GenericCamera HUDCamera { get; set; }
/// <summary> /// <summary>
/// Updates this scene. /// Updates this scene.
/// </summary> /// </summary>
/// <param name="context"></param> /// <param name="context"></param>
public virtual void Update(UpdateContext context) public virtual void Update(UpdateContext context)
{ {
_objectCollection?.Update(context);
_hud?.Update(context);
} }
/// <summary> /// <summary>
@ -61,15 +110,61 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public virtual void Draw(DrawContext context) public virtual void Draw(DrawContext context)
{ {
DrawBackground(context);
DrawMainObjects(context);
DrawHUD(context);
DrawDebug(context);
} }
/// <summary>
/// Draws only the background.
/// </summary>
/// <param name="context"></param>
public void DrawBackground(DrawContext context)
{
var backgroundDrawContext = context;
backgroundDrawContext.SetCamera(BackgroundCamera);
_Background?.Draw(backgroundDrawContext);
}
/// <summary>
/// Draws only the main objects
/// </summary>
/// <param name="context"></param>
public void DrawMainObjects(DrawContext context)
{
if (!context.Window.ForceViewportCamera && Camera != null) context.SetCamera(Camera);
_objectCollection.Draw(context);
}
/// <summary>
/// Draws only the HUD
/// </summary>
/// <param name="context"></param>
public void DrawHUD(DrawContext context)
{
context.SetCamera(HUDCamera);
_hud?.Draw(context);
}
/// <summary>
/// Draw the debug informations.
/// </summary>
/// <param name="context"></param>
public virtual void DrawDebug(DrawContext context)
{
}
/// <summary> /// <summary>
/// Adds a extension to the scene. /// Adds a extension to the scene.
/// </summary> /// </summary>
/// <param name="extension"></param> /// <param name="extension"></param>
public virtual void SetExtension(object extension) public virtual void SetExtension(object extension)
{ {
_extensions[extension.GetType()] = extension; _extensions[extension.GetType()] = extension;
} }
/// <summary> /// <summary>
@ -89,32 +184,19 @@ namespace SM.Base.Scene
return (T)ext; return (T)ext;
} }
/// <summary>
/// Called, when the user activates the scene.
/// </summary>
internal void Activate()
{
if (!IsInitialized)
{
OnInitialization();
IsInitialized = true;
}
OnActivating();
public virtual void Activate()
{
} }
/// <summary> public virtual void Initialization()
/// Called, when the user activates the scene for the first time. {
/// </summary>
protected virtual void OnInitialization()
{ }
/// <summary> }
/// Called, when the user activates the scene.
/// </summary> public virtual void Deactivate() {}
protected virtual void OnActivating()
{ }
} }
/// <summary> /// <summary>
@ -123,117 +205,43 @@ namespace SM.Base.Scene
/// <typeparam name="TCamera">The type of cameras.</typeparam> /// <typeparam name="TCamera">The type of cameras.</typeparam>
/// <typeparam name="TItem">The type of show items.</typeparam> /// <typeparam name="TItem">The type of show items.</typeparam>
/// <typeparam name="TCollection">The type for collections</typeparam> /// <typeparam name="TCollection">The type for collections</typeparam>
public abstract class GenericScene<TCamera, TCollection, TItem> : GenericScene public abstract class GenericScene<TCamera, TCollection> : GenericScene
where TCamera : GenericCamera, new() where TCamera : GenericCamera, new()
where TCollection : GenericItemCollection<TItem>, new() where TCollection : GenericItemCollection, new()
where TItem : IShowItem
{ {
private TCollection _hud = new TCollection(); public new TCollection Objects
private TCollection _objectCollection = new TCollection();
/// <summary>
/// If true, shows a axis helper at (0,0,0)
/// </summary>
public bool ShowAxisHelper { get; set; } = false;
/// <summary>
/// The active camera, that is used if the context doesn't force the viewport camera.
/// <para>If none set, it automaticly uses the viewport camera.</para>
/// </summary>
public TCamera Camera => (TCamera) _camera;
/// <summary>
/// A camera to control the background.
/// </summary>
public TCamera BackgroundCamera { get; set; } = new TCamera();
/// <summary>
/// A camera to control the HUD.
/// </summary>
public TCamera HUDCamera { get; set; } = new TCamera();
/// <summary>
/// Objects inside the scene.
/// </summary>
public TCollection Objects
{ {
get => _objectCollection; get => (TCollection) base.Objects;
set set => base.Objects = value;
}
public new TCollection HUD
{
get
{ {
value.Parent = this; base.HUD ??= new TCollection();
_objectCollection = value; return (TCollection) base.HUD;
} }
set => base.HUD = value;
} }
/// <summary> public new TCamera Camera
/// This defines the HUD objects.
/// </summary>
public TCollection HUD
{ {
get => _hud; get => (TCamera) base.Camera;
set set => base.Camera = value;
{
value.Parent = this;
_hud = value;
}
} }
/// <inheritdoc /> public new TCamera HUDCamera
public override void Update(UpdateContext context)
{ {
_objectCollection.Update(context); get => (TCamera) base.HUDCamera;
_hud.Update(context); set => base.HUDCamera = value;
} }
/// <inheritdoc /> public new TCamera BackgroundCamera
public override void Draw(DrawContext context)
{ {
DrawBackground(context); get => (TCamera) base.BackgroundCamera;
set => base.BackgroundCamera = value;
DrawMainObjects(context);
DrawHUD(context);
DrawDebug(context);
} }
/// <summary>
/// Draws only the background.
/// </summary>
/// <param name="context"></param>
public void DrawBackground(DrawContext context)
{
var backgroundDrawContext = context;
backgroundDrawContext.View = BackgroundCamera.CalculateViewMatrix();
_Background?.Draw(backgroundDrawContext);
}
/// <summary>
/// Draws only the main objects
/// </summary>
/// <param name="context"></param>
public void DrawMainObjects(DrawContext context)
{
if (!context.ForceViewport && Camera != null) context.View = Camera.CalculateViewMatrix();
_objectCollection.Draw(context);
}
/// <summary>
/// Draws only the HUD
/// </summary>
/// <param name="context"></param>
public void DrawHUD(DrawContext context)
{
context.View = HUDCamera.CalculateViewMatrix();
_hud.Draw(context);
}
/// <summary>
/// Draw the debug informations.
/// </summary>
/// <param name="context"></param>
public virtual void DrawDebug(DrawContext context)
{
}
} }
} }

View file

@ -1,4 +1,5 @@
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
namespace SM.Base.Scene namespace SM.Base.Scene
{ {
@ -7,6 +8,8 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public interface IScriptable public interface IScriptable
{ {
bool Active { get; set; }
/// <summary> /// <summary>
/// Updates the object. /// Updates the object.
/// </summary> /// </summary>

View file

@ -1,7 +1,8 @@
#region usings #region usings
using System.Collections.Generic; using System.Collections.Generic;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
#endregion #endregion
@ -11,12 +12,12 @@ namespace SM.Base.Scene
/// Adds functions, that is required for a collection. /// Adds functions, that is required for a collection.
/// </summary> /// </summary>
/// <typeparam name="TItem">The type of show item.</typeparam> /// <typeparam name="TItem">The type of show item.</typeparam>
public interface IShowCollection<TItem> where TItem : IShowItem public interface IShowCollection
{ {
/// <summary> /// <summary>
/// The object collection. /// The object collection.
/// </summary> /// </summary>
List<TItem> Objects { get; } List<IShowItem> Objects { get; }
/// <summary> /// <summary>
/// This draws the objects in the <see cref="Objects" /> list. /// This draws the objects in the <see cref="Objects" /> list.

View file

@ -1,7 +1,10 @@
#region usings #region usings
using System.Collections.Generic; using System.Collections.Generic;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Drawing;
using SM.Base.Windows;
using SM.OGL.Mesh;
#endregion #endregion
@ -26,6 +29,8 @@ namespace SM.Base.Scene
/// Contains specific flags for the object. /// Contains specific flags for the object.
/// </summary> /// </summary>
ICollection<string> Flags { get; set; } ICollection<string> Flags { get; set; }
bool Active { get; set; }
/// <summary> /// <summary>
/// Tells the object to draw its object. /// Tells the object to draw its object.
@ -43,4 +48,19 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
void OnRemoved(object sender); void OnRemoved(object sender);
} }
public interface ITransformItem<TTransform>
where TTransform : GenericTransformation
{
TTransform Transform { get; set; }
}
public interface IShowTransformItem<TTransform> : IShowItem, ITransformItem<TTransform>
where TTransform : GenericTransformation
{}
public interface IModelItem
{
GenericMesh Mesh { get; set; }
}
} }

View file

@ -10,7 +10,7 @@ namespace SM.Base.ShaderExtension
{ {
internal static void InitExtensions() 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"] = ShaderExtensions.Extensions["SM_base_vertex_basic"].StringOverrides["instanceMax"] =
SMRenderer.MaxInstances.ToString(); SMRenderer.MaxInstances.ToString();

View file

@ -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);
}

View file

@ -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);
}

View file

@ -1,7 +1,9 @@
#region usings #region usings
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
using SM.OGL.Mesh;
using SM.OGL.Shaders; using SM.OGL.Shaders;
#endregion #endregion
@ -33,17 +35,22 @@ namespace SM.Base.Drawing
/// <param name="context">The context</param> /// <param name="context">The context</param>
public virtual void Draw(DrawContext 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); DrawProcess(context);
CleanUp(); CleanUp();
GL.UseProgram(0);
context.ShaderArguments.Clear();
} }
/// <summary> /// <summary>

View file

@ -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<string, Tuple<ShaderFile, Action<UniformCollection, DrawContext>>> VertexFiles =
new Dictionary<string, Tuple<ShaderFile, Action<UniformCollection, DrawContext>>>();
static ShaderFile _extensionDefineFile = new ShaderFile("#define SM_SIMPLE_EXTENSION");
static SimpleShader()
{
VertexFiles.Add("basic", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
new ShaderFile(AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl"))
{
StringOverrides = {["extension"] = "0"}
},
BasicSetUniforms
));
VertexFiles.Add("E_basic", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
new ShaderFile(AssemblyUtility.ReadAssemblyFile("SM.Base.Shaders.SimpleShaderPresets.basic_vertex.glsl"))
{
StringOverrides = {["extension"] = "1"}
},
BasicSetUniforms
));
VertexFiles.Add("instanced", new Tuple<ShaderFile, Action<UniformCollection, DrawContext>>(
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<ShaderFile, Action<UniformCollection, DrawContext>>(
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<UniformCollection, DrawContext> SetUniform;
public SimpleShader(string vertexPreset, string fragment, Action<UniformCollection, DrawContext> setUniform) : base(new ShaderFileCollection(VertexFiles[vertexPreset].Item1, new ShaderFile(fragment)))
{
_vertexPreset = vertexPreset;
SetUniform = setUniform;
}
public SimpleShader(string vertexPreset, string vertexExtension, string fragment,
Action<UniformCollection, DrawContext> 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);
}
}
}

View file

@ -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
}

View file

@ -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
}

View file

@ -1,7 +1,8 @@
#region usings #region usings
using System; using System;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
#endregion #endregion

View file

@ -2,7 +2,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
#endregion #endregion

View file

@ -2,7 +2,8 @@
using System; using System;
using System.Diagnostics.Eventing.Reader; using System.Diagnostics.Eventing.Reader;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Windows;
#endregion #endregion

View file

@ -7,11 +7,15 @@ namespace SM.Base.Types
/// A One-dimensional Vector (also known as <see cref="float"/>), in a class. /// A One-dimensional Vector (also known as <see cref="float"/>), in a class.
/// </summary> /// </summary>
public class CVector1 public class CVector1
{ {
/// <summary> /// <summary>
/// X - Component /// X - Component
/// </summary> /// </summary>
public float X { get; set; } public float X
{
get;
set;
}
/// <summary> /// <summary>
/// The length/magnitute of the vector. /// The length/magnitute of the vector.
@ -26,6 +30,8 @@ namespace SM.Base.Types
/// </remarks> /// </remarks>
public float LengthSquared => GetLength(true); public float LengthSquared => GetLength(true);
public event Action Changed;
/// <summary> /// <summary>
/// Creates a class vector /// Creates a class vector
/// </summary> /// </summary>
@ -63,14 +69,16 @@ namespace SM.Base.Types
/// Sets the X-Component. /// Sets the X-Component.
/// </summary> /// </summary>
/// <param name="x">X-Component</param> /// <param name="x">X-Component</param>
public virtual void Set(float uniform) public virtual void Set(float uniform, bool triggerChanged = true)
{ {
X = uniform; X = uniform;
if (triggerChanged) TriggerChanged();
} }
public virtual void Add(float uniform) public virtual void Add(float uniform, bool triggerChanged = true)
{ {
X += uniform; X += uniform;
if (triggerChanged) TriggerChanged();
} }
/// <summary> /// <summary>
@ -82,15 +90,20 @@ namespace SM.Base.Types
/// </summary> /// </summary>
/// <param name="f"></param> /// <param name="f"></param>
/// <returns></returns> /// <returns></returns>
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; return X * X;
} }
private protected virtual void NormalizationProcess(float length) protected virtual void NormalizationProcess(float length)
{ {
X *= length; X *= length;
} }
protected void TriggerChanged()
{
Changed?.Invoke();
}
} }
} }

View file

@ -29,12 +29,12 @@ namespace SM.Base.Types
Y = y; Y = y;
} }
private protected override float GetLengthProcess() protected override float GetLengthProcess()
{ {
return base.GetLengthProcess() + Y * Y; return base.GetLengthProcess() + Y * Y;
} }
private protected override void NormalizationProcess(float length) protected override void NormalizationProcess(float length)
{ {
base.NormalizationProcess(length); base.NormalizationProcess(length);
Y *= length; Y *= length;
@ -44,19 +44,19 @@ namespace SM.Base.Types
/// Sets each component to the same value /// Sets each component to the same value
/// </summary> /// </summary>
/// <param name="uniform"></param> /// <param name="uniform"></param>
public override void Set(float uniform) public override void Set(float uniform, bool triggerChanged = true)
{ {
base.Set(uniform);
Y = uniform; Y = uniform;
base.Set(uniform, triggerChanged);
} }
/// <summary> /// <summary>
/// Sets each component to the <see cref="Vector2"/> counter-part. /// Sets each component to the <see cref="Vector2"/> counter-part.
/// </summary> /// </summary>
/// <param name="vector"></param> /// <param name="vector"></param>
public void Set(Vector2 vector) public void Set(Vector2 vector, bool triggerChanged = true)
{ {
Set(vector.X, vector.Y); Set(vector.X, vector.Y, triggerChanged);
} }
/// <summary> /// <summary>
@ -64,27 +64,27 @@ namespace SM.Base.Types
/// </summary> /// </summary>
/// <param name="x"></param> /// <param name="x"></param>
/// <param name="y"></param> /// <param name="y"></param>
public void Set(float x, float y) public void Set(float x, float y, bool triggerChanged = true)
{ {
base.Set(x);
Y = y; 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; 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; Y += y;
base.Add(x, triggerChanged);
} }
/// <summary> /// <summary>

View file

@ -28,56 +28,56 @@ namespace SM.Base.Types
Z = z; Z = z;
} }
private protected override float GetLengthProcess() protected override float GetLengthProcess()
{ {
return base.GetLengthProcess() + Z * Z; return base.GetLengthProcess() + Z * Z;
} }
private protected override void NormalizationProcess(float length) protected override void NormalizationProcess(float length)
{ {
base.NormalizationProcess(length); base.NormalizationProcess(length);
Z *= length; Z *= length;
} }
/// <inheritdoc /> /// <inheritdoc />
public override void Set(float uniform) public override void Set(float uniform, bool triggerChanged = true)
{ {
base.Set(uniform);
Z = uniform; Z = uniform;
base.Set(uniform, triggerChanged);
} }
/// <summary> /// <summary>
/// Sets the a own value to each component. /// Sets the a own value to each component.
/// </summary> /// </summary>
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; Z = z;
base.Set(x,y, triggerChanged);
} }
/// <summary> /// <summary>
/// Sets each component to the <see cref="Vector3"/> counter-part. /// Sets each component to the <see cref="Vector3"/> counter-part.
/// </summary> /// </summary>
/// <param name="vector"></param> /// <param name="vector"></param>
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; 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; Z += z;
base.Add(x,y, triggerChanged);
} }
/// <summary> /// <summary>

View file

@ -0,0 +1,10 @@
namespace SM.Utility
{
public interface IInitializable
{
bool IsInitialized { get; set; }
void Activate();
void Initialization();
}
}

View file

@ -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();
}
}
}

View file

@ -1,103 +1,33 @@
#region usings using System.Collections.Generic;
using System.Collections.Generic;
using System.Dynamic;
using OpenTK; using OpenTK;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Scene; using SM.Base.Scene;
using SM.OGL.Mesh; using SM.OGL.Mesh;
#endregion namespace SM.Base.Windows
namespace SM.Base.Contexts
{ {
/// <summary>
/// Contains important information for drawing.
/// </summary>
public struct DrawContext public struct DrawContext
{ {
/// <summary> public IGenericWindow Window { get; internal set; }
/// This says if it was forced to use the viewport camera. public GenericScene Scene { get; internal set; }
/// </summary> public RenderPipeline RenderPipeline { get; internal set; }
public bool ForceViewport;
/// <summary> public GenericCamera UseCamera { get; internal set; }
/// Contains the currently used render pipeline. public Matrix4 World => UseCamera.World;
/// </summary> public Matrix4 View => UseCamera.View;
public RenderPipeline ActivePipeline;
public GenericScene ActiveScene; public GenericMesh Mesh { get; set; }
public IGenericWindow Window; public Material Material { get; set; }
public MaterialShader Shader => Material.CustomShader ?? RenderPipeline.DefaultShader;
public Matrix4 ModelMatrix;
public GenericCamera UsedCamera => public Matrix3 TextureMatrix;
ForceViewport || ActiveScene._camera == null ? Window.ViewportCamera : ActiveScene._camera;
/// <summary>
/// The mesh.
/// </summary>
public GenericMesh Mesh;
/// <summary>
/// The material.
/// </summary>
public Material Material;
/// <summary>
/// The drawing instances.
/// <para>If there is only one, it's index 0</para>
/// </summary>
public IList<Instance> Instances; public IList<Instance> Instances;
public void SetCamera(GenericCamera camera)
{
/// <summary> UseCamera = camera;
/// The current world scale. camera.CalculateViewMatrix(Window);
/// </summary> }
public Vector2 WorldScale;
/// <summary>
/// The last collection the context was passed though.
/// </summary>
public object LastPassthough;
/// <summary>
/// Returns the appropriate shader.
/// <para>
/// Returns the material shader, if available, otherwise it will take the default shader from the render
/// pipeline.
/// </para>
/// </summary>
public MaterialShader Shader => Material.CustomShader ?? ActivePipeline._defaultShader;
/// <summary>
/// Arguments for shaders
/// </summary>
public IDictionary<string, object> ShaderArguments;
/// <summary>
/// The current world matrix.
/// </summary>
public Matrix4 World;
/// <summary>
/// The current view matrix.
/// </summary>
public Matrix4 View;
/// <summary>
/// The current WorldView matrix.
/// </summary>
public Matrix4 WorldView;
/// <summary>
/// The master model matrix.
/// </summary>
public Matrix4 ModelMaster;
} }
} }

View file

@ -1,32 +1,14 @@
#region usings using OpenTK.Input;
using OpenTK.Input;
using SM.Base.Scene; using SM.Base.Scene;
#endregion namespace SM.Base.Windows
namespace SM.Base.Contexts
{ {
/// <summary>
/// The update context.
/// </summary>
public struct UpdateContext public struct UpdateContext
{ {
/// <summary> public IGenericWindow Window;
/// The delta time.
/// </summary>
public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime; public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime;
/// <summary> public GenericScene Scene;
/// The current keyboard state.
/// </summary>
public KeyboardState KeyboardState;
/// <summary>
/// The current mouse state.
/// </summary>
public MouseState MouseState;
public GenericScene CurrentScene;
} }
} }

View file

@ -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<IGenericWindow> Resize;
public event Action<IGenericWindow> Load;
public event Action<IGenericWindow> 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);
}
}

View file

@ -1,37 +1,48 @@
using System.Drawing; using System;
using System.Windows; using System.Drawing;
using OpenTK; using OpenTK;
using SM.Base.Controls;
using SM.Base.Scene; using SM.Base.Scene;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
namespace SM.Base namespace SM.Base.Windows
{ {
public interface IGenericWindow : IFramebufferWindow public interface IGenericWindow : IFramebufferWindow
{ {
bool Loading { get; } 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 ForceViewportCamera { get; set; }
bool DrawWhileUnfocused { get; set; }
bool UpdateWhileUnfocused { get; set; }
int Width { get; } int Width { get; }
int Height { get; } int Height { get; }
Vector2 WindowSize { get; set; }
Rectangle ClientRectangle { get; } Rectangle ClientRectangle { get; }
Vector2 WorldScale { get; set; }
void SetWorldScale(); ISetup AppliedSetup { get; }
}
public interface IGenericWindow<TScene, TCamera> : IGenericWindow event Action<IGenericWindow> Resize;
where TScene : GenericScene, new() event Action<IGenericWindow> Load;
where TCamera : GenericCamera, new()
{
TScene CurrentScene { get; }
RenderPipeline<TScene> RenderPipeline { get; } GenericScene CurrentScene { get; }
RenderPipeline CurrentRenderPipeline { get; }
void SetScene(TScene scene); void Update(UpdateContext context);
void SetRenderPipeline(RenderPipeline<TScene> renderPipeline);
void ApplySetup(ISetup setup);
void SetScene(GenericScene scene);
void SetRenderPipeline(RenderPipeline renderPipeline);
void TriggerLoad();
void TriggerResize();
void Close();
} }
} }

View file

@ -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);
}
}

View file

@ -1,150 +1,57 @@
#region usings using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading; using System.Threading;
using SM.Base.Contexts;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Scene;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
using SM.OGL.Texture;
using SM.Utility;
#endregion namespace SM.Base.Windows
namespace SM.Base
{ {
/// <summary> public abstract class RenderPipeline : IInitializable
/// Definition of specific render options.
/// </summary>
public abstract class RenderPipeline
{ {
/// <summary> public IGenericWindow ConnectedWindow { get; internal set; }
/// If true, this pipeline was already once activated.
/// </summary>
public bool IsInitialized { get; private set; } = false;
/// <summary> public Framebuffer MainFramebuffer { get; protected set; }
/// The window the pipeline is connected to.
/// </summary>
protected IGenericWindow _window { get; private set; }
/// <summary> public List<Framebuffer> Framebuffers { get; } = new List<Framebuffer>();
/// The framebuffers, that are used in this Pipeline.
/// </summary>
public virtual List<Framebuffer> Framebuffers { get; private set; }
/// <summary> public virtual MaterialShader DefaultShader { get; protected set; }
/// The default shader for the pipeline. public virtual Material DefaultMaterial { get; protected set; }
/// </summary>
protected internal virtual MaterialShader _defaultShader { get; set; }
public virtual Framebuffer MainFramebuffer { get; protected set; }= Framebuffer.Screen; public bool IsInitialized { get; set; }
/// <summary> internal void Render(ref DrawContext context) => RenderProcess(ref context);
/// Occurs, when the window is loading.
/// </summary>
protected internal virtual void Load()
{
}
/// <summary> protected abstract void RenderProcess(ref DrawContext context);
/// Occurs, when the window is resizing.
/// </summary> public virtual void Resize()
protected internal virtual void Resize()
{ {
if (Framebuffers == null) return; if (Framebuffers == null) return;
foreach(var framebuffer in Framebuffers)
foreach (var framebuffer in Framebuffers)
framebuffer.Dispose(); framebuffer.Dispose();
Thread.Sleep(50); Thread.Sleep(50);
foreach (Framebuffer framebuffer in Framebuffers) foreach(var framebuffer in Framebuffers)
{
framebuffer.Compile(); framebuffer.Compile();
}
} }
internal void Activate(IGenericWindow window) public virtual void Activate()
{ {
_window = window;
if (!IsInitialized)
{
if (_defaultShader == null) _defaultShader = SMRenderer.DefaultMaterialShader;
Framebuffers = new List<Framebuffer>();
Initialization(window);
Framebuffers.Add(MainFramebuffer);
IsInitialized = true;
}
Activation(window);
} }
/// <summary> public virtual void Initialization()
/// Occurs, when the pipeline was connected to a window.
/// </summary>
protected internal virtual void Activation(IGenericWindow window)
{ {
if (MainFramebuffer != null) Framebuffers.Add(MainFramebuffer);
DefaultShader ??= SMRenderer.DefaultMaterialShader;
} }
public Framebuffer CreateWindowFramebuffer(int multisamples)
/// <summary>
/// Occurs, when the pipeline was connected to a window the first time.
/// </summary>
/// <param name="window"></param>
protected internal virtual void Initialization(IGenericWindow window)
{ {
Framebuffer framebuffer = new Framebuffer(window: ConnectedWindow);
} framebuffer.Append("color", new ColorAttachment(0, PixelInformation.RGBA_LDR, multisamples));
/// <summary>
/// Occurs, when the window is unloading.
/// </summary>
protected internal virtual void Unload()
{
}
/// <summary>
/// Creates a framebuffer, that has specific (often) required settings already applied.
/// </summary>
/// <returns></returns>
public static Framebuffer CreateWindowFramebuffer()
{
Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow);
framebuffer.Append("color", 0);
return framebuffer; return framebuffer;
} }
} }
/// <summary>
/// Represents a render pipeline.
/// </summary>
/// <typeparam name="TScene">The scene type</typeparam>
public abstract class RenderPipeline<TScene> : RenderPipeline
where TScene : GenericScene
{
/// <summary>
/// The system to render stuff.
/// </summary>
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);
/// <summary>
/// Event, that triggers, when the scene in the current window changes.
/// </summary>
/// <param name="scene"></param>
protected internal virtual void SceneChanged(TScene scene)
{
}
}
} }

View file

@ -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);
}
}
}

View file

@ -14,20 +14,8 @@ namespace SM.OGL.Framebuffer
/// </summary> /// </summary>
public class ColorAttachment : TextureBase public class ColorAttachment : TextureBase
{ {
/// <summary> private int _multisamples;
/// Creates a attachment with a specific id.
/// </summary>
/// <param name="attachmentId"></param>
public ColorAttachment(int attachmentId) : this(attachmentId, PixelInformation.RGBA_LDR)
{ }
public ColorAttachment(int attachmentID, PixelInformation pixelInformation)
{
AttachmentID = attachmentID;
PixelInformation = pixelInformation;
}
/// <summary> /// <summary>
/// The ID the attachment was given. /// The ID the attachment was given.
/// </summary> /// </summary>
@ -50,6 +38,22 @@ namespace SM.OGL.Framebuffer
/// </summary> /// </summary>
public DrawBuffersEnum DrawBuffersEnum => DrawBuffersEnum.ColorAttachment0 + AttachmentID; public DrawBuffersEnum DrawBuffersEnum => DrawBuffersEnum.ColorAttachment0 + AttachmentID;
public bool IsMultisampled => _multisamples > 0;
/// <summary>
/// Creates a attachment with a specific id.
/// </summary>
/// <param name="attachmentId"></param>
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;
}
/// <summary> /// <summary>
/// Generates the attachment. /// Generates the attachment.
/// </summary> /// </summary>
@ -57,20 +61,36 @@ namespace SM.OGL.Framebuffer
public void Generate(Framebuffer f) public void Generate(Framebuffer f)
{ {
_id = GL.GenTexture(); _id = GL.GenTexture();
if (IsMultisampled) GenerateMultisampledTexture(f);
else GenerateTexture(f);
}
private void GenerateTexture(Framebuffer f)
{
GL.BindTexture(TextureTarget.Texture2D, _id); GL.BindTexture(TextureTarget.Texture2D, _id);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInformation.InternalFormat, 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); 0, PixelInformation.Format, PixelInformation.DataType, IntPtr.Zero);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter,
(int) TextureMinFilter.Linear); (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter,
(int) TextureMinFilter.Linear); (int)TextureMinFilter.Linear);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS,
(int) TextureParameterName.ClampToEdge); (int)TextureParameterName.ClampToEdge);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, 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);
} }
} }
} }

View file

@ -14,6 +14,8 @@ namespace SM.OGL.Framebuffer
/// </summary> /// </summary>
public class Framebuffer : GLObject public class Framebuffer : GLObject
{ {
protected override bool AutoCompile { get; } = true;
/// <summary> /// <summary>
/// Represents the screen buffer. /// Represents the screen buffer.
/// </summary> /// </summary>
@ -92,7 +94,7 @@ namespace SM.OGL.Framebuffer
GL.DrawBuffers(enums.Length, enums); GL.DrawBuffers(enums.Length, enums);
foreach (var pair in ColorAttachments) 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); 0);
var err = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer); var err = GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer);
@ -123,7 +125,6 @@ namespace SM.OGL.Framebuffer
ColorAttachments.Add(key, value); ColorAttachments.Add(key, value);
} }
/// <summary> /// <summary>
/// Activates the framebuffer without clearing the buffer. /// Activates the framebuffer without clearing the buffer.
/// </summary> /// </summary>

View file

@ -2,6 +2,7 @@
using System; using System;
using OpenTK; using OpenTK;
using OpenTK.Graphics.OpenGL;
#endregion #endregion
@ -47,9 +48,35 @@ namespace SM.OGL.Mesh
/// <param name="y">If true, it takes the Y-value of maximum, otherwise the minimum.</param> /// <param name="y">If true, it takes the Y-value of maximum, otherwise the minimum.</param>
/// <param name="z">If true, it takes the Z-value of maximum, otherwise the minimum.</param> /// <param name="z">If true, it takes the Z-value of maximum, otherwise the minimum.</param>
/// <returns></returns> /// <returns></returns>
public Vector3 this[bool x, bool y, bool z] => public Vector3 this[bool x, bool y, bool z] => Get(x,y,z);
new Vector3(x ? Max.X : Min.X, y ? Max.Y : Min.Y, z ? Max.Z : Min.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;
}
}
/// <summary> /// <summary>
/// Updates the bounding box. /// Updates the bounding box.
/// </summary> /// </summary>

View file

@ -13,6 +13,9 @@ namespace SM.OGL.Mesh
/// </summary> /// </summary>
public abstract class GenericMesh : GLObject public abstract class GenericMesh : GLObject
{ {
private bool _boundingBoxUpdated = false;
public static int LastID { get; internal set; } = -1;
/// <summary> /// <summary>
/// Generates the AttribDataIndex /// Generates the AttribDataIndex
@ -69,14 +72,28 @@ namespace SM.OGL.Mesh
/// </summary> /// </summary>
public virtual int[] Indices { get; set; } public virtual int[] Indices { get; set; }
public void UpdateBoundingBox()
{
BoundingBox.Update(this);
_boundingBoxUpdated = true;
}
public void Activate()
{
GL.BindVertexArray(ID);
}
/// <inheritdoc /> /// <inheritdoc />
public override void Compile() public override void Compile()
{ {
_id = GL.GenVertexArray(); _id = GL.GenVertexArray();
GL.BindVertexArray(_id); GL.BindVertexArray(_id);
if (Attributes == null || Attributes.Count == 0) throw new Exception("[Critical] The model requires attributes."); if (Attributes == null || Attributes.Count == 0) throw new Exception("[Critical] The model requires attributes.");
if (!_boundingBoxUpdated)
UpdateBoundingBox();
foreach (var kvp in Attributes) foreach (var kvp in Attributes)
kvp.ConnectedVBO?.BindBuffer(kvp.Index); kvp.ConnectedVBO?.BindBuffer(kvp.Index);

View file

@ -0,0 +1,7 @@
namespace SM.OGL.Mesh
{
public interface ILineMesh
{
float LineWidth { get; set; }
}
}

View file

@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using OpenTK.Graphics.OpenGL;
namespace SM.OGL.Mesh namespace SM.OGL.Mesh
{ {
@ -50,5 +51,11 @@ namespace SM.OGL.Mesh
//if (vbo == null) return; //if (vbo == null) return;
Add(new MeshAttribute(id, name, vbo)); Add(new MeshAttribute(id, name, vbo));
} }
public bool Has(string name)
{
VBO attribute = this[name];
return attribute != null && attribute.Active;
}
} }
} }

View file

@ -40,6 +40,8 @@ namespace SM.OGL.Mesh
/// </summary> /// </summary>
public int PointerStride; public int PointerStride;
public bool Active = true;
/// <summary> /// <summary>
/// Specifies the data type of each component in the array. /// Specifies the data type of each component in the array.
/// </summary> /// </summary>
@ -133,6 +135,14 @@ namespace SM.OGL.Mesh
Add(vector.X, vector.Y, z, w); Add(vector.X, vector.Y, z, w);
} }
public void Add(params Vector2[] vectors)
{
foreach (Vector2 vector in vectors)
{
Add(vector);
}
}
/// <summary> /// <summary>
/// Adds a Vector3. /// Adds a Vector3.
/// </summary> /// </summary>
@ -149,6 +159,13 @@ namespace SM.OGL.Mesh
Add(vector.X, vector.Y, vector.Z, w); Add(vector.X, vector.Y, vector.Z, w);
} }
public void Add(params Vector3[] vectors)
{
foreach (Vector3 vector in vectors)
{
Add(vector);
}
}
/// <summary> /// <summary>
/// Adds a vector4. /// Adds a vector4.
/// </summary> /// </summary>
@ -172,6 +189,8 @@ namespace SM.OGL.Mesh
/// <param name="attribID">The id for the attribute.</param> /// <param name="attribID">The id for the attribute.</param>
internal void BindBuffer(int attribID) internal void BindBuffer(int attribID)
{ {
if (!Active) return;
var data = ToArray(); var data = ToArray();
var buffer = GL.GenBuffer(); var buffer = GL.GenBuffer();

View file

@ -51,6 +51,7 @@
<Compile Include="GLSystem.cs" /> <Compile Include="GLSystem.cs" />
<Compile Include="Mesh\BoundingBox.cs" /> <Compile Include="Mesh\BoundingBox.cs" />
<Compile Include="Mesh\GenericMesh.cs" /> <Compile Include="Mesh\GenericMesh.cs" />
<Compile Include="Mesh\ILineMesh.cs" />
<Compile Include="Mesh\MeshAttribute.cs" /> <Compile Include="Mesh\MeshAttribute.cs" />
<Compile Include="Mesh\MeshAttributeList.cs" /> <Compile Include="Mesh\MeshAttributeList.cs" />
<Compile Include="Mesh\VBO.cs" /> <Compile Include="Mesh\VBO.cs" />

View file

@ -106,6 +106,11 @@ namespace SM.OGL.Shaders
GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%"); GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%");
} }
public void Activate()
{
GL.UseProgram(ID);
}
/// <inheritdoc /> /// <inheritdoc />
public override void Compile() public override void Compile()
{ {
@ -122,7 +127,7 @@ namespace SM.OGL.Shaders
/// </summary> /// </summary>
/// <param name="mesh">The mesh.</param> /// <param name="mesh">The mesh.</param>
/// <param name="amount">The amounts for instancing.</param> /// <param name="amount">The amounts for instancing.</param>
protected void DrawObject(GenericMesh mesh, int amount = 1) public static void DrawObject(GenericMesh mesh, int amount = 1)
{ {
if (mesh.Indices != null) if (mesh.Indices != null)
GL.DrawElementsInstanced(mesh.PrimitiveType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount); GL.DrawElementsInstanced(mesh.PrimitiveType, 0, DrawElementsType.UnsignedInt, mesh.Indices, amount);
@ -138,7 +143,6 @@ namespace SM.OGL.Shaders
Uniforms.NextTexture = 0; Uniforms.NextTexture = 0;
GL.BindTexture(TextureTarget.Texture2D, 0); GL.BindTexture(TextureTarget.Texture2D, 0);
GL.BindVertexArray(0);
} }
} }
} }

View file

@ -14,17 +14,17 @@ namespace SM.OGL.Shaders
/// <summary> /// <summary>
/// Contains the vertex file. /// Contains the vertex file.
/// </summary> /// </summary>
public ShaderFile Vertex; public ShaderFile[] Vertex;
/// <summary> /// <summary>
/// Contains the geometry file. /// Contains the geometry file.
/// </summary> /// </summary>
public ShaderFile Geometry; public ShaderFile[] Geometry;
/// <summary> /// <summary>
/// Contains the fragment file. /// Contains the fragment file.
/// </summary> /// </summary>
public ShaderFile Fragment; public ShaderFile[] Fragment;
/// <summary> /// <summary>
/// Creating the collection with vertex and fragment files. /// Creating the collection with vertex and fragment files.
@ -44,6 +44,14 @@ namespace SM.OGL.Shaders
/// <param name="fragment"></param> /// <param name="fragment"></param>
/// <param name="geometry"></param> /// <param name="geometry"></param>
public ShaderFileCollection(ShaderFile vertex, ShaderFile fragment, ShaderFile geometry = default) 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; Vertex = vertex;
Geometry = geometry; Geometry = geometry;
@ -56,9 +64,15 @@ namespace SM.OGL.Shaders
/// <param name="shader"></param> /// <param name="shader"></param>
internal void Append(GenericShader shader) internal void Append(GenericShader shader)
{ {
Vertex.Compile(shader, ShaderType.VertexShader); foreach (ShaderFile file in Vertex)
Geometry?.Compile(shader, ShaderType.GeometryShader); file.Compile(shader, ShaderType.VertexShader);
Fragment.Compile(shader, ShaderType.FragmentShader);
if (Geometry != null)
foreach (ShaderFile file in Geometry)
file.Compile(shader, ShaderType.GeometryShader);
foreach (ShaderFile file in Fragment)
file.Compile(shader, ShaderType.FragmentShader);
} }
/// <summary> /// <summary>
@ -67,9 +81,15 @@ namespace SM.OGL.Shaders
/// <param name="shader"></param> /// <param name="shader"></param>
internal void Detach(GenericShader shader) internal void Detach(GenericShader shader)
{ {
GL.DetachShader(shader, Vertex); foreach (ShaderFile file in Vertex)
if (Geometry != null) GL.DetachShader(shader, Geometry); GL.DetachShader(shader, file);
GL.DetachShader(shader, Fragment);
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()}'"); GLDebugging.CheckGLErrors($"Error at detaching '{shader.GetType()}'");
} }

View file

@ -354,7 +354,7 @@ namespace SM.OGL.Shaders
#region Matrix2 #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); GL.UniformMatrix2(Location, transpose, ref matrix);
} }
@ -383,7 +383,7 @@ namespace SM.OGL.Shaders
#region Matrix3 #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); GL.UniformMatrix3(Location, transpose, ref matrix);
} }
@ -485,7 +485,7 @@ namespace SM.OGL.Shaders
{ {
Parent.NextTexture = texturePos + 1; Parent.NextTexture = texturePos + 1;
GL.ActiveTexture(TextureUnit.Texture0 + texturePos); GL.ActiveTexture(TextureUnit.Texture0 + texturePos);
GL.BindTexture(TextureTarget.Texture2D, texture); GL.BindTexture(texture.Target, texture);
SetUniform1(texturePos); SetUniform1(texturePos);
} }

View file

@ -12,6 +12,7 @@ namespace SM.OGL.Shaders
public string Name { get; internal set; } public string Name { get; internal set; }
public UniformCollection Parent { get; internal set; } public UniformCollection Parent { get; internal set; }
public GenericShader ParentShader { get; internal set; } public GenericShader ParentShader { get; internal set; }
public int Length => storedUniforms.Count;
public Dictionary<string, Uniform> this[int index] => Get(index); public Dictionary<string, Uniform> this[int index] => Get(index);

View file

@ -24,7 +24,7 @@ namespace SM.OGL.Shaders
} }
catch (KeyNotFoundException) 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); var u = new Uniform(GL.GetUniformLocation(ParentShader, KeyString + key), this);
Add(key, u); Add(key, u);
return u; return u;

View file

@ -13,12 +13,15 @@ namespace SM.OGL.Texture
{ {
/// <inheritdoc /> /// <inheritdoc />
protected override bool AutoCompile { get; } = true; protected override bool AutoCompile { get; } = true;
/// <inheritdoc /> /// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Texture; public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Texture;
public PixelInformation PixelInformation; public PixelInformation PixelInformation;
public TextureTarget Target { get; set; } = TextureTarget.Texture2D;
/// <summary> /// <summary>
/// The texture filter. /// The texture filter.
/// <para>Default: <see cref="TextureMinFilter.Linear" /></para> /// <para>Default: <see cref="TextureMinFilter.Linear" /></para>

View file

@ -1,41 +1,63 @@
#region usings using System.Collections.Generic;
using OpenTK; using OpenTK;
using OpenTK.Input;
using SM.Base.Controls; using SM.Base.Controls;
using SM.Base.Drawing;
using SM.Base.Scene;
using SM2D.Scene; using SM2D.Scene;
using SM2D.Types; using SM2D.Types;
#endregion
namespace SM2D.Controls namespace SM2D.Controls
{ {
public class Mouse2D : Mouse<IGLWindow2D> public class Mouse2D
{ {
protected internal Mouse2D(IGLWindow2D window) : base(window) public static Vector2 InWorld(Vector2 worldScale)
{ {
} var res = worldScale;
internal new void MouseMoveEvent(MouseMoveEventArgs mmea)
{
base.MouseMoveEvent(mmea);
}
public Vector2 InWorld()
{
var res = _window.WorldScale;
res.Y *= -1; 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<TObject>(Vector2 mousePos, params TObject[] checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation>
=> MouseOver(mousePos, out _, checkingObjects);
public static bool MouseOver<TObject>(Vector2 mousePos, ICollection<TObject> checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation>
=> MouseOver<TObject>(mousePos, out _, checkingObjects);
public static bool MouseOver<TObject>(Vector2 mousePos, out TObject clicked, params TObject[] checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation>
=> MouseOver<TObject>(mousePos, out clicked, (ICollection<TObject>)checkingObjects);
public static bool MouseOver<TObject>(Vector2 mousePos, out TObject clickedObj, ICollection<TObject> checkingObjects)
where TObject : IModelItem, ITransformItem<Transformation>
{
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;
} }
} }
} }

View file

@ -4,20 +4,38 @@ using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Objects.Static; using SM.Base.Objects.Static;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Textures; using SM.Base.Textures;
using SM.Base.Windows;
using SM.OGL.Texture; using SM.OGL.Texture;
using SM2D.Scene;
#endregion #endregion
namespace SM2D.Drawing 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) public DrawBackground(Color4 color)
{ {
@ -35,41 +53,12 @@ namespace SM2D.Drawing
Texture = (Texture) texture; Texture = (Texture) texture;
} }
public Color4 Color
protected override void DrawContext(ref DrawContext context)
{ {
get => _material.Tint; base.DrawContext(ref context);
set => _material.Tint = value; context.ModelMatrix = Matrix4.CreateScale((context.UseCamera as Camera).WorldScale.X, (context.UseCamera as Camera).WorldScale.Y, 1);
}
public TextureBase Texture
{
get => _material.Texture;
set => _material.Texture = value;
}
public object Parent { get; set; }
public string Name { get; set; } = "Background";
public ICollection<string> 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);
context.Shader.Draw(context); context.Shader.Draw(context);
} }
public void OnAdded(object sender)
{
}
public void OnRemoved(object sender)
{
}
} }
} }

View file

@ -2,30 +2,30 @@
using System.Drawing; using System.Drawing;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Objects; using SM.Base.Objects;
using SM.Base.Textures; using SM.Base.Textures;
using SM.Base.Windows;
using SM.OGL.Mesh;
using SM2D.Object; using SM2D.Object;
using SM2D.Scene; using SM2D.Scene;
using SM2D.Types; using SM2D.Types;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
public class DrawObject2D : DrawingBasis<Transformation>, I2DShowItem public class DrawObject2D : DrawingBasis<Transformation>
{ {
public int ZIndex { get; set; }
public Texture Texture public Texture Texture
{ {
get => (Texture) _material.Texture; get => (Texture) Material.Texture;
set => _material.Texture = value; set => Material.Texture = value;
} }
public Color4 Color public Color4 Color
{ {
get => _material.Tint; get => Material.Tint;
set => _material.Tint = value; set => Material.Tint = value;
} }
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
@ -33,37 +33,32 @@ namespace SM2D.Drawing
base.DrawContext(ref context); base.DrawContext(ref context);
context.Shader.Draw(context); context.Shader.Draw(context);
} }
public void SetShader(MaterialShader shader) => Material.CustomShader = shader;
public Material GetMaterialReference() => _material; public Polygon ApplyPolygon(ICollection<Vector2> vertices, bool centerUVs = false)
public void SetMaterialReference(Material material) => _material = material;
public void SetShader(MaterialShader shader) => _material.CustomShader = shader;
public Polygon ApplyPolygon(ICollection<Vector2> vertices)
{ {
Polygon polygon = new Polygon(vertices); Polygon polygon = new Polygon(vertices);
_mesh = polygon; Mesh = polygon;
return polygon; return polygon;
} }
public Polygon ApplyPolygon(ICollection<PolygonVertex> vertices) public Polygon ApplyPolygon(ICollection<PolygonVertex> vertices, bool centerUVs = false)
{ {
Polygon polygon = new Polygon(vertices); Polygon polygon = new Polygon(vertices);
_mesh = polygon; Mesh = polygon;
return polygon; return polygon;
} }
public void ApplyPolygon(Polygon polygon) public void ApplyPolygon(Polygon polygon)
{ {
_mesh = polygon; Mesh = polygon;
} }
public void ApplyMesh(Mesh mesh) => _mesh = mesh; public Polygon ApplyCircle(int segments = 32, bool centerUVs = false)
public Polygon ApplyCircle(int segments = 32)
{ {
Polygon pol = Polygon.GenerateCircle(segments); Polygon pol = Polygon.GenerateCircle(segments);
_mesh = pol; Mesh = pol;
return pol; return pol;
} }
} }
} }

View file

@ -7,9 +7,8 @@ using SM2D.Types;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
public class DrawParticles : ParticleDrawingBasis<Transformation, Vector2>, I2DShowItem public class DrawParticles : ParticleDrawingBasis<Transformation, Vector2>
{ {
public int ZIndex { get; set; }
public override Func<Vector2, ParticleContext, Vector2> MovementCalculation { get; set; } = ParticleMovement.Default2D; public override Func<Vector2, ParticleContext, Vector2> MovementCalculation { get; set; } = ParticleMovement.Default2D;
public DrawParticles(TimeSpan duration) : base(duration) public DrawParticles(TimeSpan duration) : base(duration)

View file

@ -1,8 +1,9 @@
#region usings #region usings
using SM.Base.Contexts; using SM.Base;
using SM.Base.Drawing.Text; using SM.Base.Drawing.Text;
using SM.Base.Types; using SM.Base.Types;
using SM.Base.Windows;
using SM2D.Scene; using SM2D.Scene;
using SM2D.Types; using SM2D.Types;
@ -10,7 +11,7 @@ using SM2D.Types;
namespace SM2D.Drawing namespace SM2D.Drawing
{ {
public class DrawText : TextDrawingBasis<Transformation>, I2DShowItem public class DrawText : TextDrawingBasis<Transformation>
{ {
public DrawText(Font font, string text) : base(font) public DrawText(Font font, string text) : base(font)
{ {
@ -18,8 +19,6 @@ namespace SM2D.Drawing
Transform.Size = new CVector2(1); Transform.Size = new CVector2(1);
} }
public int ZIndex { get; set; }
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context); base.DrawContext(ref context);

View file

@ -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<Vector2> vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices)
{
UVs.Active = false;
PrimitiveType = (PrimitiveType)lineType;
}
public PolyLine(ICollection<PolygonVertex> vertices, PolyLineType lineType = PolyLineType.NotConnected) : base(vertices)
{
UVs.Active = false;
PrimitiveType = (PrimitiveType)lineType;
}
}
}

View file

@ -16,13 +16,16 @@ namespace SM2D.Object
{ {
public Polygon(ICollection<Vector2> vertices) : base(PrimitiveType.TriangleFan) public Polygon(ICollection<Vector2> vertices) : base(PrimitiveType.TriangleFan)
{ {
Color.Active = false;
foreach (var vertex in vertices) foreach (var vertex in vertices)
{ {
Color.Add(Color4.White); Vertex.Add(vertex, 0);
AddVertex(vertex);
} }
foreach (var vertex in vertices) AddUV(vertex); UpdateBoundingBox();
if (UVs.Active) foreach (var vertex in vertices) AddUV(vertex);
} }
public Polygon(ICollection<PolygonVertex> vertices) : base(PrimitiveType.TriangleFan) public Polygon(ICollection<PolygonVertex> vertices) : base(PrimitiveType.TriangleFan)
@ -30,10 +33,12 @@ namespace SM2D.Object
foreach (var polygonVertex in vertices) foreach (var polygonVertex in vertices)
{ {
Color.Add(polygonVertex.Color); 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(); 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; 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) private void AddUV(Vector2 vertex)
{ {
var uv = Vector2.Divide(vertex - BoundingBox.Min.Xy, BoundingBox.Max.Xy - BoundingBox.Min.Xy); var uv = Vector2.Divide(vertex - BoundingBox.Min.Xy, BoundingBox.Max.Xy - BoundingBox.Min.Xy);

View file

@ -1,6 +0,0 @@
namespace SM2D.Pipelines
{
public class Adv2DPipeline
{
}
}

View file

@ -1,26 +1,23 @@
using System; using System;
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using SM.Base; using SM.Base;
using SM.Base.Contexts;
using SM.Base.Drawing; using SM.Base.Drawing;
using SM.Base.Windows;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
using SM2D.Shader; using SM2D.Shader;
namespace SM2D.Pipelines namespace SM2D.Pipelines
{ {
public class Basic2DPipeline : RenderPipeline<Scene.Scene> public class Basic2DPipeline : RenderPipeline
{ {
public static Basic2DPipeline Pipeline = new Basic2DPipeline(); 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);
} }
} }
} }

View file

@ -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<Scene.Scene>
{
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);
}
}
}

View file

@ -45,22 +45,19 @@
<Compile Include="Drawing\DrawObject2D.cs" /> <Compile Include="Drawing\DrawObject2D.cs" />
<Compile Include="Drawing\DrawParticles.cs" /> <Compile Include="Drawing\DrawParticles.cs" />
<Compile Include="Drawing\DrawText.cs" /> <Compile Include="Drawing\DrawText.cs" />
<Compile Include="Window\GLWindow2D.cs" />
<Compile Include="Window\GLWPFWindow2D.cs" />
<Compile Include="Object\Polygon.cs" /> <Compile Include="Object\Polygon.cs" />
<Compile Include="Object\PolygonVertex.cs" /> <Compile Include="Object\PolygonVertex.cs" />
<Compile Include="Pipelines\Adv2DPipeline.cs" /> <Compile Include="Object\PolyLine.cs" />
<Compile Include="Pipelines\Basic2DPipeline.cs" /> <Compile Include="Pipelines\Basic2DPipeline.cs" />
<Compile Include="Pipelines\Default2DPipeline.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Scene\Camera.cs" /> <Compile Include="Scene\Camera.cs" />
<Compile Include="Scene\I2DShowItem.cs" /> <Compile Include="Scene\I2DShowItem.cs" />
<Compile Include="Scene\ItemCollection.cs" /> <Compile Include="Scene\ItemCollection.cs" />
<Compile Include="Scene\Scene.cs" /> <Compile Include="Scene\Scene.cs" />
<Compile Include="Shader\Basic2DShader.cs" /> <Compile Include="Shader\ShaderCollection.cs" />
<Compile Include="Shader\Default2DShader.cs" />
<Compile Include="Types\Transformation.cs" /> <Compile Include="Types\Transformation.cs" />
<Compile Include="Window\IGLWindow2D.cs" /> <Compile Include="Window\Window2DSetup.cs" />
<Compile Include="Window\I2DSetup.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\SM.Base\SM.Base.csproj"> <ProjectReference Include="..\SM.Base\SM.Base.csproj">
@ -72,9 +69,6 @@
<Name>SM.OGL</Name> <Name>SM.OGL</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Shader\ShaderFiles\default.glsl" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="OpenTK"> <PackageReference Include="OpenTK">
<Version>3.3.1</Version> <Version>3.3.1</Version>

View file

@ -1,3 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation"> <wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=light_005Clightobjects/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=light_005Clightobjects/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=shader_005Cshaderfiles/@EntryIndexedValue">False</s:Boolean>
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=window/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=window/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View file

@ -1,8 +1,11 @@
#region usings #region usings
using System;
using OpenTK; using OpenTK;
using SM.Base;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Types; using SM.Base.Types;
using SM.Base.Windows;
#endregion #endregion
@ -10,18 +13,73 @@ namespace SM2D.Scene
{ {
public class Camera : GenericCamera 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<Camera> WorldScaleChanged;
public CVector2 Position = new CVector2(0); public CVector2 Position = new CVector2(0);
public override bool Orthographic { get; } = true; 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 = world = Matrix4.Identity;
Matrix4.CreateOrthographic(world.X, world.Y, 0.1f, 100f); 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);
} }
} }
} }

View file

@ -1,15 +1,16 @@
#region usings #region usings
using SM.Base.Contexts; using SM.Base;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Types; using SM.Base.Types;
using SM.Base.Windows;
using SM2D.Types; using SM2D.Types;
#endregion #endregion
namespace SM2D.Scene namespace SM2D.Scene
{ {
public class ItemCollection : GenericItemCollection<I2DShowItem, Transformation>, I2DShowItem public class ItemCollection : GenericItemCollection<Transformation>
{ {
public ItemCollection() public ItemCollection()
{ {
@ -18,11 +19,7 @@ namespace SM2D.Scene
public override void Draw(DrawContext context) public override void Draw(DrawContext context)
{ {
Sort((x, y) => x.ZIndex - y.ZIndex);
base.Draw(context); base.Draw(context);
} }
public int ZIndex { get; set; }
} }
} }

View file

@ -2,16 +2,17 @@
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using SM.Base.Contexts; using SM.Base;
using SM.Base.Objects.Static; using SM.Base.Objects.Static;
using SM.Base.Scene; using SM.Base.Scene;
using SM.Base.Windows;
using SM2D.Drawing; using SM2D.Drawing;
#endregion #endregion
namespace SM2D.Scene namespace SM2D.Scene
{ {
public class Scene : GenericScene<Camera, ItemCollection, I2DShowItem> public class Scene : GenericScene<Camera, ItemCollection>
{ {
private static DrawObject2D _axisHelper; private static DrawObject2D _axisHelper;
@ -19,16 +20,24 @@ namespace SM2D.Scene
static Scene() static Scene()
{ {
_axisHelper = new DrawObject2D(); _axisHelper = new DrawObject2D();
_axisHelper.ApplyMesh(AxisHelper.Object); _axisHelper.Mesh = AxisHelper.Object;
} }
public Scene() public Scene()
{ {
_Background = new DrawBackground(Color4.Black); _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) public override void DrawDebug(DrawContext context)
{ {

View file

@ -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);
}
}
}

View file

@ -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);
}
}
}

View file

@ -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"]);
}
}
}

View file

@ -1,20 +1,6 @@
#version 330 #version 330
//# region vertex in vec2 v_TexCoords;
in vec4 v_Color;
//# 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 vec4 Tint; uniform vec4 Tint;
uniform bool UseTexture; uniform bool UseTexture;
@ -22,7 +8,9 @@ uniform sampler2D Texture;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
void fmain() { void main() {
color = vColor * Tint; color = vec4(v_TexCoords, 0, 1);
if (UseTexture) color *= texture(Texture, vTexture); return;
color = v_Color * Tint;
if (UseTexture) color = texture(Texture, v_TexCoords);
} }

View file

@ -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);
}

Some files were not shown because too many files have changed in this diff Show more