1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-01-01 03:21:41 +00:00
OpenMW/files/data/shaders/bloomlinear.omwfx
2023-01-02 13:21:05 +01:00

223 lines
6.2 KiB
Plaintext

uniform_float uGamma {
default = 2.2;
min = 0.1;
max = 4.0;
step = 0.01;
display_name = "#{OMWShaders:GammaLevelName}";
description = "#{OMWShaders:GammaLevelDescription}";
}
uniform_float uThreshold {
default = 0.35;
min = 0.0;
max = 1.0;
step = 0.01;
display_name = "#{OMWShaders:BloomThresholdLevelName}";
description = "#{OMWShaders:BloomThresholdLevelDescription}";
}
uniform_float uClamp {
default = 1.0;
min = 0.0;
max = 1.0;
step = 0.01;
display_name = "#{OMWShaders:BloomClampLevelName}";
description = "#{OMWShaders:BloomClampLevelDescription}";
}
uniform_float uSkyFactor {
default = 0.5;
min = 0.0;
max = 2.0;
step = 0.01;
display_name = "#{OMWShaders:SkyFactorLevelName}";
description = "#{OMWShaders:SkyFactorLevelDescription}";
}
uniform_float uRadius {
default = 0.5;
min = 0.0;
max = 1.0;
step = 0.01;
display_name = "#{OMWShaders:RadiusLevelName}";
description = "#{OMWShaders:RadiusLevelDescription}";
}
uniform_float uStrength {
default = 0.25;
min = 0.0;
max = 1.0;
step = 0.01;
display_name = "#{OMWShaders:StrengthLevelName}";
description = "#{OMWShaders: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;
void main()
{
vec3 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);
}
}
technique {
passes = nomipmap, horizontal, vertical, final;
description = "#{OMWShaders:BloomDescription}";
author = "OpenMW";
version = "1.0";
}