mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-04 02:41:19 +00:00
Add wareya's linear bloom shader
This commit is contained in:
parent
9f26d6023b
commit
534f0377d5
@ -97,6 +97,7 @@ set(BUILTIN_DATA_FILES
|
||||
scripts/omw/mwui/init.lua
|
||||
|
||||
shaders/adjustments.omwfx
|
||||
shaders/bloomlinear.omwfx
|
||||
shaders/debug.omwfx
|
||||
|
||||
mygui/core.skin
|
||||
|
@ -1,4 +1,5 @@
|
||||
AdjustmentsDescription: "Colour adjustments."
|
||||
BloomDescription: "Bloom shader performing its calculations in (approximately) linear light."
|
||||
DebugDescription: "Debug shader."
|
||||
DebugHeaderDepth: "Depth Buffer"
|
||||
DebugHeaderNormals: "Normals"
|
||||
@ -9,4 +10,14 @@ DisplayNormalsName: "Visualize pass normals"
|
||||
ContrastLevelDescription: "Constrast level"
|
||||
ContrastLevelName: "Constrast"
|
||||
GammaLevelDescription: "Gamma level"
|
||||
GammaLevelName: "Gamma"
|
||||
GammaLevelName: "Gamma"
|
||||
StrengthLevelName: "Strength"
|
||||
StrengthLevelDescription: "Strength of the effect."
|
||||
RadiusLevelName: "Radius"
|
||||
RadiusLevelDescription: "Radius of the effect"
|
||||
SkyFactorLevelName: "Sky Factor"
|
||||
SkyFactorLevelDescription: "Multiplication factor for light coming directly from the sky."
|
||||
BloomClampLevelName: "Clamp Level"
|
||||
BloomClampLevelDescription: "Clamp bloom pixels brighter than this value when mixing bloom into scene."
|
||||
BloomThresholdLevelName: "Threshold"
|
||||
BloomThresholdLevelDescription: "Ignore pixels with brightnesses below this value when calculating blur. Doesn't affect the sky."
|
||||
|
231
files/data/shaders/bloomlinear.omwfx
Normal file
231
files/data/shaders/bloomlinear.omwfx
Normal file
@ -0,0 +1,231 @@
|
||||
uniform_float uGamma {
|
||||
default = 2.2;
|
||||
min = 0.1;
|
||||
max = 4.0;
|
||||
step = 0.01;
|
||||
display_name = "#{BuiltInShaders:GammaLevelName}";
|
||||
description = "#{BuiltInShaders:GammaLevelDescription}";
|
||||
}
|
||||
uniform_float uThreshold {
|
||||
default = 0.35;
|
||||
min = 0.0;
|
||||
max = 1.0;
|
||||
step = 0.01;
|
||||
description = "#{BuiltInShaders:ThresholdLevelName}";
|
||||
display_name = "#{BuiltInShaders:ThresholdLevelDescription}";
|
||||
}
|
||||
uniform_float uClamp {
|
||||
default = 1.0;
|
||||
min = 0.0;
|
||||
max = 1.0;
|
||||
step = 0.01;
|
||||
description = "#{BuiltInShaders:BloomClampLevelName}";
|
||||
display_name = "#{BuiltInShaders:BloomClampLevelDescription}";
|
||||
}
|
||||
uniform_float uSkyFactor {
|
||||
default = 0.5;
|
||||
min = 0.0;
|
||||
max = 2.0;
|
||||
step = 0.01;
|
||||
description = "#{BuiltInShaders:SkyFactorLevelName}";
|
||||
display_name = "#{BuiltInShaders:SkyFactorLevelDescription}";
|
||||
}
|
||||
uniform_float uRadius {
|
||||
default = 0.5;
|
||||
min = 0.0;
|
||||
max = 1.0;
|
||||
step = 0.01;
|
||||
description = "#{BuiltInShaders:RadiusLevelName}";
|
||||
display_name = "#{BuiltInShaders:RadiusLevelDescription}";
|
||||
}
|
||||
uniform_float uStrength {
|
||||
default = 0.25;
|
||||
min = 0.0;
|
||||
max = 1.0;
|
||||
step = 0.01;
|
||||
display_name = "#{BuiltInShaders:StrengthLevelName}";
|
||||
description = "#{BuiltInShaders:StrengthLevelDescription}";
|
||||
}
|
||||
|
||||
shared {
|
||||
float scramblify(float x)
|
||||
{
|
||||
x = fract(x);
|
||||
x = x + 4.0;
|
||||
x = x*x;
|
||||
x = x*x;
|
||||
return fract(x);
|
||||
}
|
||||
float scramblev2_inner(vec2 v, float z)
|
||||
{
|
||||
return scramblify(v.x*0.6491 + v.y*0.029 + z);
|
||||
}
|
||||
|
||||
float time = fract(omw.simulationTime);
|
||||
vec4 scramblev2(vec2 v)
|
||||
{
|
||||
v *= 61.12;
|
||||
vec2 fwup = vec2(scramblev2_inner(v, fract(time)), scramblev2_inner(v, fract(time*fract(v.x)) + 0.18943));
|
||||
return vec4(0.5) - vec4(fwup, fwup);
|
||||
}
|
||||
|
||||
float gauss(float x)
|
||||
{
|
||||
return exp(-x*x);
|
||||
}
|
||||
float calculate_radius(vec2 texcoord)
|
||||
{
|
||||
float radius = uRadius * 0.2;
|
||||
radius *= omw.resolution.y;
|
||||
radius = max(radius, 0.1);
|
||||
// hack: make the radius wider on the screen edges
|
||||
// (makes things in the corner of the screen look less "wrong" with not-extremely-low FOVs)
|
||||
radius *= pow(texcoord.x*2.0-1.0, 2)+1.0;
|
||||
radius *= pow(texcoord.y*2.0-1.0, 2)+1.0;
|
||||
return radius;
|
||||
}
|
||||
vec3 powv(vec3 a, float x)
|
||||
{
|
||||
return pow(a, vec3(x));
|
||||
}
|
||||
}
|
||||
|
||||
render_target RT_NoMipmap {
|
||||
width_ratio = 0.25;
|
||||
height_ratio = 0.25;
|
||||
internal_format = rgb16f;
|
||||
source_type = float;
|
||||
source_format = rgb;
|
||||
mipmaps = false;
|
||||
min_filter = nearest;
|
||||
mag_filter = nearest;
|
||||
}
|
||||
|
||||
render_target RT_Horizontal {
|
||||
width_ratio = 0.25;
|
||||
height_ratio = 0.25;
|
||||
internal_format = rgb16f;
|
||||
source_type = float;
|
||||
source_format = rgb;
|
||||
mipmaps = false;
|
||||
min_filter = nearest;
|
||||
mag_filter = nearest;
|
||||
}
|
||||
|
||||
render_target RT_Vertical {
|
||||
width_ratio = 0.25;
|
||||
height_ratio = 0.25;
|
||||
internal_format = rgb16f;
|
||||
source_type = float;
|
||||
source_format = rgb;
|
||||
mipmaps = false;
|
||||
min_filter = linear;
|
||||
mag_filter = linear;
|
||||
}
|
||||
|
||||
fragment nomipmap(target=RT_NoMipmap) {
|
||||
omw_In vec2 omw_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
// downsample into a smaller buffer with mipmapping disabled (no need for it + might interfere with the blurring process)
|
||||
// do the gamma compression step while we're at it
|
||||
vec3 sample = omw_GetLastShader(omw_TexCoord).rgb;
|
||||
bool is_sky = (omw_GetLinearDepth(omw_TexCoord) > omw.far*0.999);
|
||||
float factor = is_sky ? uSkyFactor : 1.0;
|
||||
vec3 ret_sample = powv(sample, uGamma);
|
||||
factor *= (!is_sky && (dot(sample, vec3(1.0/3.0)) < uThreshold)) ? 0.0 : 1.0;
|
||||
ret_sample *= factor;
|
||||
omw_FragColor = vec4(ret_sample, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
fragment horizontal(target=RT_Horizontal, rt1=RT_NoMipmap) {
|
||||
omw_In vec2 omw_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
// gaussian blur, horizontal step
|
||||
float radius = calculate_radius(omw_TexCoord);
|
||||
int radius_i = int(ceil(radius));
|
||||
vec3 sum = vec3(0.0);
|
||||
float normalize = 0.0;
|
||||
for(int x = -radius_i; x <= radius_i; x += 1)
|
||||
{
|
||||
float strength = gauss(float(x)/radius*2.0);
|
||||
normalize += strength;
|
||||
vec2 coord = omw_TexCoord + vec2(float(x), 0.0) / omw.resolution.xy;
|
||||
vec3 sample = omw_Texture2D(RT_NoMipmap, coord).rgb;
|
||||
sum += strength * sample;
|
||||
}
|
||||
sum /= normalize;
|
||||
|
||||
omw_FragColor = vec4(sum, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
fragment vertical(target=RT_Vertical, rt1=RT_Horizontal) {
|
||||
omw_In vec2 omw_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
// gaussian blur, vertical step
|
||||
float radius = calculate_radius(omw_TexCoord);
|
||||
int radius_i = int(ceil(radius));
|
||||
vec3 sum = vec3(0.0);
|
||||
float normalize = 0.0;
|
||||
for(int y = -radius_i; y <= radius_i; y += 1)
|
||||
{
|
||||
float strength = gauss(float(y)/radius*2.0);
|
||||
normalize += strength;
|
||||
vec2 coord = omw_TexCoord + vec2(0.0, float(y)) / omw.resolution.xy;
|
||||
vec3 sample = omw_Texture2D(RT_Horizontal, coord).rgb;
|
||||
sum += strength * sample;
|
||||
}
|
||||
sum /= normalize;
|
||||
|
||||
omw_FragColor = vec4(sum, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
fragment final(rt1=RT_Vertical) {
|
||||
omw_In vec2 omw_TexCoord;
|
||||
|
||||
float clampify(float x, float clamp)
|
||||
{
|
||||
if(x < clamp)
|
||||
return x;
|
||||
return ((x-clamp)*0.5)+clamp;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 color = vec3(0.0);
|
||||
color = omw_Texture2D(RT_Vertical, omw_TexCoord).rgb;
|
||||
// add dithering (in gamma-compressed light, because monitors are sRGB)
|
||||
color = powv(color, 1.0/uGamma);
|
||||
color += (scramblev2(omw_TexCoord).rgb/255.0 - vec3(0.5/255.0))*2.0;
|
||||
color = max(vec3(0.0), color);
|
||||
// also do clamping in gamma-compressed light
|
||||
float color_luma = dot(color, vec3(1.0/3.0));
|
||||
if(uClamp == 0.0)
|
||||
color *= 0.0;
|
||||
else if(color_luma > uClamp)
|
||||
color /= color_luma/uClamp;
|
||||
color = powv(color, uGamma);
|
||||
|
||||
// add bloom to base color in linear light
|
||||
vec3 base_color = powv(omw_GetLastShader(omw_TexCoord).rgb, uGamma);
|
||||
vec3 add_color = base_color + color * uStrength * 0.5;
|
||||
omw_FragColor = vec4(powv(add_color, 1.0/uGamma), 1.0);
|
||||
//omw_FragColor = vec4(powv(color, 1.0/uGamma), 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
technique {
|
||||
passes = nomipmap, horizontal, vertical, final;
|
||||
description = "#{BuiltInShaders:BloomDescription}";
|
||||
author = "OpenMW";
|
||||
version = "1.0";
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user