mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-11-04 00:26:39 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			222 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			222 lines
		
	
	
	
		
			6.2 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
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";
 | 
						|
}
 | 
						|
 |