05.01.2021

+ Bloom effect
+ PixelInformation
+ Many Summaries
+ Add-methods for CVectors
+ Exposure-Field in GenericCamera for HDR.

~ ColorAttachments now can have PixelInformation
~ Transformed MeshAttributes to a own class
~ Fixed the non-applying of transformations at texts
~ Added more information to the context
~ Improved Pipeline-Process.
~ Changed how Uniform takes arrays

- Light system
This commit is contained in:
Michel Fedde 2021-01-06 17:04:15 +01:00
parent 9b917ac181
commit 4c18127c88
52 changed files with 697 additions and 373 deletions

View file

@ -32,10 +32,17 @@ namespace SM.Base.Drawing
/// <inheritdoc /> /// <inheritdoc />
public ICollection<string> Flags { get; set; } public ICollection<string> Flags { get; set; }
/// <summary>
/// This value determents if the object should draw something.
/// </summary>
public bool Active = true;
/// <inheritdoc /> /// <inheritdoc />
public void Draw(DrawContext context) public void Draw(DrawContext context)
{ {
if (!Active) return;
context.Material = _material; context.Material = _material;
context.Mesh = _mesh; context.Mesh = _mesh;
@ -76,6 +83,7 @@ namespace SM.Base.Drawing
/// <inheritdoc /> /// <inheritdoc />
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context);
context.ModelMaster *= Transform.GetMatrix(); context.ModelMaster *= Transform.GetMatrix();
} }
} }

View file

@ -80,6 +80,7 @@ namespace SM.Base.Drawing.Text
/// <inheritdoc /> /// <inheritdoc />
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context);
if (_instances == null) GenerateMatrixes(); if (_instances == null) GenerateMatrixes();
} }

View file

@ -0,0 +1,30 @@
using System;
using OpenTK.Graphics.OpenGL4;
using SM.OGL.Mesh;
namespace SM.Base.Objects
{
public class InstancedMesh : Mesh
{
public InstancedMesh(PrimitiveType type, string[] enabledAttibute) : base(type)
{
Attributes["vertex"] = Vertex = new VBO();
foreach (string attribute in enabledAttibute)
{
switch (attribute)
{
case "uv":
Attributes["uv"] = UVs = new VBO(pointerSize: 2);
break;
case "normals":
Attributes["normal"] = Normals = new VBO();
break;
case "color":
Attributes["color"] = Color = new VBO(pointerSize: 4);
break;
}
}
}
}
}

View file

@ -13,7 +13,7 @@ namespace SM.Base.Objects
/// <summary> /// <summary>
/// While initializing, it will add the <see cref="Color" /> to the data index. /// While initializing, it will add the <see cref="Color" /> to the data index.
/// </summary> /// </summary>
public Mesh(PrimitiveType type) public Mesh(PrimitiveType type) : base()
{ {
PrimitiveType = type; PrimitiveType = type;
Attributes.Add(3, "color", Color); Attributes.Add(3, "color", Color);

View file

@ -0,0 +1,82 @@
using System.ComponentModel;
using OpenTK.Graphics.OpenGL4;
using SM.Base.Contexts;
using SM.Base.PostProcess;
using SM.OGL.Framebuffer;
using SM.OGL.Texture;
using SM.Utility;
namespace SM.Base.PostEffects
{
public class BloomEffect : PostProcessEffect
{
private Framebuffer _bloomBuffer1;
private Framebuffer _bloomBuffer2;
private ColorAttachment _xBuffer;
private ColorAttachment _yBuffer;
private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM.Base.PostEffects.Shaders.bloom_blur.glsl"));
private PostProcessShader _mergeShader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM.Base.PostEffects.Shaders.bloom_merge.glsl"));
private int _bloomLocation;
private bool _hdr;
public int Iterations = 5;
public float[] Weights = { 0.227027f, 0.1945946f, 0.1216216f, 0.054054f, 0.016216f };
public BloomEffect(int bloomLocation, bool hdr = false)
{
_bloomLocation = bloomLocation;
_hdr = hdr;
}
protected override void InitProcess()
{
Pipeline.MainFramebuffer.Append("bloom", new ColorAttachment(_bloomLocation, PixelInformation.RGBA_HDR));
_bloomBuffer1 = new Framebuffer(SMRenderer.CurrentWindow);
_bloomBuffer1.Append("xBuffer", _xBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
_bloomBuffer1.Compile();
_bloomBuffer2 = new Framebuffer(SMRenderer.CurrentWindow);
_bloomBuffer2.Append("yBuffer", _yBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
_bloomBuffer2.Compile();
Pipeline.Framebuffers.Add(_bloomBuffer1);
Pipeline.Framebuffers.Add(_bloomBuffer2);
}
public override void Draw(DrawContext context)
{
Framebuffer target = Framebuffer.GetCurrentlyActive();
bool first = true, hoz = true;
int iter = Iterations * 2;
for (int i = 0; i < iter; i++)
{
(hoz ? _bloomBuffer1 : _bloomBuffer2).Activate();
_shader.Draw(first ? Pipeline.MainFramebuffer.ColorAttachments["bloom"] : (hoz ? _yBuffer : _xBuffer), collection =>
{
collection["Horizontal"].SetUniform1(hoz);
collection["Weights"].SetUniform1(Weights);
collection["WeightCount"].SetUniform1(Weights.Length);
});
hoz = !hoz;
if (first) first = false;
}
target.Activate();
_mergeShader.Draw(Pipeline.MainFramebuffer.ColorAttachments["color"], collection =>
{
collection["Bloom"].SetTexture(_yBuffer);
collection["Exposure"].SetUniform1(context.UsedCamera.Exposure);
collection["HDR"].SetUniform1(_hdr);
});
}
}
}

View file

@ -0,0 +1,30 @@
#version 330
uniform sampler2D renderedTexture;
uniform bool Horizontal;
uniform float[32] Weights;
uniform int WeightCount;
layout(location = 0) out vec4 color;
vec4 GetRenderColorOffset(vec2 offset);
void main() {
vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0);
vec3 result = GetRenderColorOffset(vec2(0)).rgb * Weights[0];
if (Horizontal) {
for(int i = 1; i < WeightCount; i++) {
result += GetRenderColorOffset(vec2(tex_offset.x * i, 0)).rgb * Weights[i];
result += GetRenderColorOffset(vec2(-tex_offset.x * i, 0)).rgb * Weights[i];
}
} else {
for(int i = 1; i < WeightCount; i++) {
result += GetRenderColorOffset(vec2(0, tex_offset.x * i)).rgb * Weights[i];
result += GetRenderColorOffset(vec2(0, -tex_offset.x * i)).rgb * Weights[i];
}
}
color = vec4(result, 1);
}

View file

@ -0,0 +1,21 @@
#version 330
in vec2 vTexture;
uniform sampler2D renderedTexture;
uniform sampler2D Bloom;
uniform float Exposure;
uniform bool HDR;
layout(location = 0) out vec4 color;
void main() {
vec3 result = texture(Bloom, vTexture).rgb;
if (!HDR) {
result = vec3(1.0) - exp(-result * Exposure);
}
result += texture(renderedTexture, vTexture).rgb;
color = vec4(result, 1);
}

View file

@ -6,4 +6,8 @@ uniform sampler2D renderedTexture;
vec4 GetRenderColor() { vec4 GetRenderColor() {
return texture(renderedTexture, vTexture); return texture(renderedTexture, vTexture);
}
vec4 GetRenderColorOffset(vec2 offset) {
return texture(renderedTexture, vTexture + offset);
} }

View file

@ -3,6 +3,7 @@ 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.Objects.Static; using SM.Base.Objects.Static;
using SM.Base.Scene; using SM.Base.Scene;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
@ -18,27 +19,28 @@ namespace SM.Base.PostProcess
internal static Matrix4 Mvp; internal static Matrix4 Mvp;
internal static Matrix4 Model; internal static Matrix4 Model;
protected RenderPipeline Pipeline;
/// <summary>
/// Initialize the effect.
/// </summary>
/// <param name="pipeline"></param>
public void Initilize(RenderPipeline pipeline)
{
Pipeline = pipeline;
InitProcess();
}
/// <summary> /// <summary>
/// Method, to initialize the shader. /// Method, to initialize the shader.
/// </summary> /// </summary>
public virtual void Init() {} protected virtual void InitProcess() {}
/// <summary>
/// Method, to initialize the shader.
/// </summary>
public virtual void Init(Framebuffer main)
{
Init();
}
/// <summary> /// <summary>
/// Method to draw the actual effect. /// Method to draw the actual effect.
/// </summary> /// </summary>
/// <param name="main">The framebuffer, that was used.</param> public abstract void Draw(DrawContext context);
/// <param name="target">The framebuffer, the system should draw to.</param>
public abstract void Draw(Framebuffer main, Framebuffer target);
/// <summary> /// <summary>
/// Event, when the scene changed. /// Event, when the scene changed.

View file

@ -55,8 +55,10 @@
<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="Log.cs" /> <Compile Include="Log.cs" />
<Compile Include="Objects\InstancedMesh.cs" />
<Compile Include="Objects\Mesh.cs" /> <Compile Include="Objects\Mesh.cs" />
<Compile Include="Objects\Static\AxisHelper.cs" /> <Compile Include="Objects\Static\AxisHelper.cs" />
<Compile Include="PostEffects\BloomEffect.cs" />
<Compile Include="PostProcess\PostProcessEffect.cs" /> <Compile Include="PostProcess\PostProcessEffect.cs" />
<Compile Include="PostProcess\PostProcessShader.cs" /> <Compile Include="PostProcess\PostProcessShader.cs" />
<Compile Include="Scene\IScriptable.cs" /> <Compile Include="Scene\IScriptable.cs" />
@ -112,6 +114,8 @@
<ItemGroup> <ItemGroup>
<None Include="OpenTK.dll.config" /> <None Include="OpenTK.dll.config" />
<None Include="packages.config" /> <None Include="packages.config" />
<EmbeddedResource Include="PostEffects\Shaders\bloom_blur.glsl" />
<EmbeddedResource Include="PostEffects\Shaders\bloom_merge.glsl" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> </Project>

View file

@ -43,6 +43,8 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public abstract bool Orthographic { get; } public abstract bool Orthographic { get; }
public float Exposure = 1;
/// <summary> /// <summary>
/// Calculates the view matrix. /// Calculates the view matrix.
/// </summary> /// </summary>

View file

@ -30,6 +30,18 @@ namespace SM.Base.Scene
_background = value; _background = value;
} }
} }
/// <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>
internal GenericCamera _camera { get; set; }
/// <summary>
/// A collection for cameras to switch easier to different cameras.
/// </summary>
public Dictionary<string, GenericCamera> Cameras = new Dictionary<string, GenericCamera>();
/// <summary> /// <summary>
/// If true, the scene was already initialized. /// If true, the scene was already initialized.
/// </summary> /// </summary>
@ -50,7 +62,7 @@ namespace SM.Base.Scene
public virtual void Draw(DrawContext context) public virtual void Draw(DrawContext context)
{ {
} }
/// <summary> /// <summary>
/// Adds a extension to the scene. /// Adds a extension to the scene.
/// </summary> /// </summary>
@ -102,8 +114,7 @@ namespace SM.Base.Scene
/// Called, when the user activates the scene. /// Called, when the user activates the scene.
/// </summary> /// </summary>
protected virtual void OnActivating() protected virtual void OnActivating()
{ { }
}
} }
/// <summary> /// <summary>
@ -125,16 +136,11 @@ namespace SM.Base.Scene
/// </summary> /// </summary>
public bool ShowAxisHelper { get; set; } = false; public bool ShowAxisHelper { get; set; } = false;
/// <summary>
/// A collection for cameras to switch easier to different cameras.
/// </summary>
public Dictionary<string, TCamera> Cameras = new Dictionary<string, TCamera>();
/// <summary> /// <summary>
/// The active camera, that is used if the context doesn't force the viewport camera. /// 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> /// <para>If none set, it automaticly uses the viewport camera.</para>
/// </summary> /// </summary>
public TCamera Camera { get; set; } public TCamera Camera => (TCamera) _camera;
/// <summary> /// <summary>
/// A camera to control the background. /// A camera to control the background.

