1.0.14
NUGET-Changes: + Materials now have a method to draw. That should allow more freedom on how materials can have a effect on the resulting shader. ~ PostProcessEffect.Draw now needs a source ColorAttachment. ~ Added some missing summaries GIT-/SOLUTION-Changes: Remade the folder structure, to something more senseable.
This commit is contained in:
parent
db7f01dca1
commit
89de4258e1
181 changed files with 584 additions and 698 deletions
212
src/renderer/SM.Base/PostEffects/BloomEffect.cs
Normal file
212
src/renderer/SM.Base/PostEffects/BloomEffect.cs
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#region usings
|
||||
|
||||
using System.Drawing;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.Drawing;
|
||||
using SM.Base.PostProcess;
|
||||
using SM.Base.Utility;
|
||||
using SM.Base.Window;
|
||||
using SM.OGL.Framebuffer;
|
||||
using SM.OGL.Texture;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.PostEffects
|
||||
{
|
||||
/// <summary>
|
||||
/// A bloom post process effect.
|
||||
/// </summary>
|
||||
public class BloomEffect : PostProcessEffect
|
||||
{
|
||||
private static BezierCurve _defaultCurve = new BezierCurve(Vector2.UnitY, Vector2.Zero, new Vector2(0.4f, 0), new Vector2(.5f,0));
|
||||
private static readonly PostProcessShader _mergeShader = new PostProcessShader(
|
||||
AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom_merge_vert.glsl"),
|
||||
AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom_merge.glsl"));
|
||||
|
||||
private static readonly PostProcessShader _shader =
|
||||
new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom_blur.glsl"));
|
||||
private const float _defaultTextureScale = .75f;
|
||||
|
||||
private Framebuffer _source;
|
||||
|
||||
private Framebuffer _bloomBuffer1;
|
||||
private Framebuffer _bloomBuffer2;
|
||||
|
||||
private readonly bool _hdr;
|
||||
|
||||
private readonly float _textureScale = .75f;
|
||||
|
||||
private BezierCurve _weightCurve;
|
||||
private float[] _weights;
|
||||
|
||||
private ColorAttachment _xBuffer;
|
||||
private ColorAttachment _yBuffer;
|
||||
|
||||
/// <summary>
|
||||
/// A texture where you can define the amount of the bloom effect at each pixel.
|
||||
/// </summary>
|
||||
public TextureBase AmountMap;
|
||||
/// <summary>
|
||||
/// The transformation for the amount map.
|
||||
/// </summary>
|
||||
public TextureTransformation AmountTransform = new TextureTransformation();
|
||||
/// <summary>
|
||||
/// The maximal amount the amount map is clamped to.
|
||||
/// <para>Default: 1</para>
|
||||
/// </summary>
|
||||
public float MaxAmount = 1;
|
||||
/// <summary>
|
||||
/// The minimal amount the amount map is clamped to.
|
||||
/// <para>Default: 0</para>
|
||||
/// </summary>
|
||||
public float MinAmount = 0;
|
||||
|
||||
/// <summary>
|
||||
/// The defines how often the x-y-flipflop happens.
|
||||
/// <para>Default: 8</para>
|
||||
/// </summary>
|
||||
public int Iterations = 8;
|
||||
/// <summary>
|
||||
/// The Threshold for the bloom effect.
|
||||
/// <para>Default: .8f</para>
|
||||
/// </summary>
|
||||
public float Threshold = .8f;
|
||||
/// <summary>
|
||||
/// Increases the brightness of the resulting effect.
|
||||
/// <para>Default: 1</para>
|
||||
/// </summary>
|
||||
public float Power = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Radius of the effect
|
||||
/// <para>Default: 2</para>
|
||||
/// </summary>
|
||||
public float Radius = 1;
|
||||
|
||||
/// <summary>
|
||||
/// This can disable the bloom calculation.
|
||||
/// <para>Default: true</para>
|
||||
/// </summary>
|
||||
public bool Enable = true;
|
||||
|
||||
/// <summary>
|
||||
/// This defines the weight curve.
|
||||
/// </summary>
|
||||
public BezierCurve WeightCurve
|
||||
{
|
||||
get => _weightCurve;
|
||||
set
|
||||
{
|
||||
_weightCurve = value;
|
||||
UpdateWeights();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// This defines how many picks the effect should pick from the weight curve.
|
||||
/// </summary>
|
||||
public int WeightCurvePickAmount = 4;
|
||||
|
||||
/// <summary>
|
||||
/// This creates a bloom effect.
|
||||
/// </summary>
|
||||
/// <param name="source">This can specify a own source framebuffer. If not set, it will take the Pipeline MainFramebuffer.</param>
|
||||
/// <param name="hdr">This allows to enable hdr returns.</param>
|
||||
/// <param name="textureScale">This allows for a increase in performance, by lowering the calculating texture scale.</param>
|
||||
public BloomEffect(Framebuffer source = null, bool hdr = false, float? textureScale = null)
|
||||
{
|
||||
_source = source;
|
||||
_hdr = hdr;
|
||||
_textureScale = textureScale.GetValueOrDefault(_defaultTextureScale);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void InitProcess()
|
||||
{
|
||||
_source ??= Pipeline.MainFramebuffer;
|
||||
|
||||
_source.ColorAttachments["color"].PixelInformation = PixelInformation.RGBA_HDR;
|
||||
|
||||
_bloomBuffer1 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale)
|
||||
{
|
||||
Name = "BloomX"
|
||||
};
|
||||
_bloomBuffer1.Append("xBuffer", _xBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
|
||||
_bloomBuffer1.Compile();
|
||||
_bloomBuffer2 = new Framebuffer(Pipeline.ConnectedWindow, _textureScale)
|
||||
{
|
||||
Name = "BloomY"
|
||||
};
|
||||
_bloomBuffer2.Append("yBuffer", _yBuffer = new ColorAttachment(0, PixelInformation.RGBA_HDR));
|
||||
_bloomBuffer2.Compile();
|
||||
|
||||
Pipeline.Framebuffers.Add(_bloomBuffer1);
|
||||
Pipeline.Framebuffers.Add(_bloomBuffer2);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Draw(ColorAttachment source, DrawContext context)
|
||||
{
|
||||
if (Enable)
|
||||
{
|
||||
GL.Viewport(0, 0, (int) (Pipeline.ConnectedWindow.Width * _textureScale),
|
||||
(int) (Pipeline.ConnectedWindow.Height * _textureScale));
|
||||
|
||||
Framebuffer target = Framebuffer.GetCurrentlyActive();
|
||||
bool first = true, hoz = true;
|
||||
int iter = Iterations * 2;
|
||||
for (int i = 0; i < iter; i++)
|
||||
{
|
||||
(hoz ? _bloomBuffer1 : _bloomBuffer2).Activate(false);
|
||||
|
||||
_shader.Draw(collection =>
|
||||
{
|
||||
collection["renderedTexture"].SetTexture(first ? source : (hoz ? _yBuffer : _xBuffer));
|
||||
|
||||
collection["First"].SetUniform1(first);
|
||||
collection["Threshold"].SetUniform1(Threshold);
|
||||
|
||||
collection["Horizontal"].SetUniform1(hoz);
|
||||
|
||||
collection["Weights"].SetUniform1(_weights);
|
||||
collection["WeightCount"].SetUniform1(WeightCurvePickAmount);
|
||||
collection["Power"].SetUniform1(Power);
|
||||
|
||||
collection["Radius"].SetUniform1(_textureScale * Radius);
|
||||
});
|
||||
|
||||
hoz = !hoz;
|
||||
if (first) first = false;
|
||||
}
|
||||
|
||||
GL.Viewport(Pipeline.ConnectedWindow.ClientRectangle);
|
||||
target.Activate();
|
||||
}
|
||||
|
||||
_mergeShader.Draw(collection =>
|
||||
{
|
||||
collection["Scene"].SetTexture(source);
|
||||
collection["Bloom"].SetTexture(_yBuffer);
|
||||
|
||||
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);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
74
src/renderer/SM.Base/PostEffects/PostProcessUtility.cs
Normal file
74
src/renderer/SM.Base/PostEffects/PostProcessUtility.cs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
#region usings
|
||||
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using SM.Base.PostProcess;
|
||||
using SM.Base.Utility;
|
||||
using SM.OGL.Framebuffer;
|
||||
|
||||
#endregion
|
||||
|
||||
namespace SM.Base.PostEffects
|
||||
{
|
||||
/// <summary>
|
||||
/// This class has some utility for render pipelines
|
||||
/// </summary>
|
||||
public static class PostProcessUtility
|
||||
{
|
||||
private static readonly PostProcessShader _hdrExposureShader =
|
||||
new PostProcessShader(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".finalize_hdr.glsl"));
|
||||
|
||||
private static readonly PostProcessShader _gammaShader =
|
||||
new PostProcessShader(
|
||||
AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".finalize_gamma.glsl"));
|
||||
|
||||
/// <summary>
|
||||
/// The gamma that is used for <see cref="FinalizeGamma"/> and <see cref="FinalizeHDR"/>.
|
||||
/// </summary>
|
||||
public static float Gamma = 2.2f;
|
||||
|
||||
/// <summary>
|
||||
/// This resolves a multisampled framebuffer to a non-multisampled renderbuffer.
|
||||
/// <para>This removes the depth buffer.</para>
|
||||
/// </summary>
|
||||
/// <param name="multisampledBuffers"></param>
|
||||
/// <param name="target"></param>
|
||||
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();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This converts HDR to LDR and applys gamma.
|
||||
/// </summary>
|
||||
/// <param name="attachment"></param>
|
||||
/// <param name="exposure"></param>
|
||||
public static void FinalizeHDR(ColorAttachment attachment, float exposure)
|
||||
{
|
||||
_hdrExposureShader.Draw(u =>
|
||||
{
|
||||
u["Gamma"].SetUniform1(Gamma);
|
||||
u["Exposure"].SetUniform1(exposure);
|
||||
u["Scene"].SetTexture(attachment);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This applys gamma
|
||||
/// </summary>
|
||||
/// <param name="attachment"></param>
|
||||
public static void FinalizeGamma(ColorAttachment attachment)
|
||||
{
|
||||
_gammaShader.Draw(u =>
|
||||
{
|
||||
u["Gamma"].SetUniform1(Gamma);
|
||||
u["Scene"].SetTexture(attachment);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
48
src/renderer/SM.Base/PostEffects/Shaders/bloom_blur.glsl
Normal file
48
src/renderer/SM.Base/PostEffects/Shaders/bloom_blur.glsl
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
#version 330
|
||||
#define PI 3.14159265359
|
||||
|
||||
uniform sampler2D renderedTexture;
|
||||
uniform float RenderScale;
|
||||
|
||||
uniform bool First;
|
||||
uniform float Threshold;
|
||||
|
||||
uniform bool Horizontal;
|
||||
|
||||
uniform float[32] Weights;
|
||||
uniform int WeightCount;
|
||||
uniform float Power;
|
||||
|
||||
uniform float Radius;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
vec4 GetRenderColorOffset(vec2 offset);
|
||||
|
||||
float brightness(vec3 c)
|
||||
{
|
||||
return max(max(c.r, c.g), c.b);
|
||||
}
|
||||
|
||||
float bright;
|
||||
|
||||
float GetWeight(int dif) {
|
||||
return Weights[dif];
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec3 thres = vec3(First ? Threshold : 0);
|
||||
|
||||
vec2 tex_offset = 1.0 / textureSize(renderedTexture, 0) * vec2(Horizontal ? 1 : 0, Horizontal ? 0 : 1);
|
||||
|
||||
vec3 result = max(GetRenderColorOffset(vec2(0)).rgb - thres, 0) * (First ? Power : 1) * GetWeight(0);
|
||||
|
||||
float radi = Radius + (length(result));
|
||||
|
||||
for(int i = 1; i < WeightCount; i++) {
|
||||
result += max(GetRenderColorOffset(tex_offset * i * radi).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i);
|
||||
result += max(GetRenderColorOffset(-tex_offset * i * radi).rgb - thres, 0) * (First ? Power : 1) * GetWeight(i);
|
||||
}
|
||||
|
||||
color = vec4(result, 1);
|
||||
}
|
||||
30
src/renderer/SM.Base/PostEffects/Shaders/bloom_merge.glsl
Normal file
30
src/renderer/SM.Base/PostEffects/Shaders/bloom_merge.glsl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
#version 330
|
||||
|
||||
in vec2 vTexture;
|
||||
in vec2 TransformedTexture;
|
||||
|
||||
uniform sampler2D Scene;
|
||||
uniform sampler2D Bloom;
|
||||
|
||||
uniform float MinAmount;
|
||||
uniform float MaxAmount;
|
||||
uniform sampler2D AmountMap;
|
||||
uniform bool HasAmountMap;
|
||||
|
||||
uniform float Exposure;
|
||||
uniform bool HDR;
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main() {
|
||||
vec3 result = texture(Bloom, vTexture).rgb;
|
||||
if (HasAmountMap) result *= clamp(length(texture(AmountMap, TransformedTexture).rgb) * (MaxAmount - MinAmount) + MinAmount, 0, 1);
|
||||
if (!HDR) {
|
||||
result = vec3(1.0) - exp(-result * Exposure);
|
||||
}
|
||||
|
||||
|
||||
result = texture(Scene, vTexture).rgb + result;
|
||||
|
||||
color = vec4(result, 1);
|
||||
}
|
||||
|
|
@ -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));
|
||||
}
|
||||
12
src/renderer/SM.Base/PostEffects/Shaders/finalize_gamma.glsl
Normal file
12
src/renderer/SM.Base/PostEffects/Shaders/finalize_gamma.glsl
Normal 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);
|
||||
}
|
||||
15
src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl
Normal file
15
src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl
Normal 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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue