mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-31 19:26:38 +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";
 | |
| }
 | |
| 
 |