View file

@ -35,14 +35,7 @@ namespace SM.Base.Types
X = x; X = x;
} }
/// <summary>
/// Sets the X-Component.
/// </summary>
/// <param name="x">X-Component</param>
public virtual void Set(float x)
{
X = x;
}
/// <summary> /// <summary>
/// Get the length of the vector. /// Get the length of the vector.
@ -66,6 +59,19 @@ namespace SM.Base.Types
NormalizationProcess(length); NormalizationProcess(length);
} }
/// <summary>
/// Sets the X-Component.
/// </summary>
/// <param name="x">X-Component</param>
public virtual void Set(float uniform)
{
X = uniform;
}
public virtual void Add(float uniform)
{
X += uniform;
}
/// <summary> /// <summary>
/// Conversion into <see cref="float"/> /// Conversion into <see cref="float"/>

View file

@ -70,6 +70,23 @@ namespace SM.Base.Types
Y = y; Y = y;
} }
public override void Add(float uniform)
{
base.Add(uniform);
Y += uniform;
}
public void Add(Vector2 vector)
{
Add(vector.X, vector.Y);
}
public void Add(float x, float y)
{
base.Add(x);
Y += y;
}
/// <summary> /// <summary>
/// Converts to <see cref="Vector2"/> /// Converts to <see cref="Vector2"/>
/// </summary> /// </summary>

View file

@ -63,6 +63,23 @@ namespace SM.Base.Types
Set(vector.X, vector.Y, vector.Z); Set(vector.X, vector.Y, vector.Z);
} }
public override void Add(float uniform)
{
base.Add(uniform);
Z += uniform;
}
public void Add(Vector3 vector)
{
Add(vector.X, vector.Y, vector.Z);
}
public void Add(float x, float y, float z)
{
base.Add(x,y);
Z += z;
}
/// <summary> /// <summary>
/// Converts to <see cref="Vector3"/> /// Converts to <see cref="Vector3"/>
/// </summary> /// </summary>

View file

@ -21,6 +21,65 @@ namespace SM.Base.Contexts
/// </summary> /// </summary>
public bool ForceViewport; public bool ForceViewport;
/// <summary>
/// Contains the currently used render pipeline.
/// </summary>
public RenderPipeline ActivePipeline;
public GenericScene ActiveScene;
public GenericWindow 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> /// <summary>
/// The current world matrix. /// The current world matrix.
/// </summary> /// </summary>
@ -40,50 +99,5 @@ namespace SM.Base.Contexts
/// The master model matrix. /// The master model matrix.
/// </summary> /// </summary>
public Matrix4 ModelMaster; public Matrix4 ModelMaster;
/// <summary>
/// The drawing instances.
/// <para>If there is only one, it's index 0</para>
/// </summary>
public IList<Instance> Instances;
/// <summary>
/// The mesh.
/// </summary>
public GenericMesh Mesh;
/// <summary>
/// The material.
/// </summary>
public Material Material;
/// <summary>
/// Contains the currently used render pipeline.
/// </summary>
public RenderPipeline ActivePipeline;
/// <summary>
/// The current world scale.
/// </summary>
public Vector2 WorldScale;
/// <summary>
/// The last collection the context was passed though.
/// </summary>
public object LastPassthough;
/// <summary>
/// Arguments for shaders
/// </summary>
public IDictionary<string, object> ShaderArguments;
/// <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;
} }
} }

