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

View file

@ -80,6 +80,7 @@ namespace SM.Base.Drawing.Text
/// <inheritdoc />
protected override void DrawContext(ref DrawContext context)
{
base.DrawContext(ref context);
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>
/// While initializing, it will add the <see cref="Color" /> to the data index.
/// </summary>
public Mesh(PrimitiveType type)
public Mesh(PrimitiveType type) : base()
{
PrimitiveType = type;
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() {
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 OpenTK;
using OpenTK.Graphics.OpenGL4;
using SM.Base.Contexts;
using SM.Base.Objects.Static;
using SM.Base.Scene;
using SM.OGL.Framebuffer;
@ -18,27 +19,28 @@ namespace SM.Base.PostProcess
internal static Matrix4 Mvp;
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>
/// Method, to initialize the shader.
/// </summary>
public virtual void Init() {}
/// <summary>
/// Method, to initialize the shader.
/// </summary>
public virtual void Init(Framebuffer main)
{
Init();
}
protected virtual void InitProcess() {}
/// <summary>
/// Method to draw the actual effect.
/// </summary>
/// <param name="main">The framebuffer, that was used.</param>
/// <param name="target">The framebuffer, the system should draw to.</param>
public abstract void Draw(Framebuffer main, Framebuffer target);
public abstract void Draw(DrawContext context);
/// <summary>
/// Event, when the scene changed.

View file

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

View file

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

View file

@ -30,6 +30,18 @@ namespace SM.Base.Scene
_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>
/// If true, the scene was already initialized.
/// </summary>
@ -50,7 +62,7 @@ namespace SM.Base.Scene
public virtual void Draw(DrawContext context)
{
}
/// <summary>
/// Adds a extension to the scene.
/// </summary>
@ -102,8 +114,7 @@ namespace SM.Base.Scene
/// Called, when the user activates the scene.
/// </summary>
protected virtual void OnActivating()
{
}
{ }
}
/// <summary>
@ -125,16 +136,11 @@ namespace SM.Base.Scene
/// </summary>
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>
/// 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 { get; set; }
public TCamera Camera => (TCamera) _camera;
/// <summary>
/// A camera to control the background.

View file

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

View file

@ -70,6 +70,23 @@ namespace SM.Base.Types
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>
/// Converts to <see cref="Vector2"/>
/// </summary>

View file

@ -63,6 +63,23 @@ namespace SM.Base.Types
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>
/// Converts to <see cref="Vector3"/>
/// </summary>

View file

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

View file

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