1 Oct 2021
~ Made Shaders now able to use Defines. ~ Moved complete Bloom-shader code in a single file (not working at the moment)
This commit is contained in:
parent
443877019b
commit
8a84182563
15 changed files with 325 additions and 44 deletions
|
|
@ -17,6 +17,14 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace SM.Base.PostEffects
|
||||
{
|
||||
enum BloomEffectShaderType
|
||||
{
|
||||
Filtering,
|
||||
Downsampling,
|
||||
Upsampling,
|
||||
Combine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The recommended bloom effect, that looks way better than the old one.
|
||||
/// <para>Based on Blender's implermentation, which is based on COD: Infinite Warfare.</para>
|
||||
|
|
@ -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<bool, PostProcessShader[]> _ppShaders = new Dictionary<bool, PostProcessShader[]>(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<Framebuffer> _downsampler;
|
||||
private List<Framebuffer> _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.
|
||||
/// </summary>
|
||||
/// <param name="hdr">This allows to enable hdr returns.</param>
|
||||
public BloomEffect(bool hdr = false)
|
||||
/// <param name="highSetting">If set true, it will use the high quality settings.</param>
|
||||
public BloomEffect(bool hdr = false, bool highSetting = true)
|
||||
{
|
||||
_hdr = hdr;
|
||||
//shaders = GetShaders(highSetting);
|
||||
shaders = new[] { _filterShader, _downsampleShader, _upsampleShader, _combineShader };
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
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);
|
||||
|
||||
|
|
|
|||
|
|
@ -23,13 +23,14 @@ namespace SM.Base.PostEffects
|
|||
/// </summary>
|
||||
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<HDRColorCurve, PostProcessShader> _hdrExposureShader = new Dictionary<HDRColorCurve, PostProcessShader>()
|
||||
{
|
||||
{ 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 =
|
||||
|
|
|
|||
188
src/renderer/SM.Base/PostEffects/Shaders/bloom.frag
Normal file
188
src/renderer/SM.Base/PostEffects/Shaders/bloom.frag
Normal file
|
|
@ -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);
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
uniform vec2 renderedTextureTexelSize;
|
||||
|
||||
vec4 GetRenderColor();
|
||||
vec4 GetRenderColorOffset(vec2);
|
||||
|
||||
float getBrightness(vec3 col) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
21
src/renderer/SM.Base/PostEffects/Shaders/hdr_curves.frag
Normal file
21
src/renderer/SM.Base/PostEffects/Shaders/hdr_curves.frag
Normal file
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue