From 8a841825632e95cb959db8a9c2d7dc6026a546c9 Mon Sep 17 00:00:00 2001 From: Nineto Nine Date: Fri, 1 Oct 2021 19:43:00 +0200 Subject: [PATCH] 1 Oct 2021 ~ Made Shaders now able to use Defines. ~ Moved complete Bloom-shader code in a single file (not working at the moment) --- .../SM.Base/PostEffects/BloomEffect.cs | 58 +++++- .../SM.Base/PostEffects/PostProcessUtility.cs | 7 +- .../SM.Base/PostEffects/Shaders/bloom.frag | 188 ++++++++++++++++++ .../PostEffects/Shaders/bloom/downsample.frag | 1 - .../PostEffects/Shaders/bloom/sampling.frag | 2 +- .../PostEffects/Shaders/finalize_hdr.glsl | 23 +-- .../PostEffects/Shaders/hdr_curves.frag | 21 ++ .../SM.Base/PostProcess/PostProcessShader.cs | 2 + src/renderer/SM.Base/SM.Base.csproj | 2 + .../SM.Base/Shaders/MaterialShader.cs | 1 + src/renderer/SM.OGL/Shaders/GenericShader.cs | 11 +- src/renderer/SM.OGL/Shaders/ShaderFile.cs | 37 +++- .../SM.OGL/Shaders/ShaderFileCollection.cs | 12 +- tests/SM_TEST/Program.cs | 2 +- tests/SM_TEST/TestRenderPipeline.cs | 2 +- 15 files changed, 325 insertions(+), 44 deletions(-) create mode 100644 src/renderer/SM.Base/PostEffects/Shaders/bloom.frag create mode 100644 src/renderer/SM.Base/PostEffects/Shaders/hdr_curves.frag diff --git a/src/renderer/SM.Base/PostEffects/BloomEffect.cs b/src/renderer/SM.Base/PostEffects/BloomEffect.cs index 347a082..32b0e30 100644 --- a/src/renderer/SM.Base/PostEffects/BloomEffect.cs +++ b/src/renderer/SM.Base/PostEffects/BloomEffect.cs @@ -17,6 +17,14 @@ using System.Threading.Tasks; namespace SM.Base.PostEffects { + enum BloomEffectShaderType + { + Filtering, + Downsampling, + Upsampling, + Combine + } + /// /// The recommended bloom effect, that looks way better than the old one. /// Based on Blender's implermentation, which is based on COD: Infinite Warfare. @@ -38,13 +46,47 @@ namespace SM.Base.PostEffects new ShaderFile(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom.combine.vert")), AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom.combine.frag") ); - + static BloomEffect() { _upsampleShader.ShaderFiles.Fragment[0].GLSLExtensions.Add(samplingFile); _combineShader.ShaderFiles.Fragment[0].GLSLExtensions.Add(samplingFile); } + /* + private static readonly string bloomFile = AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom.frag"); + private static readonly ShaderFile combineVertex = new ShaderFile(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".bloom.combine.vert")); + + static Dictionary _ppShaders = new Dictionary(2); + + static PostProcessShader[] GetShaders(bool high) + { + if (_ppShaders.ContainsKey(high)) return _ppShaders[high]; + + PostProcessShader[] shaders; + _ppShaders.Add(high, shaders = new PostProcessShader[4]); + + for(int i = 0; i < 4; i++) + { + ShaderFile file = new ShaderFile(bloomFile) + { + Defines = + { + "ACTION_"+((BloomEffectShaderType)i).ToString().ToUpper(), + } + }; + if (high) file.Defines.Add("HIGH"); + + PostProcessShader shader; + if (i == 3) shader = new PostProcessShader(vertex: combineVertex, file); + else shader = new PostProcessShader(file); + + shaders[i] = shader; + } + + return shaders; + }*/ + const int MAXBLOOMSTEPS = 8; const float INTENSITY = .1f; @@ -52,6 +94,7 @@ namespace SM.Base.PostEffects private List _downsampler; private List _upsample; + private PostProcessShader[] shaders; private int _iterations; private float _sampleSize; @@ -98,9 +141,12 @@ namespace SM.Base.PostEffects /// This creates a more prettier bloom effect. /// /// This allows to enable hdr returns. - public BloomEffect(bool hdr = false) + /// If set true, it will use the high quality settings. + public BloomEffect(bool hdr = false, bool highSetting = true) { _hdr = hdr; + //shaders = GetShaders(highSetting); + shaders = new[] { _filterShader, _downsampleShader, _upsampleShader, _combineShader }; } /// protected override void InitProcess() => CreateFramebuffers(); @@ -168,7 +214,7 @@ namespace SM.Base.PostEffects // Filtering _downsampler[0].Activate(true); - _filterShader.Draw(source, col => + shaders[0].Draw(source, col => { col["ThresholdCurve"].SetVector4(_thresholdCurve); }); @@ -180,7 +226,7 @@ namespace SM.Base.PostEffects ColorAttachment downsampleSource = last; Framebuffer downsampleTarget = _downsampler[i]; downsampleTarget.Activate(true); - _downsampleShader.Draw(downsampleSource); + shaders[1].Draw(downsampleSource); last = downsampleTarget["0"]; } @@ -193,7 +239,7 @@ namespace SM.Base.PostEffects upsampleTarget.Activate(true); - _upsampleShader.Draw(last, (a) => + shaders[2].Draw(last, (a) => { if (last != null) a["baseBuffer"].SetTexture(downsampleSource); a["sampleSize"].SetFloat(_sampleSize); @@ -204,7 +250,7 @@ namespace SM.Base.PostEffects // combine target.Activate(true); - _combineShader.Draw(last, (a) => + shaders[3].Draw(last, (a) => { a["sampleSize"].SetFloat(_sampleSize); diff --git a/src/renderer/SM.Base/PostEffects/PostProcessUtility.cs b/src/renderer/SM.Base/PostEffects/PostProcessUtility.cs index 67431d9..0d77ac4 100644 --- a/src/renderer/SM.Base/PostEffects/PostProcessUtility.cs +++ b/src/renderer/SM.Base/PostEffects/PostProcessUtility.cs @@ -23,13 +23,14 @@ namespace SM.Base.PostEffects /// public static class PostProcessUtility { + public static readonly ShaderFile HDRCurves = new ShaderFile(AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".hdr_curves.frag")); private static readonly string _finalizeHdrCode = AssemblyUtility.ReadAssemblyFile(SMRenderer.PostProcessPath + ".finalize_hdr.glsl"); private static readonly Dictionary _hdrExposureShader = new Dictionary() { - { HDRColorCurve.OnlyExposure, new PostProcessShader(new ShaderFile(_finalizeHdrCode) { StringOverrides = { { "TYPE", "0" } } }) }, - { HDRColorCurve.Reinhard, new PostProcessShader(new ShaderFile(_finalizeHdrCode) { StringOverrides = { { "TYPE", "1" } } }) }, - { HDRColorCurve.ACES, new PostProcessShader(new ShaderFile(_finalizeHdrCode) { StringOverrides = { { "TYPE", "2" } } }) }, + { HDRColorCurve.OnlyExposure, new PostProcessShader(new ShaderFile(_finalizeHdrCode) {GLSLExtensions = { HDRCurves } }) }, + { HDRColorCurve.Reinhard, new PostProcessShader(new ShaderFile(_finalizeHdrCode) { GLSLExtensions = { HDRCurves }, Defines = { "TYPE_REINHARD" } }) }, + { HDRColorCurve.ACES, new PostProcessShader(new ShaderFile(_finalizeHdrCode) { GLSLExtensions = { HDRCurves }, Defines = { "TYPE_ACES" } }) }, }; private static readonly PostProcessShader _gammaShader = diff --git a/src/renderer/SM.Base/PostEffects/Shaders/bloom.frag b/src/renderer/SM.Base/PostEffects/Shaders/bloom.frag new file mode 100644 index 0000000..2401377 --- /dev/null +++ b/src/renderer/SM.Base/PostEffects/Shaders/bloom.frag @@ -0,0 +1,188 @@ +#version 330 core +/* ACTIONS: +0 = Filtering +1 = Downsamping +2 = Upsampling +3 = Combine +*/ + +in vec2 vTexture; + +uniform vec2 renderedTextureTexelSize; +// Uniforms +uniform vec4 ThresholdCurve; + + +// Downsampling + +uniform float sampleSize; +uniform sampler2D baseBuffer; + +in vec2 amountUV; + +uniform sampler2D scene; +uniform vec4 bloomColor; +uniform bool HDR; + +uniform bool hasAmountMap; +uniform sampler2D amountMap; +uniform vec2 amountLimit; + + +layout(location = 0) out vec4 color; +layout(location = 1) out vec4 sceneOutput; + +vec4 GetRenderColorOffset(vec2); +vec3 reinhardTone(vec3); + +// ---- Utils ---- +vec3 safe_color(vec3 c) { + return clamp(c, vec3(0.0), vec3(1e20)); +} +vec3 median(vec3 a, vec3 b, vec3 c) +{ + return a + b + c - min(min(a, b), c) - max(max(a, b), c); +} +float getBrightness(vec3 col) { + return max(col.r, max(col.g, col.b)); + return (col.r + col.r + col.b + col.g + col.g + col.g) / 6.0; +} + +// ---- Functions ---- +vec3 simpleBoxFilter() { + #if defined (ACTION_DOWNSAMPLING) + vec4 d = renderedTextureTexelSize.xyxy * vec4(-1,-1,1,1); + #else + vec4 d = renderedTextureTexelSize.xyxy * vec4(-1,-1,1,1) * (sampleSize * 0.5); + #endif + + vec3 s; + s = GetRenderColorOffset(d.xy).rgb; + s += GetRenderColorOffset(d.zy).rgb; + s += GetRenderColorOffset(d.xw).rgb; + s += GetRenderColorOffset(d.zw).rgb; + + return s * 0.25; // 1 / 4 = 0.25 +} + +// Downsampling: +vec3 downsample_high() { + vec4 d = renderedTextureTexelSize.xyxy * vec4(-1,-1, +1, +1); + vec3 s1 = GetRenderColorOffset(d.xy).rgb; // - - + // X - + + vec3 s2 = GetRenderColorOffset(d.zy).rgb; // - - + // - X + + vec3 s3 = GetRenderColorOffset(d.xw).rgb; // X - + // - - + + vec3 s4 = GetRenderColorOffset(d.zw).rgb; // X - + // - - + + float s1w = 1.0 / (getBrightness(s1) + 1.0); + float s2w = 1.0 / (getBrightness(s2) + 1.0); + float s3w = 1.0 / (getBrightness(s3) + 1.0); + float s4w = 1.0 / (getBrightness(s4) + 1.0); + float one_div = 1.0 / (s1w + s2w + s3w + s4w); + + return (s1 * s1w + s2 * s2w + s3 * s3w + s4 * s4w) * one_div; +} + +// Upsampling: +vec3 upsample_high() { + vec4 d = renderedTextureTexelSize.xyxy * vec4(1, 1,-1,0) * sampleSize; + + vec3 s; + // Line + 1 + s = GetRenderColorOffset(d.zy).rgb; // x - - + s += GetRenderColorOffset(d.wy).rgb * 2; // - X - + s += GetRenderColorOffset(d.xy).rgb; // - - X + + // Line 0 + s += GetRenderColorOffset(d.zw).rgb * 2; // X - - + s += GetRenderColorOffset(vec2(0)).rgb * 4; // - X - + s += GetRenderColorOffset(d.xw).rgb * 2; // - - X + + // Line - 1 + s += GetRenderColorOffset(d.zz).rgb; // X - - + s += GetRenderColorOffset(d.wz).rgb * 2; // - X - + s += GetRenderColorOffset(d.xz).rgb; // - - X + + return texture2D(baseBuffer, vTexture).rgb + s * 0.0625; // 1 / 16 = 0.0625 +} + +// ---- Actions ---- +vec3 filtering() { + + + vec3 col = safe_color(GetRenderColorOffset(vec2(0)).rgb); + sceneOutput = vec4(col, 1); + return sceneOutput.rgb; + + #ifdef HIGH + vec3 d = renderedTextureTexelSize.xyx * vec3(1,1,0); + vec3 s0 = col + vec3(.1); + vec3 s1 = safe_color(GetRenderColorOffset(-d.xz).rgb) + vec3(.1); + vec3 s2 = safe_color(GetRenderColorOffset(+d.xz).rgb) + vec3(.1); + vec3 s3 = safe_color(GetRenderColorOffset(-d.zy).rgb) + vec3(.1); + vec3 s4 = safe_color(GetRenderColorOffset(+d.zy).rgb) + vec3(.1); + vec3 col = median(median(s0, s1, s2), s3, s4); + #endif + + float br = getBrightness(col); + + float rq = clamp(br - ThresholdCurve.x, 0, ThresholdCurve.y); + rq = ThresholdCurve.z * rq * rq; + + float resultBr = max(rq, br - ThresholdCurve.w) / max(1e-5, br); + return col * resultBr; +} + +vec3 downsample() { + #ifdef HIGH + return downsample_high(); + #else + return simpleBoxFilter(); + #endif +} + +vec3 upsample() { + #ifdef HIGH + return upsample_high(); + #else + return simpleBoxFilter(); + #endif +} + +vec3 combine() { + vec3 scene = safe_color(texture2D(scene, vTexture).rgb); + vec3 blur = upsample() * bloomColor.rgb; + + if (hasAmountMap) { + blur *= clamp(texture2D(amountMap, amountUV).r * (amountLimit.y - amountLimit.x) + amountLimit.x, 0, 1); + } + + if (HDR) { + return scene + blur; + } + + return scene + reinhardTone(blur); +} + +// main: +void main() { + vec3 col; + + #if defined(ACTION_FILTERING) + col = filtering(); + #elif defined(ACTION_DOWNSAMPLING) + col = downsample(); + #elif defined(ACTION_UPSAMPLING) + col = upsample(); + #else + col = combine(); + #endif + + color = vec4(col, 1); +} diff --git a/src/renderer/SM.Base/PostEffects/Shaders/bloom/downsample.frag b/src/renderer/SM.Base/PostEffects/Shaders/bloom/downsample.frag index b2fec34..c0c5178 100644 --- a/src/renderer/SM.Base/PostEffects/Shaders/bloom/downsample.frag +++ b/src/renderer/SM.Base/PostEffects/Shaders/bloom/downsample.frag @@ -2,7 +2,6 @@ uniform vec2 renderedTextureTexelSize; -vec4 GetRenderColor(); vec4 GetRenderColorOffset(vec2); float getBrightness(vec3 col) { diff --git a/src/renderer/SM.Base/PostEffects/Shaders/bloom/sampling.frag b/src/renderer/SM.Base/PostEffects/Shaders/bloom/sampling.frag index 46054ee..9f08e3d 100644 --- a/src/renderer/SM.Base/PostEffects/Shaders/bloom/sampling.frag +++ b/src/renderer/SM.Base/PostEffects/Shaders/bloom/sampling.frag @@ -8,7 +8,7 @@ vec4 GetRenderColorOffset(vec2); vec3 upsample_filter_high() { - vec4 d = renderedTextureTexelSize.xyxy * vec4(1, 1,-1,0); + vec4 d = renderedTextureTexelSize.xyxy * vec4(1, 1,-1,0) * sampleSize; vec3 s; // Line + 1 diff --git a/src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl b/src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl index bf754bb..eeacf82 100644 --- a/src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl +++ b/src/renderer/SM.Base/PostEffects/Shaders/finalize_hdr.glsl @@ -1,5 +1,4 @@ #version 330 -#define TYPE //!TYPE in vec2 vTexture; @@ -9,31 +8,19 @@ uniform float Gamma; layout(location = 0) out vec4 color; -vec3 ACES(vec3 x) { - const float a = 2.51; - const float b = 0.03; - const float c = 2.43; - const float d = 0.59; - const float e = 0.14; +vec3 ACES(vec3); - return clamp((x * (a * x + b)) / (x * (c * x + d) + e), 0,1.0); -} +vec3 reinhardTone(vec3); -vec3 reinhardTone(vec3 col) { - return col / (col + vec3(1.0)); -} - -vec3 exposure(vec3 scene) { - return vec3(1) - exp(-texture(Scene, vTexture).rgb * Exposure); -} +vec3 exposure(vec3); void main() { vec3 scene = texture2D(Scene, vTexture).rgb; vec3 result = exposure(scene); - #if (TYPE == 1) + #if defined(TYPE_REINHARD) result = reinhardTone(result); - #elif (TYPE == 2) + #elif defined(TYPE_ACES) result = ACES(result); #endif diff --git a/src/renderer/SM.Base/PostEffects/Shaders/hdr_curves.frag b/src/renderer/SM.Base/PostEffects/Shaders/hdr_curves.frag new file mode 100644 index 0000000..6ec0e52 --- /dev/null +++ b/src/renderer/SM.Base/PostEffects/Shaders/hdr_curves.frag @@ -0,0 +1,21 @@ +#version 330 core + +uniform float Exposure; + +vec3 ACES(vec3 col) { + const float a = 2.51; + const float b = 0.03; + const float c = 2.43; + const float d = 0.59; + const float e = 0.14; + + return clamp((col * (a * col + b)) / (col * (c * col + d) + e), 0.0,1.0); +} + +vec3 reinhardTone(vec3 col) { + return col / (col + vec3(1.0)); +} + +vec3 exposure(vec3 col) { + return vec3(1) - exp(-col * Exposure); +} \ No newline at end of file diff --git a/src/renderer/SM.Base/PostProcess/PostProcessShader.cs b/src/renderer/SM.Base/PostProcess/PostProcessShader.cs index 1ef0498..b1a4744 100644 --- a/src/renderer/SM.Base/PostProcess/PostProcessShader.cs +++ b/src/renderer/SM.Base/PostProcess/PostProcessShader.cs @@ -113,6 +113,8 @@ namespace SM.Base.PostProcess /// public void Draw(Action setUniformAction) { + if (ErrorInShader) return; + Activate(); Plate.Object.Activate(); diff --git a/src/renderer/SM.Base/SM.Base.csproj b/src/renderer/SM.Base/SM.Base.csproj index e40c61b..2f713e0 100644 --- a/src/renderer/SM.Base/SM.Base.csproj +++ b/src/renderer/SM.Base/SM.Base.csproj @@ -170,6 +170,8 @@ + + diff --git a/src/renderer/SM.Base/Shaders/MaterialShader.cs b/src/renderer/SM.Base/Shaders/MaterialShader.cs index 6aa9a48..10c3387 100644 --- a/src/renderer/SM.Base/Shaders/MaterialShader.cs +++ b/src/renderer/SM.Base/Shaders/MaterialShader.cs @@ -37,6 +37,7 @@ namespace SM.Base.Shaders /// The context public virtual void Draw(DrawContext context) { + if (ErrorInShader) return; context.Shader.Activate(); context.Mesh.Activate(); diff --git a/src/renderer/SM.OGL/Shaders/GenericShader.cs b/src/renderer/SM.OGL/Shaders/GenericShader.cs index fb1df8c..c6617a6 100644 --- a/src/renderer/SM.OGL/Shaders/GenericShader.cs +++ b/src/renderer/SM.OGL/Shaders/GenericShader.cs @@ -16,6 +16,8 @@ namespace SM.OGL.Shaders /// protected override bool AutoCompile { get; set; } = true; + public bool ErrorInShader { get; private set; } + /// /// Contains the different files for the shader. /// @@ -102,12 +104,17 @@ namespace SM.OGL.Shaders public void Load() { _id = GL.CreateProgram(); + Uniforms = new UniformCollection { ParentShader = this }; - ShaderFiles.Append(this); + ErrorInShader = !ShaderFiles.Append(this); + if (ErrorInShader) + { + GL.DeleteProgram(_id); + return; + } GL.LinkProgram(_id); ShaderFiles.Detach(this); - Uniforms = new UniformCollection {ParentShader = this}; Uniforms.Import(this); GLDebugging.CheckGLErrors($"A error occured at shader creation for '{GetType()}': %code%"); diff --git a/src/renderer/SM.OGL/Shaders/ShaderFile.cs b/src/renderer/SM.OGL/Shaders/ShaderFile.cs index 5cb23f8..4e395b5 100644 --- a/src/renderer/SM.OGL/Shaders/ShaderFile.cs +++ b/src/renderer/SM.OGL/Shaders/ShaderFile.cs @@ -14,12 +14,14 @@ namespace SM.OGL.Shaders public class ShaderFile : GLObject { private string _data; - + /// /// Contains other shader files to allow access to their functions. /// public List GLSLExtensions = new List(); + public List Defines = new List(); + /// /// Gets/Sets the name for this shader file. /// @@ -63,21 +65,44 @@ namespace SM.OGL.Shaders _data = _data.Replace("//!" + kvp.Key, kvp.Value); } - internal void Compile(GenericShader shader, ShaderType type) + internal bool Compile(GenericShader shader, ShaderType type) { if (_id < 0) { GenerateSource(); _id = GL.CreateShader(type); - GL.ShaderSource(_id, _data); + if (Defines.Count > 0) + { + string defineString = ""; + foreach(string define in Defines) + { + defineString += "#define " + define + Environment.NewLine; + } + + GL.ShaderSource(_id, 2, new string[] { defineString, _data }, new int[] { defineString.Length, _data.Length }); + } else GL.ShaderSource(_id, _data); GL.CompileShader(_id); } - GL.AttachShader(shader, _id); - GLDebugging.CheckGLErrors($"Error at loading shader file: '{shader.GetType()}', '{type}', %code%"); + GL.GetShader(_id, ShaderParameter.CompileStatus, out int compileStatus); + if (compileStatus != 1) + { + GL.GetShader(_id, ShaderParameter.InfoLogLength, out int loglength); - for (var i = 0; i < GLSLExtensions.Count; i++) GLSLExtensions[i].Compile(shader, type); + GLCustomActions.AtWarning?.Invoke($"Shader '{ToString()}' doesn't compile correctly.\nReason:" + GL.GetShaderInfoLog(_id)); + + GL.DeleteShader(_id); + return false; + } + + GL.AttachShader(shader, _id); + + + for (var i = 0; i < GLSLExtensions.Count; i++) { + if (!GLSLExtensions[i].Compile(shader, type)) return false; + } + return true; } /// diff --git a/src/renderer/SM.OGL/Shaders/ShaderFileCollection.cs b/src/renderer/SM.OGL/Shaders/ShaderFileCollection.cs index 0b6f2a7..33b92ed 100644 --- a/src/renderer/SM.OGL/Shaders/ShaderFileCollection.cs +++ b/src/renderer/SM.OGL/Shaders/ShaderFileCollection.cs @@ -68,17 +68,19 @@ namespace SM.OGL.Shaders /// Appends the files to the shader. /// /// - internal void Append(GenericShader shader) + internal bool Append(GenericShader shader) { foreach (ShaderFile file in Vertex) - file.Compile(shader, ShaderType.VertexShader); + if (!file.Compile(shader, ShaderType.VertexShader)) return false; if (Geometry != null) foreach (ShaderFile file in Geometry) - file.Compile(shader, ShaderType.GeometryShader); + if (!file.Compile(shader, ShaderType.GeometryShader)) return false; - foreach (ShaderFile file in Fragment) - file.Compile(shader, ShaderType.FragmentShader); + foreach (ShaderFile file in Fragment) + if (!file.Compile(shader, ShaderType.FragmentShader)) return false; + + return true; } /// diff --git a/tests/SM_TEST/Program.cs b/tests/SM_TEST/Program.cs index be64d6a..d122521 100644 --- a/tests/SM_TEST/Program.cs +++ b/tests/SM_TEST/Program.cs @@ -110,7 +110,7 @@ namespace SM_TEST private static void Window_RenderFrame(object sender, FrameEventArgs e) { - window.Title = Math.Floor(e.Time * 1000) + "ms"; + window.Title = Math.Round(e.Time * 1000,2) + "ms"; } } } \ No newline at end of file diff --git a/tests/SM_TEST/TestRenderPipeline.cs b/tests/SM_TEST/TestRenderPipeline.cs index 1c8368a..978c66a 100644 --- a/tests/SM_TEST/TestRenderPipeline.cs +++ b/tests/SM_TEST/TestRenderPipeline.cs @@ -20,7 +20,7 @@ namespace SM_TEST MainFramebuffer = CreateWindowFramebuffer(8, PixelInformation.RGBA_HDR, true); _postBuffer = CreateWindowFramebuffer(0, PixelInformation.RGB_HDR, false); - _bloom = new BloomEffect(true) + _bloom = new BloomEffect(true, true) { Radius = 20, AmountMap = new Texture(new System.Drawing.Bitmap("bloom_amountMap.png"))