View file

@ -49,6 +49,8 @@ namespace SM.Base
/// </summary> /// </summary>
public bool ReactWhileUnfocused = false; public bool ReactWhileUnfocused = false;
internal GenericCamera _viewportCamera;
/// <inheritdoc /> /// <inheritdoc />
protected GenericWindow() : this(1280, 720, "Generic OGL Title", GameWindowFlags.Default) protected GenericWindow() : this(1280, 720, "Generic OGL Title", GameWindowFlags.Default)
{ {
@ -223,13 +225,16 @@ namespace SM.Base
/// <inheritdoc /> /// <inheritdoc />
protected GenericWindow() protected GenericWindow()
{ {
ViewportCamera = new TCamera(); _viewportCamera = new TCamera();
} }
/// <summary> /// <summary>
/// The viewport camera. /// The viewport camera.
/// </summary> /// </summary>
public TCamera ViewportCamera { get; } public TCamera ViewportCamera {
get => (TCamera)_viewportCamera;
set => _viewportCamera = value;
}
/// <summary> /// <summary>
/// This forces the render to use the viewport camera. /// This forces the render to use the viewport camera.
@ -258,29 +263,37 @@ namespace SM.Base
{ {
if (!ReactWhileUnfocused && !Focused) return; if (!ReactWhileUnfocused && !Focused) return;
if (CurrentScene == null) return;
SMRenderer.CurrentFrame++; SMRenderer.CurrentFrame++;
Deltatime.RenderDelta = (float) e.Time; Deltatime.RenderDelta = (float) e.Time;
var drawContext = new DrawContext var drawContext = new DrawContext
{ {
World = ViewportCamera.World, ForceViewport = ForceViewportCamera,
View = ViewportCamera.CalculateViewMatrix(), ActiveScene = CurrentScene,
ModelMaster = Matrix4.Identity, Window = this,
Instances = new[] Instances = new[]
{ {
new Instance new Instance
{ModelMatrix = Matrix4.Identity, TexturePosition = Vector2.Zero, TextureScale = Vector2.One} {ModelMatrix = Matrix4.Identity, TexturePosition = Vector2.Zero, TextureScale = Vector2.One}
}, },
ShaderArguments = new Dictionary<string, object>(),
Mesh = Plate.Object, Mesh = Plate.Object,
ForceViewport = ForceViewportCamera,
WorldScale = _worldScale, WorldScale = _worldScale,
LastPassthough = this LastPassthough = this,
ShaderArguments = new Dictionary<string, object>(),
World = ViewportCamera.World,
View = ViewportCamera.CalculateViewMatrix(),
ModelMaster = Matrix4.Identity
}; };
base.OnRenderFrame(e); base.OnRenderFrame(e);
RenderPipeline.Render(ref drawContext, CurrentScene); RenderPipeline.Render(ref drawContext);
SwapBuffers(); SwapBuffers();

View file

@ -29,12 +29,14 @@ namespace SM.Base
/// <summary> /// <summary>
/// The framebuffers, that are used in this Pipeline. /// The framebuffers, that are used in this Pipeline.
/// </summary> /// </summary>
protected virtual List<Framebuffer> _framebuffers { get; } public virtual List<Framebuffer> Framebuffers { get; private set; }
/// <summary> /// <summary>
/// The default shader for the pipeline. /// The default shader for the pipeline.
/// </summary> /// </summary>
protected internal virtual MaterialShader _defaultShader { get; } = SMRenderer.DefaultMaterialShader; protected internal virtual MaterialShader _defaultShader { get; set; }
public virtual Framebuffer MainFramebuffer { get; protected set; }= Framebuffer.Screen;
/// <summary> /// <summary>
/// Occurs, when the window is loading. /// Occurs, when the window is loading.
@ -48,14 +50,14 @@ namespace SM.Base
/// </summary> /// </summary>
protected internal 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 (Framebuffer framebuffer in Framebuffers)
{ {
framebuffer.Compile(); framebuffer.Compile();
} }
@ -67,7 +69,13 @@ namespace SM.Base
if (!IsInitialized) if (!IsInitialized)
{ {
if (_defaultShader == null) _defaultShader = SMRenderer.DefaultMaterialShader;
Framebuffers = new List<Framebuffer>();
Initialization(window); Initialization(window);
Framebuffers.Add(MainFramebuffer);
IsInitialized = true; IsInitialized = true;
} }
@ -106,7 +114,6 @@ namespace SM.Base
{ {
Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow); Framebuffer framebuffer = new Framebuffer(window: SMRenderer.CurrentWindow);
framebuffer.Append("color", 0); framebuffer.Append("color", 0);
framebuffer.Compile();
return framebuffer; return framebuffer;
} }
} }
@ -121,11 +128,15 @@ namespace SM.Base
/// <summary> /// <summary>
/// The system to render stuff. /// The system to render stuff.
/// </summary> /// </summary>
protected internal virtual void Render(ref DrawContext context, TScene scene) internal void Render(ref DrawContext context)
{ {
context.ActivePipeline = this; context.ActivePipeline = this;
RenderProcess(ref context, (TScene)context.ActiveScene);
} }
protected abstract void RenderProcess(ref DrawContext context, TScene scene);
/// <summary> /// <summary>
/// Event, that triggers, when the scene in the current window changes. /// Event, that triggers, when the scene in the current window changes.
/// </summary> /// </summary>

View file

@ -8,31 +8,64 @@ using SM.OGL.Texture;
namespace SM.OGL.Framebuffer namespace SM.OGL.Framebuffer
{ {
/// <summary>
/// Represents a Framebuffer-Color Attachment.
/// <para>Can be use like a texture.</para>
/// </summary>
public class ColorAttachment : TextureBase public class ColorAttachment : TextureBase
{ {
public ColorAttachment(int attachmentId) /// <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)
{ {
AttachmentID = attachmentId;
AttachmentID = attachmentID;
PixelInformation = pixelInformation;
} }
/// <summary>
/// The ID the attachment was given.
/// </summary>
public int AttachmentID { get; } public int AttachmentID { get; }
/// <summary>
/// Returns the <see cref="OpenTK.Graphics.OpenGL4.FramebufferAttachment"/> of this ColorAttachment.
/// </summary>
public FramebufferAttachment FramebufferAttachment => FramebufferAttachment.ColorAttachment0 + AttachmentID; public FramebufferAttachment FramebufferAttachment => FramebufferAttachment.ColorAttachment0 + AttachmentID;
/// <summary>
/// Returns the <see cref="OpenTK.Graphics.OpenGL4.DrawBufferMode"/> of this ColorAttachment.
/// </summary>
public DrawBufferMode DrawBufferMode => DrawBufferMode.ColorAttachment0 + AttachmentID; public DrawBufferMode DrawBufferMode => DrawBufferMode.ColorAttachment0 + AttachmentID;
/// <summary>
/// Returns the <see cref="OpenTK.Graphics.OpenGL4.ReadBufferMode"/> of this ColorAttachment.
/// </summary>
public ReadBufferMode ReadBufferMode => ReadBufferMode.ColorAttachment0 + AttachmentID; public ReadBufferMode ReadBufferMode => ReadBufferMode.ColorAttachment0 + AttachmentID;
/// <summary>
/// Returns the <see cref="OpenTK.Graphics.OpenGL4.DrawBuffersEnum"/> of this ColorAttachment.
/// </summary>
public DrawBuffersEnum DrawBuffersEnum => DrawBuffersEnum.ColorAttachment0 + AttachmentID; public DrawBuffersEnum DrawBuffersEnum => DrawBuffersEnum.ColorAttachment0 + AttachmentID;
/// <summary>
/// Generates the attachment.
/// </summary>
/// <param name="f"></param>
public void Generate(Framebuffer f) public void Generate(Framebuffer f)
{ {
_id = GL.GenTexture(); _id = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, _id); GL.BindTexture(TextureTarget.Texture2D, _id);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba8, GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInformation.InternalFormat,
(int) f.Size.X, (int) f.Size.Y, (int) f.Size.X, (int) f.Size.Y,
0, PixelFormat.Bgra, PixelType.UnsignedByte, 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);

View file

@ -9,9 +9,14 @@ using OpenTK.Graphics.OpenGL4;
namespace SM.OGL.Framebuffer namespace SM.OGL.Framebuffer
{ {
// TODO: Write summeries for framebuffer-system. /// <summary>
/// Represents a OpenGL Framebuffer.
/// </summary>
public class Framebuffer : GLObject public class Framebuffer : GLObject
{ {
/// <summary>
/// Represents the screen buffer.
/// </summary>
public static readonly Framebuffer Screen = new Framebuffer public static readonly Framebuffer Screen = new Framebuffer
{ {
_id = 0, _id = 0,
@ -23,10 +28,18 @@ namespace SM.OGL.Framebuffer
private INativeWindow _window; private INativeWindow _window;
private float _windowScale; private float _windowScale;
/// <summary>
/// Creates a buffer without any options.
/// </summary>
public Framebuffer() public Framebuffer()
{ {
} }
/// <summary>
/// Creates a buffer, while always respecting the screen.
/// </summary>
/// <param name="window"></param>
/// <param name="scale"></param>
public Framebuffer(INativeWindow window, float scale = 1) : this(new Vector2(window.Width * scale, public Framebuffer(INativeWindow window, float scale = 1) : this(new Vector2(window.Width * scale,
window.Height * scale)) window.Height * scale))
{ {
@ -34,18 +47,30 @@ namespace SM.OGL.Framebuffer
_windowScale = scale; _windowScale = scale;
} }
/// <summary>
/// Creates a buffer, with a specified size.
/// </summary>
/// <param name="size"></param>
public Framebuffer(Vector2 size) public Framebuffer(Vector2 size)
{ {
Size = size; Size = size;
} }
/// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer; public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Framebuffer;
/// <summary>
/// Contains the size of the framebuffer.
/// </summary>
public Vector2 Size { get; private set; } public Vector2 Size { get; private set; }
/// <summary>
/// Contains all color attachments.
/// </summary>
public Dictionary<string, ColorAttachment> ColorAttachments { get; private set; } = public Dictionary<string, ColorAttachment> ColorAttachments { get; private set; } =
new Dictionary<string, ColorAttachment>(); new Dictionary<string, ColorAttachment>();
/// <inheritdoc />
public override void Compile() public override void Compile()
{ {
if (!_canBeCompiled) return; if (!_canBeCompiled) return;
@ -78,6 +103,7 @@ namespace SM.OGL.Framebuffer
GL.BindTexture(TextureTarget.Texture2D, 0); GL.BindTexture(TextureTarget.Texture2D, 0);
} }
/// <inheritdoc />
public override void Dispose() public override void Dispose()
{ {
base.Dispose(); base.Dispose();
@ -85,32 +111,76 @@ namespace SM.OGL.Framebuffer
GL.DeleteFramebuffer(this); GL.DeleteFramebuffer(this);
} }
/// <summary>
/// Appends a color attachment.
/// </summary>
public void Append(string key, int pos) => Append(key, new ColorAttachment(pos)); public void Append(string key, int pos) => Append(key, new ColorAttachment(pos));
/// <summary>
/// Appends a color attachment.
/// </summary>
public void Append(string key, ColorAttachment value) public void Append(string key, ColorAttachment value)
{ {
ColorAttachments.Add(key, value); ColorAttachments.Add(key, value);
} }
/// <summary>
/// Activates the framebuffer without clearing the buffer.
/// </summary>
public void Activate() public void Activate()
{ {
Activate(FramebufferTarget.Framebuffer, ClearBufferMask.None); Activate(FramebufferTarget.Framebuffer, ClearBufferMask.None);
} }
/// <summary>
/// Activates the framebuffer for the specific target framebuffer and without clearing.
/// </summary>
/// <param name="target"></param>
public void Activate(FramebufferTarget target) public void Activate(FramebufferTarget target)
{ {
Activate(target, ClearBufferMask.None); Activate(target, ClearBufferMask.None);
} }
/// <summary>
/// Activates the framebuffer while clearing the specified buffer.
/// </summary>
/// <param name="clearMask"></param>
public void Activate(ClearBufferMask clearMask) public void Activate(ClearBufferMask clearMask)
{ {
Activate(FramebufferTarget.Framebuffer, clearMask); Activate(FramebufferTarget.Framebuffer, clearMask);
} }
/// <summary>
/// Activates the framebuffer for the specific target and with clearing.
/// </summary>
/// <param name="target"></param>
/// <param name="clear"></param>
public void Activate(FramebufferTarget target, ClearBufferMask clear) public void Activate(FramebufferTarget target, ClearBufferMask clear)
{ {
GL.BindFramebuffer(target, this); GL.BindFramebuffer(target, this);
GL.Clear(clear); GL.Clear(clear);
} }
public static Framebuffer GetCurrentlyActive(FramebufferTarget target = FramebufferTarget.Framebuffer)
{
Framebuffer buffer = new Framebuffer()
{
_canBeCompiled = false,
};
switch (target)
{
case FramebufferTarget.ReadFramebuffer:
GL.GetInteger(GetPName.ReadFramebufferBinding, out buffer._id);
break;
case FramebufferTarget.DrawFramebuffer:
GL.GetInteger(GetPName.DrawFramebufferBinding, out buffer._id);
break;
case FramebufferTarget.Framebuffer:
GL.GetInteger(GetPName.FramebufferBinding, out buffer._id);
break;
}
return buffer;
}
} }
} }

View file

@ -7,6 +7,9 @@ using OpenTK.Graphics.OpenGL4;
namespace SM.OGL namespace SM.OGL
{ {
/// <summary>
/// Allows the system to send custom actions.
/// </summary>
public class GLCustomActions public class GLCustomActions
{ {
/// <summary> /// <summary>

View file

@ -63,6 +63,11 @@ namespace SM.OGL
return hasError; return hasError;
} }
/// <summary>
/// Checks for OpenGL errors, while allowing to put stuff before and behind it.
/// </summary>
/// <param name="formating"></param>
/// <returns></returns>
public static bool CheckGLErrors(string formating) public static bool CheckGLErrors(string formating)
{ {
var hasError = false; var hasError = false;

View file

@ -54,6 +54,7 @@ namespace SM.OGL
/// <summary> /// <summary>
/// The action, that is called, when "ID" tries to compile something. /// The action, that is called, when "ID" tries to compile something.
/// </summary> /// </summary>
[DebuggerStepThrough]
public virtual void Compile() public virtual void Compile()
{ {
} }

View file

@ -1,7 +1,13 @@
namespace SM.OGL namespace SM.OGL
{ {
/// <summary>
/// Settings that are only accountable for SM.OGL
/// </summary>
public class GLSettings public class GLSettings
{ {
/// <summary>
/// Send a <see cref="GLCustomActions.AtInfo"/>, for each uniform from a shader.
/// </summary>
public static bool InfoEveryUniform = false; public static bool InfoEveryUniform = false;
/// <summary> /// <summary>
@ -10,6 +16,9 @@
/// </summary> /// </summary>
public static Version ForcedVersion { get; set; } = new Version(); public static Version ForcedVersion { get; set; } = new Version();
/// <summary>
/// Allows to disable/enable preprocessing for shaders.
/// </summary>
public static bool ShaderPreProcessing { get; set; } = false; public static bool ShaderPreProcessing { get; set; } = false;
} }
} }

View file

@ -75,9 +75,10 @@ namespace SM.OGL.Mesh
_id = GL.GenVertexArray(); _id = GL.GenVertexArray();
GL.BindVertexArray(_id); GL.BindVertexArray(_id);
if (Attributes == null) throw new Exception("[Critical] The model requires attributes."); if (Attributes == null || Attributes.Count == 0) throw new Exception("[Critical] The model requires attributes.");
foreach (var kvp in Attributes) kvp.ConnectedVBO?.BindBuffer(kvp.Index); foreach (var kvp in Attributes)
kvp.ConnectedVBO?.BindBuffer(kvp.Index);
GL.BindVertexArray(0); GL.BindVertexArray(0);
} }

View file

@ -1,9 +1,21 @@
namespace SM.OGL.Mesh namespace SM.OGL.Mesh
{ {
public struct MeshAttribute /// <summary>
/// This represents a attribute of a mesh.
/// </summary>
public class MeshAttribute
{ {
/// <summary>
/// Index of attribute
/// </summary>
public int Index; public int Index;
/// <summary>
/// Name of the attribute
/// </summary>
public string Name; public string Name;
/// <summary>
/// Connected buffer object.
/// </summary>
public VBO ConnectedVBO; public VBO ConnectedVBO;
public MeshAttribute(int index, string name, VBO buffer) public MeshAttribute(int index, string name, VBO buffer)

View file

@ -4,8 +4,14 @@ using System.Runtime.InteropServices;
namespace SM.OGL.Mesh namespace SM.OGL.Mesh
{ {
/// <summary>
/// List of mesh attributes.
/// </summary>
public class MeshAttributeList : List<MeshAttribute> public class MeshAttributeList : List<MeshAttribute>
{ {
/// <summary>
/// Returns the VBO (or null) that is connected to the specified name.
/// </summary>
public VBO this[string name] public VBO this[string name]
{ {
get get
@ -20,11 +26,28 @@ namespace SM.OGL.Mesh
return null; return null;
} }
set
{
for (int i = 0; i < Count; i++)
{
if (this[i].Name == name)
{
this[i].ConnectedVBO = value;
return;
}
}
}
} }
/// <summary>
/// Adds a new attribute.
/// </summary>
/// <param name="id"></param>
/// <param name="name"></param>
/// <param name="vbo"></param>
public void Add(int id, string name, VBO vbo) public void Add(int id, string name, VBO vbo)
{ {
if (vbo == null) return; //if (vbo == null) return;
Add(new MeshAttribute(id, name, vbo)); Add(new MeshAttribute(id, name, vbo));
} }
} }

View file

@ -21,8 +21,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile> <DocumentationFile>bin\Debug\SM.OGL.xml</DocumentationFile>
</DocumentationFile>
<LangVersion>latest</LangVersion> <LangVersion>latest</LangVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
@ -64,6 +63,7 @@
<Compile Include="Shaders\Uniform.cs" /> <Compile Include="Shaders\Uniform.cs" />
<Compile Include="Shaders\UniformArray.cs" /> <Compile Include="Shaders\UniformArray.cs" />
<Compile Include="Shaders\UniformCollection.cs" /> <Compile Include="Shaders\UniformCollection.cs" />
<Compile Include="Texture\PixelInformation.cs" />
<Compile Include="Texture\TextureBase.cs" /> <Compile Include="Texture\TextureBase.cs" />
<Compile Include="Version.cs" /> <Compile Include="Version.cs" />
</ItemGroup> </ItemGroup>

View file

@ -14,6 +14,7 @@ namespace SM.OGL.Shaders
/// </summary> /// </summary>
public abstract class GenericShader : GLObject public abstract class GenericShader : GLObject
{ {
/// <inheritdoc />
protected override bool AutoCompile { get; } = true; protected override bool AutoCompile { get; } = true;
/// <summary> /// <summary>
@ -26,6 +27,10 @@ namespace SM.OGL.Shaders
/// </summary> /// </summary>
protected UniformCollection Uniforms; protected UniformCollection Uniforms;
/// <summary>
///
/// </summary>
/// <param name="combinedData"></param>
protected GenericShader(string combinedData) protected GenericShader(string combinedData)
{ {
int firstPos = combinedData.IndexOf("//# region ", StringComparison.Ordinal); int firstPos = combinedData.IndexOf("//# region ", StringComparison.Ordinal);
@ -106,7 +111,6 @@ 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>
/// <param name="bindVAO">Binds the vertex array for the mesh.</param>
protected void DrawObject(GenericMesh mesh, int amount = 1) protected void DrawObject(GenericMesh mesh, int amount = 1)
{ {
if (mesh.Indices != null) if (mesh.Indices != null)

View file

@ -1,7 +1,13 @@
namespace SM.OGL.Shaders namespace SM.OGL.Shaders
{ {
/// <summary>
/// Uniform interface
/// </summary>
public interface IUniform public interface IUniform
{ {
/// <summary>
/// Location of the uniforms
/// </summary>
int Location { get; } int Location { get; }
} }
} }

View file

@ -8,16 +8,33 @@ using System.Reflection;
namespace SM.OGL.Shaders namespace SM.OGL.Shaders
{ {
/// <summary>
/// Holder for shader extensions
/// </summary>
public class ShaderExtensions public class ShaderExtensions
{ {
/// <summary>
/// Holds the extensions.
/// </summary>
public static Dictionary<string, ShaderFile> Extensions { get; private set; } = public static Dictionary<string, ShaderFile> Extensions { get; private set; } =
new Dictionary<string, ShaderFile>(); new Dictionary<string, ShaderFile>();
/// <summary>
/// Adds extensions from the calling assembly
/// </summary>
/// <param name="prefix">Prefix for the added extensions.</param>
/// <param name="path">Path, where the extensions are located.</param>
public static void AddAssemblyExtensions(string prefix, string path) public static void AddAssemblyExtensions(string prefix, string path)
{ {
AddAssemblyExtensions(prefix, Assembly.GetCallingAssembly(), path); AddAssemblyExtensions(prefix, Assembly.GetCallingAssembly(), path);
} }
/// <summary>
/// Adds extensions from the specific assembly
/// </summary>
/// <param name="prefix">Prefix for the added extensions.</param>
/// <param name="assembly">The specific assembly</param>
/// <param name="path">Path, where the extensions are located.</param>
public static void AddAssemblyExtensions(string prefix, Assembly assembly, string path) public static void AddAssemblyExtensions(string prefix, Assembly assembly, string path)
{ {
var paths = assembly.GetManifestResourceNames(); var paths = assembly.GetManifestResourceNames();

View file

@ -31,6 +31,7 @@ namespace SM.OGL.Shaders
/// </summary> /// </summary>
/// <param name="vertex">The vertex source file.</param> /// <param name="vertex">The vertex source file.</param>
/// <param name="fragment">The fragment source file.</param> /// <param name="fragment">The fragment source file.</param>
/// <param name="geometry">The geometry source file.</param>
public ShaderFileCollection(string vertex, string fragment, string geometry = "") : this(new ShaderFile(vertex), public ShaderFileCollection(string vertex, string fragment, string geometry = "") : this(new ShaderFile(vertex),
new ShaderFile(fragment), geometry != "" ? new ShaderFile(geometry) : null) new ShaderFile(fragment), geometry != "" ? new ShaderFile(geometry) : null)
{ {

View file

@ -7,8 +7,14 @@ using System.Collections.Generic;
namespace SM.OGL.Shaders namespace SM.OGL.Shaders
{ {
/// <summary>
/// Holds Actions for the preprocessor.
/// </summary>
public class ShaderPreProcess public class ShaderPreProcess
{ {
/// <summary>
/// Holds actions for the preprocessor.
/// </summary>
public static Dictionary<string, Action<ShaderFile, string>> Actions = public static Dictionary<string, Action<ShaderFile, string>> Actions =
new Dictionary<string, Action<ShaderFile, string>> new Dictionary<string, Action<ShaderFile, string>>
{ {

View file

@ -24,14 +24,29 @@ namespace SM.OGL.Shaders
/// </summary> /// </summary>
public UniformCollection Parent { get; } public UniformCollection Parent { get; }
/// <summary>
/// This creates a new uniform manager, that has a null parent.
/// </summary>
/// <param name="location"></param>
public Uniform(int location) : this(location, null) public Uniform(int location) : this(location, null)
{ {
} }
/// <summary>
/// This creates a new uniform manager, that get the location from the provided shader and with a null parent.
/// </summary>
/// <param name="name"></param>
/// <param name="shader"></param>
public Uniform(string name, GenericShader shader) : this(GL.GetUniformLocation(shader, name), null) public Uniform(string name, GenericShader shader) : this(GL.GetUniformLocation(shader, name), null)
{ {
} }
/// <summary>
/// This creates a new uniform manager, that get the location from the provided shader and with a parent.
/// </summary>
/// <param name="name"></param>
/// <param name="shader"></param>
/// <param name="parent"></param>
public Uniform(string name, GenericShader shader, UniformCollection parent) : this(GL.GetUniformLocation(shader, name), parent) public Uniform(string name, GenericShader shader, UniformCollection parent) : this(GL.GetUniformLocation(shader, name), parent)
{ {
@ -60,9 +75,9 @@ namespace SM.OGL.Shaders
GL.Uniform1(Location, value); GL.Uniform1(Location, value);
} }
public void SetUniform1(int count, params int[] values) public void SetUniform1(params int[] values)
{ {
GL.Uniform1(Location, count, values); GL.Uniform1(Location, values.Length, values);
} }
public void SetUniform1(int count, ref int values) public void SetUniform1(int count, ref int values)
@ -76,9 +91,9 @@ namespace SM.OGL.Shaders
GL.Uniform1(Location, value); GL.Uniform1(Location, value);
} }
public void SetUniform1(int count, params uint[] values) public void SetUniform1(params uint[] values)
{ {
GL.Uniform1(Location, count, values); GL.Uniform1(Location, values.Length, values);
} }
public void SetUniform1(int count, ref uint values) public void SetUniform1(int count, ref uint values)
@ -92,9 +107,9 @@ namespace SM.OGL.Shaders
GL.Uniform1(Location, value); GL.Uniform1(Location, value);
} }
public void SetUniform1(int count, params float[] values) public void SetUniform1(params float[] values)
{ {
GL.Uniform1(Location, count, values); GL.Uniform1(Location, values.Length, values);
} }
public void SetUniform1(int count, ref float value) public void SetUniform1(int count, ref float value)
@ -108,9 +123,9 @@ namespace SM.OGL.Shaders
GL.Uniform1(Location, value); GL.Uniform1(Location, value);
} }
public void SetUniform1(int count, params double[] values) public void SetUniform1(params double[] values)
{ {
GL.Uniform1(Location, count, values); GL.Uniform1(Location, values.Length, values);
} }
public void SetUniform1(int count, ref double value) public void SetUniform1(int count, ref double value)
@ -142,24 +157,24 @@ namespace SM.OGL.Shaders
GL.Uniform2(Location, x, y); GL.Uniform2(Location, x, y);
} }
public void SetUniform2(int count, params float[] values) public void SetUniform2(params float[] values)
{ {
GL.Uniform2(Location, count, values); GL.Uniform2(Location, values.Length / 2, values);
} }
public void SetUniform2(int count, params double[] values) public void SetUniform2(params double[] values)
{ {
GL.Uniform2(Location, count, values); GL.Uniform2(Location, values.Length / 2, values);
} }
public void SetUniform2(int count, params int[] values) public void SetUniform2(params int[] values)
{ {
GL.Uniform2(Location, count, values); GL.Uniform2(Location, values.Length / 2, values);
} }
public void SetUniform2(int count, params uint[] values) public void SetUniform2(params uint[] values)
{ {
GL.Uniform2(Location, count, values); GL.Uniform2(Location, values.Length / 2, values);
} }
public void SetUniform2(int count, ref float values) public void SetUniform2(int count, ref float values)
@ -211,24 +226,24 @@ namespace SM.OGL.Shaders
GL.Uniform3(Location, x, y, z); GL.Uniform3(Location, x, y, z);
} }
public void SetUniform3(int count, params float[] values) public void SetUniform3(params float[] values)
{ {
GL.Uniform3(Location, count, values); GL.Uniform3(Location, values.Length / 3, values);
} }
public void SetUniform3(int count, params double[] values) public void SetUniform3(params double[] values)
{ {
GL.Uniform3(Location, count, values); GL.Uniform3(Location, values.Length / 3, values);
} }
public void SetUniform3(int count, params int[] values) public void SetUniform3(params int[] values)
{ {
GL.Uniform3(Location, count, values); GL.Uniform3(Location, values.Length / 3, values);
} }
public void SetUniform3(int count, params uint[] values) public void SetUniform3(params uint[] values)
{ {
GL.Uniform3(Location, count, values); GL.Uniform3(Location, values.Length / 3, values);
} }
public void SetUniform3(int count, ref float values) public void SetUniform3(int count, ref float values)
@ -280,24 +295,24 @@ namespace SM.OGL.Shaders
GL.Uniform4(Location, x, y, z, w); GL.Uniform4(Location, x, y, z, w);
} }
public void SetUniform4(int count, params float[] values) public void SetUniform4(params float[] values)
{ {
GL.Uniform4(Location, count, values); GL.Uniform4(Location, values.Length / 4, values);
} }
public void SetUniform4(int count, params double[] values) public void SetUniform4(params double[] values)
{ {
GL.Uniform4(Location, count, values); GL.Uniform4(Location, values.Length / 4, values);
} }
public void SetUniform4(int count, params int[] values) public void SetUniform4(params int[] values)
{ {
GL.Uniform4(Location, count, values); GL.Uniform4(Location, values.Length / 4, values);
} }
public void SetUniform4(int count, params uint[] values) public void SetUniform4(params uint[] values)
{ {
GL.Uniform4(Location, count, values); GL.Uniform4(Location, values.Length / 4, values);
} }
public void SetUniform4(int count, ref float values) public void SetUniform4(int count, ref float values)

View file

@ -74,6 +74,16 @@ namespace SM.OGL.Shaders
if (key.Contains("[")) if (key.Contains("["))
{ {
var keySplits = key.Split('[', ']'); var keySplits = key.Split('[', ']');
if (keySplits[2] == "")
{
if (keySplits[1] == "0")
{
Add(keySplits[0], loc);
}
continue;
}
if (keySplits[0] != lastArrayKey) if (keySplits[0] != lastArrayKey)
{ {
if (arrayFilled) Add(lastArrayKey, array); if (arrayFilled) Add(lastArrayKey, array);

View file

@ -0,0 +1,23 @@
using OpenTK.Graphics.OpenGL4;
namespace SM.OGL.Texture
{
public struct PixelInformation
{
public static PixelInformation RGB_LDR = new PixelInformation(PixelInternalFormat.Rgb, PixelFormat.Rgb, PixelType.UnsignedByte);
public static PixelInformation RGB_HDR = new PixelInformation(PixelInternalFormat.Rgb16f, PixelFormat.Rgb, PixelType.Float);
public static PixelInformation RGBA_LDR = new PixelInformation(PixelInternalFormat.Rgba, PixelFormat.Rgba, PixelType.UnsignedByte);
public static PixelInformation RGBA_HDR = new PixelInformation(PixelInternalFormat.Rgba16f, PixelFormat.Rgba, PixelType.Float);
public PixelInternalFormat InternalFormat { get; }
public PixelFormat Format { get; }
public PixelType DataType { get; }
public PixelInformation(PixelInternalFormat internalFormat, PixelFormat format, PixelType dataType)
{
InternalFormat = internalFormat;
Format = format;
DataType = dataType;
}
}
}

View file

@ -17,6 +17,8 @@ namespace SM.OGL.Texture
/// <inheritdoc /> /// <inheritdoc />
public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Texture; public override ObjectLabelIdentifier TypeIdentifier { get; } = ObjectLabelIdentifier.Texture;
public PixelInformation PixelInformation;
/// <summary> /// <summary>
/// The texture filter. /// The texture filter.
/// <para>Default: <see cref="TextureMinFilter.Linear" /></para> /// <para>Default: <see cref="TextureMinFilter.Linear" /></para>

View file

@ -4,6 +4,7 @@ using OpenTK;
using OpenTK.Input; using OpenTK.Input;
using SM.Base.Controls; using SM.Base.Controls;
using SM2D.Scene; using SM2D.Scene;
using SM2D.Types;
#endregion #endregion

View file

@ -16,8 +16,6 @@ namespace SM2D.Drawing
{ {
public int ZIndex { get; set; } public int ZIndex { get; set; }
public bool ShadowCaster = false;
public Texture Texture public Texture Texture
{ {
get => (Texture) _material.Texture; get => (Texture) _material.Texture;
@ -33,7 +31,6 @@ namespace SM2D.Drawing
protected override void DrawContext(ref DrawContext context) protected override void DrawContext(ref DrawContext context)
{ {
base.DrawContext(ref context); base.DrawContext(ref context);
context.ShaderArguments["occluder"] = ShadowCaster;
context.Shader.Draw(context); context.Shader.Draw(context);
} }

View file

@ -1,25 +0,0 @@
using System.Collections.Generic;
using OpenTK;
using OpenTK.Graphics;
using SM.Base;
using SM.Base.Types;
using SM.OGL.Shaders;
namespace SM2D.Light
{
public abstract class LightObject
{
private Vector2 _posNorm => Vector2.Divide(Position, (SMRenderer.CurrentWindow as GLWindow2D).WorldScale);
internal abstract int Type { get; }
public CVector2 Position = new CVector2(0);
public Color4 Color = Color4.White;
internal virtual void SetUniforms(Dictionary<string, Uniform> uniforms)
{
uniforms["Type"].SetUniform1(Type);
uniforms["Position"].SetUniform2(Position);
uniforms["Color"].SetUniform4(Color);
}
}
}

View file

@ -1,23 +0,0 @@
using System.Collections.Generic;
using SM.OGL.Shaders;
namespace SM2D.Light
{
public class PointLight : LightObject
{
internal override int Type { get; } = 0;
public float Power = 5;
public float InnerCircle = 1;
public float OuterCircle = 1;
internal override void SetUniforms(Dictionary<string, Uniform> uniforms)
{
base.SetUniforms(uniforms);
uniforms["Power"].SetUniform1(Power);
uniforms["Inner"].SetUniform1(1 / InnerCircle);
uniforms["Outer"].SetUniform1(1 / OuterCircle);
}
}
}

View file

@ -1,49 +0,0 @@
using System.Reflection;
using SM.Base;
using SM.Base.PostProcess;
using SM.Base.Scene;
using SM.OGL.Framebuffer;
using SM.OGL.Shaders;
using SM.Utility;
using SM2D.Scene;
namespace SM2D.Light
{
public class LightPostEffect : PostProcessEffect
{
private PostProcessShader _shader = new PostProcessShader(AssemblyUtility.ReadAssemblyFile("SM2D.Light.light.frag"));
private LightSceneExtension sceneExtension;
public override void Init(Framebuffer main)
{
base.Init(main);
main.Append("occluder", 1);
}
public override void Draw(Framebuffer main, Framebuffer target)
{
_shader.Draw(main.ColorAttachments["color"], collection =>
{
collection["FragSize"].SetUniform2((SMRenderer.CurrentWindow as GLWindow2D).WorldScale);
collection["Ambient"].SetUniform4(sceneExtension.Ambient);
collection["LightCount"].SetUniform1(sceneExtension.Lights.Count);
collection["OccluderMap"].SetTexture(main.ColorAttachments["occluder"]);
collection["ShadowSensitivty"].SetUniform1(1f);
UniformArray array = collection.GetArray("Lights");
for (int i = 0; i < sceneExtension.Lights.Count; i++)
{
sceneExtension.Lights[i].SetUniforms(array[i]);
}
});
}
public override void SceneChanged(GenericScene scene)
{
base.SceneChanged(scene);
sceneExtension = scene.GetExtension<LightSceneExtension>();
}
}
}

View file

@ -1,12 +0,0 @@
using System.Collections.Generic;
using OpenTK.Graphics;
namespace SM2D.Light
{
public class LightSceneExtension
{
public Color4 Ambient = Color4.White;
public List<LightObject> Lights = new List<LightObject>();
}
}

View file

@ -1,81 +0,0 @@
#version 330
#define PI 3.14159265359
struct Light {
int Type;
vec2 Position;
vec4 Color;
// pointStuff;
float Power;
float Inner;
float Outer;
};
in vec2 vTexture;
in vec2 FragPos;
uniform vec2 FragSize;
uniform vec4 Ambient = vec4(1);
uniform Light[24] Lights;
uniform int LightCount;
uniform float ShadowSensitivty;
uniform sampler2D OccluderMap;
layout(location = 0) out vec4 color;
vec4 GetRenderColor();
vec3 calcPointLight(Light light) {
vec2 diff = light.Position - FragPos;
float dif = 20 / length(diff);
float intensity = light.Power * (dif) * (dif * dif);
return vec3(light.Color * intensity);
}
float occluded(Light light) {
float occluder = 1 - length(texture(OccluderMap, vTexture).rgb);
if (occluder != 0) {
vec2 diff = light.Position - FragPos;
vec2 dir = normalize(diff);
float steps = length(diff) / ShadowSensitivty;
vec2 curPos = FragPos;
for(int i = 0; i < steps; i++) {
curPos += dir * i * ShadowSensitivty;
}
}
return occluder;
}
vec3 calcLight() {
vec3 addedLight = vec3(0);
for(int i = 0; i < LightCount; i++) {
Light light = Lights[i];
vec3 lightColor;
switch(light.Type) {
case 0:
lightColor += calcPointLight(light);
break;
}
addedLight += lightColor * occluded(light);
}
return addedLight;
}
void main() {
vec4 render = GetRenderColor();
color = render * Ambient;
color += vec4(calcLight(), 1);
}

View file

@ -12,16 +12,14 @@ namespace SM2D.Pipelines
{ {
public static Basic2DPipeline Pipeline = new Basic2DPipeline(); public static Basic2DPipeline Pipeline = new Basic2DPipeline();
protected override MaterialShader _defaultShader { get; } = Basic2DShader.Shader;
private Basic2DPipeline() private Basic2DPipeline()
{ {
Console.WriteLine(); _defaultShader = Basic2DShader.Shader;
} }
protected override void Render(ref DrawContext context, Scene.Scene scene) protected override void RenderProcess(ref DrawContext context, Scene.Scene scene)
{ {
base.Render(ref context, scene);
Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
if (scene != null) scene.Draw(context); if (scene != null) scene.Draw(context);

View file

@ -6,7 +6,6 @@ using SM.Base;
using SM.Base.Contexts; using SM.Base.Contexts;
using SM.Base.Scene; using SM.Base.Scene;
using SM.OGL.Framebuffer; using SM.OGL.Framebuffer;
using SM2D.Light;
using SM2D.Shader; using SM2D.Shader;
#endregion #endregion
@ -17,11 +16,7 @@ namespace SM2D.Pipelines
{ {
public static Default2DPipeline Pipeline = new Default2DPipeline(); public static Default2DPipeline Pipeline = new Default2DPipeline();
private Framebuffer _tempWindow;
private Light.LightPostEffect _lightEffect;
protected override List<Framebuffer> _framebuffers { get; } = new List<Framebuffer>();
private Default2DPipeline() private Default2DPipeline()
{ {
@ -29,27 +24,19 @@ namespace SM2D.Pipelines
protected override void Initialization(GenericWindow window) protected override void Initialization(GenericWindow window)
{ {
_tempWindow = CreateWindowFramebuffer(); MainFramebuffer = CreateWindowFramebuffer();
_lightEffect = new LightPostEffect();
_framebuffers.Add(_tempWindow);
_lightEffect.Init(_tempWindow);
} }
protected override void Render(ref DrawContext context, Scene.Scene scene) protected override void RenderProcess(ref DrawContext context, Scene.Scene scene)
{ {
base.Render(ref context, scene);
if (scene != null) if (scene != null)
{ {
_tempWindow.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); MainFramebuffer.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
scene.DrawBackground(context); scene.DrawBackground(context);
scene.DrawMainObjects(context); scene.DrawMainObjects(context);
Framebuffer.Screen.Activate(); Framebuffer.Screen.Activate();
_lightEffect.Draw(_tempWindow, Framebuffer.Screen);
scene.DrawHUD(context); scene.DrawHUD(context);
scene.DrawDebug(context); scene.DrawDebug(context);
@ -59,7 +46,6 @@ namespace SM2D.Pipelines
protected override void SceneChanged(Scene.Scene scene) protected override void SceneChanged(Scene.Scene scene)
{ {
base.SceneChanged(scene); base.SceneChanged(scene);
_lightEffect.SceneChanged(scene);
} }
} }
} }

View file

@ -45,10 +45,6 @@
<Compile Include="Drawing\DrawParticles.cs" /> <Compile Include="Drawing\DrawParticles.cs" />
<Compile Include="Drawing\DrawText.cs" /> <Compile Include="Drawing\DrawText.cs" />
<Compile Include="GLWindow2D.cs" /> <Compile Include="GLWindow2D.cs" />
<Compile Include="Light\LightObjects\LightObject.cs" />
<Compile Include="Light\LightObjects\PointLight.cs" />
<Compile Include="Light\LightPostEffect.cs" />
<Compile Include="Light\LightSceneExtension.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="Pipelines\Adv2DPipeline.cs" />
@ -81,9 +77,6 @@
<Version>3.2.1</Version> <Version>3.2.1</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Light\light.frag" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Shader\ShaderFiles\basic.glsl" /> <EmbeddedResource Include="Shader\ShaderFiles\basic.glsl" />
</ItemGroup> </ItemGroup>

View file

@ -6,7 +6,6 @@ using SM.Base.Contexts;
using SM.Base.Objects.Static; using SM.Base.Objects.Static;
using SM.Base.Scene; using SM.Base.Scene;
using SM2D.Drawing; using SM2D.Drawing;
using SM2D.Light;
#endregion #endregion
@ -17,7 +16,6 @@ namespace SM2D.Scene
private static DrawObject2D _axisHelper; private static DrawObject2D _axisHelper;
public float AxisHelperSize = 100; public float AxisHelperSize = 100;
public LightSceneExtension LightInformations;
static Scene() static Scene()
{ {
_axisHelper = new DrawObject2D(); _axisHelper = new DrawObject2D();
@ -27,8 +25,6 @@ namespace SM2D.Scene
public Scene() public Scene()
{ {
_Background = new DrawBackground(Color4.Black); _Background = new DrawBackground(Color4.Black);
SetExtension(LightInformations = new LightSceneExtension());
} }

View file

@ -24,11 +24,9 @@ uniform bool UseTexture;
uniform sampler2D Texture; uniform sampler2D Texture;
layout(location = 0) out vec4 color; layout(location = 0) out vec4 color;
layout(location = 1) out vec4 occluder; layout(location = 1) out vec4 bloom;
void fmain() { void fmain() {
color = vColor * Tint; color = vColor * Tint;
if (UseTexture) color *= texture(Texture, vTexture); if (UseTexture) color *= texture(Texture, vTexture);
occluder = vec4(occlude,0,0,1);
} }

View file

@ -39,7 +39,7 @@ namespace SM_TEST
window = new GLWindow2D {Scaling = new Vector2(0, 1000)}; window = new GLWindow2D {Scaling = new Vector2(0, 1000)};
//window.GrabCursor(); //window.GrabCursor();
window.SetRenderPipeline(Basic2DPipeline.Pipeline); window.SetRenderPipeline(new TestRenderPipeline());
window.SetScene(scene = new Scene()); window.SetScene(scene = new Scene());
window.Load += WindowOnLoad; window.Load += WindowOnLoad;
window.RenderFrame += WindowOnUpdateFrame; window.RenderFrame += WindowOnUpdateFrame;
@ -60,16 +60,12 @@ namespace SM_TEST
{ {
scene.ShowAxisHelper = true; scene.ShowAxisHelper = true;
DrawObject2D kasten = new DrawObject2D();
kasten.ShadowCaster = true;
kasten.Texture = new Texture(new Bitmap("herosword.png"));
kasten.Transform.ApplyTextureSize(kasten.Texture, 500);
scene.Objects.Add(kasten);
//scene.Background.Color = Color4.White; //scene.Background.Color = Color4.White;
DrawText text = new DrawText(font, "Text"); DrawText text = new DrawText(font, "Text");
text.Transform.Position.Set(0, 500); text.Transform.Position.Set(0, 0);
text.Transform.Size.Set(2);
scene.Objects.Add(text); scene.Objects.Add(text);
light = new PointLight light = new PointLight

View file

@ -49,6 +49,7 @@
<ItemGroup> <ItemGroup>
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="TestRenderPipeline.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />

View file

@ -0,0 +1,39 @@
using System.Collections.Generic;
using OpenTK.Graphics.OpenGL4;
using SM.Base;
using SM.Base.Contexts;
using SM.Base.Drawing;
using SM.Base.PostEffects;
using SM.OGL.Framebuffer;
using SM2D.Scene;
namespace SM_TEST
{
public class TestRenderPipeline : RenderPipeline<Scene>
{
private BloomEffect _bloom;
protected override void Initialization(GenericWindow window)
{
base.Initialization(window);
_bloom = new BloomEffect(1);
MainFramebuffer = CreateWindowFramebuffer();
_bloom.Initilize(this);
}
protected override void RenderProcess(ref DrawContext context, Scene scene)
{
MainFramebuffer.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
scene.DrawBackground(context);
scene.DrawMainObjects(context);
Framebuffer.Screen.Activate(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
_bloom.Draw(context);
scene.DrawHUD(context);
scene.DrawDebug(context);
}
}
}